Advent Calendar 2020: ソフトウェア無線
注意:LimeSDR などのソフトウェア無線は技術基準適合証明(通称,技適)を受けていないため,これらの機器を日本国内で無線機として利用することは電波法により禁じられています。無線機として使用するためには,実験試験局免許を取得するか電波暗室・シールドボックスなどの設備を使用する必要があります。または,アンテナの代わりにケーブルとアッテネータを用い有線接続をし電波を発しないようにすることで,無線通信ではなく有線通信とはなりますが実験することができます(この場合も電波が漏れないように注意してください)。このページを参照される方は,実験される国や地域の法令などを遵守するようにご注意ください。また,実験等はご自身の責任でお願いします。
Day 14: オリジナルプロトコルの実装 (4)
12日目 と 13日目 に実装した物理層とデータリンク層のフレーム構築実装を用いて,今日はオリジナルプロトコルの送信部分を書いていきます。
以下の通り,SoapySDR のデバイスインスタンス sdr
,送信ストリーム txStream
,32ビットのbitstring.BitArray
型の宛先および送信元アドレス dst
および src
,シーケンス番号 seqno
,送信するバイト列 data
を引数とする transmit_packet()
関数を実装します。
"""
Transmit
"""
def transmit_packet(sdr, txStream, dst, src, seqno, data):
# Build the datalink layer frame
frame = build_datalink(dst, src, seqno, bitstring.BitArray(data))
# Build the physical layer protocol header
phy = build_phy(frame.size)
# Combine the physical layer header and the data-link frame
symbols = np.concatenate([phy, frame])
# Get samples from symbols
samples = np.repeat(symbols, SAMPLES_PER_SYMBOL)
mtu = sdr.getStreamMTU(txStream)
sent = 0
while sent < len(samples):
chunk = samples[sent:sent+mtu]
status = sdr.writeStream(txStream, [chunk], chunk.size, timeoutUs=1000000)
if status.ret != chunk.size:
sys.stderr.write("Failed to transmit all samples in writeStream(): {}\n".format(status.ret))
return False
sent += status.ret
return True
この関数では,まず送信するバイト列 data
を bitstring.BitArray
型に変換し,データリンク層のフレーム frame
を構築します。次にデータリンク層のフレームのシンボル長を含む物理層のプロトコルヘッダ phy
を構築します。これらを組み合わせたものをシンボル列として送信します。
4日目 で説明したのと同様に,今回も1シンボルあたり10サンプルで信号を表します。シンボルからサンプルを得るには,以下のように NumPy の repeat()
を使うと簡単です。
np.repeat(symbols, SAMPLES_PER_SYMBOL)
これにより symbols
のそれぞれの要素が SAMPLES_PER_SYMBOL
回連続するような配列を得ることができます。
このようにして得られたサンプル列を sdr.writeStream()
により txStream
に送信するのですが,送信ストリームには最大送信単位であるMTUがあるため,MTUに合わせてサンプル列を分割して送ります。上記コードの while 文の中でその処理を行っています。
今日のまとめと明日の予定
今日はデータをパケットとして送信する機能を実装しました。明日はこのデータの受信を行っていこうと思います。