diff options
author | flarroca <flarroca@fing.edu.uy> | 2015-12-09 18:38:38 -0800 |
---|---|---|
committer | Ron Economos <w6rz@comcast.net> | 2015-12-09 18:38:38 -0800 |
commit | 761b62d4660a121c78b6a7ad17fd7b08badcbb88 (patch) | |
tree | b6a61e08188fe3e3fdb54347fe6c6f453480fb16 | |
parent | a463feccf7e6c3687b3588a5c6be5f8854c2de1e (diff) |
gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver.
-rw-r--r-- | gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc | 178 | ||||
-rw-r--r-- | gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h | 21 |
2 files changed, 102 insertions, 97 deletions
diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc index 84b20f9ad4..abef1d0510 100644 --- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc @@ -34,12 +34,12 @@ namespace gr { namespace dtv { int - dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha) + dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float alpha) { d_avg_alpha = alpha; d_threshold_factor_rise = threshold_factor_rise; - d_threshold_factor_fall = threshold_factor_fall; - d_avg = 0; + d_avg_max = - (float)INFINITY; + d_avg_min = (float)INFINITY; return (0); } @@ -47,56 +47,50 @@ namespace gr { int dvbt_ofdm_sym_acquisition_impl::peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max) { - int state = 0; - float peak_val = -(float)INFINITY; int peak_index = 0; int peak_pos_length = 0; + unsigned int peak_index = 0; + int peak_pos_length = 0; - int i = 0; + volk_32f_index_max_16u(&peak_index, &datain[0], datain_length); - while(i < datain_length) { - if (state == 0) { - if (datain[i] > d_avg * d_threshold_factor_rise) { - state = 1; - } - else { - d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; - i++; - } + peak_pos_length = 1; + if (datain_length >= d_fft_length) { + float min = datain[(peak_index + d_fft_length / 2) % d_fft_length]; + if (d_avg_min == (float)INFINITY) { + d_avg_min = min; } - else if (state == 1) { - if (datain[i] > peak_val) { - peak_val = datain[i]; - peak_index = i; - d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg; - i++; - } - else if (datain[i] > d_avg * d_threshold_factor_fall) { - d_avg = (d_avg_alpha) * datain[i] + (1 - d_avg_alpha) * d_avg; - i++; - } - else { - peak_pos[peak_pos_length] = peak_index; - peak_pos_length++; - state = 0; - peak_val = - (float)INFINITY; - } + else { + d_avg_min = d_avg_alpha * min + (1 - d_avg_alpha) * d_avg_min; } } - // Find peak of peaks - if (peak_pos_length) { - float max = datain[peak_pos[0]]; - int maxi = 0; + if (d_avg_max == -(float)INFINITY) { + // Initialize d_avg_max with the first value. + d_avg_max = datain[peak_index]; + } + else if (datain[peak_index] > d_avg_max - d_threshold_factor_rise * (d_avg_max-d_avg_min)) { + d_avg_max = d_avg_alpha * datain[peak_index] + (1 - d_avg_alpha) * d_avg_max; + } + else { + peak_pos_length = 0; + } - for (int i = 1; i < peak_pos_length; i++) { - if (datain[peak_pos[i]] > max) { - max = datain[peak_pos[i]]; - maxi = i; - } + // We now check whether the peak is in the border of the search interval. This would mean that + // the search interval is not correct, and it should be re-set. This happens for instance when the + // hardware dropped some samples. + // Our definition of "border of the search interval" depends if the search interval is "big" or not. + if (datain_length < d_fft_length) { + if ((peak_index == 0) || (peak_index == (unsigned int)datain_length - 1)) { + peak_pos_length = 0; + } + } + else { + if ((peak_index < 5) || (peak_index > (unsigned int)datain_length - 5)) { + peak_pos_length = 0; } - - *peak_max = maxi; } + peak_pos[0] = peak_index; + *peak_max = 0; return (peak_pos_length); } @@ -119,7 +113,8 @@ namespace gr { volk_32fc_magnitude_squared_32f(&d_norm[low], &in[low], size); // Calculate gamma on each point - low = lookup_stop - d_cp_length + 1; + // TODO check these boundaries!!!!!!! + low = lookup_stop - (d_cp_length - 1); size = lookup_start - low + 1; volk_32fc_x2_multiply_conjugate_32fc(&d_corr[low - d_fft_length], &in[low], &in[low - d_fft_length], size); @@ -220,6 +215,12 @@ namespace gr { this->add_item_tag(0, offset, key, value); } + // Derotates the signal + void dvbt_ofdm_sym_acquisition_impl::derotate(const gr_complex * in, gr_complex * out) + { + volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[0], d_fft_length); + } + dvbt_ofdm_sym_acquisition::sptr dvbt_ofdm_sym_acquisition::make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr) { @@ -234,11 +235,10 @@ namespace gr { : block("dvbt_ofdm_sym_acquisition", io_signature::make(1, 1, sizeof (gr_complex) * blocks), io_signature::make(1, 1, sizeof (gr_complex) * blocks * fft_length)), - d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr), - d_index(0), d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_count(0), d_nextphaseinc(0), d_nextpos(0), \ - d_sym_acq_count(0),d_sym_acq_timeout(100), d_initial_acquisition(0), \ - d_freq_correction_count(0), d_freq_correction_timeout(0), d_cp_start(0), \ - d_to_consume(0), d_to_out(0) + d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr), \ + d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_nextphaseinc(0), d_nextpos(0), \ + d_initial_acquisition(0), d_cp_start(0), \ + d_to_consume(0), d_to_out(0), d_consumed(0), d_out(0) { set_relative_rate(1.0 / (double) (d_cp_length + d_fft_length)); @@ -296,7 +296,7 @@ namespace gr { exit(1); } - peak_detect_init(0.8, 0.9, 30, 0.9); + peak_detect_init(0.3, 0.9); } /* @@ -319,7 +319,7 @@ namespace gr { // make sure we receive at least (symbol_length + fft_length) for (int i = 0; i < ninputs; i++) { - ninput_items_required[i] = (2 * d_fft_length + d_cp_length) * noutput_items; + ninput_items_required[i] = (d_cp_length + d_fft_length) * (noutput_items + 1); } } @@ -336,45 +336,52 @@ namespace gr { { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - - int low, size; - - // This is initial acquisition of symbol start - // TODO - make a FSM - if (!d_initial_acquisition) { - d_initial_acquisition = ml_sync(in, 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \ - &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); - - // Send sync_start downstream - send_sync_start(); - } - - // This is fractional frequency correction (pre FFT) - // It is also called coarse frequency correction - if (d_initial_acquisition) { - d_cp_found = ml_sync(in, d_cp_start + 16, d_cp_start, \ - &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); + int low; + + d_consumed = 0; + d_out = 0; + + for (int i = 0; i < noutput_items; i++) { + // This is initial acquisition of symbol start + // TODO - make a FSM + if (!d_initial_acquisition) { + d_initial_acquisition = ml_sync(&in[d_consumed], 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); + d_cp_found = d_initial_acquisition; + } + else { + // If we are here it means that in the previous iteration we found the CP. We + // now thus only search near it. + d_cp_found = ml_sync(&in[d_consumed], d_cp_start + 8, std::max(d_cp_start - 8, d_cp_length+d_fft_length - 1), \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out); + if (!d_cp_found) { + // We may have not found the CP because the smaller search range was too small (rare, but possible). + // We re-try with the whole search range. + d_cp_found = ml_sync(&in[d_consumed], 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \ + &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out ); + } + } if (d_cp_found) { - d_freq_correction_count = 0; - - // Derotate the signal and out - low = d_cp_start - d_fft_length + 1; - size = d_cp_start - (d_cp_start - d_fft_length + 1) + 1; - - volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[low], size); + low = d_consumed + d_cp_start - d_fft_length + 1; + derotate(&in[low], &out[i * d_fft_length]); } else { - // If we have a number of consecutive misses then we restart acquisition - if (++d_freq_correction_count > d_freq_correction_timeout) { - d_initial_acquisition = 0; - d_freq_correction_count = 0; - - // Restart with a half number so that we'll not endup with the same situation - // This will prevent peak_detect to not detect anything - d_to_consume = d_to_consume / 2; - } + // Send sync_start downstream + send_sync_start(); + d_initial_acquisition = 0; + + // Restart wit a half number so that we'll not end up with the same situation + // This will prevent peak_detect to not detect anything + d_to_consume = d_to_consume / 2; + d_consumed += d_to_consume; + consume_each(d_consumed); + + // Tell runtime system how many output items we produced. + return (d_out); } + d_consumed += d_to_consume; + d_out += d_to_out; } // Tell runtime system how many input items we consumed on @@ -386,3 +393,4 @@ namespace gr { } } /* namespace dtv */ } /* namespace gr */ + diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h index e7b92cbd41..0964361b1e 100644 --- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h +++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h @@ -35,8 +35,6 @@ namespace gr { float d_snr; float d_rho; - int d_index; - gr_complex * d_conj; float * d_norm; gr_complex * d_corr; @@ -45,37 +43,35 @@ namespace gr { // For peak detector float d_threshold_factor_rise; - float d_threshold_factor_fall; float d_avg_alpha; - float d_avg; + float d_avg_min; + float d_avg_max; float d_phase; double d_phaseinc; int d_cp_found; - int d_count; double d_nextphaseinc; int d_nextpos; - int d_sym_acq_count; - int d_sym_acq_timeout; - int d_initial_acquisition; - int d_freq_correction_count; - int d_freq_correction_timeout; - int d_cp_start; gr_complex * d_derot; int d_to_consume; int d_to_out; + int d_consumed; + int d_out; int ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out); - int peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha); + int peak_detect_init(float threshold_factor_rise, float alpha); int peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max); void send_sync_start(); + + void derotate(const gr_complex * in, gr_complex *out); + public: dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr); ~dvbt_ofdm_sym_acquisition_impl(); @@ -92,3 +88,4 @@ namespace gr { } // namespace gr #endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H */ + |