[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 03/06: gr-dtv: Vastly improved OFDM symbol
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 03/06: gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver. |
Date: |
Sun, 27 Dec 2015 21:43:03 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 761b62d4660a121c78b6a7ad17fd7b08badcbb88
Author: flarroca <address@hidden>
Date: Wed Dec 9 18:38:38 2015 -0800
gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver.
---
gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc | 178 +++++++++++-----------
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 84b20f9..abef1d0 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 e7b92cb..0964361 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 */
+
- [Commit-gnuradio] [gnuradio] branch master updated (cf67421 -> 7278728), git, 2015/12/27
- [Commit-gnuradio] [gnuradio] 05/06: Merge remote-tracking branch 'mmueller/blocks_repeat_add_dynamic_interp', git, 2015/12/27
- [Commit-gnuradio] [gnuradio] 02/06: Provided thread safety to dynamic repeat, git, 2015/12/27
- [Commit-gnuradio] [gnuradio] 01/06: repeat: Adding dynamic interpolation, git, 2015/12/27
- [Commit-gnuradio] [gnuradio] 06/06: Merge remote-tracking branch 'drmpeg/dvbt-ofdm-fix', git, 2015/12/27
- [Commit-gnuradio] [gnuradio] 03/06: gr-dtv: Vastly improved OFDM symbol acquisition for DVB-T receiver.,
git <=
- [Commit-gnuradio] [gnuradio] 04/06: Merge branch 'maint', git, 2015/12/27