benchmark_tx.py

「benchmark_tx.py」の編集履歴(バックアップ)一覧に戻る

benchmark_tx.py - (2011/04/25 (月) 03:28:51) の編集履歴(バックアップ)


パケット送信プログラムのサンプルコード。
例)./benchmark_tx.py -m dbpsk -f 2.45G

ペイロードデータ

デフォルトではパケット番号+パケット番号下位1バイトのペイロードが作られる。
Pythonではバイト列を文字列として扱う
data = (pkt_size - 2) * chr(pktno & 0xff) #chr()は引数に対応するascii文字を返す。これを指定パケットサイズ-2個繋げてdataに格納。
payload = struct.pack('!H', pktno & 0xffff) + data #パケット番号の下位2バイト(複数バイトなのでネットワークバイトオーダーを指定)とdataを繋げてpayload完成。
send_pkt(payload)

パケットの作成:mod_pkts.send_pkt→packet_utils.make_packet

  • パディング
1パケットを512バイトで送るため、4 bytes/sample(DACのダイナミックレンジ) × 128 samples にする。
pkt = pkt + (_npadding_bytes(len(pkt), samples_per_symbol, bits_per_symbol) * '\x55') #'55'をパディング。
def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol):
   """
   Generate sufficient padding such that each packet ultimately ends
   up being a multiple of 512 bytes when sent across the USB.  We
   send 4-byte samples across the USB (16-bit I and 16-bit Q), thus
   we want to pad so that after modulation the resulting packet
   is a multiple of 128 samples.
   @param ptk_byte_len: len in bytes of packet, not including padding.
   @param samples_per_symbol: samples per bit (1 bit / symbolwidth GMSK) ※1シンボルで何回サンプルするか。dbpskの場合2
   @type samples_per_symbol: int
   @param bits_per_symbol: bits per symbol (log2(modulation order)) ※1シンボルで何ビット送れるか。dbpskの場合1(modulation order は2)
   @type bits_per_symbol: int
   @returns number of bytes of padding to append.
   """
   modulus = 128
   byte_modulus = gru.lcm(modulus/8, samples_per_symbol) * bits_per_symbol / samples_per_symbol #(16-byte/パケット)×(bits/sample)。dbpskの場合8-byte
   r = pkt_byte_len % byte_modulus #余っていて送らないといけないバイト数#bdpskでパケットサイズが1519bytesの場合7bytes
   if r == 0:
       return 0
   return byte_modulus - r #パディングするバイト数

変調ブロック:modulation_utils.type_1_mods()

バイトストリームを入力に複素数ベースバンド信号を出力する。
Type 1 modulators accept a stream of bytes on their input and produce complex baseband output
おそらくUSRPに直行変調器が実装されており、そこのIQの値を設定するブロックである。
呼び出しているクラスdbpsk_modでこの中で以下のものが呼び出されている。
  • bytes2chunks = gr.packed_to_unpacked_bb(bits_per_chunk, gr.GR_MSB_FIRST)
The bits in the bytes input stream are grouped into chunks of bits_per_chunk bits and each resulting chunk is written right-justified to the output stream of bytes.
入力する1バイトの中身をbits_per_chunkで指定した数の塊に分けて右揃えのバイト列を出力する。bits_per_chunk=1でbitのベクトルになる。
1バイトの中身はintegerで表現される。例えば、70('F')で表されるbit列は01000110であり、
bits_per_chunk=1にすると0,1,0,0,0,1,1,0の8bytesのバイト列となって出力される。
この時、gr.GR_MSB_FIRSTを指定すると左の0が先頭のバイト列なる。
QPSKの場合bits_per_chunk(= bits_per_simbol)は2となる。
この時、上の例と同じように1バイトの中身が70の場合、1,0,1,2の4bytesで出力バイトストリームが得られる。
  • symbol_mapper = gr.map_bb(psk.binary_to_ungray[arity]):arityはシンボルの種類数
ビット入力をマッピングして出力する。bpskの場合、0or1に、qpskの場合0or1or2or3にマッピングされる。
output[i] = psk.binary_to_ungray[input[i]]
  • diffenc = gr.diff_encoder_bb(arity:modulus):
y[0] = (x[0] + y[-1]) % M
Differential encoder
前の時間との差分で符号化する。
  • chunks2symbols = gr.chunks_to_symbols_bc(psk.constellation[arity]:symbol_table)
シンボル列(ビット列:integer)をコンスタレーションにマッピングし、複素信号を生成。
Map a stream of symbol indexes (unpacked bytes or shorts) to stream of float or complex constellation points.in D dimensions (D = 1 by default)
input: stream of unsigned char; output: stream of gr_complex.
out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1
例えば、in[i] = {1, 0, 1, 1}, D = 1(dbpsk)の場合
out[0] = symbol_table[in[0]],
out[1] = symbol_table[in[1]],
....
この時のsymbol_tableは以下のm = 2 の場合
def make_constellation(m):
   return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)]
つまり、return [1, -1]
symobol_tableがm = 4(qpsk)の場合
return [1, j, -1, -j]
入力シンボルが0の場合、1を出力し、入力シンボルが1の場合、-1を出力する。

増幅ブロック:gr.multiply_const_cc(1)

USRPシンクブロック:create_usrp_sink → generic_usrp.generic_usrp_sink_c → usrp2.cource_32fc

32ビットfloatの複素信号を入力にしたusrpのsink。