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)