diff --git a/examples/test_cc.grc b/examples/test_cc.grc index 86267c2..bc088ed 100644 --- a/examples/test_cc.grc +++ b/examples/test_cc.grc @@ -207,7 +207,7 @@ value - [[x,x,x,x,x] for x in STANAG_4285.PhysicalLayer.get_preamble()['symb'].tolist()] + [[x,x,x,x,x] for x in STANAG_4285.PhysicalLayer.get_preamble()['symb'][9:40].tolist()] @@ -812,7 +812,7 @@ mark_delay - nF+2 + nF+2-9*sps threshold_method diff --git a/lib/adaptive_dfe_impl.cc b/lib/adaptive_dfe_impl.cc index c0ec835..3892efc 100644 --- a/lib/adaptive_dfe_impl.cc +++ b/lib/adaptive_dfe_impl.cc @@ -23,9 +23,14 @@ #endif #include +#include #include #include "adaptive_dfe_impl.h" +#define VOLK_SAFE_DELETE(x) \ + volk_free(x); \ + x = nullptr + namespace gr { namespace digitalhf { @@ -84,7 +89,6 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol , _scramble() , _descrambled_symbols() , _symbol_counter(0) - , _sum_phase_diff(0) , _df(0) , _phase(0) , _b{0.338187046465954, -0.288839024460507} @@ -98,6 +102,10 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol */ adaptive_dfe_impl::~adaptive_dfe_impl() { + VOLK_SAFE_DELETE(_taps_samples); + VOLK_SAFE_DELETE(_taps_symbols); + VOLK_SAFE_DELETE(_hist_samples); + VOLK_SAFE_DELETE(_hist_symbols); } void @@ -120,43 +128,13 @@ adaptive_dfe_impl::general_work(int noutput_items, int i = 0; for (; i M_PI) - _phase -= 2*M_PI; - if (_phase < -M_PI) - _phase += 2*M_PI; - _hist_samples[_hist_sample_index] = _hist_samples[_hist_sample_index+_nB+_nF+1] = in[i] * std::exp(gr_complex(0,_phase)); - if (++_hist_sample_index == _nB+_nF+1) - _hist_sample_index = 0; + insert_sample(in[i]); if (_state == WAIT_FOR_PREAMBLE) { - std::vector v; - get_tags_in_window(v, 0, i,i+1); - float phase_est = 0; - float corr_est = 0; uint64_t offset = 0; - for (int j=0; j 130e3) { - offset = v[j].offset - nitems_read(0); - break; - } - } - } - if (corr_est > 130e3) { + float phase_est = 0; + if (get_correlation_tag(i, offset, phase_est)) { _state = DO_FILTER; _sample_counter = 0; _symbol_counter = 0; @@ -168,10 +146,10 @@ adaptive_dfe_impl::general_work(int noutput_items, std::fill_n(_hist_symbols, 2*_nW, gr_complex(0)); std::fill_n(_taps_samples, _nB+_nF+1, gr_complex(0)); std::fill_n(_taps_symbols, _nW, gr_complex(0)); - //_phase = -phase_est; - _taps_samples[_nB+1] = std::exp(gr_complex(0, -phase_est)); + _phase = -phase_est; + _taps_samples[_nB+1] = 1;//gr_expj(-phase_est); _taps_symbols[0] = 1; - GILLock lock; + GILLock gil_lock; try { update_frame_information(_physicalLayer.attr("get_frame")()); } catch (boost::python::error_already_set const&) { @@ -182,16 +160,16 @@ adaptive_dfe_impl::general_work(int noutput_items, if (_state == DO_FILTER) { gr_complex dot_samples = 0; // volk_32fc_x2_dot_prod_32fc(&dot_samples, - // &_hist_samples.front()+_hist_sample_index, - // &_taps_samples.front(), - // _taps_samples.size()); - gr_complex filter_output = dot_samples; + // _hist_samples+_hist_sample_index, + // _taps_samples, + // _nB+_nF+1); // if (_sample_counter < 80*5) // std::cout << "SAMPLE " << _sample_counter << " " << dot_samples << std::endl; + gr_complex filter_output = dot_samples; if ((_sample_counter%_sps) == 0) { if (_symbol_counter == _symbols.size()) { _symbol_counter = 0; - GILLock lock; + GILLock gil_lock; try { boost::python::numpy::ndarray s = boost::python::numpy::from_data(&_descrambled_symbols.front(), boost::python::numpy::dtype::get_builtin(), @@ -243,7 +221,8 @@ adaptive_dfe_impl::general_work(int noutput_items, _taps_symbols[j] -= _mu*err*std::conj(_hist_symbols[_hist_symbol_index+j]) + _alpha*_taps_symbols[j]; } } - // std::cout << "filter: " << _symbol_counter << " " << _sample_counter << " " << filter_output << " " << known_symbol << " " << std::abs(err) << std::endl; + // if (_sample_counter < 80*5) + // std::cout << "filter: " << _symbol_counter << " " << _sample_counter << " " << filter_output << " " << known_symbol << " " << std::abs(err) << std::endl; } if (is_known) { _taps_symbols[_hist_symbol_index] = _taps_symbols[_hist_symbol_index + _nW] = known_symbol; @@ -266,15 +245,16 @@ adaptive_dfe_impl::general_work(int noutput_items, bool adaptive_dfe_impl::start() { + gr::thread::scoped_lock lock(d_setlock); // make sure python is ready for threading if( Py_IsInitialized() ){ - GILLock lock; + GILLock gil_lock; if(PyEval_ThreadsInitialized() != 1 ){ PyEval_InitThreads(); } boost::python::numpy::initialize(); } else { - throw std::runtime_error("dont use es_pyhandler without python!"); + throw std::runtime_error("dont use adaptive_dfe without python!"); } _taps_samples = (gr_complex*)(volk_malloc( (_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment())); _taps_symbols = (gr_complex*)(volk_malloc( _nW*sizeof(gr_complex), volk_get_alignment())); @@ -284,7 +264,7 @@ bool adaptive_dfe_impl::start() _taps_symbols[0] = 1; std::cout << "adaptive_dfe_impl::start()" << std::endl; - GILLock lock; + GILLock gil_lock; try { boost::python::object module = boost::python::import(boost::python::str("digitalhf.physical_layer." + _py_module_name)); boost::python::object PhysicalLayer = module.attr("PhysicalLayer"); @@ -298,13 +278,14 @@ bool adaptive_dfe_impl::start() } bool adaptive_dfe_impl::stop() { + gr::thread::scoped_lock lock(d_setlock); std::cout << "adaptive_dfe_impl::stop()" << std::endl; - GILLock lock; + GILLock gil_lock; _physicalLayer = boost::python::object(); - volk_free(_taps_samples); - volk_free(_taps_symbols); - volk_free(_hist_samples); - volk_free(_hist_symbols); + VOLK_SAFE_DELETE(_taps_samples); + VOLK_SAFE_DELETE(_taps_symbols); + VOLK_SAFE_DELETE(_hist_samples); + VOLK_SAFE_DELETE(_hist_symbols); return true; } @@ -348,19 +329,55 @@ void adaptive_dfe_impl::update_doppler_information(boost::python::object obj) { int const n = boost::python::extract(obj.attr("__len__")()); assert(n==2); - double const do_continue = boost::python::extract(obj[0]); - double const doppler = boost::python::extract(obj[1]); + bool const do_continue = boost::python::extract(obj[0]); + float const doppler = boost::python::extract(obj[1]); - float delta_f = doppler/_sps; + update_pll(doppler); +} + +void adaptive_dfe_impl::update_pll(float doppler) { + if (doppler == 0) + return; + float const delta_f = doppler/_sps; if (_df == 0) { // init - _ud = _df = -delta_f; + _ud = _df = delta_f; } else { - const float ud_old = _ud; - _ud = -delta_f; + float const ud_old = _ud; + _ud = delta_f; _df +=_b[0]*_ud + _b[1]*ud_old; } std::cout << "PLL: " << _df << " " << delta_f << std::endl; - _sum_phase_diff = 0; +} +void adaptive_dfe_impl::insert_sample(gr_complex z) { + // local oscillator update + _phase += _df; + if (_phase > M_PI) + _phase -= 2*M_PI; + if (_phase < -M_PI) + _phase += 2*M_PI; + + // insert sample into the circular buffer + _hist_samples[_hist_sample_index] = _hist_samples[_hist_sample_index+_nB+_nF+1] = z * gr_expj(-_phase); + if (++_hist_sample_index == _nB+_nF+1) + _hist_sample_index = 0; +} +bool adaptive_dfe_impl::get_correlation_tag(uint64_t i, uint64_t& offset, float& phase_est) { + std::vector v; + get_tags_in_window(v, 0, i,i+1); + for (int j=0; j 18e3) + return true; + } + } + return false; } } /* namespace digitalhf */ diff --git a/lib/adaptive_dfe_impl.h b/lib/adaptive_dfe_impl.h index 28061ac..870546f 100644 --- a/lib/adaptive_dfe_impl.h +++ b/lib/adaptive_dfe_impl.h @@ -60,7 +60,6 @@ private: int _symbol_counter; // PLL for doppler tracking - float _sum_phase_diff; float _df; // frequency offset in radians per sample float _phase; // accumulated phase for frequency correction const float _b[2]; @@ -75,6 +74,10 @@ private: void update_frame_information(boost::python::object obj); void update_doppler_information(boost::python::object obj); + void insert_sample(gr_complex z); + void update_pll(float doppler); + bool get_correlation_tag(uint64_t i, uint64_t& offset, float& phase_est); + public: adaptive_dfe_impl(int sps, // samples per symbol int nB, // number of forward FIR taps diff --git a/python/physical_layer/STANAG_4285.py b/python/physical_layer/STANAG_4285.py index d449c1f..3c6646b 100644 --- a/python/physical_layer/STANAG_4285.py +++ b/python/physical_layer/STANAG_4285.py @@ -41,7 +41,7 @@ class PhysicalLayer(object): if self._counter == 0: ## preamble doppler = PhysicalLayer.data_aided_frequency_estimation(s, self._preamble[0]['symb']) self._counter = (self._counter+1)&1 - return [True, 2*doppler] + return [True, doppler] @staticmethod def get_preamble():