panda's tech note

Advent Calendar 2020: ソフトウェア無線

注意LimeSDR などのソフトウェア無線は技術基準適合証明(通称,技適)を受けていないため,これらの機器を日本国内で無線機として利用することは電波法により禁じられています。無線機として使用するためには,実験試験局免許を取得するか電波暗室・シールドボックスなどの設備を使用する必要があります。または,アンテナの代わりにケーブルとアッテネータを用い有線接続をし電波を発しないようにすることで,無線通信ではなく有線通信とはなりますが実験することができます(この場合も電波が漏れないように注意してください)。このページを参照される方は,実験される国や地域の法令などを遵守するようにご注意ください。また,実験等はご自身の責任でお願いします。

Day 17: オリジナルプロトコルの実装 (7)

今日はプリアンブルを含むパケットのシンボル列を復調して,データを取り出す部分を実装します。16日目 で取り出したシンボル列を分析します.

まず,BPSK方式での変調なので,前のシンボルの位相と比較して,同位相であれば同一のビット,位相が反転した場合(判定としては90度を超える場合)は反転したビットなので,シンボル間の位相差を計算します。その後,最初のシンボルをビット 0 として,ビット列に変換します.ここからプリアンブルとSFDを探索するのですが,シンボル列を最初のシンボルをビット 0 と想定してビット列に変換したので,逆位相で同期されている場合を考えて,ビット反転したビット列に対してもプリアンブルとSFDを探索します.このうち,プリアンブルとSFDが先に見つかったものをデータとして取り出します.

この復調を行う関数を以下の通り demodulate() 関数として実装しました。

"""
Demodulate and decode symbols
"""
def demodulate(symbols):
    # Demodulate symbols (to bits)
    bits = []
    # Calculate angles from previous symbols
    cur = symbols[1:] # current symbols
    prev = symbols[0:-1] # previous symbols
    prev = np.where(prev==0, prev + 1e-9, prev) # to avoid zero division
    diffAngles = np.angle(cur / prev)
    prev = False
    for a in np.absolute(diffAngles):
        if a > math.pi / 2:
            prev = not prev
        bits.append(prev)

    # Convert to binary string
    binary = bitstring.BitArray(bits)

    # Find the preamble + SFD
    pattern1 = bitstring.BitArray(hex='aa') + SFD
    pattern2 = ~pattern1
    found1 = binary.find(pattern1)
    found2 = binary.find(pattern2)
    if (not found1) and (not found2):
        return False
    if not found1 or (found2 and found2[0] < found1[0]):
        data = ~binary[found2[0]+pattern2.len:]
    else:
        data = binary[found1[0]+pattern1.len:]

    return data

これを 16日目while ループの最後に追加することで,得られたシンボル列を復調します。

今日のまとめと明日の予定

今日は復調関数を実装しました。明日は今日までの内容をまとめてオリジナルプロトコルの送受信を実験します。