def test_sc_tag(self): constA = [-3.0+1j, -1.0-1j, 1.0+1j, 3-1j] constB = [12.0+1j, -12.0-1j, 6.0+1j, -6-1j] src_data = (0, 1, 2, 3, 3, 2, 1, 0) expected_result = (-3+1j, -1-1j, 1+1j, 3-1j, -6-1j, 6+1j, -12-1j, 12+1j) first_tag = gr.tag_t() first_tag.key = pmt.intern("set_symbol_table") first_tag.value = pmt.init_c32vector(len(constA), constA) first_tag.offset = 0 second_tag = gr.tag_t() second_tag.key = pmt.intern("set_symbol_table") second_tag.value = pmt.init_c32vector(len(constB), constB) second_tag.offset = 4 src = blocks.vector_source_s(src_data, False, 1, [first_tag, second_tag]) op = digital.chunks_to_symbols_sc(constB) dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() actual_result = dst.data() self.assertEqual(expected_result, actual_result)
def test_001_three (self): in_data1 = [1+1j, 0-1j] in_data2 = [1, 0] in_data3 = [1j, -1] expected_data = in_data1 + in_data2 + in_data3 dict1 = pmt.dict_add(pmt.make_dict(), pmt.intern("burst_index"), pmt.cons(pmt.from_uint64(1), pmt.from_uint64(3))) dict2 = pmt.dict_add(pmt.make_dict(), pmt.intern("burst_index"), pmt.cons(pmt.from_uint64(2), pmt.from_uint64(3))) dict3 = pmt.dict_add(pmt.make_dict(), pmt.intern("burst_index"), pmt.cons(pmt.from_uint64(3), pmt.from_uint64(3))) in_pdu1 = pmt.cons(dict1, pmt.init_c32vector(len(in_data1), in_data1)) in_pdu2 = pmt.cons(dict2, pmt.init_c32vector(len(in_data2), in_data2)) in_pdu3 = pmt.cons(dict3, pmt.init_c32vector(len(in_data3), in_data3)) expected_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(expected_data), expected_data)) self.tb.start() time.sleep(.001) # handle non-pair input self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) # handle malformed pair self.emitter.emit(pmt.cons(pmt.intern("NON-PDU"), pmt.intern("PAIR"))) time.sleep(.001) # handle out of order PDU self.emitter.emit(in_pdu3) time.sleep(.001) self.emitter.emit(in_pdu1) time.sleep(.001) self.emitter.emit(in_pdu2) time.sleep(.001) self.emitter.emit(in_pdu3) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertComplexTuplesAlmostEqual(out_data, expected_data)
def test_001_t(self): self.emitter = pdu_utils.message_emitter() self.qd = pdu_utils.pdu_quadrature_demod_cf(1) self.debug = blocks.message_debug() self.tb.msg_connect((self.emitter, 'msg'), (self.qd, 'cpdus')) self.tb.msg_connect((self.qd, 'fpdus'), (self.debug, 'store')) in_data1 = [1., 1.j, -1., -1.j, 1.] in_data2 = [7. + 7.j, -7. + 7.j, -7. - 7.j, 7. - 7.j, 7. + 7.j] expected_data = [PI / 2, PI / 2, PI / 2, PI / 2] in_pdu1 = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data1), in_data1)) in_pdu2 = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data2), in_data2)) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu1) time.sleep(.01) self.emitter.emit(in_pdu2) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.f32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertFloatTuplesAlmostEqual(out_data, expected_data, 4) out_data = pmt.f32vector_elements(pmt.cdr(self.debug.get_message(1))) self.assertFloatTuplesAlmostEqual(out_data, expected_data, 4)
def test_001_c32(self): ''' uint8_t input data, no decimation, no filter ''' self.dut = pdu_utils.pdu_fir_filter(1, [1.0]) self.connectUp() i_data = [1, 0, 0, 0] * 5 i_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_float(1000.0)) in_pdu = pmt.cons(i_meta, pmt.init_c32vector(len(i_data), i_data)) e_data = [1, 0, 0, 0] * 5 e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_float(1000.0)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) self.tb.start() time.sleep(.01) self.emitter.emit(in_pdu) time.sleep(.1) self.tb.stop() self.tb.wait() #print("test_001:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print self.assertTrue(pmt.equal(self.debug.get_message(0), e_pdu))
def test_002_oneshot(self): in_data1 = [1 + 1j, 0 - 1j] expected_data = in_data1 dict1 = pmt.dict_add(pmt.make_dict(), pmt.intern("burst_index"), pmt.cons(pmt.from_uint64(1), pmt.from_uint64(1))) in_pdu1 = pmt.cons(dict1, pmt.init_c32vector(len(in_data1), in_data1)) expected_pdu = pmt.cons( pmt.make_dict(), pmt.init_c32vector(len(expected_data), expected_data)) self.tb.start() time.sleep(.001) # handle non-pair input self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) # handle malformed pair self.emitter.emit(pmt.cons(pmt.intern("NON-PDU"), pmt.intern("PAIR"))) time.sleep(.001) self.emitter.emit(in_pdu1) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertComplexTuplesAlmostEqual(out_data, expected_data)
def test_sc_tag(self): constA = [-3.0 + 1j, -1.0 - 1j, 1.0 + 1j, 3 - 1j] constB = [12.0 + 1j, -12.0 - 1j, 6.0 + 1j, -6 - 1j] src_data = (0, 1, 2, 3, 3, 2, 1, 0) expected_result = (-3 + 1j, -1 - 1j, 1 + 1j, 3 - 1j, -6 - 1j, 6 + 1j, -12 - 1j, 12 + 1j) first_tag = gr.tag_t() first_tag.key = pmt.intern("set_symbol_table") first_tag.value = pmt.init_c32vector(len(constA), constA) first_tag.offset = 0 second_tag = gr.tag_t() second_tag.key = pmt.intern("set_symbol_table") second_tag.value = pmt.init_c32vector(len(constB), constB) second_tag.offset = 4 src = blocks.vector_source_s(src_data, False, 1, [first_tag, second_tag]) op = digital.chunks_to_symbols_sc(constB) dst = blocks.vector_sink_c() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() actual_result = dst.data() self.assertEqual(expected_result, actual_result)
def test_002_normal(self): tnow = time.time() in_data = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1] meta = pmt.dict_add(pmt.make_dict(), pmt.intern( 'system_time'), pmt.from_double(tnow - 10.0)) in_pdu = pmt.cons(meta, pmt.init_c32vector(len(in_data), in_data)) e_data = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1] e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern( 'system_time'), pmt.from_double(tnow)) e_meta = pmt.dict_add(e_meta, pmt.intern( 'sys time delta (ms)'), pmt.from_double(10000.0)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) # set up fg self.tb.start() self.time_delta.to_basic_block()._post(pmt.intern("pdu"), in_pdu) self.waitFor(lambda: self.debug.num_messages() == 1, timeout=1.0, poll_interval=0.01) self.tb.stop() self.tb.wait() # check data self.assertEqual(1, self.debug.num_messages()) a_meta = pmt.car(self.debug.get_message(0)) time_tag = pmt.dict_ref(a_meta, pmt.intern("system_time"), pmt.PMT_NIL) delta_tag = pmt.dict_ref(a_meta, pmt.intern( "sys time delta (ms)"), pmt.PMT_NIL) self.assertAlmostEqual(tnow, pmt.to_double(time_tag), delta=60) self.assertAlmostEqual(10000, pmt.to_double(delta_tag), delta=10)
def test_coerce(self): samp_rate = 1e6 freq_offset = -400e3 center_freq = 911e6 # blocks self.emitter = pdu_utils.message_emitter() self.cf = fhss_utils.cf_estimate(fhss_utils.COERCE, [x * 1e6 for x in range(900, 930)]) self.debug = blocks.message_debug() # connections self.tb.msg_connect((self.emitter, 'msg'), (self.cf, 'in')) self.tb.msg_connect((self.cf, 'out'), (self.debug, 'store')) # data in_data = (1 + 0j, ) * 2048 i_vec = pmt.init_c32vector(len(in_data), in_data) out_data = np.exp(1j * np.arange(0, 2 * np.pi * (freq_offset / samp_rate * len(in_data)), 2 * np.pi * (freq_offset / samp_rate), dtype=np.complex64)) e_vec = pmt.init_c32vector(len(out_data), out_data.tolist( )) # pmt doesn't play nice with numpy sometimes, convert to list meta = pmt.make_dict() meta = pmt.dict_add(meta, pmt.intern("sample_rate"), pmt.from_float(samp_rate)) meta = pmt.dict_add(meta, pmt.intern("center_frequency"), pmt.from_float(center_freq + freq_offset)) in_pdu = pmt.cons(meta, i_vec) e_pdu = pmt.cons(meta, e_vec) # flowgraph self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() # parse output #print "got ", list(pmt.to_python(pmt.cdr(self.debug.get_message(0)))) #print "got ", self.debug.get_message(0) rcv = self.debug.get_message(0) rcv_meta = pmt.car(rcv) rcv_data = pmt.cdr(rcv) rcv_cf = pmt.dict_ref(rcv_meta, pmt.intern("center_frequency"), pmt.PMT_NIL) # asserts self.assertComplexTuplesAlmostEqual( tuple(pmt.c32vector_elements(rcv_data)), tuple(out_data), 2) self.assertTrue(pmt.equal(rcv_cf, pmt.from_float(911e6)))
def test_002_normal(self): tnow = time.time() in_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 ] meta = pmt.dict_add(pmt.make_dict(), pmt.intern('wall_clock_time'), pmt.from_double(tnow - 10)) in_pdu = pmt.cons(meta, pmt.init_c32vector(len(in_data), in_data)) e_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 ] e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern('wall_clock_time'), pmt.from_double(tnow)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) # set up fg self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() # check data self.assertEqual(1, self.debug.num_messages()) #print("test_002_normal2:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print a_meta = pmt.car(self.debug.get_message(0)) time_tag = pmt.dict_ref(a_meta, pmt.intern("wall_clock_time"), pmt.PMT_NIL) if not pmt.eqv(time_tag, pmt.PMT_NIL): self.assertAlmostEqual(tnow, pmt.to_double(time_tag), delta=60) else: self.assertTrue(False) delta_tag = pmt.dict_ref(a_meta, pmt.intern("time_delta_ms"), pmt.PMT_NIL) if not pmt.eqv(delta_tag, pmt.PMT_NIL): self.assertAlmostEqual(10000, pmt.to_double(delta_tag), delta=10) else: self.assertTrue(False)
def test_coerce(self): self.emitter = pdu_utils.message_emitter() self.cf = fhss_utils.cf_estimate(fhss_utils.COERCE, [x * 1e6 for x in range(900, 930)]) self.debug = blocks.message_debug() self.tb.msg_connect((self.emitter, 'msg'), (self.cf, 'in')) self.tb.msg_connect((self.cf, 'out'), (self.debug, 'store')) # original data in_data = np.exp(1j * np.array(np.linspace(0, 10 * np.pi * 2, 20))) i_vec = pmt.init_c32vector(len(in_data), in_data) out_data = [(1 + 0j), (-0.9863691 - 0.16454819j), (0.9458478 + 0.32461047j), (-0.8795409 - 0.47582325j), (0.7892561 + 0.61406416j), (-0.67745465 - 0.7355646j), (0.54718447 + 0.8370121j), (-0.40199703 - 0.915641j), (0.24585037 + 0.9693079j), (-0.083001345 - 0.9965495j), (-0.08211045 + 0.99662334j), (0.24498378 - 0.96952736j), (-0.4011784 + 0.9160001j), (0.5464361 - 0.83750105j), (-0.6767969 + 0.73617005j), (0.78870696 - 0.6147696j), (-0.87911534 + 0.47660938j), (0.94555736 - 0.3254559j), (-0.9862217 + 0.16542989j), (0.9999997 - 0.00089395075j)] e_vec = pmt.init_c32vector(len(out_data), out_data) meta = pmt.make_dict() meta = pmt.dict_add(meta, pmt.intern("sample_rate"), pmt.from_float(1e3)) meta = pmt.dict_add(meta, pmt.intern("center_frequency"), pmt.from_float(910.6e6)) in_pdu = pmt.cons(meta, i_vec) e_pdu = pmt.cons(meta, e_vec) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() # parse output #print "got ", list(pmt.to_python(pmt.cdr(self.debug.get_message(0)))) #print "got ", self.debug.get_message(0) rcv = self.debug.get_message(0) rcv_meta = pmt.car(rcv) rcv_data = pmt.cdr(rcv) rcv_cf = pmt.dict_ref(rcv_meta, pmt.intern("center_frequency"), pmt.PMT_NIL) # asserts self.assertComplexTuplesAlmostEqual( tuple(pmt.c32vector_elements(rcv_data)), tuple(out_data), 2) self.assertTrue(pmt.equal(rcv_cf, pmt.from_float(911e6)))
def test_half_power(self): self.emitter = pdu_utils.message_emitter() self.cf = fhss_utils.cf_estimate(fhss_utils.HALF_POWER, []) self.debug = blocks.message_debug() self.tb.msg_connect((self.emitter, 'msg'), (self.cf, 'in')) self.tb.msg_connect((self.cf, 'out'), (self.debug, 'store')) # original data in_data = np.exp(1j * np.array(np.linspace(0, 1 * np.pi * .02, 20))) i_vec = pmt.init_c32vector(len(in_data), in_data) out_data = [(1 + 0j), (0.9999945 + 0.0033069337j), (0.9999781 + 0.006613831j), (0.99995077 + 0.009920656j), (0.9999125 + 0.013227372j), (0.9998633 + 0.016533945j), (0.9998032 + 0.019840335j), (0.9997321 + 0.02314651j), (0.99965006 + 0.026452431j), (0.99955714 + 0.029758062j), (0.99945325 + 0.03306337j), (0.99933845 + 0.036368314j), (0.99921274 + 0.039672863j), (0.99907607 + 0.042976975j), (0.9989285 + 0.04628062j), (0.99877 + 0.049583755j), (0.99860054 + 0.05288635j), (0.9984202 + 0.056188367j), (0.9982289 + 0.059489768j), (0.9980267 + 0.06279052j)] e_vec = pmt.init_c32vector(len(out_data), out_data) meta = pmt.make_dict() meta = pmt.dict_add(meta, pmt.intern("sample_rate"), pmt.from_float(1e6)) meta = pmt.dict_add(meta, pmt.intern("center_frequency"), pmt.from_float(910.6e6)) in_pdu = pmt.cons(meta, i_vec) e_pdu = pmt.cons(meta, e_vec) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() # parse output #print "got ", list(pmt.to_python(pmt.cdr(self.debug.get_message(0)))) #print "got ", self.debug.get_message(0) rcv = self.debug.get_message(0) rcv_meta = pmt.car(rcv) rcv_data = pmt.cdr(rcv) rcv_cf = pmt.to_double( pmt.dict_ref(rcv_meta, pmt.intern("center_frequency"), pmt.PMT_NIL)) # asserts self.assertComplexTuplesAlmostEqual( tuple(pmt.c32vector_elements(rcv_data)), tuple(out_data), 2) self.assertTrue(abs(rcv_cf - 910.6e6) < 100)
def test_rms(self): self.emitter = pdu_utils.message_emitter() self.cf = fhss_utils.cf_estimate(fhss_utils.RMS, []) self.debug = blocks.message_debug() self.tb.msg_connect((self.emitter, 'msg'), (self.cf, 'in')) self.tb.msg_connect((self.cf, 'out'), (self.debug, 'store')) # original data in_data = np.exp(1j * np.array(np.linspace(0, 1 * np.pi * .02, 20))) i_vec = pmt.init_c32vector(len(in_data), in_data) out_data = [(1 + 0j), (0.9999966 + 0.0026077442j), (0.9999864 + 0.0052154697j), (0.9999694 + 0.007823161j), (0.99994564 + 0.010430798j), (0.99991506 + 0.013038365j), (0.99987763 + 0.015645843j), (0.99983346 + 0.018253215j), (0.99978244 + 0.020860463j), (0.9997247 + 0.023467569j), (0.99966 + 0.026074518j), (0.99958867 + 0.028681284j), (0.9995105 + 0.03128786j), (0.9994256 + 0.033894222j), (0.99933374 + 0.03650035j), (0.99923515 + 0.03910623j), (0.9991298 + 0.04171185j), (0.99901766 + 0.044317182j), (0.9988987 + 0.046922214j), (0.9987729 + 0.04952693j)] e_vec = pmt.init_c32vector(len(out_data), out_data) meta = pmt.make_dict() meta = pmt.dict_add(meta, pmt.intern("sample_rate"), pmt.from_float(1e6)) meta = pmt.dict_add(meta, pmt.intern("center_frequency"), pmt.from_float(910.6e6)) in_pdu = pmt.cons(meta, i_vec) e_pdu = pmt.cons(meta, e_vec) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() # parse output #print("got ", list(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print("got ", self.debug.get_message(0)) rcv = self.debug.get_message(0) rcv_meta = pmt.car(rcv) rcv_data = pmt.cdr(rcv) rcv_cf = pmt.to_double( pmt.dict_ref(rcv_meta, pmt.intern("center_frequency"), pmt.PMT_NIL)) # asserts self.assertComplexTuplesAlmostEqual( tuple(pmt.c32vector_elements(rcv_data)), tuple(out_data), 2) self.assertTrue(abs(rcv_cf - 910.6001e6) < 100)
def handler(self, pdu): meta = pmt.car(pdu) samples = pmt.cdr(pdu) x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) x_pow = numpy.power(x, 2) X2 = numpy.fft.fftshift(numpy.absolute(numpy.fft.fft(x_pow))) f = numpy.linspace(-self.Fs / 2, self.Fs / 2, num=len(x_pow)) #This generates two peaks, find max peak first max_1 = numpy.argmax(X2) cfo_est_1 = f[max_1] #suppress first peak, including +- 10 bins on either side pk1_range = numpy.linspace(max_1 - 10, max_1 + 10, 21) #print pk1_range, max_1 for i in pk1_range: X2[int(i)] = 0 #find second peak max_2 = numpy.argmax(X2) cfo_est_2 = f[max_2] #baud rate should be from to ratelines baud = numpy.absolute(cfo_est_1 - cfo_est_2) #find halfway point between the peaks in frequency (not index) if (cfo_est_2 > cfo_est_1): cfo_est = (cfo_est_1 + baud / 2.0) / 2.0 elif (cfo_est_2 < cfo_est_1): cfo_est = (cfo_est_2 + baud / 2.0) / 2.0 #print cfo_est_1, cfo_est_2, baud, cfo_est #add snr to metadata meta = pmt.dict_add(meta, pmt.intern("cfo_est"), pmt.from_double(cfo_est)) meta = pmt.dict_add(meta, pmt.intern("baud_est"), pmt.from_double(baud)) # perform the frequency correction t0 = numpy.arange(0, len(x), 1) / float(self.Fs) freqCorrVector = numpy.exp(-1j * 2 * numpy.pi * cfo_est * t0) y = numpy.multiply(x, freqCorrVector) x_out = pmt.init_c32vector(len(x), map(lambda i: complex(i), x)) cpdu_original = pmt.cons(meta, x_out) y_out = pmt.init_c32vector(len(y), map(lambda i: complex(i), y)) cpdu_corrected = pmt.cons(meta, y_out) self.message_port_pub(pmt.intern("out"), cpdu_original) self.message_port_pub(pmt.intern("corrected"), cpdu_corrected)
def test_006_c32(self): ''' complex input data, complicated input, decimation, and filtering ''' self.dut = pdu_utils.pdu_fir_filter(2, [2.5, 5, 10, 20, 10, 5, 2.5]) self.connectUp() i_data = [ 1j, 1, -1j, -1, ] * 4 i_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_double(22.2)) i_meta = pmt.dict_add(i_meta, pmt.intern("start_time"), pmt.from_double(0)) in_pdu = pmt.cons(i_meta, pmt.init_c32vector(len(i_data), i_data)) e_data = [ 7.5 + 15.j, 2.5 - 10.j, 10.j, -0 - 10.j, +10.j, -0 - 10.j, +10.j, -2.5 - 15.j ] e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("start_time"), pmt.from_double(0)) e_meta = pmt.dict_add(e_meta, pmt.intern("sample_rate"), pmt.from_double(11.1)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) self.tb.start() time.sleep(.01) self.emitter.emit(in_pdu) time.sleep(.1) self.tb.stop() self.tb.wait() #print("test_005:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print self.assertTrue(pmt.equal(pmt.car(self.debug.get_message(0)), e_meta)) v_diff = np.abs( pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) - np.array(e_data)) / np.abs(e_data) print("Maximum error is", np.max(v_diff)) self.assertTrue(np.max(v_diff) < 0.0001)
def test_005_c32(self): ''' complex input data, no decimation, even number of taps ''' self.dut = pdu_utils.pdu_fir_filter(1, [.2] * 6) self.connectUp() i_data = [ 1, ] * 10 i_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_double(100.0)) i_meta = pmt.dict_add(i_meta, pmt.intern("start_time"), pmt.from_double(9.9)) in_pdu = pmt.cons(i_meta, pmt.init_c32vector(len(i_data), i_data)) e_data = [ .6, .8, 1, ] + [ 1.2, ] * 5 + [1, .8, .6] e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_double(100.0)) e_meta = pmt.dict_add(e_meta, pmt.intern("start_time"), pmt.from_double(9.895)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) self.tb.start() time.sleep(.01) self.emitter.emit(in_pdu) time.sleep(.1) self.tb.stop() self.tb.wait() #print("test_005:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print self.assertTrue(pmt.equal(pmt.car(self.debug.get_message(0)), e_meta)) v_diff = np.abs( pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) - np.array(e_data)) / np.abs(e_data) print("Maximum error is", np.max(v_diff)) self.assertTrue(np.max(v_diff) < 0.00001)
def test_001_basic(self): in_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 ] in_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data), in_data)) e_tag_0 = gr.tag_utils.python_to_tag( (0, pmt.intern("tx_sob"), pmt.PMT_T, pmt.PMT_NIL)) e_tag_1 = gr.tag_utils.python_to_tag( (len(in_data) - 1, pmt.intern("tx_eob"), pmt.PMT_T, pmt.PMT_NIL)) self.tb.start() self.p2s.to_basic_block()._post(pmt.intern("pdus"), pmt.intern("MALFORMED PDU")) self.p2s.to_basic_block()._post(pmt.intern("pdus"), in_pdu) self.waitFor(lambda: len(self.vs.tags()) == 2, timeout=1.0, poll_interval=0.01) self.tb.stop() self.tb.wait() tags = self.vs.tags() self.assertEqual(len(tags), 2) self.assertEqual(tags[0].offset, e_tag_0.offset) self.assertTrue(pmt.equal(tags[0].key, e_tag_0.key)) self.assertTrue(pmt.equal(tags[0].value, e_tag_0.value)) self.assertEqual(tags[1].offset, e_tag_1.offset) self.assertTrue(pmt.equal(tags[1].key, e_tag_1.key)) self.assertTrue(pmt.equal(tags[1].value, e_tag_1.value)) self.assertTrue((in_data == np.real(self.vs.data())).all())
def test_001_t (self): in_data = [0, 1, 0, 0, 1, 0, 1, 1] print("in_data = ", in_data) expected_data = [(1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (0.9999558329582214-0.009149551391601562j), (0.9986380934715271-0.05212688446044922j), (0.9845290780067444-0.17521238327026367j), (0.9109043478965759-0.4126133918762207j), (0.6968833208084106-0.717181921005249j), (0.31042835116386414-0.950594425201416j), (-0.17273569107055664-0.9849666953086853j), (-0.6225566864013672-0.7825717926025391j), (-0.914273738861084-0.4051017761230469j), (-0.999992847442627-0.003090381622314453j), (-0.9691651463508606+0.24640250205993652j), (-0.968771755695343+0.24795293807983398j), (-0.9999971389770508+0.0017070770263671875j), (-0.9174799919128418-0.39777708053588867j), (-0.6312775611877441-0.7755542993545532j), (-0.18532180786132812-0.9826757907867432j), (0.2910269498825073-0.9567151069641113j), (0.6513003706932068-0.7588169574737549j), (0.81996750831604-0.5724067687988281j), (0.8208843469619751-0.5710964202880859j), (0.6549332737922668-0.7556841373443604j), (0.2986666262149811-0.9543551206588745j), (-0.17431020736694336-0.9846884608268738j), (-0.6225566864013672-0.7825717926025391j), (-0.9215338230133057-0.3883037567138672j), (-0.994880199432373+0.10103797912597656j), (-0.8246530294418335+0.5656423568725586j), (-0.4525153636932373+0.8917537331581116j), (0.030410051345825195+0.9995390772819519j), (0.5058896541595459+0.8625954985618591j), (0.8575133085250854+0.5144641399383545j), (0.9991825222969055+0.040370840579271317j), (0.9041904211044312-0.42713212966918945j), (0.6559781432151794-0.7547774314880371j), (0.44701042771339417-0.8945262432098389j), (0.44557973742485046-0.8952407836914062j), (0.6523504257202148-0.7579166889190674j), (0.9007443785667419-0.43434762954711914j), (0.9995729923248291+0.029183024540543556j), (0.8648265600204468+0.5020678639411926j), (0.533815860748291+0.8455996513366699j), (0.14855670928955078+0.9889022707939148j), (-0.1027672290802002+0.99470454454422j), (-0.10435843467712402+0.9945414066314697j), (0.14381003379821777+0.9896029233932495j), (0.5270366668701172+0.8498398065567017j), (0.8591512441635132+0.5117172598838806j), (0.9991825222969055+0.040370840579271317j), (0.9041904211044312-0.42713212966918945j), (0.6559781432151794-0.7547774314880371j), (0.44701042771339417-0.8945262432098389j), (0.44557973742485046-0.8952407836914062j), (0.6523504257202148-0.7579166889190674j), (0.9007443785667419-0.43434762954711914j), (0.9995729923248291+0.029183024540543556j), (0.8648265600204468+0.5020678639411926j), (0.5182530879974365+0.8552265167236328j), (0.04479217529296875+0.9989947080612183j), (-0.4396350383758545+0.8981758952140808j), (-0.8164236545562744+0.5774505138397217j), (-0.9933251738548279+0.11534643173217773j), (-0.9270230531692505-0.3749988079071045j), (-0.6337566375732422-0.773532509803772j), (-0.18532228469848633-0.9826757311820984j), (0.29976776242256165-0.954010009765625j), (0.6899716258049011-0.7238376140594482j), (0.9075756072998047-0.41988372802734375j), (0.9833885431289673-0.18150663375854492j), (0.9983774423599243-0.05691719055175781j), (0.9999259114265442-0.012347698211669922j), (0.9999974370002747-0.0015993118286132812j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j), (1.000002384185791+7.219194575469601e-09j)] log_scale = [10**((x-50)/10.) for x in range(0,50)] for i in range(len(log_scale)): expected_data[i] *= log_scale[i] in_pdu = pmt.cons(pmt.make_dict(), pmt.init_u8vector(len(in_data), in_data)) expected_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(expected_data), expected_data)) self.tb.start() time.sleep(.001) # handle non-pair input self.emitter2.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) # handle malformed pair self.emitter2.emit(pmt.cons(pmt.intern("NON-PDU"), pmt.intern("PAIR"))) time.sleep(.001) # handle incorrect PDU self.emitter2.emit(in_pdu) time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertComplexTuplesAlmostEqual(out_data, expected_data, 5)
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 handler(self, pdu): meta = pmt.car(pdu); samples = pmt.cdr(pdu); x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) x_2 = numpy.real(x * x.conjugate()) #mag squared # smoothing filter, running average, with 'length' samples x_2f = numpy.convolve(self.length*[1], x_2); # find max power to compute power thresh maxidx = numpy.argmax(x_2f); maxpow = x_2f[maxidx]; # find min power to compute power thresh minidx = numpy.argmin(x_2f); minpow = x_2f[minidx]; thr = maxpow / 16; # 6db down from max #find avg (or median) of samples above thresh (signal) min_avg = numpy.average(x_2f[x_2f<=thr]) #find avg (or median) of samples below thresh (noise) max_avg = numpy.average(x_2f[x_2f>thr]) #compute log scale snr [dB] #already have power of 2 from x_2 calc, so 10log10(snr) snr = 10 * numpy.log10(max_avg / min_avg) #Correction ratio based on samples per symbol snr = snr + 10*numpy.log10(self.sps) #add snr to metadata meta = pmt.dict_add(meta, pmt.intern("snr"), pmt.from_double(snr)); samples_out = pmt.init_c32vector(len(x), map(lambda i: complex(i), x)) cpdu = pmt.cons(meta,samples_out) self.message_port_pub(pmt.intern("out"), cpdu);
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 len_tag_key = "frame_len" tx_data = (1, ) * fft_len * n_syms len_tag = gr.tag_t() len_tag.offset = 0 len_tag.key = pmt.string_to_symbol(len_tag_key) len_tag.value = pmt.from_long(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, (len_tag, chan_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, len_tag_key) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, eq, sink) self.tb.run() # Check data self.assertEqual(tx_data, sink.data())
def handler(self, pdu): meta = pmt.to_python(pmt.car(pdu)) samples = pmt.cdr(pdu) x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) #print meta #print meta['rx_time'], meta['es::event_time'] time_delta = meta['es::event_time'] / self.samp_rate rx_int_sec = meta['rx_time'][1][0] rx_frac_sec = meta['rx_time'][1][1] #print rx_int_sec, rx_frac_sec #print time_delta, math.modf(time_delta) td = math.modf(time_delta) dt = (numpy.int64(rx_int_sec + td[1]), rx_frac_sec + td[0]) #print datetime ts = numpy.datetime64(datetime.datetime.utcfromtimestamp(dt[0])) ts = ts + numpy.timedelta64(int(dt[1] * 1e9), 'ns') ts_ns = numpy.datetime_as_string(ts) + "Z" meta = pmt.to_pmt(meta) #meta = pmt.dict_add(meta, pmt.intern("pkt_rx_time"), pmt.make_tuple(dt)); meta = pmt.dict_add(meta, pmt.intern("datetime"), pmt.string_to_symbol(ts_ns)) #meta['pkt_rx_time'] = dt #meta['datetime'] = ts_ns samples_out = pmt.init_c32vector(len(x), map(lambda i: complex(i), x)) cpdu = pmt.cons(meta, samples_out) self.message_port_pub(pmt.intern("out"), cpdu)
def test_simple(self): self.emitter = pdu_utils.message_emitter() self.ctm2 = pdu_utils.pdu_complex_to_mag2() self.debug = blocks.message_debug() self.tb.msg_connect((self.emitter, 'msg'), (self.ctm2, 'cpdus')) self.tb.msg_connect((self.ctm2, 'fpdus'), (self.debug, 'store')) # gnuradio uses single-precision floats by default i_vec = pmt.init_c32vector(3, [3 + 4j, 1 + 0j, 0 + 1j]) e_vec = pmt.init_f32vector(3, [25, 1, 1]) in_pdu = pmt.cons(pmt.make_dict(), i_vec) e_pdu = pmt.cons(pmt.make_dict(), e_vec) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() print("test ctm2:") print("pdu expected: " + repr(pmt.car(e_pdu))) print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) print() self.assertTrue(pmt.equal(self.debug.get_message(0), e_pdu))
def test_001_simplelog(self): in_data_c32 = [4.1 - 2.4j, 0. - 0.j, 1. + 1.j, 1e-9 - 1e-9j] in_pdu_c32 = pmt.cons( pmt.make_dict(), pmt.init_c32vector(len(in_data_c32), in_data_c32)) in_data_f32 = [4.1, -2.4, 0., -0., 1., 1., 1e-9, -1e-9] in_pdu_f32 = pmt.cons( pmt.make_dict(), pmt.init_f32vector(len(in_data_f32), in_data_f32)) in_data_u8 = [1, 2, 3, 4, 5, 6, 7, 8] in_pdu_u8 = pmt.cons(pmt.make_dict(), pmt.init_u8vector(len(in_data_u8), in_data_u8)) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu_c32) time.sleep(.001) self.emitter.emit(in_pdu_f32) time.sleep(.001) self.emitter.emit(in_pdu_u8) time.sleep(.01) self.tb.stop() self.tb.wait() #TODO check contents of PDUs os.remove(QA_LOG_DIR + 'raw-c32_0000.fc32') os.remove(QA_LOG_DIR + 'raw-f32_0001.f32') os.remove(QA_LOG_DIR + 'raw-u8_0002.u8')
def test_001_basic(self): in_data = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 ] in_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data), in_data)) e_tag_0 = gr.tag_utils.python_to_tag( (0, pmt.intern("tx_sob"), pmt.PMT_T, pmt.PMT_NIL)) e_tag_1 = gr.tag_utils.python_to_tag( (len(in_data) - 1, pmt.intern("tx_eob"), pmt.PMT_T, pmt.PMT_NIL)) self.tb.start() time.sleep(.001) self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() tags = self.vs.tags() self.assertEqual(len(tags), 2) self.assertEqual(tags[0].offset, e_tag_0.offset) self.assertTrue(pmt.equal(tags[0].key, e_tag_0.key)) self.assertTrue(pmt.equal(tags[0].value, e_tag_0.value)) self.assertEqual(tags[1].offset, e_tag_1.offset) self.assertTrue(pmt.equal(tags[1].key, e_tag_1.key)) self.assertTrue(pmt.equal(tags[1].value, e_tag_1.value)) self.assertTrue((in_data == numpy.real(self.vs.data())).all())
def test_004_c32noise_gaus(self): self.add.set_scale(4) self.add.set_offset(3) self.add.set_noise_level(0.1) self.add.set_noise_dist(pdu_utils.GAUSSIAN) self.add.set_seed(123) in_data = range(8) expected_data = [(3.3071127 + 3.283337j), (6.8398867 + 2.5212853j), (11.206407 + 2.7046404j), (15.492073 + 3.1152205j), (18.979256 + 3.5126355j), (23.402103 + 2.8895853j), (26.984592 + 3.0831635j), (31.213652 + 3.4955065j)] in_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data), in_data)) self.tb.start() time.sleep(.001) self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertComplexTuplesAlmostEqual(out_data, expected_data, 3)
def test_simple(self): # make the data and expected results data = [x + x * 1j for x in range(10)] pdu_in = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(data), data)) expected_energy = sum([abs(x)**2 for x in data]) expected_power = 10 * np.log10(expected_energy / len(data)) # run flowgraph self.tb.start() time.sleep(.001) self.emitter.emit(pmt.intern("BAD PDU")) time.sleep(.001) self.emitter.emit(pdu_in) time.sleep(.01) self.tb.stop() self.tb.wait() # don't wait...may not return in time # extract results rcv_pdu = self.debug.get_message(0) rcv_meta = pmt.car(rcv_pdu) rcv_data = pmt.c32vector_elements(pmt.cdr(rcv_pdu)) rcv_energy = pmt.to_double( pmt.dict_ref(rcv_meta, pmt.intern("energy"), pmt.PMT_NIL)) rcv_power = pmt.to_double( pmt.dict_ref(rcv_meta, pmt.intern("power"), pmt.PMT_NIL)) # assert expectations precision = 1e-3 self.assertTrue(abs(rcv_energy - expected_energy) < precision) self.assertTrue(abs(rcv_power - expected_power) < precision)
def test_003_c32noise(self): self.add.set_scale(4) self.add.set_offset(3) self.add.set_noise_level(0.1) self.add.set_seed(123) in_data = range(8) expected_data = [(3.1111398 + 3.1204658j), (6.879022 + 2.959537j), (10.845484 + 3.1079807j), (15.029028 + 3.12397j), (19.124151 + 2.994976j), (22.956503 + 3.1584077j), (27.271961 + 2.9496112j), (31.104555 + 3.0450819j)] in_pdu = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data), in_data)) self.tb.start() time.sleep(.001) self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() out_data = pmt.c32vector_elements(pmt.cdr(self.debug.get_message(0))) self.assertComplexTuplesAlmostEqual(out_data, expected_data, 3)
def handler(self, msg): #print "synch starting new sync" self.start_timer() # get input meta = pmt.car(msg) samples = pmt.cdr(msg) x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) self.diff_timer("get_input") # correct for CFO eqBurst = self.qpskBurstCFOCorrect(x, self.Fs) self.diff_timer("cfo") # determine preamble start preCrossCorr = numpy.absolute( numpy.correlate(self.preSyms_x2, eqBurst, 'full')) maxIdx = numpy.argmax(preCrossCorr) preambleIdxStart = len(eqBurst) - maxIdx - 1 eqIn = eqBurst[preambleIdxStart:] # decimate the signal to 1sps (right now the constructor enforces teh 2 sps) eqIn_decimated = eqIn[0:len(eqIn):2] self.diff_timer("timing") wOpt = self.determineOptimalFilter(eqIn_decimated) self.diff_timer("est_filter") # filter the input signal w/ the optimal filter (in MMSE sense) # todo, do we need to remove the extra syms at the end produced by conv? whFilt = numpy.convolve(wOpt, eqIn_decimated) whFiltMean = numpy.mean(numpy.absolute(whFilt)) whFilt /= whFiltMean self.diff_timer("apply filt") # correct any residual phase offset w/ the 1st order PLL alpha = 0.002 phRecoveredSyms = self.qpskFirstOrderPLL(whFilt, alpha) self.diff_timer("residual phase") # if(self.debugMode): # dictToSave = {} # dictToSave['gr_eqBurst'] = eqBurst # dictToSave['gr_preCrossCorr'] = preCrossCorr # dictToSave['gr_eqIn'] = eqIn # dictToSave['gr_wOpt'] = wOpt # dictToSave['gr_whFilt'] = whFilt # dictToSave['gr_phRecoveredSyms'] = phRecoveredSyms # sio.savemat(self.debugFilename, dictToSave) # publish equalized symbols c = map(lambda i: complex(i), phRecoveredSyms) xcm = pmt.init_c32vector(len(c), c) #xcm = pmt.init_c32vector(phRecoveredSyms.size, map(lambda i: complex(i), phRecoveredSyms)) xcm_cpdu = pmt.cons(meta, xcm) self.message_port_pub(pmt.intern("cpdus"), xcm_cpdu) self.diff_timer("publish result") self.burstidx = self.burstidx + 1
def test_003_double_msg(self): in_data1 = [0, 0, 0, 0, 0, 0, 0, 0] in_data2 = [1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1] in_data = in_data1 + in_data1 + in_data2 tag_time = pmt.make_tuple(pmt.from_uint64(11), pmt.from_double(0.123456)) in_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), tag_time) in_pdu1 = pmt.cons(in_dict, pmt.init_c32vector(len(in_data1), in_data1)) in_pdu2 = pmt.cons(pmt.make_dict(), pmt.init_c32vector(len(in_data2), in_data2)) e_tag_0 = gr.tag_utils.python_to_tag( (len(in_data1), pmt.intern("tx_sob"), pmt.PMT_T, pmt.PMT_NIL)) e_tag_1 = gr.tag_utils.python_to_tag( (len(in_data1), pmt.intern("tx_time"), tag_time, pmt.PMT_NIL)) e_tag_2 = gr.tag_utils.python_to_tag( (len(in_data) - 1, pmt.intern("tx_eob"), pmt.PMT_T, pmt.PMT_NIL)) self.tb.start() time.sleep(.001) self.emitter.emit(pmt.intern("MALFORMED PDU")) time.sleep(.001) self.emitter.emit(in_pdu1) time.sleep(.005) self.emitter.emit(in_pdu1) self.emitter.emit(in_pdu2) time.sleep(.01) self.tb.stop() self.tb.wait() tags = self.vs.tags() for tag in tags: print tag.offset, tag.key, tag.value self.assertEqual(len(tags), 6) self.assertEqual(tags[3].offset, e_tag_0.offset) self.assertTrue(pmt.equal(tags[3].key, e_tag_0.key)) self.assertTrue(pmt.equal(tags[3].value, e_tag_0.value)) self.assertEqual(tags[4].offset, e_tag_1.offset) self.assertTrue(pmt.equal(tags[4].key, e_tag_1.key)) self.assertTrue(pmt.equal(tags[4].value, e_tag_1.value)) self.assertEqual(tags[5].offset, e_tag_2.offset) self.assertTrue(pmt.equal(tags[5].key, e_tag_2.key)) self.assertTrue(pmt.equal(tags[5].value, e_tag_2.value)) self.assertTrue((in_data == numpy.real(self.vs.data())).all())
def handler(self, msg): #print "synch starting new sync" self.start_timer(); # get input meta = pmt.car(msg); samples = pmt.cdr(msg); x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) self.diff_timer("get_input"); # correct for CFO eqBurst = self.qpskBurstCFOCorrect(x, self.Fs) self.diff_timer("cfo") # determine preamble start preCrossCorr = numpy.absolute(numpy.correlate(self.preSyms_x2, eqBurst, 'full')) maxIdx = numpy.argmax(preCrossCorr) preambleIdxStart = len(eqBurst) - maxIdx - 1 eqIn = eqBurst[preambleIdxStart:] # decimate the signal to 1sps (right now the constructor enforces teh 2 sps) eqIn_decimated = eqIn[0:len(eqIn):2] self.diff_timer("timing") wOpt = self.determineOptimalFilter(eqIn_decimated) self.diff_timer("est_filter") # filter the input signal w/ the optimal filter (in MMSE sense) # todo, do we need to remove the extra syms at the end produced by conv? whFilt = numpy.convolve(wOpt, eqIn_decimated) whFiltMean = numpy.mean(numpy.absolute(whFilt)) whFilt /= whFiltMean self.diff_timer("apply filt") # correct any residual phase offset w/ the 1st order PLL alpha = 0.002 phRecoveredSyms = self.qpskFirstOrderPLL(whFilt, alpha) self.diff_timer("residual phase") # if(self.debugMode): # dictToSave = {} # dictToSave['gr_eqBurst'] = eqBurst # dictToSave['gr_preCrossCorr'] = preCrossCorr # dictToSave['gr_eqIn'] = eqIn # dictToSave['gr_wOpt'] = wOpt # dictToSave['gr_whFilt'] = whFilt # dictToSave['gr_phRecoveredSyms'] = phRecoveredSyms # sio.savemat(self.debugFilename, dictToSave) # publish equalized symbols c = map(lambda i: complex(i), phRecoveredSyms); xcm = pmt.init_c32vector(len(c), c) #xcm = pmt.init_c32vector(phRecoveredSyms.size, map(lambda i: complex(i), phRecoveredSyms)) xcm_cpdu = pmt.cons(meta,xcm) self.message_port_pub(pmt.intern("cpdus"), xcm_cpdu); self.diff_timer("publish result") self.burstidx = self.burstidx + 1;
def test_002(self): ''' Input data has extra quiet time front and rear ''' self.dut = pdu_utils.pdu_fine_time_measure(0.005, 0.005, 10, 15) self.connectUp() i_data = [0.1 + 0j] * 10 + [1.0 + 0j] * 980 + [0.1 + 0j] * 10 i_vec = pmt.init_c32vector(3, [3 + 4j, 1 + 0j, 0 + 1j]) i_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("start_time"), pmt.from_double(1.0)) i_meta = pmt.dict_add(i_meta, pmt.intern("sample_rate"), pmt.from_float(1000.0)) i_meta = pmt.dict_add(i_meta, pmt.intern("duration"), pmt.from_float(1000.0)) in_pdu = pmt.cons(i_meta, pmt.init_c32vector(len(i_data), i_data)) e_data = [1.0 + 0j] * 980 + [0.1 + 0j] * 10 e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_float(1000.0)) e_meta = pmt.dict_add(e_meta, pmt.intern("start_time"), pmt.from_double(1.01)) e_meta = pmt.dict_add(e_meta, pmt.intern("duration"), pmt.from_float(999.99)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() #print("test_002:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print self.assertTrue(pmt.equal(self.debug.get_message(0), e_pdu))
def test_001(self): ''' Input data perfectly matches params to pdu_fine_time_measure ''' self.dut = pdu_utils.pdu_fine_time_measure(0.005, 0.005, 10, 15) self.connectUp() i_data = [0.1 + 0j] * 5 + [1.0 + 0j] * 990 + [0.1 + 0j] * 5 i_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("start_time"), pmt.from_double(1.0)) i_meta = pmt.dict_add(i_meta, pmt.intern("sample_rate"), pmt.from_float(1000.0)) i_meta = pmt.dict_add(i_meta, pmt.intern("duration"), pmt.from_float(1000.0)) in_pdu = pmt.cons(i_meta, pmt.init_c32vector(len(i_data), i_data)) e_data = [1.0 + 0j] * 990 + [0.1 + 0j] * 5 e_meta = pmt.dict_add(pmt.make_dict(), pmt.intern("sample_rate"), pmt.from_float(1000.0)) e_meta = pmt.dict_add(e_meta, pmt.intern("start_time"), pmt.from_double(1.005)) e_meta = pmt.dict_add(e_meta, pmt.intern("duration"), pmt.from_float(999.995)) e_pdu = pmt.cons(e_meta, pmt.init_c32vector(len(e_data), e_data)) self.tb.start() time.sleep(.001) self.emitter.emit(in_pdu) time.sleep(.01) self.tb.stop() self.tb.wait() #print("test_001:") #print("pdu expected: " + repr(pmt.car(e_pdu))) #print("pdu got: " + repr(pmt.car(self.debug.get_message(0)))) #print("data expected: " + repr(pmt.to_python(pmt.cdr(e_pdu)))) #print("data got: " + repr(pmt.to_python(pmt.cdr(self.debug.get_message(0))))) #print self.assertTrue(pmt.equal(self.debug.get_message(0), e_pdu))
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)) len_tag_key = "frame_len" len_tag = gr.tag_t() len_tag.offset = 0 len_tag.key = pmt.string_to_symbol(len_tag_key) len_tag.value = pmt.from_long(4) 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, (len_tag, chan_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, len_tag_key, True) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, eq, sink) self.tb.run () rx_data = [cnst.decision_maker_v((x,)) if x != 0 else -1 for x in sink.data()] self.assertEqual(tx_data, rx_data) for tag in sink.tags(): if pmt.symbol_to_string(tag.key) == len_tag_key: self.assertEqual(pmt.to_long(tag.value), 4) if 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_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 len_tag_key = "frame_len" tx_data = (1,) * fft_len * n_syms len_tag = gr.tag_t() len_tag.offset = 0 len_tag.key = pmt.string_to_symbol(len_tag_key) len_tag.value = pmt.from_long(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, (len_tag, chan_tag, random_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, len_tag_key) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, eq, sink) self.tb.run () # Check data self.assertEqual(tx_data, sink.data()) # Check tags tag_dict = dict() for tag in sink.tags(): ptag = gr.tag_to_python(tag) tag_dict[ptag.key] = ptag.value expected_dict = { 'frame_len': n_syms, 'foo': 42 } self.assertEqual(tag_dict, expected_dict)
def handler(self, msg): # get input meta = pmt.car(msg); samples = pmt.cdr(msg); x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) # correct for CFO eqBurst = self.qpskBurstCFOCorrect(x, self.Fs) # determine preamble start preCrossCorr = numpy.absolute(numpy.correlate(self.preSyms_x2, eqBurst, 'full')) maxIdx = numpy.argmax(preCrossCorr) preambleIdxStart = len(eqBurst) - maxIdx - 1 eqIn = eqBurst[preambleIdxStart:] # decimate the signal to 1sps (right now the constructor enforces teh 2 sps) eqIn_decimated = eqIn[0:len(eqIn):2] wOpt = self.determineOptimalFilter(eqIn_decimated) # filter the input signal w/ the optimal filter (in MMSE sense) whFilt = signal.lfilter(wOpt, [1], eqIn_decimated) whFiltMean = numpy.mean(numpy.absolute(whFilt)) whFilt /= whFiltMean # correct any residual phase offset w/ the 1st order PLL alpha = 0.002 phRecoveredSyms = self.qpskFirstOrderPLL(whFilt, alpha) if(self.debugMode): dictToSave = {} dictToSave['gr_eqBurst'] = eqBurst dictToSave['gr_preCrossCorr'] = preCrossCorr dictToSave['gr_eqIn'] = eqIn dictToSave['gr_wOpt'] = wOpt dictToSave['gr_whFilt'] = whFilt dictToSave['gr_phRecoveredSyms'] = phRecoveredSyms sio.savemat(self.debugFilename, dictToSave) # publish equalized symbols xcm = pmt.init_c32vector(phRecoveredSyms.size, map(lambda i: complex(i), phRecoveredSyms)) xcm_cpdu = pmt.cons(meta,xcm) self.message_port_pub(pmt.intern("cpdus"), xcm_cpdu);
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_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 len_tag_key = "frame_len" tx_data = (1,) * fft_len * n_syms len_tag = gr.tag_t() len_tag.offset = 0 len_tag.key = pmt.string_to_symbol(len_tag_key) len_tag.value = pmt.from_long(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, (len_tag, chan_tag)) eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, len_tag_key) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, eq, sink) self.tb.run () # Check data self.assertEqual(tx_data, sink.data())
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_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 handler(self, msg): meta = pmt.car(msg); samples = pmt.cdr(msg); x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) x_2 = numpy.real(x * x.conjugate()) # smoothing filter x_2f = numpy.convolve(50*[1], x_2); # find max power to compute power thresh maxidx = numpy.argmax(x_2f); maxpow = x_2f[maxidx]; thr = maxpow / 16; # 6db down # find where we are below thresh start_offset = 1000; idx = numpy.argmax(x_2f[start_offset:] < thr) + start_offset + 1000; # print "below = (%d, %f)"%(idx, x_2f[idx]) # discard bursts where we dont find an end if idx == start_offset: print "WARNING: length detect: discarding burst" return # tack on some metadata meta = pmt.dict_add(meta, pmt.intern("est_len"), pmt.from_double(int(idx))); meta = pmt.dict_add(meta, pmt.intern("orig_len"), pmt.from_double(len(x))); # extract the useful signal x = x[0:idx]; # send it on its way samples_out = pmt.init_c32vector(len(x), map(lambda i: complex(i), x)) cpdu = pmt.cons(meta,samples_out) self.message_port_pub(pmt.intern("cpdus"), cpdu);
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)
def handler(self, msg): # get input meta = pmt.car(msg); samples = pmt.cdr(msg); x = numpy.array(pmt.c32vector_elements(samples), dtype=numpy.complex64) # upsample and normalize power xi = signal.resample(x, len(x)* (self.N / self.T)); # compute the symbol timing xt = numpy.real(xi*xi.conjugate()) * numpy.exp( (-1j*2.0*numpy.pi/self.N) * numpy.linspace(1,len(xi),len(xi)) ); s = numpy.sum(x); tau = (-self.T/(2*numpy.pi)) * numpy.arctan2(numpy.imag(s), numpy.real(s)); # publish timing metric for debugging tm = pmt.init_c32vector(xt.size, map(lambda i: complex(i), xt)) tm_cpdu = pmt.cons(meta,tm) self.message_port_pub(pmt.intern("timing_metric"), tm_cpdu); # extract symbols offset = round(self.N*tau/self.T); fo = (offset + self.N)%self.N; sym = xi[fo:-1:self.N]; # normalize power to 1 sym = sym / numpy.mean(numpy.real(sym * sym.conjugate())); # publish timing correct symbols (with frequency offset) sm = pmt.init_c32vector(sym.size, map(lambda i: complex(i), sym)) sm_cpdu = pmt.cons(meta,sm) self.message_port_pub(pmt.intern("sym_timed"), sm_cpdu); # compute symbol frequency offset (linear phase offset within block) x_n = numpy.power(sym[200:1000], self.O); phase_ramp = numpy.unwrap(numpy.angle( x_n )); f_off_O = numpy.mean(numpy.diff(phase_ramp)); goodstat = numpy.std(numpy.diff(phase_ramp)); f_off = f_off_O / self.O; # check percentages self.nburst = self.nburst + 1; if(goodstat < 1.0): self.nburst_ok = self.nburst_ok + 1; else: print "WARNING: feedforward synchronizer discarding burst, goodness metric %f < 1.0 (likely poor timing recovery occurred, the CFO phase ramp looks like garbage)"%(goodstat) return print "sync: "+str((goodstat, self.nburst, self.nburst_ok, self.nburst_ok*100.0 / self.nburst)); # export phase ramp pr = pmt.init_f32vector(phase_ramp.size, map(lambda i: float(i), phase_ramp)) pr_fpdu = pmt.cons(meta,pr) self.message_port_pub(pmt.intern("phase_ramp"), pr_fpdu); # apply frequency offset correction xc = numpy.multiply(sym, numpy.exp(-1j * f_off * numpy.linspace(1,sym.size,sym.size))); # compute and correct static symbol phase offset xcp = numpy.power(xc[400:1000], self.O); # linear mean theta = numpy.mean( numpy.angle( xcp ) ) / self.O + numpy.pi/4; # weighted mean # theta = numpy.sum(numpy.angle(xcp) * numpy.abs(xcp)) / numpy.sum(numpy.abs(xcp)); # theta = theta / self.O + numpy.pi/4; xc = xc * numpy.exp(-1j*theta); # show time, frequency and phase estimates #print "tau = %f, f_off = %f, theta = %f"%(tau, f_off, theta); # add our estimates to the metadata dictionary meta = pmt.dict_add(meta, pmt.intern("tau"), pmt.from_double(tau)); meta = pmt.dict_add(meta, pmt.intern("f_off"), pmt.from_double(f_off)); meta = pmt.dict_add(meta, pmt.intern("theta"), pmt.from_double(theta)); # publish freq corrected symbols xcm = pmt.init_c32vector(xc.size, map(lambda i: complex(i), xc)) xcm_cpdu = pmt.cons(meta,xcm) self.message_port_pub(pmt.intern("cpdus"), xcm_cpdu);
def test11(self): v = pmt.init_c32vector(3, [11 + -101j, -22 + 202j, 33 + -303j]) s = pmt.serialize_str(v) d = pmt.deserialize_str(s) self.assertTrue(pmt.equal(v, d))