panda's tech note

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

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

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

今日からはビット列を扱うために Python の bitstring パッケージを使います。また,CRC-16/32の計算には crcmod パッケージを使います。また,チェックサム計算で出てきた値をビッグエンディアン

そのため,

import bitstring
import crcmod

とインポートします。

CRC-16/32チェックサム関数

昨日説明した通り,物理層のチェックサムには CRC-16-CCITT を使います。自分で実装しても良いですが,今回は crcmod パッケージを使います。後日気が向いたときに自分で実装し直せるように,以下の通り crc16() 関数として定義します。

"""
CRC-16
"""
def crc16(bstr):
    f = crcmod.predefined.mkPredefinedCrcFun('crc-aug-ccitt')
    return f(bstr)

上記のチェックサム関数は引数にバイナリ文字列を指定し,16ビットの整数を返します。CRC-16-CCITT のチェックサム検算は,元のビット列にチェックサムをビッグエンディアン(ネットワークエンディアン)で追加したものに対し,crc16() 関数を適応し, 0 になるかどうかで確認します。0 にならない場合は受信したビット列のどこかにビット誤りが発生していることを意味します。

また,データリンク層のフレームチェックサムは CRC-32 を使います。同じく crcmod パッケージを使い,crc32() 関数として定義します。

"""
CRC-32
"""
def crc32(bstr):
    f = crcmod.predefined.mkPredefinedCrcFun('crc32')
    return f(bstr)

上記のチェックサム関数は引数にバイナリ文字列を指定し,32ビットの整数を返します。チェックサムの検算をする際は,CRC-16-CCITT とは違いちょっと複雑で,こちらで求めたチェックサムをリトルエンディアンでビット列に含めたものに対してCRC-32を計算して 0x2144df1c になることで確認します。

これを踏まえて,チェックサムのバイト列を精製する関数 crc16_checksum() および crc32_checksum() と チェックサムを検証する関数 crc16_check() および crc32_check() を以下の通り実装します。

def crc16_checksum(bstr):
    return crc16(bstr).to_bytes(2, 'big')
def crc32_checksum(bstr):
    return crc32(bstr).to_bytes(4, 'little')
def crc16_check(bstr):
    if crc16(bstr) == 0:
        return True
    else:
        return False
def crc32_check(bstr):
    if crc32(bstr) == 0x2144df1c:
        return True
    else:
        return False

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

今日はフレームのチェックサムを検証する関数を書きました。crcmod を使っただけですが,今日はここまでにします。明日は変調を実装する予定です。