From 127449e592eb22fa8e9827aa6a74c9cc9d2a69cd Mon Sep 17 00:00:00 2001 From: cmayer Date: Thu, 28 Mar 2019 17:23:15 +0100 Subject: [PATCH] update of decoders (intermediate) --- examples/test_188-110A.grc | 2 +- examples/test_188-110C.grc | 97 ++++- examples/test_s4285.grc | 482 +++++++++++++++++++++- lib/CMakeLists.txt | 3 +- lib/adaptive_dfe_impl.cc | 35 +- lib/doppler_correction_cc_impl.cc | 58 +-- lib/doppler_correction_cc_impl.h | 1 + python/__init__.py | 4 +- python/msg_proxy.py | 16 +- python/physical_layer/MIL_STD_188_110A.py | 90 +++- python/physical_layer/MIL_STD_188_110C.py | 45 +- python/physical_layer/STANAG_4285.py | 26 ++ python/physical_layer_driver.py | 7 +- 13 files changed, 746 insertions(+), 120 deletions(-) diff --git a/examples/test_188-110A.grc b/examples/test_188-110A.grc index 4ecae36..c0a333b 100644 --- a/examples/test_188-110A.grc +++ b/examples/test_188-110A.grc @@ -633,7 +633,7 @@ file - /Users/chm/Software/signal-analysis/20181104T143753Z_5680800_SM2KOT_iq.wav + /Users/chm/Software/signal-analysis/20181114T104644Z_9188800_KPH_iq.wav _coordinate diff --git a/examples/test_188-110C.grc b/examples/test_188-110C.grc index a687b37..978c298 100644 --- a/examples/test_188-110C.grc +++ b/examples/test_188-110C.grc @@ -164,7 +164,7 @@ value - 0.005 + 0.0035 _enabled @@ -324,7 +324,7 @@ value - 12001 + 12000 @@ -382,7 +382,7 @@ _coordinate - (448, 133) + (768, 133) _rotation @@ -511,6 +511,57 @@ 1 + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + file + /Users/chm/Software/gr-digitalhf/examples/symb.bin + + + _coordinate + (544, 528) + + + _rotation + 180 + + + id + blocks_file_sink_0_0 + + + type + complex + + + unbuffered + True + + + vlen + 1 + + blocks_float_to_complex @@ -676,7 +727,7 @@ _coordinate - (661, 154) + (480, 154) _rotation @@ -731,7 +782,7 @@ file - /Users/chm/Software/signal-analysis/gnuradio/20181026T063629Z_7815000_SM2GCT_iq.wav + /Users/chm/Software/gr-kiwisdr/examples/20190326T120049Z_2670000_GB3WE_iq.wav _coordinate @@ -865,7 +916,7 @@ _coordinate - (554, 538) + (544, 624) gui_hint @@ -1492,7 +1543,7 @@ size - 1024 + 1024/4 srate @@ -1863,7 +1914,7 @@ srate - samp_rate/sps/3 + samp_rate/sps stemplot @@ -1950,11 +2001,11 @@ fftsize - 1024*4 + 1024 _coordinate - (1066, 101) + (1045, 80) gui_hint @@ -2134,7 +2185,7 @@ update_time - 0.10 + 0.01 wintype @@ -2143,7 +2194,13 @@ analog_agc2_xx_0 - blocks_throttle_0 + digitalhf_physical_layer_driver_0 + 0 + 0 + + + analog_agc2_xx_0 + qtgui_waterfall_sink_x_0 0 0 @@ -2155,7 +2212,7 @@ blocks_float_to_complex_0 - analog_agc2_xx_0 + blocks_throttle_0 0 0 @@ -2173,13 +2230,7 @@ blocks_throttle_0 - digitalhf_physical_layer_driver_0 - 0 - 0 - - - blocks_throttle_0 - qtgui_waterfall_sink_x_0 + analog_agc2_xx_0 0 0 @@ -2201,6 +2252,12 @@ 1 0 + + digitalhf_physical_layer_driver_0 + blocks_file_sink_0_0 + 0 + 0 + digitalhf_physical_layer_driver_0 qtgui_const_sink_x_0 diff --git a/examples/test_s4285.grc b/examples/test_s4285.grc index 8899d89..91dfe36 100644 --- a/examples/test_s4285.grc +++ b/examples/test_s4285.grc @@ -93,6 +93,77 @@ (0,0) + + variable_cc_decoder_def + + padding + False + + + comment + + + + k + 7 + + + dim1 + 1 + + + dim2 + 1 + + + _enabled + True + + + state_end + -1 + + + framebits + 30*8 + + + _coordinate + (32, 341) + + + _rotation + 0 + + + id + CCSDS_27 + + + value + "ok" + + + ndim + 0 + + + polys + [109,79] + + + rate + 2 + + + state_start + 0 + + + mode + fec.CC_STREAMING + + variable_qtgui_range @@ -263,7 +334,7 @@ value - 0.005 + 0.0035 _enabled @@ -396,7 +467,7 @@ value - 4 + 3 @@ -453,6 +524,49 @@ 5 + + variable_dummy_decoder_def + + comment + + + + dim1 + 1 + + + dim2 + 1 + + + _enabled + True + + + framebits + 2048 + + + _coordinate + (106, 634) + + + _rotation + 0 + + + id + variable_dummy_decoder_def_0 + + + value + "ok" + + + ndim + 0 + + analog_agc2_xx @@ -473,7 +587,7 @@ decay_rate - 1e-2 + 1e-1 _enabled @@ -559,6 +673,108 @@ 1 + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + /Users/chm/Software/gr-digitalhf/examples/bits.bin + + + _coordinate + (1109, 581) + + + _rotation + 0 + + + id + blocks_file_sink_0 + + + type + byte + + + unbuffered + False + + + vlen + 1 + + + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + /Users/chm/Software/gr-digitalhf/examples/soft_dec_test.bin + + + _coordinate + (864, 506) + + + _rotation + 0 + + + id + blocks_file_sink_0_0 + + + type + float + + + unbuffered + False + + + vlen + 1 + + blocks_float_to_complex @@ -602,6 +818,53 @@ 1 + + blocks_pdu_to_tagged_stream + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (576, 592) + + + _rotation + 0 + + + id + blocks_pdu_to_tagged_stream_0 + + + type + float + + + tag + packet_len + + + maxoutbuf + 0 + + + minoutbuf + 0 + + blocks_tag_debug @@ -626,7 +889,7 @@ _coordinate - (1184, 464) + (1152, 677) _rotation @@ -638,7 +901,7 @@ type - complex + byte filter @@ -657,6 +920,53 @@ 1 + + blocks_tagged_stream_to_pdu + + alias + + + + comment + + + + affinity + + + + _enabled + 0 + + + _coordinate + (490, 730) + + + _rotation + 0 + + + id + blocks_tagged_stream_to_pdu_0 + + + type + byte + + + tag + packet_len + + + maxoutbuf + 0 + + + minoutbuf + 0 + + blocks_throttle @@ -732,7 +1042,7 @@ file - /Users/chm/Software/signal-analysis/gnuradio/20181027T095433Z_6407800_SM2GCT_iq.wav + /Users/chm/Software/gr-digitalhf/examples/on5kq.ddns.net_2019-03-20T12_49_38Z_2381.40_iq.wav _coordinate @@ -760,7 +1070,7 @@ repeat - True + False @@ -838,6 +1148,104 @@ samp_rate + + fec_decode_ccsds_27_fb + + alias + + + + comment + + + + affinity + + + + _enabled + 0 + + + _coordinate + (853, 805) + + + _rotation + 0 + + + id + fec_decode_ccsds_27_fb_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + fec_extended_decoder + + ann + None + + + alias + + + + comment + + + + affinity + + + + decoder_list + CCSDS_27 + + + _enabled + True + + + _coordinate + (853, 618) + + + _rotation + 0 + + + id + fec_extended_decoder_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + puncpat + '11' + + + threadtype + capillary + + + value + fec_extended_decoder + + qtgui_const_sink_x @@ -1588,7 +1996,7 @@ _coordinate - (320, 293) + (320, 272) gui_hint @@ -1884,7 +2292,7 @@ tr_mode - qtgui.TRIG_MODE_AUTO + qtgui.TRIG_MODE_TAG tr_slope @@ -1892,11 +2300,11 @@ tr_tag - "soft_dec" + "packet_len" type - msg_float + float update_time @@ -2160,6 +2568,30 @@ 0 0 + + blocks_pdu_to_tagged_stream_0 + blocks_file_sink_0_0 + 0 + 0 + + + blocks_pdu_to_tagged_stream_0 + fec_decode_ccsds_27_fb_0 + 0 + 0 + + + blocks_pdu_to_tagged_stream_0 + fec_extended_decoder_0 + 0 + 0 + + + blocks_pdu_to_tagged_stream_0 + qtgui_time_sink_x_1 + 0 + 0 + blocks_throttle_0 digitalhf_physical_layer_driver_0 @@ -2198,8 +2630,32 @@ digitalhf_physical_layer_driver_0 - qtgui_time_sink_x_1 + blocks_pdu_to_tagged_stream_0 soft_dec - in + pdus + + + fec_decode_ccsds_27_fb_0 + blocks_file_sink_0 + 0 + 0 + + + fec_decode_ccsds_27_fb_0 + blocks_tag_debug_0 + 0 + 0 + + + fec_extended_decoder_0 + blocks_file_sink_0 + 0 + 0 + + + fec_extended_decoder_0 + blocks_tag_debug_0 + 0 + 0 diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 938caa3..87626f4 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,7 +36,7 @@ if(NOT digitalhf_sources) endif(NOT digitalhf_sources) add_library(gnuradio-digitalhf SHARED ${digitalhf_sources}) -target_link_libraries(gnuradio-digitalhf ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${PYTHON_LIBRARIES}) +target_link_libraries(gnuradio-digitalhf ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${LOG4CPP_LIBRARIES}) set_target_properties(gnuradio-digitalhf PROPERTIES DEFINE_SYMBOL "gnuradio_digitalhf_EXPORTS") if(APPLE) @@ -71,6 +71,7 @@ target_link_libraries( ${GNURADIO_RUNTIME_LIBRARIES} ${Boost_LIBRARIES} ${CPPUNIT_LIBRARIES} + ${LOG4CPP_LIBRARIES} gnuradio-digitalhf ) GR_ADD_TEST(test_digitalhf test-digitalhf) diff --git a/lib/adaptive_dfe_impl.cc b/lib/adaptive_dfe_impl.cc index 98ce497..90ccf24 100644 --- a/lib/adaptive_dfe_impl.cc +++ b/lib/adaptive_dfe_impl.cc @@ -84,8 +84,8 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol , _symbol_counter(0) , _save_soft_decisions(false) , _vec_soft_decisions() - , _msg_ports{{"soft_dec", pmt::mp("soft_dec")}, - {"frame_info", pmt::mp("frame_info")}} + , _msg_ports{{"soft_dec", pmt::intern("soft_dec")}, + {"frame_info", pmt::intern("frame_info")}} , _msg_metadata(pmt::make_dict()) , _state(WAIT_FOR_PREAMBLE) { @@ -96,7 +96,7 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol message_port_register_out(_msg_ports["soft_dec"]); - pmt::pmt_t constellations_port = pmt::mp("constellations"); + pmt::pmt_t constellations_port = pmt::intern("constellations"); message_port_register_in(constellations_port); set_msg_handler(constellations_port, boost::bind(&adaptive_dfe_impl::update_constellations, this, _1)); @@ -128,6 +128,7 @@ adaptive_dfe_impl::general_work(int noutput_items, gr_vector_void_star &output_items) { gr::thread::scoped_lock lock(d_setlock); + //GR_LOG_DEBUG(d_logger, str(boost::format("work: %d") % noutput_items)); gr_complex const* in = (gr_complex const *)input_items[0]; gr_complex *out = (gr_complex *)output_items[0]; @@ -142,7 +143,7 @@ adaptive_dfe_impl::general_work(int noutput_items, switch (_state) { case WAIT_FOR_PREAMBLE: { std::vector v; - get_tags_in_window(v, 0, history()-1, ninput, pmt::mp("preamble_start")); + get_tags_in_window(v, 0, history()-1, ninput, pmt::intern("preamble_start")); if (v.empty()) { consume(0, ninput - history()+1); } else { @@ -164,9 +165,10 @@ adaptive_dfe_impl::general_work(int noutput_items, break; } // WAIT_FOR_PREAMBLE case WAIT_FOR_FRAME_INFO: { + //GR_LOG_DEBUG(d_logger, "WAIT_FOR_FRAME_INFO"); //update_frame_info(delete_head_blocking(_msg_ports["frame_info"])); break; - } // WAIT_FOR_MESSAGE + } // WAIT_FOR_FRAME_INFO case DO_FILTER: { // std::cout << "========= offset (DO_FILTER) nitems_read(0)= " << nitems_read(0) << " ==========" << std::endl; int ninput_processed = 0; @@ -315,7 +317,10 @@ void adaptive_dfe_impl::publish_frame_info() { pmt::pmt_t data = pmt::make_dict(); GR_LOG_DEBUG(d_logger, str(boost::format("publish_frame_info %d == %d") % _descrambled_symbols.size() % _symbols.size())); - data = pmt::dict_add(data, pmt::mp("symbols"), pmt::init_c32vector(_descrambled_symbols.size(), &_descrambled_symbols.front())); + data = pmt::dict_add(data, pmt::intern("symbols"), pmt::init_c32vector(_descrambled_symbols.size(), &_descrambled_symbols.front())); + // for (int i=0; i<_vec_soft_decisions.size(); ++i) + // _vec_soft_decisions[i] = std::max(-1.0f, std::min(1.0f, _vec_soft_decisions[i])); + data = pmt::dict_add(data, pmt::intern("soft_dec"), pmt::init_f32vector(_vec_soft_decisions.size(), &_vec_soft_decisions.front())); message_port_pub(_msg_ports["frame_info"], data); _descrambled_symbols.clear(); } @@ -325,7 +330,7 @@ void adaptive_dfe_impl::publish_soft_dec() if (_vec_soft_decisions.empty()) return; message_port_pub(_msg_ports["soft_dec"], - pmt::cons(pmt::dict_add(_msg_metadata, pmt::mp("packet_len"), pmt::mp(_vec_soft_decisions.size())), + pmt::cons(pmt::dict_add(_msg_metadata, pmt::intern("packet_len"), pmt::mp(_vec_soft_decisions.size())), pmt::init_f32vector(_vec_soft_decisions.size(), _vec_soft_decisions))); _vec_soft_decisions.clear(); } @@ -341,11 +346,11 @@ void adaptive_dfe_impl::update_constellations(pmt::pmt_t data) { for (int i=0; i=0 && idx < n); _constellations[idx] = gr::digital::constellation_calcdist::make - (pmt::c32vector_elements(pmt::dict_ref(c, pmt::mp("points"), pmt::PMT_NIL)), - pmt::s32vector_elements(pmt::dict_ref(c, pmt::mp("symbols"), pmt::PMT_NIL)), + (pmt::c32vector_elements(pmt::dict_ref(c, pmt::intern("points"), pmt::PMT_NIL)), + pmt::s32vector_elements(pmt::dict_ref(c, pmt::intern("symbols"), pmt::PMT_NIL)), rotational_symmetry, dimensionality); _npwr[i].reset(_npwr_max_time_constant); } @@ -354,11 +359,11 @@ void adaptive_dfe_impl::update_constellations(pmt::pmt_t data) { void adaptive_dfe_impl::update_frame_info(pmt::pmt_t data) { //GR_LOG_DEBUG(d_logger,str(boost::format("adaptive_dfe_impl::update_frame_info() %s") % data)); - _symbols = pmt::c32vector_elements(pmt::dict_ref(data, pmt::mp("symb"), pmt::PMT_NIL)); - _scramble = pmt::c32vector_elements(pmt::dict_ref(data, pmt::mp("scramble"), pmt::PMT_NIL)); - _constellation_index = pmt::to_long(pmt::dict_ref(data, pmt::mp("constellation_idx"), pmt::PMT_NIL)); - _save_soft_decisions = pmt::to_bool(pmt::dict_ref(data, pmt::mp("save_soft_dec"), pmt::PMT_F)); - bool const do_continue = pmt::to_bool(pmt::dict_ref(data, pmt::mp("do_continue"), pmt::PMT_F)); + _symbols = pmt::c32vector_elements(pmt::dict_ref(data, pmt::intern("symb"), pmt::PMT_NIL)); + _scramble = pmt::c32vector_elements(pmt::dict_ref(data, pmt::intern("scramble"), pmt::PMT_NIL)); + _constellation_index = pmt::to_long(pmt::dict_ref(data, pmt::intern("constellation_idx"), pmt::PMT_NIL)); + _save_soft_decisions = pmt::to_bool(pmt::dict_ref(data, pmt::intern("save_soft_dec"), pmt::PMT_F)); + bool const do_continue = pmt::to_bool(pmt::dict_ref(data, pmt::intern("do_continue"), pmt::PMT_F)); assert(_symbols.size() == _scramble.size()); _descrambled_symbols.resize(_symbols.size()); _vec_soft_decisions.clear(); diff --git a/lib/doppler_correction_cc_impl.cc b/lib/doppler_correction_cc_impl.cc index 3d77467..8d4a23b 100644 --- a/lib/doppler_correction_cc_impl.cc +++ b/lib/doppler_correction_cc_impl.cc @@ -51,16 +51,15 @@ doppler_correction_cc_impl::doppler_correction_cc_impl(unsigned int preamble_len , _rotator() , _state(WAIT_FOR_PHASE_EST_TAG) , _msg_metadata(pmt::make_dict()) - , _port_name(pmt::mp("doppler")) + , _port_name(pmt::intern("doppler")) , _phase_est(0) { GR_LOG_DECLARE_LOGPTR(d_logger); GR_LOG_ASSIGN_LOGPTR(d_logger, "doppler_correction_cc"); message_port_register_out(_port_name); message_port_register_in (_port_name); -// set_msg_handler(_port_name, boost::bind(&doppler_correction_cc_impl::handle_message, this, _1)); + set_msg_handler(_port_name, boost::bind(&doppler_correction_cc_impl::handle_message, this, _1)); set_tag_propagation_policy(TPP_DONT); - set_output_multiple(2*_preamble_length); // without this the CPU usage goes up to 100% } doppler_correction_cc_impl::~doppler_correction_cc_impl() @@ -68,27 +67,32 @@ doppler_correction_cc_impl::~doppler_correction_cc_impl() } void -doppler_correction_cc_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) +doppler_correction_cc_impl::handle_message(pmt::pmt_t msg) { - ninput_items_required[0] = noutput_items + _preamble_length; + gr::thread::scoped_lock lock(d_setlock); + bool const success = pmt::to_bool(pmt::dict_ref(msg, pmt::intern("success"), pmt::get_PMT_F())); + if (!success) { + // GR_LOG_DEBUG(d_logger, "next state > CONSUME_AND_SKIP success=false"); + if (_state == WAIT_FOR_MSG) + _state = CONSUME_AND_SKIP; + return; + } + float const doppler = pmt::to_float(pmt::dict_ref(msg, pmt::intern("doppler"), pmt::from_float(0))); + _rotator.set_phase_incr(gr_expj(-doppler)); + if (_state == WAIT_FOR_MSG) { + _rotator.set_phase(gr_expj(-_phase_est + 0.5*doppler*_preamble_length_cc)); + _state = CONSUME_AND_INSERT_PREAMBLE_TAG; + GR_LOG_DEBUG(d_logger, str(boost::format("next state > CONSUME_AND_INSERT_PREAMBLE_TAG phase_est=%f doppler=%f") + % (_phase_est - 0.5*doppler*_preamble_length_cc) + % doppler)); + } } void -doppler_correction_cc_impl::handle_message(pmt::pmt_t msg) +doppler_correction_cc_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) { - bool const success = pmt::to_bool(pmt::dict_ref(msg, pmt::mp("success"), pmt::get_PMT_F())); - if (!success) { - // GR_LOG_DEBUG(d_logger, "next state > CONSUME_AND_SKIP success=false"); - _state = CONSUME_AND_SKIP; - return; - } - float const doppler = pmt::to_float(pmt::dict_ref(msg, pmt::mp("doppler"), pmt::from_float(0))); - _rotator.set_phase(gr_expj(-_phase_est + 0.5*doppler*_preamble_length_cc)); - _rotator.set_phase_incr(gr_expj(-doppler)); - // GR_LOG_DEBUG(d_logger, str(boost::format("next state > CONSUME_AND_INSERT_PREAMBLE_TAG phase_est=%f doppler=%f") - // % (_phase_est - 0.5*doppler*_preamble_length_cc) - // % doppler)); - _state = CONSUME_AND_INSERT_PREAMBLE_TAG; + ninput_items_required[0] = _preamble_length + 1; +// GR_LOG_DEBUG(d_logger, str(boost::format("forecast: %d %d %d") % noutput_items % ninput_items_required[0] % _preamble_length)); } int @@ -96,18 +100,18 @@ doppler_correction_cc_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + gr::thread::scoped_lock lock(d_setlock); gr_complex const* in = (gr_complex const*)input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - -// assert(noutput_items >= _preamble_length); - noutput_items -= _preamble_length; - if (noutput_items < 0) + // GR_LOG_DEBUG(d_logger, str(boost::format("work: %d %d") % noutput_items % _preamble_length)); + if (noutput_items < _preamble_length) return 0; + noutput_items -= _preamble_length; int nout = 0; switch (_state) { case WAIT_FOR_PHASE_EST_TAG: { std::vector v; - get_tags_in_window(v, 0, 0, noutput_items, pmt::mp("phase_est")); + get_tags_in_window(v, 0, 0, noutput_items, pmt::intern("phase_est")); if (v.empty()) { nout = noutput_items; } else { @@ -115,7 +119,7 @@ doppler_correction_cc_impl::work(int noutput_items, uint64_t const offset = tag.offset - nitems_read(0); nout = offset; _phase_est = pmt::to_double(tag.value); - _msg_metadata = pmt::dict_add(_msg_metadata, pmt::mp("packet_len"), pmt::from_long(_preamble_length)); + _msg_metadata = pmt::dict_add(_msg_metadata, pmt::intern("packet_len"), pmt::from_long(_preamble_length)); message_port_pub(_port_name, pmt::cons(_msg_metadata, pmt::init_c32vector(_preamble_length, in+nout))); @@ -126,11 +130,11 @@ doppler_correction_cc_impl::work(int noutput_items, } // WAIT_FOR_PHASE_EST_TAG case WAIT_FOR_MSG: { // GR_LOG_DEBUG(d_logger, "WAIT_FOR_MSG"); - handle_message(delete_head_blocking(_port_name)); + // handle_message(delete_head_nowait(_port_name)); break; } // WAIT_FOR_MSG case CONSUME_AND_INSERT_PREAMBLE_TAG: { - add_item_tag(0, nitems_read(0), pmt::mp("preamble_start"), pmt::from_long(0)); + add_item_tag(0, nitems_read(0), pmt::intern("preamble_start"), pmt::from_long(0)); nout = _preamble_length; // GR_LOG_DEBUG(d_logger, str(boost::format("next state > WAIT_FOR_PHASE_EST_TAG %lld") % nitems_read(0))); _state = WAIT_FOR_PHASE_EST_TAG; diff --git a/lib/doppler_correction_cc_impl.h b/lib/doppler_correction_cc_impl.h index fdab73c..9810dae 100644 --- a/lib/doppler_correction_cc_impl.h +++ b/lib/doppler_correction_cc_impl.h @@ -54,6 +54,7 @@ public: int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + protected: void handle_message(pmt::pmt_t msg); diff --git a/python/__init__.py b/python/__init__.py index 61f3827..5c912f8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -31,6 +31,6 @@ except ImportError: pass # import any pure python here -from physical_layer_driver import physical_layer_driver -from msg_proxy import msg_proxy +from .physical_layer_driver import physical_layer_driver +from .msg_proxy import msg_proxy # diff --git a/python/msg_proxy.py b/python/msg_proxy.py index 660e26d..731f1a8 100644 --- a/python/msg_proxy.py +++ b/python/msg_proxy.py @@ -44,6 +44,9 @@ class msg_proxy(gr.basic_block): self.message_port_register_out(self._port_frame_info) self.set_msg_handler(self._port_frame_info, self.msg_handler_frame) + self._port_soft_dec = pmt.intern("soft_dec") + self.message_port_register_out(self._port_soft_dec) + def msg_handler_doppler(self, msg_in): ## print('-------------------- msg_handler_doppler --------------------') iq_samples = pmt.to_python(pmt.cdr(msg_in)) @@ -57,8 +60,19 @@ class msg_proxy(gr.basic_block): def msg_handler_frame(self, msg_in): ## print('-------------------- msg_handler_frame --------------------') ## print(msg_in) - symbols = pmt.to_python(pmt.dict_ref(msg_in, pmt.intern('symbols'), pmt.PMT_NIL)) + symbols = pmt.to_python(pmt.dict_ref(msg_in, pmt.intern('symbols'), pmt.PMT_NIL)) + soft_dec = pmt.to_python(pmt.dict_ref(msg_in, pmt.intern('soft_dec'), pmt.PMT_NIL)) symb,constellation_idx,do_continue,save_soft_dec = self._obj.get_next_frame(symbols) + if do_continue and len(soft_dec) != 0: + d = self._obj.decode_soft_dec(soft_dec) + msg_out = pmt.make_dict() + msg_out = pmt.dict_add(msg_out, pmt.intern('packet_len'), pmt.to_pmt(len(d))) + d = np.array(d, dtype=np.float32) + d[abs(d)==np.Inf] = 0 + vv = pmt.to_pmt(d) + msg = pmt.cons(msg_out, vv) + self.message_port_pub(self._port_soft_dec, msg) + ## TODO: publish the bits if success ##print('symb=', symb, symb['symb'], symb['scramble']) msg_out = pmt.make_dict() msg_out = pmt.dict_add(msg_out, pmt.intern('symb'), pmt.to_pmt(symb['symb'])) diff --git a/python/physical_layer/MIL_STD_188_110A.py b/python/physical_layer/MIL_STD_188_110A.py index 699667c..8126b77 100644 --- a/python/physical_layer/MIL_STD_188_110A.py +++ b/python/physical_layer/MIL_STD_188_110A.py @@ -2,17 +2,17 @@ from __future__ import print_function import numpy as np -from common import * +import common ## ---- Walsh-4 codes ----------------------------------------------------------- -WALSH = np.array([[0,0,0,0, 0,0,0,0], - [0,1,0,1, 0,1,0,1], - [0,0,1,1, 0,0,1,1], - [0,1,1,0, 0,1,1,0], - [0,0,0,0, 1,1,1,1], - [0,1,0,1, 1,0,1,0], - [0,0,1,1, 1,1,0,0], - [0,1,1,0, 1,0,0,1]], +WALSH = np.array([[0,0,0,0, 0,0,0,0], # 0 - 000 + [0,1,0,1, 0,1,0,1], # 1 - 001 + [0,0,1,1, 0,0,1,1], # 2 - 010 + [0,1,1,0, 0,1,1,0], # 3 - 011 + [0,0,0,0, 1,1,1,1], # 4 - 100 + [0,1,0,1, 1,0,1,0], # 5 - 010 + [0,0,1,1, 1,1,0,0], # 6 - 011 + [0,1,1,0, 1,0,0,1]], # 7 - 111 dtype=np.uint8) FROM_WALSH = -np.ones(256, dtype=np.int8) @@ -31,12 +31,12 @@ TRIBIT_SCRAMBLE = np.array( ## ---- preamble symbols --------------------------------------------------------- D1=D2=C1=C2=C3=0 ## not known -PRE_SYMBOLS = n_psk(2, np.concatenate( +PRE_SYMBOLS = common.n_psk(2, np.concatenate( [TRIBIT[i][:] for i in [0,1,3,0,1,3,1,2,0,D1,D2,C1,C2,C3,0]])) PRE_SYMBOLS[9*32:14*32] = 0 ## ---- preamble scramble symbols ------------------------------------------------ -PRE_SCRAMBLE = n_psk(8, np.concatenate([TRIBIT_SCRAMBLE for _ in range(15)])) +PRE_SCRAMBLE = common.n_psk(8, np.concatenate([TRIBIT_SCRAMBLE for _ in range(15)])) ## ---- data scrambler ----------------------------------------------------------- class ScrambleData(object): @@ -64,9 +64,9 @@ class ScrambleData(object): return self._state ## ---- constellatios ----------------------------------------------------------- -BPSK=np.array(zip(np.exp(2j*np.pi*np.arange(2)/2), [0,1]), CONST_DTYPE) -QPSK=np.array(zip(np.exp(2j*np.pi*np.arange(4)/4), [0,1,3,2]), CONST_DTYPE) -PSK8=np.array(zip(np.exp(2j*np.pi*np.arange(8)/8), [0,1,3,2,7,6,4,5]), CONST_DTYPE) +BPSK=np.array(zip(np.exp(2j*np.pi*np.arange(2)/2), [0,1]), common.CONST_DTYPE) +QPSK=np.array(zip(np.exp(2j*np.pi*np.arange(4)/4), [0,1,3,2]), common.CONST_DTYPE) +PSK8=np.array(zip(np.exp(2j*np.pi*np.arange(8)/8), [0,1,3,2,7,6,4,5]), common.CONST_DTYPE) ## ---- constellation indices --------------------------------------------------- MODE_BPSK=0 @@ -96,6 +96,41 @@ MODE[5][4] = {'bit_rate': 150, 'ci':MODE_BPSK, 'interleaver':['L', 40,144], 'unk MODE[7][5] = {'bit_rate': 75, 'ci':MODE_QPSK, 'interleaver':['S', 10, 9], 'unknown':-1,'known': 0, 'nsymb':32, 'coding_rate':1./2} MODE[5][4] = {'bit_rate': 75, 'ci':MODE_QPSK, 'interleaver':['L', 20, 36], 'unknown':-1,'known': 0, 'nsymb':32, 'coding_rate':1./2} +## ---- deinterleaver ----------------------------------------------------------- + +class Deinterleaver(object): + """deinterleave""" + def __init__(self, rows, cols): + self._a = np.zeros((rows, cols), dtype=np.float32) + self._i = 0 + self._j = 0 + self._di = 9 if rows==40 else 7 + self._dj = -17 if rows==40 else -7 + self._buffer = np.zeros(0, dtype=np.float32) + print('deinterleaver: ', rows, cols, self._di, self._dj) + + def fetch(self, a): + pass + + def load(self, a): + self._buffer = np.append(self._buffer, a) + print('interleaver load', self._a.shape, a.shape, self._buffer.shape) + if self._buffer.shape[0] < self._a.shape[0]: + return np.zeros(0, dtype=np.float32) + print('interleaver load buffer:', len(self._buffer),self._i,self._j) + i = np.arange(self._a.shape[0]) + j = (self._j + self._dj*np.arange(self._a.shape[0])) % self._a.shape[1] + self._a[i,j] = self._buffer[0:self._a.shape[0]] + self._buffer = np.delete(self._buffer, i) + self._j += 1 + print('interleaver load buffer:', len(self._buffer),self._i,self._j) + if self._j == self._a.shape[1]: + self._j = 0 + print('==================== interleaver is full! ====================') + return np.concatenate([self._a[(self._di*i)%self._a.shape[0],j] for j in range(self._a.shape[1])]) + else: + return np.zeros(0, dtype=np.float32) + ## ---- physcal layer class ----------------------------------------------------- class PhysicalLayer(object): """Physical layer description for MIL-STD-188-110 Appendix A""" @@ -145,8 +180,8 @@ class PhysicalLayer(object): def get_next_data_frame(self, success): if self._frame_counter == self._num_frames_per_block: self._frame_counter = 0 - scramble_for_frame = n_psk(8, np.array([self._scr_data.next() - for _ in range(self._frame_len)])) + scramble_for_frame = common.n_psk(8, np.array([self._scr_data.next() + for _ in range(self._frame_len)])) a = np.array(zip(scramble_for_frame, scramble_for_frame), dtype=[('symb', np.complex64), @@ -155,8 +190,8 @@ class PhysicalLayer(object): a['symb'][0:n_unknown] = 0 if self._frame_counter >= self._num_frames_per_block-2: idx_d1d2 = self._frame_counter - self._num_frames_per_block + 2; - a['symb'][n_unknown :n_unknown+ 8] *= n_psk(2, WALSH[self._d1d2[idx_d1d2]][:]) - a['symb'][n_unknown+8:n_unknown+16] *= n_psk(2, WALSH[self._d1d2[idx_d1d2]][:]) + a['symb'][n_unknown :n_unknown+ 8] *= common.n_psk(2, WALSH[self._d1d2[idx_d1d2]][:]) + a['symb'][n_unknown+8:n_unknown+16] *= common.n_psk(2, WALSH[self._d1d2[idx_d1d2]][:]) if not success: self._frame_counter = -1 self._pre_counter = -1 @@ -183,10 +218,10 @@ class PhysicalLayer(object): pks = [np.correlate(iq_samples[imax+i*32*sps+idx], zp[ i*32*sps+idx])[0] for i in range(9)] - doppler = freq_est(pks)/(32*sps) - print('success=', success, 'doppler=', doppler, - np.abs(np.array(pks)), - np.angle(np.array(pks))) + doppler = common.freq_est(pks)/(32*sps) + print('success=', success, 'doppler=', doppler, + np.abs(np.array(pks)), + np.angle(np.array(pks))) return success,doppler def decode_preamble(self, symbols): @@ -202,11 +237,22 @@ class PhysicalLayer(object): self._block_len = 11520 if self._mode['interleaver'][0] == 'L' else 1440 self._frame_len = self._mode['known'] + self._mode['unknown'] self._num_frames_per_block = self._block_len/self._frame_len; + self._deinterleaver = Deinterleaver(self._mode['interleaver'][1], self._mode['interleaver'][2]) + print(self._d1d2, self._mode, self._frame_len) return True def set_mode(self, _): pass + def decode_soft_dec(self, soft_dec): + print('decode_soft_dec', len(soft_dec), soft_dec.dtype) + r = self._deinterleaver.load(soft_dec) + print('decode_soft_dec r=', r.shape) + if r.shape[0] != 0: + for i in range(r.shape[0]//4): + print('BB:', r[4*i]<0, r[4*i+2]<0, '|', r[4*i+1]<0, r[4*i+3]<0) + return soft_dec ## TODO + @staticmethod def get_preamble(): """preamble symbols + scrambler""" diff --git a/python/physical_layer/MIL_STD_188_110C.py b/python/physical_layer/MIL_STD_188_110C.py index e6e2c02..9e5b3f0 100644 --- a/python/physical_layer/MIL_STD_188_110C.py +++ b/python/physical_layer/MIL_STD_188_110C.py @@ -156,14 +156,14 @@ class PhysicalLayer(object): self._frame_counter += 1 return [self._preamble,MODE_BPSK,success,False] - frame_counter_mod = self._frame_counter%72 - if frame_counter_mod == 0: ## --- re-inserted preamble + frame_counter_mod72 = self._frame_counter%72 + if frame_counter_mod72 == 0: ## --- re-inserted preamble self._frame_counter += 1 success = self.get_preamble_quality(symbols) return [self.make_reinserted_preamble(self._preamble_offset,success),MODE_QPSK,success,False] - if frame_counter_mod >= 1: ## ---- data frames - got_reinserted_preamble = frame_counter_mod == 1 + if frame_counter_mod72 >= 1: ## ---- data frames + got_reinserted_preamble = frame_counter_mod72 == 1 self._frame_counter += 1 if got_reinserted_preamble: success = self.decode_reinserted_preamble(symbols) @@ -176,21 +176,29 @@ class PhysicalLayer(object): success,doppler = True,0 if len(iq_samples) != 0: sps = self._sps - idx = np.arange(23*sps) + m = 23*sps + idx = np.arange(m) + idx2 = np.arange(m+23*sps) _,zp = self.get_preamble_z() - cc = np.correlate(iq_samples, zp[idx]) + n = len(zp) + cc = np.correlate(iq_samples, zp) imax = np.argmax(np.abs(cc[0:23*sps])) - pks = [np.correlate(iq_samples[imax+i*23*sps+idx], - zp[i*23*sps+idx])[0] - for i in range(8)] - success = np.mean(np.abs(pks)) > 2*np.mean(np.abs(cc[imax+11*sps+range(-sps,sps)])) - print('test:',imax, np.mean(np.abs(pks)), np.mean(np.abs(cc[imax+11*sps+range(-sps,sps)]))) + print('imax=', imax, len(iq_samples)) + pks = [np.correlate(iq_samples[imax+i*m+idx], + zp[i*m+idx])[0] + for i in range(n//m)] + val = [np.mean(np.abs(np.correlate(iq_samples[imax+i*m+idx2], + zp[i*m+idx])[11*sps+np.arange(-2*sps,2*sps)])) + for i in range((n//m)-1)] + tests = np.abs(pks[0:-1])/val + success = np.median(tests) > 2.0 + print('test:', np.abs(pks), tests) if success: print('doppler apks', np.abs(pks)) print('doppler ppks', np.angle(pks), - np.diff(np.unwrap(np.angle(pks)))/23, - np.mean(np.diff(np.unwrap(np.angle(pks)))/23)) - doppler = freq_est(pks)/(23*sps); + np.diff(np.unwrap(np.angle(pks)))/m, + np.mean(np.diff(np.unwrap(np.angle(pks)))/m)) + doppler = freq_est(pks)/m; print('success=', success, 'doppler=', doppler) return success,doppler @@ -238,13 +246,13 @@ class PhysicalLayer(object): ('scramble', np.complex64)]) a['symb'][-72:-72+3*13] = 0 ## D0,D1,D2 if not success: - sefl._frame_counter = -1 + self._frame_counter = -1 return a def make_data_frame(self, success): self._preamble_offset = -72 ## all following reinserted preambles start at index -72 - a=np.zeros(256+31, dtype=[('symb', np.complex64), - ('scramble', np.complex64)]) + a = np.zeros(256+31, dtype=[('symb', np.complex64), + ('scramble', np.complex64)]) a['scramble'][:256] = self._data_scramble n = (self._frame_counter-2)%72 m = n%18 @@ -258,6 +266,9 @@ class PhysicalLayer(object): self._frame_counter = -1 return a + def decode_soft_dec(self, soft_dec): + return soft_dec + @staticmethod def get_preamble(): """preamble symbols + scrambler""" diff --git a/python/physical_layer/STANAG_4285.py b/python/physical_layer/STANAG_4285.py index e2b80cb..86f51cd 100644 --- a/python/physical_layer/STANAG_4285.py +++ b/python/physical_layer/STANAG_4285.py @@ -2,6 +2,22 @@ import numpy as np +class Deinterleaver(object): + "S4285 deinterleaver" + def __init__(self, incr): + ## incr = 12 -> L + ## incr = 1 -> S + self._buf = [np.zeros(incr*(31-i) + 1) for i in range(32)] + + def push(self, a): + assert(len(a) == 32) + for i in range(32): + self._buf[i][0] = a[i] + self._buf[i] = np.roll(self._buf[i],1) + + def fetch(self): + return np.array([self._buf[(9*i)%32][0] for i in range(32)]) + class PhysicalLayer(object): """Physical layer description for STANAG 4285""" @@ -20,6 +36,7 @@ class PhysicalLayer(object): self.make_psk(8, [1,0,2,3,6,7,5,4])] self._preamble = self.get_preamble() self._data = self.get_data() + self._deinterleaver = Deinterleaver(12) ## for now BPSK L fixed def set_mode(self, mode): """set phase modultation type""" @@ -88,6 +105,15 @@ class PhysicalLayer(object): a = PhysicalLayer.get_preamble() return 2,np.array([z for z in a['symb'][0:31] for _ in range(self._sps)]) + def decode_soft_dec(self, soft_dec): + assert(len(soft_dec) == 128) + print('decode_soft_dec: ', len(soft_dec)) + res = [] + for i in range(0,128,32): + self._deinterleaver.push(soft_dec[i:i+32]) + res.extend(self._deinterleaver.fetch().tolist()) + return res + @staticmethod def get_preamble(): """preamble symbols + scrambler(=1)""" diff --git a/python/physical_layer_driver.py b/python/physical_layer_driver.py index 368de65..ed667fd 100644 --- a/python/physical_layer_driver.py +++ b/python/physical_layer_driver.py @@ -54,7 +54,11 @@ class physical_layer_driver(gr.hier_block2): preamble_offset,preamble_samples = self._physical_layer_driver_description.get_preamble_z() preamble_length = sps*len(self._physical_layer_driver_description.get_preamble()) self._rrc_filter = filter.fir_filter_ccc(1, (self._rrc_taps)) - self._corr_est = digital.corr_est_cc((preamble_samples.tolist()), sps, preamble_offset, 0.5) + self._corr_est = digital.corr_est_cc(symbols = (preamble_samples.tolist()), + sps = sps, + mark_delay = preamble_offset, + threshold = 0.5, + threshold_method = 1) self._doppler_correction = digitalhf.doppler_correction_cc(preamble_length, len(preamble_samples)) self._adaptive_filter = digitalhf.adaptive_dfe(sps, nB, nF, nW, mu, alpha) self._msg_proxy = digitalhf.msg_proxy(self._physical_layer_driver_description) @@ -80,6 +84,7 @@ class physical_layer_driver(gr.hier_block2): self.message_port_register_hier_out('soft_dec') self.msg_connect((self._adaptive_filter, 'soft_dec'), (self, 'soft_dec')) + self.msg_connect((self._msg_proxy, 'soft_dec'), (self, 'soft_dec')) def set_mu(self, mu): self._adaptive_filter.set_mu(mu)