mirror of
https://github.com/hb9fxq/gr-digitalhf
synced 2024-11-04 21:55:53 +00:00
doppler correction using unequalized samples
This commit is contained in:
parent
c34a2b3975
commit
56ae39c0ed
|
@ -136,7 +136,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1120, 101)</value>
|
||||
<value>(1141, 80)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
@ -210,6 +210,168 @@
|
|||
<value>[[x,x,x,x,x] for x in STANAG_4285.PhysicalLayer.get_preamble()['symb'][9:40].tolist()]</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable_qtgui_chooser</key>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(42, 384)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>mode</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label0</key>
|
||||
<value>PSK</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label1</key>
|
||||
<value>QPSK</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label2</key>
|
||||
<value>8PSK</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label3</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label4</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label</key>
|
||||
<value>mode</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>labels</key>
|
||||
<value>[]</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>num_opts</key>
|
||||
<value>3</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>option0</key>
|
||||
<value>'0'</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>option1</key>
|
||||
<value>'1'</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>option2</key>
|
||||
<value>'1'</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>option3</key>
|
||||
<value>3</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>option4</key>
|
||||
<value>4</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>options</key>
|
||||
<value>[0, 1, 2]</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>orient</key>
|
||||
<value>Qt.QVBoxLayout</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>string</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>widget</key>
|
||||
<value>combo_box</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable_qtgui_range</key>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>0.002</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1024, 80)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
<value>(3,0,1,2)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>mu</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>label</key>
|
||||
<value>mu</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>min_len</key>
|
||||
<value>200</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>orient</key>
|
||||
<value>Qt.Horizontal</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>start</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>step</key>
|
||||
<value>0.001</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>stop</key>
|
||||
<value>0.02</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>rangeType</key>
|
||||
<value>float</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>widget</key>
|
||||
<value>counter_slider</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable</key>
|
||||
<param>
|
||||
|
@ -234,7 +396,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>12*sps</value>
|
||||
<value>15</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -261,7 +423,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>9*sps</value>
|
||||
<value>15</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -288,7 +450,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>5</value>
|
||||
<value>4</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -365,7 +527,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(906, 325)</value>
|
||||
<value>(928, 314)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -408,7 +570,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(245, 165)</value>
|
||||
<value>(256, 154)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -443,7 +605,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>const</key>
|
||||
<value>4</value>
|
||||
<value>5</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
|
@ -455,7 +617,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(416, 186)</value>
|
||||
<value>(426, 176)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -506,7 +668,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(949, 144)</value>
|
||||
<value>(917, 133)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -557,7 +719,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(576, 186)</value>
|
||||
<value>(586, 176)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -616,7 +778,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(10, 165)</value>
|
||||
<value>(32, 154)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -663,7 +825,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(864, 453)</value>
|
||||
<value>(874, 458)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -685,6 +847,18 @@
|
|||
<key>sps</key>
|
||||
<value>sps</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alpha</key>
|
||||
<value>0.0005</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>mode</key>
|
||||
<value>mode</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>mu</key>
|
||||
<value>mu</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>nB</key>
|
||||
<value>nB</value>
|
||||
|
@ -784,7 +958,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(629, 282)</value>
|
||||
<value>(640, 272)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -812,7 +986,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>mark_delay</key>
|
||||
<value>nF+2-9*sps</value>
|
||||
<value>(nF-9)*sps+2</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>threshold_method</key>
|
||||
|
@ -820,7 +994,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>threshold</key>
|
||||
<value>0.3</value>
|
||||
<value>0.5</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -851,7 +1025,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1088, 474)</value>
|
||||
<value>(1120, 496)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
@ -1206,7 +1380,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1098, 314)</value>
|
||||
<value>(1120, 304)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
@ -1573,7 +1747,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1098, 229)</value>
|
||||
<value>(1120, 218)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
<key>digitalhf_adaptive_dfe</key>
|
||||
<category>[digitalhf]</category>
|
||||
<import>import digitalhf</import>
|
||||
<make>digitalhf.adaptive_dfe($sps,$nB,$nF,$nW,$py_obj_name)</make>
|
||||
<make>digitalhf.adaptive_dfe($sps,$nB,$nF,$nW,$mu,$alpha,$py_obj_name)</make>
|
||||
<callback>set_mu($mu)</callback>
|
||||
<callback>set_mode($mode)</callback>
|
||||
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
|
||||
Sub-nodes:
|
||||
* name
|
||||
|
@ -30,11 +32,26 @@
|
|||
<key>nW</key>
|
||||
<type>int</type>
|
||||
</param>
|
||||
<param>
|
||||
<name>mu</name>
|
||||
<key>mu</key>
|
||||
<type>float</type>
|
||||
</param>
|
||||
<param>
|
||||
<name>alpha</name>
|
||||
<key>alpha</key>
|
||||
<type>float</type>
|
||||
</param>
|
||||
<param>
|
||||
<name>py_obj_name</name>
|
||||
<key>py_obj_name</key>
|
||||
<type>string</type>
|
||||
</param>
|
||||
<param>
|
||||
<name>mode</name>
|
||||
<key>mode</key>
|
||||
<type>string</type>
|
||||
</param>
|
||||
|
||||
<!-- Make one 'sink' node per input. Sub-nodes:
|
||||
* name (an identifier for the GUI)
|
||||
|
|
|
@ -38,6 +38,7 @@ class DIGITALHF_API adaptive_dfe : virtual public gr::block
|
|||
public:
|
||||
typedef boost::shared_ptr<adaptive_dfe> sptr;
|
||||
|
||||
virtual ~adaptive_dfe() {}
|
||||
/*!
|
||||
* \brief Return a shared_ptr to a new instance of digitalhf::adaptive_dfe.
|
||||
*
|
||||
|
@ -50,8 +51,12 @@ class DIGITALHF_API adaptive_dfe : virtual public gr::block
|
|||
int nB, // number of forward FIR taps
|
||||
int nF, // number of backward FIR taps
|
||||
int nW, // number of feedback taps
|
||||
float mu, //
|
||||
float alpha, //
|
||||
std::string physical_layer_description);
|
||||
|
||||
virtual void set_mu(float) = 0;
|
||||
virtual void set_mode(std::string) = 0;
|
||||
} ;
|
||||
|
||||
} // namespace digitalhf
|
||||
|
|
|
@ -51,10 +51,12 @@ adaptive_dfe::make(int sps, // samples per symbol
|
|||
int nB, // number of forward FIR taps
|
||||
int nF, // number of backward FIR taps
|
||||
int nW, // number of feedback taps
|
||||
float mu,
|
||||
float alpha,
|
||||
std::string python_module_name)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new adaptive_dfe_impl(sps, nB, nF, nW, python_module_name));
|
||||
(new adaptive_dfe_impl(sps, nB, nF, nW, mu, alpha, python_module_name));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -64,16 +66,18 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol
|
|||
int nB, // number of forward FIR taps
|
||||
int nF, // number of backward FIR taps
|
||||
int nW, // number of feedback taps
|
||||
float mu,
|
||||
float alpha,
|
||||
std::string python_module_name)
|
||||
: gr::block("adaptive_dfe",
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex)))
|
||||
, _sps(sps)
|
||||
, _nB(nB)
|
||||
, _nF(nF)
|
||||
, _nB(nB*sps)
|
||||
, _nF(nF*sps)
|
||||
, _nW(nW)
|
||||
, _mu(0.01)
|
||||
, _alpha(0.001)
|
||||
, _mu(mu)
|
||||
, _alpha(alpha)
|
||||
, _py_module_name(python_module_name)
|
||||
, _physicalLayer()
|
||||
, _taps_samples(nullptr)
|
||||
|
@ -84,7 +88,11 @@ adaptive_dfe_impl::adaptive_dfe_impl(int sps, // samples per symbol
|
|||
, _hist_symbol_index(0)
|
||||
, _sample_counter(0)
|
||||
, _constellations()
|
||||
, _npwr()
|
||||
, _npwr_counter()
|
||||
, _npwr_max_time_constant(10)
|
||||
, _constellation_index()
|
||||
, _samples()
|
||||
, _symbols()
|
||||
, _scramble()
|
||||
, _descrambled_symbols()
|
||||
|
@ -146,8 +154,9 @@ 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));
|
||||
_samples.clear();
|
||||
_phase = -phase_est;
|
||||
_taps_samples[_nB+1] = 1;//gr_expj(-phase_est);
|
||||
_taps_samples[_nB+1] = 1;
|
||||
_taps_symbols[0] = 1;
|
||||
GILLock gil_lock;
|
||||
try {
|
||||
|
@ -166,17 +175,26 @@ adaptive_dfe_impl::general_work(int noutput_items,
|
|||
// if (_sample_counter < 80*5)
|
||||
// std::cout << "SAMPLE " << _sample_counter << " " << dot_samples << std::endl;
|
||||
gr_complex filter_output = dot_samples;
|
||||
_samples.push_back(_hist_samples[_hist_sample_index+_nB+1]);
|
||||
if ((_sample_counter%_sps) == 0) {
|
||||
if (_symbol_counter == _symbols.size()) {
|
||||
_symbol_counter = 0;
|
||||
GILLock gil_lock;
|
||||
try {
|
||||
boost::python::numpy::ndarray s = boost::python::numpy::from_data(&_descrambled_symbols.front(),
|
||||
boost::python::numpy::dtype::get_builtin<gr_complex>(),
|
||||
boost::python::make_tuple(_descrambled_symbols.size()),
|
||||
boost::python::make_tuple(sizeof(gr_complex)),
|
||||
boost::python::object());
|
||||
update_doppler_information(_physicalLayer.attr("get_doppler")(s));
|
||||
boost::python::numpy::ndarray sy =
|
||||
boost::python::numpy::from_data(&_descrambled_symbols.front(),
|
||||
boost::python::numpy::dtype::get_builtin<gr_complex>(),
|
||||
boost::python::make_tuple(_descrambled_symbols.size()),
|
||||
boost::python::make_tuple(sizeof(gr_complex)),
|
||||
boost::python::object());
|
||||
boost::python::numpy::ndarray sa =
|
||||
boost::python::numpy::from_data(&_samples.front(),
|
||||
boost::python::numpy::dtype::get_builtin<gr_complex>(),
|
||||
boost::python::make_tuple(_samples.size()),
|
||||
boost::python::make_tuple(sizeof(gr_complex)),
|
||||
boost::python::object());
|
||||
_samples.clear();
|
||||
update_doppler_information(_physicalLayer.attr("get_doppler")(sy, sa));
|
||||
update_frame_information(_physicalLayer.attr("get_frame")());
|
||||
} catch (boost::python::error_already_set const&) {
|
||||
PyErr_Print();
|
||||
|
@ -184,46 +202,66 @@ adaptive_dfe_impl::general_work(int noutput_items,
|
|||
}
|
||||
gr_complex known_symbol = _symbols[_symbol_counter];
|
||||
bool is_known = true;
|
||||
for (int k=0; k<1; ++k) {
|
||||
filter_output = 0;
|
||||
filter_output = 0;
|
||||
#if 1
|
||||
volk_32fc_x2_dot_prod_32fc(&filter_output,
|
||||
_hist_samples+_hist_sample_index,
|
||||
_taps_samples,
|
||||
_nB+_nF+1);
|
||||
volk_32fc_x2_dot_prod_32fc(&filter_output,
|
||||
_hist_samples+_hist_sample_index,
|
||||
_taps_samples,
|
||||
_nB+_nF+1);
|
||||
#else
|
||||
for (int l=0; l<_nB+_nF+1; ++l) {
|
||||
assert(_hist_sample_index+l < 2*(_nB+_nF+1));
|
||||
filter_output += _hist_samples[_hist_sample_index+l]*_taps_samples[l];
|
||||
for (int l=0; l<_nB+_nF+1; ++l) {
|
||||
assert(_hist_sample_index+l < 2*(_nB+_nF+1));
|
||||
filter_output += _hist_samples[_hist_sample_index+l]*_taps_samples[l];
|
||||
}
|
||||
#endif
|
||||
gr_complex dot_symbols=0;
|
||||
for (int l=0; l<_nW; ++l) {
|
||||
assert(_hist_symbol_index+l < 2*_nW);
|
||||
dot_symbols += _hist_symbols[_hist_symbol_index+l]*_taps_symbols[l];
|
||||
}
|
||||
filter_output += dot_symbols;
|
||||
if (std::abs(known_symbol) < 1e-5) { // not known
|
||||
is_known = false;
|
||||
gr_complex descrambled_filter_output = std::conj(_scramble[_symbol_counter]) * filter_output;
|
||||
gr::digital::constellation_sptr constell = _constellations[_constellation_index];
|
||||
unsigned int jc = constell->decision_maker(&descrambled_filter_output);
|
||||
constell->map_to_points(jc, &descrambled_filter_output);
|
||||
known_symbol = _scramble[_symbol_counter] * descrambled_filter_output;
|
||||
}
|
||||
gr_complex err = filter_output - known_symbol;
|
||||
for (int j=0; j<_nB+_nF+1; ++j) {
|
||||
_taps_samples[j] -= _mu*err*std::conj(_hist_samples[_hist_sample_index+j]);
|
||||
}
|
||||
for (int j=0; j<_nW; ++j) {
|
||||
assert(_hist_symbol_index+j < 2*_nW);
|
||||
_taps_symbols[j] -= _mu*err*std::conj(_hist_symbols[_hist_symbol_index+j]) + _alpha*_taps_symbols[j];
|
||||
}
|
||||
// if (_sample_counter < 80*5)
|
||||
// std::cout << "filter: " << _symbol_counter << " " << _sample_counter << " " << filter_output << " " << known_symbol << " " << std::abs(err) << std::endl;
|
||||
gr_complex dot_symbols=0;
|
||||
for (int l=0; l<_nW; ++l) {
|
||||
assert(_hist_symbol_index+l < 2*_nW);
|
||||
dot_symbols += _hist_symbols[_hist_symbol_index+l]*_taps_symbols[l];
|
||||
}
|
||||
filter_output += dot_symbols;
|
||||
if (std::abs(known_symbol) < 1e-5) { // not known
|
||||
is_known = false;
|
||||
gr_complex descrambled_filter_output = std::conj(_scramble[_symbol_counter]) * filter_output;
|
||||
gr::digital::constellation_sptr constell = _constellations[_constellation_index];
|
||||
unsigned int jc = constell->decision_maker(&descrambled_filter_output);
|
||||
gr_complex descrambled_symbol = 0;
|
||||
constell->map_to_points(jc, &descrambled_symbol);
|
||||
|
||||
// make soft decisions
|
||||
float const err = std::abs(descrambled_filter_output - descrambled_symbol);
|
||||
_npwr_counter[_constellation_index] += (_npwr_counter[_constellation_index] < _npwr_max_time_constant);
|
||||
float const alpha = 1.0f/_npwr_counter[_constellation_index];
|
||||
_npwr[_constellation_index] = (1-alpha)*_npwr[_constellation_index] + alpha*err;
|
||||
std::vector<float> soft_dec = constell->calc_soft_dec(descrambled_filter_output, _npwr[_constellation_index]);
|
||||
// std::cout << "soft_dec " << _npwr[_constellation_index] << " : ";
|
||||
// for (int k=0; k<soft_dec.size(); ++k) {
|
||||
// std::cout << soft_dec[k] << " ";
|
||||
// }
|
||||
// std::cout << "\n";
|
||||
|
||||
known_symbol = _scramble[_symbol_counter] * descrambled_symbol;
|
||||
}
|
||||
gr_complex err = filter_output - known_symbol;
|
||||
int jMax=0;
|
||||
float tMax=0;
|
||||
for (int j=0; j<_nB+_nF+1; ++j) {
|
||||
assert(_hist_sample_index+j < 2*(_nB+_nF+1));
|
||||
_taps_samples[j] -= _mu*err*std::conj(_hist_samples[_hist_sample_index+j]);
|
||||
// if (std::abs(_taps_samples[j]) > tMax) {
|
||||
// tMax = std::abs(_taps_samples[j]);
|
||||
// jMax = j;
|
||||
// }
|
||||
}
|
||||
// std::cout << "taps_max: " << jMax << " " << tMax << std::endl;
|
||||
for (int j=0; j<_nW; ++j) {
|
||||
assert(_hist_symbol_index+j < 2*_nW);
|
||||
_taps_symbols[j] -= _mu*err*std::conj(_hist_symbols[_hist_symbol_index+j]) + _alpha*_taps_symbols[j];
|
||||
}
|
||||
// if (_sample_counter < 80*5)
|
||||
// std::cout << "filter: " << _symbol_counter << " " << _sample_counter << " " << filter_output << " " << known_symbol << " " << std::abs(err) << std::endl;
|
||||
if (is_known || true) {
|
||||
_taps_symbols[_hist_symbol_index] = _taps_symbols[_hist_symbol_index + _nW] = known_symbol;
|
||||
_hist_symbols[_hist_symbol_index] = _hist_symbols[_hist_symbol_index + _nW] = known_symbol;
|
||||
if (++_hist_symbol_index == _nW)
|
||||
_hist_symbol_index = 0;
|
||||
}
|
||||
|
@ -258,10 +296,17 @@ bool adaptive_dfe_impl::start()
|
|||
_taps_symbols = (gr_complex*)(volk_malloc( _nW*sizeof(gr_complex), volk_get_alignment()));
|
||||
_hist_samples = (gr_complex*)(volk_malloc(2*(_nB+_nF+1)*sizeof(gr_complex), volk_get_alignment()));
|
||||
_hist_symbols = (gr_complex*)(volk_malloc( 2*_nW*sizeof(gr_complex), volk_get_alignment()));
|
||||
|
||||
_samples.clear();
|
||||
std::fill_n(_hist_samples, 2*(_nB+_nF+1), gr_complex(0));
|
||||
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));
|
||||
|
||||
_taps_samples[_nB+1] = 1;
|
||||
_taps_symbols[0] = 1;
|
||||
|
||||
std::cout << "adaptive_dfe_impl::start()" << std::endl;
|
||||
std::cout << "adaptive_dfe_impl::start() " << _nB << " " << _nF << " " << _mu << " " << _alpha << std::endl;
|
||||
GILLock gil_lock;
|
||||
try {
|
||||
boost::python::object module = boost::python::import(boost::python::str("digitalhf.physical_layer." + _py_module_name));
|
||||
|
@ -287,10 +332,25 @@ bool adaptive_dfe_impl::stop()
|
|||
return true;
|
||||
}
|
||||
|
||||
void adaptive_dfe_impl::set_mode(std::string mode) {
|
||||
gr::thread::scoped_lock lock(d_setlock);
|
||||
std::cout << "adaptive_dfe_impl::stop()" << std::endl;
|
||||
GILLock gil_lock;
|
||||
try {
|
||||
_physicalLayer.attr("set_mode")(mode);
|
||||
} catch (boost::python::error_already_set const&) {
|
||||
PyErr_Print();
|
||||
return;
|
||||
}
|
||||
update_constellations(_physicalLayer.attr("get_constellations")());
|
||||
}
|
||||
|
||||
void adaptive_dfe_impl::update_constellations(boost::python::object obj)
|
||||
{
|
||||
int const n = boost::python::extract<int>(obj.attr("__len__")());
|
||||
_constellations.resize(n);
|
||||
_npwr.resize(n);
|
||||
_npwr_counter.resize(n);
|
||||
for (int i=0; i<n; ++i) {
|
||||
boost::python::numpy::ndarray const& array = boost::python::numpy::array(obj[i]);
|
||||
char const* data = array.get_data();
|
||||
|
@ -304,6 +364,8 @@ void adaptive_dfe_impl::update_constellations(boost::python::object obj)
|
|||
unsigned int const rotational_symmetry = 0;
|
||||
unsigned int const dimensionality = 1;
|
||||
_constellations[i] = gr::digital::constellation_calcdist::make(constell, pre_diff_code, rotational_symmetry, dimensionality);
|
||||
_npwr[i] = 0.0f;
|
||||
_npwr_counter[i] = 0;
|
||||
}
|
||||
}
|
||||
void adaptive_dfe_impl::update_frame_information(boost::python::object obj)
|
||||
|
@ -316,6 +378,7 @@ void adaptive_dfe_impl::update_frame_information(boost::python::object obj)
|
|||
_symbols.resize(m);
|
||||
_scramble.resize(m);
|
||||
_descrambled_symbols.resize(m);
|
||||
_samples.clear();
|
||||
for (int i=0; i<m; ++i) {
|
||||
std::memcpy(&_symbols[i], data+16*i, sizeof(gr_complex));
|
||||
std::memcpy(&_scramble[i], data+16*i+8, sizeof(gr_complex));
|
||||
|
@ -355,17 +418,17 @@ void adaptive_dfe_impl::update_pll(float doppler) {
|
|||
std::cout << "PLL: " << _df << " " << delta_f << std::endl;
|
||||
}
|
||||
void adaptive_dfe_impl::insert_sample(gr_complex z) {
|
||||
// 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;
|
||||
|
||||
// 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<tag_t> v;
|
||||
|
|
|
@ -53,7 +53,11 @@ private:
|
|||
std::size_t _sample_counter;
|
||||
|
||||
std::vector<gr::digital::constellation_sptr> _constellations;
|
||||
std::vector<float> _npwr;
|
||||
std::vector<int> _npwr_counter;
|
||||
int _npwr_max_time_constant;
|
||||
int _constellation_index;
|
||||
std::vector<gr_complex> _samples;
|
||||
std::vector<gr_complex> _symbols;
|
||||
std::vector<gr_complex> _scramble;
|
||||
std::vector<gr_complex> _descrambled_symbols;
|
||||
|
@ -83,6 +87,8 @@ public:
|
|||
int nB, // number of forward FIR taps
|
||||
int nF, // number of backward FIR taps
|
||||
int nW, // number of symbol taps
|
||||
float mu,
|
||||
float alpha,
|
||||
std::string physical_layer_description);
|
||||
virtual ~adaptive_dfe_impl();
|
||||
|
||||
|
@ -96,6 +102,9 @@ public:
|
|||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
|
||||
virtual void set_mu(float mu) { _mu = mu; }
|
||||
virtual void set_mode(std::string);
|
||||
|
||||
} ;
|
||||
|
||||
} // namespace digitalhf
|
||||
|
|
|
@ -6,7 +6,7 @@ from gnuradio import digital
|
|||
class PhysicalLayer(object):
|
||||
"""Physical layer description for STANAG 4285"""
|
||||
|
||||
def __init__(self, mode=1):
|
||||
def __init__(self, mode=0):
|
||||
"""For STANAG 4258 the mode has to be set manually: mode=0 -> BPSK, mode=1 -> QPSK, mode=2 -> 8PSK"""
|
||||
self._constellations = [PhysicalLayer.make_psk(2, [0,1]),
|
||||
PhysicalLayer.make_psk(4, [0,1,3,2]),
|
||||
|
@ -18,7 +18,8 @@ class PhysicalLayer(object):
|
|||
|
||||
def set_mode(self, mode):
|
||||
"""For STANAG 4258 the mode has to be set manually: mode=0 -> BPSK, mode=1 -> QPSK, mode=2 -> 8PSK"""
|
||||
self._data[1] = mode
|
||||
print('set_mode', mode)
|
||||
self._data[1] = int(mode)
|
||||
|
||||
def get_constellations(self):
|
||||
return self._constellations
|
||||
|
@ -28,22 +29,30 @@ class PhysicalLayer(object):
|
|||
print('-------------------- get_frame --------------------',self._counter)
|
||||
return self._preamble if self._counter == 0 else self._data
|
||||
|
||||
def get_doppler(self, s):
|
||||
def get_doppler(self, sy, sa):
|
||||
"""used for doppler shift update, for determining which frame to provide next,
|
||||
and for stopping at end of data/when the signal quality is too low"""
|
||||
print('-------------------- get_doppler --------------------',self._counter)
|
||||
success,doppler = self.quality_preamble(s) if self._counter == 0 else self.quality_data(s)
|
||||
and for stopping at end of data/when the signal quality is too low
|
||||
sy ... equalized symbols; sa ... samples"""
|
||||
print('-------------------- get_doppler --------------------',self._counter,len(sy),len(sa))
|
||||
success,doppler = self.quality_preamble(sy,sa) if self._counter == 0 else self.quality_data(sy)
|
||||
self._counter = (self._counter+1)&1 if success else 0
|
||||
self._is_first_frame = not success
|
||||
return success,doppler
|
||||
|
||||
def quality_preamble(self, s):
|
||||
def quality_preamble(self, sy, sa):
|
||||
sps = 5
|
||||
zp = [x for x in self._preamble[0]['symb'][9:40] for i in range(sps)]
|
||||
cc = np.array([np.sum(sa[ i*5:(31+i)*5]*zp) for i in range(49)])
|
||||
imax = np.argmax(np.abs(cc[0:18]))
|
||||
pks = cc[(imax,imax+15,imax+16,imax+31),]
|
||||
apks = np.abs(pks)
|
||||
test = np.mean(apks[(0,3),]) > 2*np.mean(apks[(1,2),])
|
||||
doppler = np.diff(np.unwrap(np.angle(pks[(0,3),])))[0]/31 if test else 0
|
||||
idx = range(80)
|
||||
if self._is_first_frame:
|
||||
idx = range(30,80)
|
||||
z = s[idx]*np.conj(self._preamble[0]['symb'][idx])
|
||||
idx = range(30,80)
|
||||
z = sy[idx]*np.conj(self._preamble[0]['symb'][idx])
|
||||
success = np.sum(np.real(z)<0) < 30
|
||||
doppler = PhysicalLayer.data_aided_frequency_estimation(s[idx], self._preamble[0]['symb'][idx])
|
||||
return success,doppler
|
||||
|
||||
def quality_data(self, s):
|
||||
|
|
Loading…
Reference in a new issue