def test_004_connect(self): """ Advanced test: - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer - FFT does shift (moves DC to middle) - Make sure input == output - Frequency offset is -2 carriers """ fft_len = 8 n_syms = 1 carr_offset = -2 freq_offset = 1.0 / fft_len * carr_offset # Normalized frequency occupied_carriers = ((-2, -1, 1, 2), ) pilot_carriers = ((-3, ), (3, )) pilot_symbols = ((1j, ), (-1j, )) tx_data = [1, 2, 3, 4] offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, 1, (offsettag, )) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key) tx_ifft = fft.fft_vcc(fft_len, False, (1.0 / fft_len, ) * fft_len, True) oscillator = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0) mixer = blocks.multiply_cc() rx_fft = fft.fft_vcc(fft_len, True, (), True) sink2 = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect(rx_fft, sink2) serializer = digital.ofdm_serializer_vcc(alloc, "", 0, "ofdm_sync_carr_offset", True) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_data), self.tsb_key), alloc, tx_ifft, blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len), (mixer, 0), blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), rx_fft, serializer, sink) self.tb.connect(oscillator, (mixer, 1)) self.tb.run() self.assertComplexTuplesAlmostEqual( sink.data()[0][-len(occupied_carriers[0]):], tx_data, places=4)
def test_004_connect (self): """ Advanced test: - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer - FFT does shift (moves DC to middle) - Make sure input == output - Frequency offset is -2 carriers """ fft_len = 8 n_syms = 1 carr_offset = -2 freq_offset = 1.0 / fft_len * carr_offset # Normalized frequency occupied_carriers = ((-2, -1, 1, 2),) pilot_carriers = ((-3,),(3,)) pilot_symbols = ((1j,),(-1j,)) tx_data = (1, 2, 3, 4) offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, 1, (offsettag,)) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key) tx_ifft = fft.fft_vcc(fft_len, False, (1.0 / fft_len,)*fft_len, True) oscillator = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0) mixer = blocks.multiply_cc() rx_fft = fft.fft_vcc(fft_len, True, (), True) sink2 = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect(rx_fft, sink2) serializer = digital.ofdm_serializer_vcc( alloc, "", 0, "ofdm_sync_carr_offset", True ) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_data), self.tsb_key), alloc, tx_ifft, blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len), (mixer, 0), blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), rx_fft, serializer, sink ) self.tb.connect(oscillator, (mixer, 1)) self.tb.run () self.assertComplexTuplesAlmostEqual(sink.data()[0][-len(occupied_carriers[0]):], tx_data, places=4)
def test_001_t (self): """ pretty simple (the carrier allocation here is not a practical OFDM configuration!) """ fft_len = 6 tx_symbols = (1, 2, 3) # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 pilot_symbols = ((1j,),) occupied_carriers = ((0, 1, 2),) pilot_carriers = ((3,),) sync_word = (list(range(fft_len)),) expected_result = tuple(sync_word[0] + [1j, 0, 0, 1, 2, 3]) # ^ DC carrier src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, sync_word, self.tsb_key) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink ) self.tb.run() self.assertEqual(sink.data()[0], expected_result)
def test_002_t (self): """ same, but using negative carrier indices """ fft_len = 6 tx_symbols = (1, 2, 3) pilot_symbols = ((1j,),) occupied_carriers = ((-1, 1, 2),) pilot_carriers = ((3,),) expected_result = (1j, 0, 1, 0, 2, 3) src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink ) self.tb.run () self.assertEqual(sink.data()[0], expected_result)
def test_001_t(self): """ pretty simple (the carrier allocation here is not a practical OFDM configuration!) """ fft_len = 6 tx_symbols = (1, 2, 3) # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 pilot_symbols = ((1j, ), ) occupied_carriers = ((0, 1, 2), ) pilot_carriers = ((3, ), ) sync_word = (list(range(fft_len)), ) expected_result = sync_word[0] + [1j, 0, 0, 1, 2, 3] # ^ DC carrier src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, sync_word, self.tsb_key) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result)
def test_001_t2(self): """ pretty simple (same as before, but odd fft len) """ fft_len = 5 tx_symbols = (1, 2, 3) # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 occupied_carriers = ((0, 1, 2), ) pilot_carriers = ((-2, ), ) pilot_symbols = ((1j, ), ) expected_result = [1j, 0, 1, 2, 3] # ^ DC carrier src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result)
def test_002_with_offset(self): """ Standard test, carrier offset """ fft_len = 16 tx_symbols = list(range(1, 16)) tx_symbols = (0, 0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0) carr_offset = 1 # Compare this with tx_symbols from the previous test expected_result = list(range(1, 16)) + [0, 0, 0] occupied_carriers = ( (1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14), ) n_syms = len(tx_symbols) // fft_len offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_symbols, False, fft_len, (offsettag, )) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key, "", 0, "ofdm_sync_carr_offset", False) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) self.assertEqual(len(sink.tags()), 1)
def test_003_connect(self): """ Connect carrier_allocator to ofdm_serializer, make sure output==input """ fft_len = 8 n_syms = 1 occupied_carriers = ((1, 2, 6, 7), ) pilot_carriers = ((3, ), (5, )) pilot_symbols = ((1j, ), (-1j, )) #tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)]) tx_data = [1, 2, 3, 4] src = blocks.vector_source_c(tx_data, False, 1) alloc = digital.ofdm_carrier_allocator_cvc( fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), # No sync word self.tsb_key, True # Output is shifted (default) ) serializer = digital.ofdm_serializer_vcc( alloc, "", # Len tag key 0, # Symbols skipped "", # Carrier offset key True # Input is shifted (default) ) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_data), self.tsb_key), alloc, serializer, sink) self.tb.run() self.assertEqual(sink.data()[0], tx_data)
def test_002_with_offset (self): """ Standard test, carrier offset """ fft_len = 16 tx_symbols = list(range(1, 16)); tx_symbols = (0, 0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0) carr_offset = 1 # Compare this with tx_symbols from the previous test expected_result = tuple(range(1, 16)) + (0, 0, 0) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) n_syms = len(tx_symbols) // fft_len offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_symbols, False, fft_len, (offsettag,)) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) serializer = digital.ofdm_serializer_vcc( fft_len, occupied_carriers, self.tsb_key, "", 0, "ofdm_sync_carr_offset", False ) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result) self.assertEqual(len(sink.tags()), 1)
def test_005_packet_len_tag(self): """ Standard test """ fft_len = 16 tx_symbols = list(range(1, 16)) tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) expected_result = list(range(1, 16)) occupied_carriers = ( (1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14), ) n_syms = len(tx_symbols) // fft_len packet_len_tsb_key = "packet_len" tag2 = gr.tag_t() tag2.offset = 0 tag2.key = pmt.string_to_symbol("packet_len") tag2.value = pmt.from_long(len(expected_result)) src = blocks.vector_source_c(tx_symbols, False, fft_len, (tag2, )) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key, packet_len_tsb_key, 0, "", False) sink = blocks.tsb_vector_sink_c(tsb_key=packet_len_tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result)
def test_003_connect (self): """ Connect carrier_allocator to ofdm_serializer, make sure output==input """ fft_len = 8 n_syms = 1 occupied_carriers = ((1, 2, 6, 7),) pilot_carriers = ((3,),(5,)) pilot_symbols = ((1j,),(-1j,)) #tx_data = tuple([numpy.random.randint(0, 10) for x in range(4 * n_syms)]) tx_data = (1, 2, 3, 4) src = blocks.vector_source_c(tx_data, False, 1) alloc = digital.ofdm_carrier_allocator_cvc( fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), # No sync word self.tsb_key, True # Output is shifted (default) ) serializer = digital.ofdm_serializer_vcc( alloc, "", # Len tag key 0, # Symbols skipped "", # Carrier offset key True # Input is shifted (default) ) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_data), self.tsb_key), alloc, serializer, sink) self.tb.run () self.assertEqual(sink.data()[0], tx_data)
def test_001b_simple_skip_nothing(self): """ Same as before, but put a skip-header in there """ fft_len = 8 equalizer = digital.ofdm_equalizer_static(fft_len, symbols_skipped=1) n_syms = 3 tx_data = [ 1, ] * fft_len * n_syms chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, (1, ) * fft_len) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag, )) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink) self.tb.run() # Check data self.assertEqual(tx_data, sink.data()[0])
def test_with_tags_2s_rolloff_multiples_cps(self): "Two CP lengths, 2-sample rolloff and tags." fft_len = 8 cp_lengths = (3, 2, 2) rolloff = 2 tag_name = "ts_last" expected_result = [ 6.0 / 2, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1 7.0 / 2 + 1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0 / 2 # Last tail ] # First test tag tag0 = gr.tag_t() tag0.offset = 0 tag0.key = pmt.string_to_symbol("first_tag") tag0.value = pmt.from_long(24) # Second test tag tag1 = gr.tag_t() tag1.offset = 1 tag1.key = pmt.string_to_symbol("second_tag") tag1.value = pmt.from_long(42) src = blocks.vector_source_c( list(range(1, fft_len + 1)) * 2, False, fft_len, (tag0, tag1)) cp = digital.ofdm_cyclic_prefixer(fft_len, cp_lengths, rolloff, tag_name) sink = blocks.tsb_vector_sink_c(tsb_key=tag_name) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, 2, tag_name), cp, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) expected_tags = [(0, "first_tag", 24), (fft_len + cp_lengths[0], "second_tag", 42)] self.assertEqual(tags, expected_tags)
def test_003_t (self): """ more advanced: - 6 symbols per carrier - 2 pilots per carrier - have enough data for nearly 3 OFDM symbols - send that twice - add some random tags - don't shift """ tx_symbols = list(range(1, 16)); # 15 symbols pilot_symbols = ((1j, 2j), (3j, 4j)) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) pilot_carriers = ((2, 13), (3, 12)) expected_result = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) fft_len = 16 testtag1 = gr.tag_t() testtag1.offset = 0 testtag1.key = pmt.string_to_symbol('tag1') testtag1.value = pmt.from_long(0) testtag2 = gr.tag_t() testtag2.offset = 7 # On the 2nd OFDM symbol testtag2.key = pmt.string_to_symbol('tag2') testtag2.value = pmt.from_long(0) testtag3 = gr.tag_t() testtag3.offset = len(tx_symbols)+1 # First OFDM symbol of packet 2 testtag3.key = pmt.string_to_symbol('tag3') testtag3.value = pmt.from_long(0) testtag4 = gr.tag_t() testtag4.offset = 2*len(tx_symbols)-1 # Last OFDM symbol of packet 2 testtag4.key = pmt.string_to_symbol('tag4') testtag4.value = pmt.from_long(0) src = blocks.vector_source_c(tx_symbols * 2, False, 1, (testtag1, testtag2, testtag3, testtag4)) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key, False) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result) tags_found = {'tag1': False, 'tag2': False, 'tag3': False, 'tag4': False} correct_offsets = {'tag1': 0, 'tag2': 1, 'tag3': 3, 'tag4': 5} for tag in sink.tags(): key = pmt.symbol_to_string(tag.key) if key in list(tags_found.keys()): tags_found[key] = True self.assertEqual(correct_offsets[key], tag.offset) self.assertTrue(all(tags_found.values()))
def test_001_simple (self): """ Standard test """ fft_len = 16 tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) expected_result = tuple(range(1, 16)) + (0, 0, 0) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) n_syms = len(tx_symbols) // fft_len src = blocks.vector_source_c(tx_symbols, False, fft_len) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key, "", 0, "", False) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result)
def test_002_simpledfe (self): """ Use the simple DFE equalizer. """ fft_len = 8 # 4 5 6 7 0 1 2 3 tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0 -1, -1, 0, 2, -1, 2, 0, -1, # 8 -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols) -1, -1, 1, 1, -1, 0, 2, -1] # 24 cnst = digital.constellation_qpsk() tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data] occupied_carriers = ((1, 2, 6, 7),) pilot_carriers = ((), (), (1, 2, 6, 7), ()) pilot_symbols = ( [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], [] ) equalizer = digital.ofdm_equalizer_simpledfe( fft_len, cnst.base(), occupied_carriers, pilot_carriers, pilot_symbols, 0, 0.01 ) channel = [ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly... 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here. ] for idx in range(fft_len, 2*fft_len): channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5)) idx2 = idx+2*fft_len channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5)) chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len]) src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (chan_tag,)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key, True) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) self.tb.run () rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()[0]] self.assertEqual(tx_data, rx_data) self.assertEqual(len(sink.tags()), 1) tag = sink.tags()[0] self.assertEqual(pmt.symbol_to_string(tag.key), "ofdm_sync_chan_taps") self.assertComplexTuplesAlmostEqual(list(pmt.c32vector_elements(tag.value)), channel[-fft_len:], places=1)
def test_002_static_wo_tags (self): """ Same as before, but the input stream has no tag. We specify the frame size in the constructor. We also specify a tag key, so the output stream *should* have a TSB tag. """ fft_len = 8 n_syms = 4 # 4 5 6 7 0 1 2 3 tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0 -1, -1, 0, 2, -1, 2, 0, -1, # 8 -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols) -1, -1, 1, 1, -1, 0, 2, -1] # 24 cnst = digital.constellation_qpsk() tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data] occupied_carriers = ((1, 2, 6, 7),) pilot_carriers = ((), (), (1, 2, 6, 7), ()) pilot_symbols = ( [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], [] ) equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers, pilot_carriers, pilot_symbols) channel = [ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly (below)... 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! 0, 0, 1j, 1j, 0, 1j, 1j, 0 # ...and again here. ] for idx in range(fft_len, 2*fft_len): channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5)) idx2 = idx+2*fft_len channel[idx2] = channel[idx2] * numpy.exp(1j * 0 * numpy.pi * (numpy.random.rand()-.5)) src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key, False, n_syms) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) self.tb.run () rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()[0]] self.assertEqual(tx_data, rx_data) # Check TSB Functionality packets = sink.data() self.assertEqual(len(packets), 1) self.assertEqual(len(packets[0]), len(tx_data))
def test_with_tags_2s_rolloff(self): " With tags and a 2-sample rolloff " fft_len = 8 cp_len = 2 tag_name = "ts_last" expected_result = [ 7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0 / 2 + 1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0 / 2 ] tag2 = gr.tag_t() tag2.offset = 1 tag2.key = pmt.string_to_symbol("random_tag") tag2.value = pmt.from_long(42) src = blocks.vector_source_c( list(range(1, fft_len + 1)) * 2, False, fft_len, (tag2, )) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) sink = blocks.tsb_vector_sink_c(tsb_key=tag_name) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, 2, tag_name), cp, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) expected_tags = [(fft_len + cp_len, "random_tag", 42)] self.assertEqual(tags, expected_tags)
def test_001c_carrier_offset_no_cp(self): """ Same as before, but put a carrier offset in there """ fft_len = 8 cp_len = 0 n_syms = 1 carr_offset = 1 occupied_carriers = ((-2, -1, 1, 2), ) tx_data = ( 0, 0, 0, -1j, -1j, 0, -1j, -1j, ) # The rx'd signal is shifted rx_expected = (0, 0, 1, 1, 0, 1, 1, 0) * n_syms equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers) chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") # Note: this is shifted to the correct position! chan_tag.value = pmt.init_c32vector(fft_len, (0, 0, -1j, -1j, 0, -1j, -1j, 0)) offset_tag = gr.tag_t() offset_tag.offset = 0 offset_tag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offset_tag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag, offset_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), cp_len, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink) self.tb.run() # Check data self.assertComplexTuplesAlmostEqual(rx_expected, sink.data()[0], places=4)
def test_001b_shifted (self): """ Same as before, but shifted, because that's the normal mode in OFDM Rx """ fft_len = 16 tx_symbols = ( 0, 0, 0, 0, 0, 0, 1, 2, 0, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1j, 7, 8, 0, 9, 10, 1j, 11, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, 15, 16, 17, 0, 0, 0, 0, ) expected_result = tuple(range(18)) occupied_carriers = ((13, 14, 15, 1, 2, 3), (-4, -2, -1, 1, 2, 4),) n_syms = len(tx_symbols) // fft_len src = blocks.vector_source_c(tx_symbols, False, fft_len) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result)
def test_002_tb(self): """ once again, but this time add a sync word """ fft_len = 6 sync_word = (0, ) * fft_len tx_symbols = (1, 2, 3, 4, 5, 6) pilot_symbols = ((1j, ), ) occupied_carriers = ((-1, 1, 2), ) pilot_carriers = ((3, ), ) expected_result = list(sync_word + (1j, 0, 1, 0, 2, 3) + (1j, 0, 4, 0, 5, 6)) special_tag1 = gr.tag_t() special_tag1.offset = 0 special_tag1.key = pmt.string_to_symbol("spam") special_tag1.value = pmt.to_pmt(23) special_tag2 = gr.tag_t() special_tag2.offset = 4 special_tag2.key = pmt.string_to_symbol("eggs") special_tag2.value = pmt.to_pmt(42) src = blocks.vector_source_c(tx_symbols, False, 1, (special_tag1, special_tag2)) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, sync_words=(sync_word, ), len_tag_key=self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) tags_expected = [ (0, 'spam', 23), (2, 'eggs', 42), ] self.assertEqual(tags, tags_expected)
def test_002_t (self): """ once again, but this time add a sync word """ fft_len = 6 sync_word = (0,) * fft_len tx_symbols = (1, 2, 3, 4, 5, 6) pilot_symbols = ((1j,),) occupied_carriers = ((-1, 1, 2),) pilot_carriers = ((3,),) expected_result = sync_word + (1j, 0, 1, 0, 2, 3) + (1j, 0, 4, 0, 5, 6) special_tag1 = gr.tag_t() special_tag1.offset = 0 special_tag1.key = pmt.string_to_symbol("spam") special_tag1.value = pmt.to_pmt(23) special_tag2 = gr.tag_t() special_tag2.offset = 4 special_tag2.key = pmt.string_to_symbol("eggs") special_tag2.value = pmt.to_pmt(42) src = blocks.vector_source_c( tx_symbols, False, 1, (special_tag1, special_tag2) ) alloc = digital.ofdm_carrier_allocator_cvc( fft_len, occupied_carriers, pilot_carriers, pilot_symbols, sync_words=(sync_word,), len_tag_key=self.tsb_key ) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) tags_expected = [ (0, 'spam', 23), (2, 'eggs', 42), ] self.assertEqual(tags, tags_expected)
def test_001_simple (self): """ Very simple functionality testing: - static equalizer - init channel state with all ones - transmit all ones - make sure we rx all ones - Tag check: put in frame length tag and one other random tag, make sure they're propagated """ fft_len = 8 equalizer = digital.ofdm_equalizer_static(fft_len) n_syms = 3 tx_data = (1,) * fft_len * n_syms chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, (1,) * fft_len) random_tag = gr.tag_t() random_tag.offset = 1 random_tag.key = pmt.string_to_symbol("foo") random_tag.value = pmt.from_long(42) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag, random_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink ) self.tb.run () # Check data self.assertEqual(tx_data, sink.data()[0]) # Check tags tag_dict = dict() for tag in sink.tags(): ptag = gr.tag_to_python(tag) tag_dict[ptag.key] = ptag.value expected_dict = { 'foo': 42 } self.assertEqual(tag_dict, expected_dict)
def test_005_packet_len_tag (self): """ Standard test """ fft_len = 16 tx_symbols = list(range(1, 16)); tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) expected_result = tuple(range(1, 16)) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) n_syms = len(tx_symbols) // fft_len packet_len_tsb_key = "packet_len" tag2 = gr.tag_t() tag2.offset = 0 tag2.key = pmt.string_to_symbol("packet_len") tag2.value = pmt.from_long(len(expected_result)) src = blocks.vector_source_c(tx_symbols, False, fft_len, (tag2,)) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key, packet_len_tsb_key , 0, "", False) sink = blocks.tsb_vector_sink_c(tsb_key=packet_len_tsb_key) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), serializer, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result)
def test_001c_carrier_offset_cp (self): """ Same as before, but put a carrier offset in there and a CP """ fft_len = 8 cp_len = 2 n_syms = 3 # cp_len/fft_len == 1/4, therefore, the phase is rotated by # carr_offset * \pi/2 in every symbol occupied_carriers = ((-2, -1, 1, 2),) carr_offset = -1 tx_data = ( 0,-1j,-1j, 0,-1j,-1j, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, 1j, 1j, 0, 1j, 1j, 0, 0, ) # Rx'd signal is corrected rx_expected = (0, 0, 1, 1, 0, 1, 1, 0) * n_syms equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers) chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, (0, 0, 1, 1, 0, 1, 1, 0)) offset_tag = gr.tag_t() offset_tag.offset = 0 offset_tag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offset_tag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag, offset_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), cp_len, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink ) self.tb.run () # Check data self.assertComplexTuplesAlmostEqual(rx_expected, sink.data()[0], places=4)
def test_with_tags_2s_rolloff(self): " With tags and a 2-sample rolloff " fft_len = 8 cp_len = 2 tag_name = "ts_last" expected_result = (7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0 / 2+1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0 / 2) tag2 = gr.tag_t() tag2.offset = 1 tag2.key = pmt.string_to_symbol("random_tag") tag2.value = pmt.from_long(42) src = blocks.vector_source_c(list(range(1, fft_len+1)) * 2, False, fft_len, (tag2,)) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) sink = blocks.tsb_vector_sink_c(tsb_key=tag_name) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, 2, tag_name), cp, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) expected_tags = [ (fft_len+cp_len, "random_tag", 42) ] self.assertEqual(tags, expected_tags)
def test_002_t(self): """ same, but using negative carrier indices """ fft_len = 6 tx_symbols = (1, 2, 3) pilot_symbols = ((1j, ), ) occupied_carriers = ((-1, 1, 2), ) pilot_carriers = ((3, ), ) expected_result = [1j, 0, 1, 0, 2, 3] src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result)
def test_001b_simple_skip_nothing (self): """ Same as before, but put a skip-header in there """ fft_len = 8 equalizer = digital.ofdm_equalizer_static(fft_len, symbols_skipped=1) n_syms = 3 tx_data = (1,) * fft_len * n_syms chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, (1,) * fft_len) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag,)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink ) self.tb.run () # Check data self.assertEqual(tx_data, sink.data()[0])
def test_001_t2 (self): """ pretty simple (same as before, but odd fft len) """ fft_len = 5 tx_symbols = (1, 2, 3) # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 occupied_carriers = ((0, 1, 2),) pilot_carriers = ((-2,),) pilot_symbols = ((1j,),) expected_result = (1j, 0, 1, 2, 3) # ^ DC carrier src = blocks.vector_source_c(tx_symbols, False, 1) alloc = digital.ofdm_carrier_allocator_cvc( fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key ) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run () self.assertEqual(sink.data()[0], expected_result)
def test_001c_carrier_offset_no_cp (self): """ Same as before, but put a carrier offset in there """ fft_len = 8 cp_len = 0 n_syms = 1 carr_offset = 1 occupied_carriers = ((-2, -1, 1, 2),) tx_data = ( 0, 0, 0, -1j, -1j, 0, -1j, -1j, ) # The rx'd signal is shifted rx_expected = (0, 0, 1, 1, 0, 1, 1, 0) * n_syms equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers) chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") # Note: this is shifted to the correct position! chan_tag.value = pmt.init_c32vector(fft_len, (0, 0, -1j, -1j, 0, -1j, -1j, 0)) offset_tag = gr.tag_t() offset_tag.offset = 0 offset_tag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offset_tag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, fft_len, (chan_tag, offset_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), cp_len, self.tsb_key) sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, n_syms, self.tsb_key), eq, sink ) self.tb.run () # Check data self.assertComplexTuplesAlmostEqual(rx_expected, sink.data()[0], places=4)
def test_003_t(self): """ more advanced: - 6 symbols per carrier - 2 pilots per carrier - have enough data for nearly 3 OFDM symbols - send that twice - add some random tags - don't shift """ tx_symbols = list(range(1, 16)) # 15 symbols pilot_symbols = ((1j, 2j), (3j, 4j)) occupied_carriers = ( (1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14), ) pilot_carriers = ((2, 13), (3, 12)) expected_result = list( (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0)) fft_len = 16 testtag1 = gr.tag_t() testtag1.offset = 0 testtag1.key = pmt.string_to_symbol('tag1') testtag1.value = pmt.from_long(0) testtag2 = gr.tag_t() testtag2.offset = 7 # On the 2nd OFDM symbol testtag2.key = pmt.string_to_symbol('tag2') testtag2.value = pmt.from_long(0) testtag3 = gr.tag_t() testtag3.offset = len(tx_symbols) + 1 # First OFDM symbol of packet 2 testtag3.key = pmt.string_to_symbol('tag3') testtag3.value = pmt.from_long(0) testtag4 = gr.tag_t() testtag4.offset = 2 * len( tx_symbols) - 1 # Last OFDM symbol of packet 2 testtag4.key = pmt.string_to_symbol('tag4') testtag4.value = pmt.from_long(0) src = blocks.vector_source_c(tx_symbols * 2, False, 1, (testtag1, testtag2, testtag3, testtag4)) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), self.tsb_key, False) sink = blocks.tsb_vector_sink_c(fft_len) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, 1, len(tx_symbols), self.tsb_key), alloc, sink) self.tb.run() self.assertEqual(sink.data()[0], expected_result) tags_found = { 'tag1': False, 'tag2': False, 'tag3': False, 'tag4': False } correct_offsets = {'tag1': 0, 'tag2': 1, 'tag3': 3, 'tag4': 5} for tag in sink.tags(): key = pmt.symbol_to_string(tag.key) if key in list(tags_found.keys()): tags_found[key] = True self.assertEqual(correct_offsets[key], tag.offset) self.assertTrue(all(tags_found.values()))
def test_002_static (self): """ - Add a simple channel - Make symbols QPSK """ fft_len = 8 # 4 5 6 7 0 1 2 3 tx_data = [-1, -1, 1, 2, -1, 3, 0, -1, # 0 -1, -1, 0, 2, -1, 2, 0, -1, # 8 -1, -1, 3, 0, -1, 1, 0, -1, # 16 (Pilot symbols) -1, -1, 1, 1, -1, 0, 2, -1] # 24 cnst = digital.constellation_qpsk() tx_signal = [cnst.map_to_points_v(x)[0] if x != -1 else 0 for x in tx_data] occupied_carriers = ((1, 2, 6, 7),) pilot_carriers = ((), (), (1, 2, 6, 7), ()) pilot_symbols = ( [], [], [cnst.map_to_points_v(x)[0] for x in (1, 0, 3, 0)], [] ) equalizer = digital.ofdm_equalizer_static(fft_len, occupied_carriers, pilot_carriers, pilot_symbols) channel = [ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly (but less than \pi/2) 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! 0, 0, 1j, 1j, 0, 1j, 1j, 0 ] channel = [ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, # These coefficients will be rotated slightly (but less than \pi/2) 0, 0, 1j, 1j, 0, 1j, 1j, 0, # Go crazy here! 0, 0, 1j, 1j, 0, 1j, 1j, 0 ] for idx in range(fft_len, 2*fft_len): channel[idx] = channel[idx-fft_len] * numpy.exp(1j * .1 * numpy.pi * (numpy.random.rand()-.5)) chan_tag = gr.tag_t() chan_tag.offset = 0 chan_tag.key = pmt.string_to_symbol("ofdm_sync_chan_taps") chan_tag.value = pmt.init_c32vector(fft_len, channel[:fft_len]) src = blocks.vector_source_c(numpy.multiply(tx_signal, channel), False, fft_len, (chan_tag,)) sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key, True) self.tb.connect( src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) self.tb.run () rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()[0]] # Check data self.assertEqual(tx_data, rx_data) # Check tags tag_dict = dict() for tag in sink.tags(): ptag = gr.tag_to_python(tag) tag_dict[ptag.key] = ptag.value if ptag.key == 'ofdm_sync_chan_taps': tag_dict[ptag.key] = list(pmt.c32vector_elements(tag.value)) else: tag_dict[ptag.key] = pmt.to_python(tag.value) expected_dict = { 'ofdm_sync_chan_taps': channel[-fft_len:] } self.assertEqual(tag_dict, expected_dict)