summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/lib')
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am9
-rw-r--r--gnuradio-core/src/lib/general/general.i6
-rw-r--r--gnuradio-core/src/lib/general/gr_math.h13
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_correlator.cc231
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc223
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h (renamed from gnuradio-core/src/lib/general/gr_ofdm_correlator.h)57
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i (renamed from gnuradio-core/src/lib/general/gr_ofdm_correlator.i)28
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc79
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h17
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i6
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc4
-rw-r--r--gnuradio-core/src/lib/general/gr_ofdm_sampler.cc18
-rw-r--r--gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc106
-rw-r--r--gnuradio-core/src/lib/general/gr_peak_detector2_fb.h108
-rw-r--r--gnuradio-core/src/lib/general/gr_peak_detector2_fb.i45
15 files changed, 643 insertions, 307 deletions
diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am
index b466ad44b..cde6a7549 100644
--- a/gnuradio-core/src/lib/general/Makefile.am
+++ b/gnuradio-core/src/lib/general/Makefile.am
@@ -96,7 +96,7 @@ libgeneral_la_SOURCES = \
gr_nop.cc \
gr_null_sink.cc \
gr_null_source.cc \
- gr_ofdm_correlator.cc \
+ gr_ofdm_frame_acquisition.cc \
gr_ofdm_cyclic_prefixer.cc \
gr_ofdm_demapper_vcb.cc \
gr_ofdm_mapper_bcv.cc \
@@ -109,6 +109,7 @@ libgeneral_la_SOURCES = \
gr_ofdm_sampler.cc \
gr_pa_2x2_phase_combiner.cc \
gr_packet_sink.cc \
+ gr_peak_detector2_fb.cc \
gr_phase_modulator_fc.cc \
gr_pll_carriertracking_cc.cc \
gr_pll_freqdet_cf.cc \
@@ -239,7 +240,7 @@ grinclude_HEADERS = \
gr_nop.h \
gr_null_sink.h \
gr_null_source.h \
- gr_ofdm_correlator.h \
+ gr_ofdm_frame_acquisition.h \
gr_ofdm_cyclic_prefixer.h \
gr_ofdm_demapper_vcb.h \
gr_ofdm_mapper_bcv.h \
@@ -252,6 +253,7 @@ grinclude_HEADERS = \
gr_ofdm_sampler.h \
gr_pa_2x2_phase_combiner.h \
gr_packet_sink.h \
+ gr_peak_detector2_fb.h \
gr_phase_modulator_fc.h \
gr_pll_carriertracking_cc.h \
gr_pll_freqdet_cf.h \
@@ -383,7 +385,7 @@ swiginclude_HEADERS = \
gr_nop.i \
gr_null_sink.i \
gr_null_source.i \
- gr_ofdm_correlator.i \
+ gr_ofdm_frame_acquisition.i \
gr_ofdm_cyclic_prefixer.i \
gr_ofdm_demapper_vcb.i \
gr_ofdm_mapper_bcv.i \
@@ -396,6 +398,7 @@ swiginclude_HEADERS = \
gr_ofdm_sampler.i \
gr_pa_2x2_phase_combiner.i \
gr_packet_sink.i \
+ gr_peak_detector2_fb.i \
gr_phase_modulator_fc.i \
gr_pll_carriertracking_cc.i \
gr_pll_freqdet_cf.i \
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index e9780ea13..0eab24f1a 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -93,7 +93,7 @@
#include <gr_probe_avg_mag_sqrd_cf.h>
#include <gr_probe_avg_mag_sqrd_f.h>
#include <gr_probe_signal_f.h>
-#include <gr_ofdm_correlator.h>
+#include <gr_ofdm_frame_acquisition.h>
#include <gr_ofdm_cyclic_prefixer.h>
#include <gr_ofdm_bpsk_demapper.h>
#include <gr_ofdm_mapper_bcv.h>
@@ -128,6 +128,7 @@
#include <gr_bin_statistics_f.h>
#include <gr_glfsr_source_b.h>
#include <gr_glfsr_source_f.h>
+#include <gr_peak_detector2_fb.h>
%}
%include "gr_nop.i"
@@ -201,7 +202,7 @@
%include "gr_probe_avg_mag_sqrd_cf.i"
%include "gr_probe_avg_mag_sqrd_f.i"
%include "gr_probe_signal_f.i"
-%include "gr_ofdm_correlator.i"
+%include "gr_ofdm_frame_acquisition.i"
%include "gr_ofdm_cyclic_prefixer.i"
%include "gr_ofdm_bpsk_demapper.i"
%include "gr_ofdm_mapper_bcv.i"
@@ -236,3 +237,4 @@
%include "gr_bin_statistics_f.i"
%include "gr_glfsr_source_b.i"
%include "gr_glfsr_source_f.i"
+%include "gr_peak_detector2_fb.i"
diff --git a/gnuradio-core/src/lib/general/gr_math.h b/gnuradio-core/src/lib/general/gr_math.h
index 439e5f4b9..2cd5b8eb7 100644
--- a/gnuradio-core/src/lib/general/gr_math.h
+++ b/gnuradio-core/src/lib/general/gr_math.h
@@ -64,4 +64,17 @@ static inline float gr_fast_atan2f(gr_complex z)
return gr_fast_atan2f(z.imag(), z.real());
}
+
+/* This bounds x by +/- clip without a branch */
+
+static inline float gr_branchless_clip(float x, float clip)
+{
+ float x1 = fabsf(x+clip);
+ float x2 = fabsf(x-clip);
+ x1 -= x2;
+ return 0.5*x1;
+}
+
+
+
#endif /* _GR_MATH_H_ */
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc b/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
deleted file mode 100644
index e396eeb8e..000000000
--- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006, 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_ofdm_correlator.h>
-#include <gr_io_signature.h>
-#include <gr_expj.h>
-
-#define VERBOSE 0
-#define M_TWOPI (2*M_PI)
-#define MAX_NUM_SYMBOLS 1000
-
-gr_ofdm_correlator_sptr
-gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len)
-{
- return gr_ofdm_correlator_sptr (new gr_ofdm_correlator (occupied_carriers, fft_length, cplen,
- known_symbol1, known_symbol2,
- max_fft_shift_len));
-}
-
-gr_ofdm_correlator::gr_ofdm_correlator (unsigned occupied_carriers, unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len)
- : gr_block ("ofdm_correlator",
- gr_make_io_signature (1, 1, sizeof(gr_complex)*fft_length),
- gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char))),
- d_occupied_carriers(occupied_carriers),
- d_fft_length(fft_length),
- d_cplen(cplen),
- d_freq_shift_len(max_fft_shift_len),
- d_known_symbol1(known_symbol1),
- d_known_symbol2(known_symbol2),
- d_coarse_freq(0),
- d_phase_count(0)
-{
- d_diff_corr_factor.resize(d_occupied_carriers);
- d_hestimate.resize(d_occupied_carriers);
-
- std::vector<gr_complex>::iterator i1, i2;
-
- unsigned int i = 0, j = 0;
- gr_complex one(1.0, 0.0);
- for(i1 = d_known_symbol1.begin(), i2 = d_known_symbol2.begin(); i1 != d_known_symbol1.end(); i1++, i2++) {
- d_diff_corr_factor[i] = one / ((*i1) * conj(*i2));
- i++;
- }
-
- d_phase_lut = new gr_complex[(2*d_freq_shift_len+1) * MAX_NUM_SYMBOLS];
- for(i = 0; i <= 2*d_freq_shift_len; i++) {
- for(j = 0; j < MAX_NUM_SYMBOLS; j++) {
- d_phase_lut[j + i*MAX_NUM_SYMBOLS] = gr_expj(-M_TWOPI*d_cplen/d_fft_length*(i-d_freq_shift_len)*j);
- }
- }
-}
-
-gr_ofdm_correlator::~gr_ofdm_correlator(void)
-{
- delete [] d_phase_lut;
-}
-
-void
-gr_ofdm_correlator::forecast (int noutput_items, gr_vector_int &ninput_items_required)
-{
- unsigned ninputs = ninput_items_required.size ();
- for (unsigned i = 0; i < ninputs; i++)
- ninput_items_required[i] = 2;
-}
-
-gr_complex
-gr_ofdm_correlator::coarse_freq_comp(int freq_delta, int symbol_count)
-{
- // return gr_complex(cos(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count),
- // sin(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count));
-
- return gr_expj(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count);
-
- //assert(d_freq_shift_len + freq_delta >= 0);
- //assert(symbol_count <= MAX_NUM_SYMBOLS);
-
- //return d_phase_lut[MAX_NUM_SYMBOLS * (d_freq_shift_len + freq_delta) + symbol_count];
-}
-
-bool
-gr_ofdm_correlator::correlate(const gr_complex *previous, const gr_complex *current,
- int zeros_on_left)
-{
- unsigned int i = 0;
- int search_delta = 0;
- bool found = false;
-
- gr_complex h_sqrd = gr_complex(0.0,0.0);
- float power = 0.0F;
-
- while(!found && ((unsigned)abs(search_delta) <= d_freq_shift_len)) {
- h_sqrd = gr_complex(0.0,0.0);
- power = 0.0F;
-
- for(i = 0; i < d_occupied_carriers; i++) {
- h_sqrd = h_sqrd + previous[i+zeros_on_left+search_delta] *
- conj(coarse_freq_comp(search_delta,1)*current[i+zeros_on_left+search_delta]) *
- d_diff_corr_factor[i];
-
- power = power + norm(current[i+zeros_on_left+search_delta]); // No need to do coarse freq here
- }
-
-#if VERBOSE
- printf("bin %d\th_sqrd = ( %f, %f )\t power = %f\t real(h)/p = %f\t angle = %f\n",
- search_delta, h_sqrd.real(), h_sqrd.imag(), power, h_sqrd.real()/power, arg(h_sqrd));
-#endif
- // FIXME: Look at h_sqrd.read() > power
- if((h_sqrd.real() > 0.82*power) && (h_sqrd.real() < 1.1 * power)) {
- found = true;
- //printf("search delta: %d\n", search_delta);
- d_coarse_freq = search_delta;
- d_phase_count = 1;
- //d_snr_est = 10*log10(power/(power-h_sqrd.real()));
-
- // check for low noise power; sets maximum SNR at 100 dB
- if(fabs(h_sqrd.imag()) <= 1e-12) {
- d_snr_est = 100.0;
- }
- else {
- d_snr_est = 10*log10(fabs(h_sqrd.real()/h_sqrd.imag()));
- }
-
-#if VERBOSE
- printf("CORR: Found, bin %d\tSNR Est %f dB\tcorr power fraction %f\n",
- search_delta, d_snr_est, h_sqrd.real()/power);
-#endif
-
- // search_delta,10*log10(h_sqrd.real()/fabs(h_sqrd.imag())),h_sqrd.real()/power);
- break;
- }
- else {
- if(search_delta <= 0)
- search_delta = (-search_delta) + 2;
- else
- search_delta = -search_delta;
- }
- }
- return found;
-}
-
-void
-gr_ofdm_correlator::calculate_equalizer(const gr_complex *previous, const gr_complex *current,
- int zeros_on_left)
-{
- unsigned int i=0;
-
- for(i = 0; i < d_occupied_carriers; i++) {
- // FIXME possibly add small epsilon in divisor to protect from div 0
- //d_hestimate[i] = 0.5F * (d_known_symbol1[i] / previous[i+zeros_on_left] +
- // d_known_symbol2[i] / (coarse_freq_comp(d_coarse_freq,1)*
- // current[i+zeros_on_left+d_coarse_freq]));
- d_hestimate[i] = 0.5F * (d_known_symbol1[i] / previous[i+zeros_on_left+d_coarse_freq] +
- d_known_symbol2[i] / (coarse_freq_comp(d_coarse_freq,1)*
- current[i+zeros_on_left+d_coarse_freq]));
- }
-#if VERBOSE
- fprintf(stderr, "\n");
-#endif
-}
-
-int
-gr_ofdm_correlator::general_work(int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
- const gr_complex *in = (const gr_complex *)input_items[0];
- const gr_complex *previous = &in[0];
- const gr_complex *current = &in[d_fft_length];
-
- gr_complex *out = (gr_complex *) output_items[0];
- char *sig = (char *) output_items[1];
-
- unsigned int i=0;
-
- int unoccupied_carriers = d_fft_length - d_occupied_carriers;
- int zeros_on_left = (int)ceil(unoccupied_carriers/2.0);
-
- bool corr = correlate(previous, current, zeros_on_left);
- if(corr) {
- calculate_equalizer(previous, current, zeros_on_left);
- sig[0] = 1;
- }
- else {
- sig[0] = 0;
- }
-
- for(i = 0; i < d_occupied_carriers; i++) {
- out[i] = d_hestimate[i]*coarse_freq_comp(d_coarse_freq,d_phase_count)*current[i+zeros_on_left+d_coarse_freq];
- }
-
-
- d_phase_count++;
- if(d_phase_count == MAX_NUM_SYMBOLS) {
- d_phase_count = 1;
- }
-
- consume_each(1);
- return 1;
-}
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
new file mode 100644
index 000000000..0fa6a3d3e
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
@@ -0,0 +1,223 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006, 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_ofdm_frame_acquisition.h>
+#include <gr_io_signature.h>
+#include <gr_expj.h>
+#include <gr_math.h>
+
+#define VERBOSE 0
+#define M_TWOPI (2*M_PI)
+#define MAX_NUM_SYMBOLS 1000
+
+gr_ofdm_frame_acquisition_sptr
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len)
+{
+ return gr_ofdm_frame_acquisition_sptr (new gr_ofdm_frame_acquisition (occupied_carriers, fft_length, cplen,
+ known_symbol, max_fft_shift_len));
+}
+
+gr_ofdm_frame_acquisition::gr_ofdm_frame_acquisition (unsigned occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len)
+ : gr_block ("ofdm_frame_acquisition",
+ gr_make_io_signature2 (2, 2, sizeof(gr_complex)*fft_length, sizeof(char)),
+ gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char))),
+ d_occupied_carriers(occupied_carriers),
+ d_fft_length(fft_length),
+ d_cplen(cplen),
+ d_freq_shift_len(max_fft_shift_len),
+ d_known_symbol(known_symbol),
+ d_coarse_freq(0),
+ d_phase_count(0)
+{
+ d_symbol_phase_diff.resize(d_fft_length);
+ d_known_phase_diff.resize(d_occupied_carriers);
+ d_hestimate.resize(d_occupied_carriers);
+
+ unsigned int i = 0, j = 0;
+
+ std::fill(d_known_phase_diff.begin(), d_known_phase_diff.end(), 0);
+ for(i = 0; i < d_known_symbol.size()-2; i+=2) {
+ d_known_phase_diff[i] = fabs(gr_fast_atan2f(d_known_symbol[i]) - gr_fast_atan2f(d_known_symbol[i+2]));
+ }
+
+ d_phase_lut = new gr_complex[(2*d_freq_shift_len+1) * MAX_NUM_SYMBOLS];
+ for(i = 0; i <= 2*d_freq_shift_len; i++) {
+ for(j = 0; j < MAX_NUM_SYMBOLS; j++) {
+ d_phase_lut[j + i*MAX_NUM_SYMBOLS] = gr_expj(-M_TWOPI*d_cplen/d_fft_length*(i-d_freq_shift_len)*j);
+ }
+ }
+}
+
+gr_ofdm_frame_acquisition::~gr_ofdm_frame_acquisition(void)
+{
+ delete [] d_phase_lut;
+}
+
+void
+gr_ofdm_frame_acquisition::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ unsigned ninputs = ninput_items_required.size ();
+ for (unsigned i = 0; i < ninputs; i++)
+ ninput_items_required[i] = 1;
+}
+
+gr_complex
+gr_ofdm_frame_acquisition::coarse_freq_comp(int freq_delta, int symbol_count)
+{
+ // return gr_complex(cos(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count),
+ // sin(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count));
+
+ return gr_expj(-M_TWOPI*freq_delta*d_cplen/d_fft_length*symbol_count);
+
+ //return d_phase_lut[MAX_NUM_SYMBOLS * (d_freq_shift_len + freq_delta) + symbol_count];
+}
+
+
+
+bool
+gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int zeros_on_left)
+{
+ unsigned int i = 0, j = 0;
+
+ std::fill(d_symbol_phase_diff.begin(), d_symbol_phase_diff.end(), 0);
+ for(i = 0; i < d_fft_length-2; i++) {
+ d_symbol_phase_diff[i] = fabs(gr_fast_atan2f(symbol[i]) - gr_fast_atan2f(symbol[i+2]));
+ }
+
+ int index = 0;
+ float max = 0, sum=0;
+ for(i = zeros_on_left - d_freq_shift_len; i < zeros_on_left + d_freq_shift_len; i+=2) {
+ sum = 0;
+ for(j = 0; j < d_occupied_carriers; j++) {
+ sum += (d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
+ }
+ if(fabs(sum) > max) {
+ max = sum;
+ index = i;
+ }
+ }
+
+ d_coarse_freq = index - zeros_on_left;
+
+ if(VERBOSE) {
+ fprintf(stderr, "Coarse Freq Offset: %d\n", d_coarse_freq);
+ for(i = 0; i < 40; i++) {
+ fprintf(stderr, "%+.4f %+.4f\n", d_known_phase_diff[i],
+ d_symbol_phase_diff[zeros_on_left+d_coarse_freq+i]);
+ }
+ }
+
+ return true; //FIXME: don't need ot return anything now
+}
+
+void
+gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, int zeros_on_left)
+{
+ unsigned int i=0;
+
+ // Set first tap of equalizer
+ d_hestimate[0] = d_known_symbol[0] /
+ (coarse_freq_comp(d_coarse_freq,1)*symbol[zeros_on_left+d_coarse_freq]);
+
+ // set every even tap based on known symbol
+ // linearly interpolate between set carriers to set zero-filled carriers
+ // FIXME: is this the best way to set this?
+ for(i = 2; i < d_occupied_carriers; i+=2) {
+ d_hestimate[i] = d_known_symbol[i] /
+ (coarse_freq_comp(d_coarse_freq,1)*(symbol[i+zeros_on_left+d_coarse_freq]));
+ d_hestimate[i-1] = (d_hestimate[i] + d_hestimate[i-2]) / gr_complex(2.0, 0.0);
+ }
+
+ // with even number of carriers; last equalizer tap is wrong
+ if(!(d_occupied_carriers & 1)) {
+ d_hestimate[d_occupied_carriers-1] = d_hestimate[d_occupied_carriers-2];
+ }
+
+ if(VERBOSE) {
+ fprintf(stderr, "Equalizer setting:\n");
+ for(i = 0; i < d_occupied_carriers; i++) {
+ gr_complex sym = coarse_freq_comp(d_coarse_freq,1)*symbol[i+zeros_on_left+d_coarse_freq];
+ gr_complex output = sym * d_hestimate[i];
+ fprintf(stderr, "sym: %+.4f + j%+.4f ks: %+.4f + j%+.4f eq: %+.4f + j%+.4f ==> %+.4f + j%+.4f\n",
+ sym .real(), sym.imag(),
+ d_known_symbol[i].real(), d_known_symbol[i].imag(),
+ d_hestimate[i].real(), d_hestimate[i].imag(),
+ output.real(), output.imag());
+ }
+ fprintf(stderr, "\n");
+ }
+}
+
+int
+gr_ofdm_frame_acquisition::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *symbol = (const gr_complex *)input_items[0];
+ const char *trigger = (const char *)input_items[1];
+
+ gr_complex *out = (gr_complex *) output_items[0];
+ char *sig = (char *) output_items[1];
+
+ int unoccupied_carriers = d_fft_length - d_occupied_carriers;
+ int zeros_on_left = (int)ceil(unoccupied_carriers/2.0);
+
+ int found = 0;
+ for(int i = 0; i < ninput_items[1]; i++) {
+ found += trigger[i];
+ }
+
+ if(found) {
+ d_phase_count = 1;
+ correlate(symbol, zeros_on_left);
+ calculate_equalizer(symbol, zeros_on_left);
+ sig[0] = 1;
+ }
+ else {
+ sig[0] = 0;
+ }
+
+ for(unsigned int i = 0; i < d_occupied_carriers; i++) {
+ out[i] = d_hestimate[i]*coarse_freq_comp(d_coarse_freq,d_phase_count)
+ *symbol[i+zeros_on_left+d_coarse_freq];
+ }
+
+ d_phase_count++;
+ if(d_phase_count == MAX_NUM_SYMBOLS) {
+ d_phase_count = 1;
+ }
+
+ consume(0,1);
+ consume(1,ninput_items[1]);
+ return 1;
+}
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
index 55ee4e190..af63f3e4c 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.h
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
@@ -20,22 +20,21 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef INCLUDED_GR_OFDM_CORRELATOR_H
-#define INCLUDED_GR_OFDM_CORRELATOR_H
+#ifndef INCLUDED_GR_OFDM_FRAME_ACQUISITION_H
+#define INCLUDED_GR_OFDM_FRAME_ACQUISITION_H
#include <gr_block.h>
#include <vector>
-class gr_ofdm_correlator;
-typedef boost::shared_ptr<gr_ofdm_correlator> gr_ofdm_correlator_sptr;
+class gr_ofdm_frame_acquisition;
+typedef boost::shared_ptr<gr_ofdm_frame_acquisition> gr_ofdm_frame_acquisition_sptr;
-gr_ofdm_correlator_sptr
-gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len=10);
+gr_ofdm_frame_acquisition_sptr
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len=10);
/*!
* \brief take a vector of complex constellation points in from an FFT
@@ -54,7 +53,7 @@ gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length
* distortion caused by the channel.
*/
-class gr_ofdm_correlator : public gr_block
+class gr_ofdm_frame_acquisition : public gr_block
{
/*!
* \brief Build an OFDM correlator and equalizer.
@@ -68,35 +67,33 @@ class gr_ofdm_correlator : public gr_block
* for phase changes between symbols.
* \param max_fft_shift_len Set's the maximum distance you can look between bins for correlation
*/
- friend gr_ofdm_correlator_sptr
- gr_make_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len);
+ friend gr_ofdm_frame_acquisition_sptr
+ gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len);
- protected:
- gr_ofdm_correlator (unsigned int occupied_carriers, unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len);
+protected:
+ gr_ofdm_frame_acquisition (unsigned int occupied_carriers, unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len);
private:
unsigned char slicer(gr_complex x);
- bool correlate(const gr_complex *previous, const gr_complex *current, int zeros_on_left);
- void calculate_equalizer(const gr_complex *previous,
- const gr_complex *current, int zeros_on_left);
+ bool correlate(const gr_complex *symbol, int zeros_on_left);
+ void calculate_equalizer(const gr_complex *symbol, int zeros_on_left);
gr_complex coarse_freq_comp(int freq_delta, int count);
unsigned int d_occupied_carriers; // !< \brief number of subcarriers with data
unsigned int d_fft_length; // !< \brief length of FFT vector
unsigned int d_cplen; // !< \brief length of cyclic prefix in samples
unsigned int d_freq_shift_len; // !< \brief number of surrounding bins to look at for correlation
- std::vector<gr_complex> d_known_symbol1, d_known_symbol2; // !< \brief known symbols at start of frame
- std::vector<gr_complex> d_diff_corr_factor; // !< \brief factor used in correlation
+ std::vector<gr_complex> d_known_symbol; // !< \brief known symbols at start of frame
+ std::vector<float> d_known_phase_diff; // !< \brief factor used in correlation from known symbol
+ std::vector<float> d_symbol_phase_diff; // !< \brief factor used in correlation from received symbol
std::vector<gr_complex> d_hestimate; // !< channel estimate
- signed int d_coarse_freq; // !< \brief search distance in number of bins
+ int d_coarse_freq; // !< \brief search distance in number of bins
unsigned int d_phase_count; // !< \brief accumulator for coarse freq correction
float d_snr_est; // !< an estimation of the signal to noise ratio
@@ -110,7 +107,7 @@ class gr_ofdm_correlator : public gr_block
*/
float snr() { return d_snr_est; }
- ~gr_ofdm_correlator(void);
+ ~gr_ofdm_frame_acquisition(void);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_correlator.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
index 2e39e2150..0fd0bc58b 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_correlator.i
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
@@ -22,25 +22,23 @@
#include <vector>
-GR_SWIG_BLOCK_MAGIC(gr,ofdm_correlator);
+GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_acquisition);
-gr_ofdm_correlator_sptr
-gr_make_ofdm_correlator (unsigned int occupied_carriers,
- unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len=4);
+gr_ofdm_frame_acquisition_sptr
+gr_make_ofdm_frame_acquisition (unsigned int occupied_carriers,
+ unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len=4);
-class gr_ofdm_correlator : public gr_sync_decimator
+class gr_ofdm_frame_acquisition : public gr_sync_decimator
{
protected:
- gr_ofdm_correlator (unsigned int occupied_carriers,
- unsigned int fft_length,
- unsigned int cplen,
- const std::vector<gr_complex> &known_symbol1,
- const std::vector<gr_complex> &known_symbol2,
- unsigned int max_fft_shift_len);
+ gr_ofdm_frame_acquisition (unsigned int occupied_carriers,
+ unsigned int fft_length,
+ unsigned int cplen,
+ const std::vector<gr_complex> &known_symbol,
+ unsigned int max_fft_shift_len);
public:
float snr() { return d_snr_est; }
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
index d75b693a2..a1ac66ff7 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc
@@ -26,8 +26,12 @@
#include <gr_ofdm_frame_sink.h>
#include <gr_io_signature.h>
+#include <gr_expj.h>
+#include <gr_math.h>
+#include <math.h>
#include <cstdio>
#include <stdexcept>
+#include <iostream>
#define VERBOSE 0
@@ -55,6 +59,11 @@ gr_ofdm_frame_sink::enter_have_sync()
d_header = 0;
d_headerbytelen_cnt = 0;
+
+ // Resetting PLL
+ d_freq = 0.0;
+ d_phase = 0.0;
+ fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
}
inline void
@@ -96,7 +105,11 @@ unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
unsigned char *out)
{
unsigned int i=0, bytes_produced=0;
+ gr_complex carrier;
+
+ carrier=gr_expj(d_phase);
+ gr_complex accum_error = 0.0;
while(i < d_occupied_carriers) {
if(d_nresid > 0) {
d_partial_byte |= d_resid;
@@ -106,8 +119,23 @@ unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
}
while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
- //fprintf(stderr, "%f+j%f = %d\n", in[i].real(), in[i].imag(), slicer(in[i]));
- unsigned char bits = slicer(in[i++]);
+ gr_complex sigrot = in[i]*carrier*d_dfe[i];
+
+ if(d_derotated_output != NULL){
+ d_derotated_output[i] = sigrot;
+ }
+
+ unsigned char bits = slicer(sigrot);
+
+ gr_complex closest_sym = d_sym_position[bits];
+
+ accum_error += sigrot * conj(closest_sym);
+
+ // FIX THE FOLLOWING STATEMENT
+ if (norm(sigrot)> 0.001) d_dfe[i] += d_eq_gain*(closest_sym/sigrot-d_dfe[i]);
+
+ i++;
+
if((8 - d_byte_offset) >= d_nbits) {
d_partial_byte |= bits << (d_byte_offset);
d_byte_offset += d_nbits;
@@ -130,7 +158,18 @@ unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
d_partial_byte = 0;
}
}
+ //std::cerr << "accum_error " << accum_error << std::endl;
+
+ float angle = arg(accum_error);
+ d_freq = d_freq - d_freq_gain*angle;
+ d_phase = d_phase + d_freq - d_phase_gain*angle;
+ if (d_phase >= 2*M_PI) d_phase -= 2*M_PI;
+ if (d_phase <0) d_phase += 2*M_PI;
+
+ //if(VERBOSE)
+ // std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << std::endl;
+
return bytes_produced;
}
@@ -138,24 +177,30 @@ unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
gr_ofdm_frame_sink_sptr
gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_carriers)
+ gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
+ float phase_gain, float freq_gain)
{
return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(sym_position, sym_value_out,
- target_queue, occupied_carriers));
+ target_queue, occupied_carriers,
+ phase_gain, freq_gain));
}
gr_ofdm_frame_sink::gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_carriers)
+ gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
+ float phase_gain, float freq_gain)
: gr_sync_block ("ofdm_frame_sink",
gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)),
- gr_make_io_signature (0, 0, 0)),
+ gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)),
d_target_queue(target_queue), d_occupied_carriers(occupied_carriers),
d_byte_offset(0), d_partial_byte(0),
- d_resid(0), d_nresid(0)
+ d_resid(0), d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain),
+ d_eq_gain(0.05)
{
d_bytes_out = new unsigned char[d_occupied_carriers];
+ d_dfe.resize(occupied_carriers);
+ fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0));
set_sym_value_out(sym_position, sym_value_out);
@@ -179,7 +224,7 @@ gr_ofdm_frame_sink::set_sym_value_out(const std::vector<gr_complex> &sym_positio
d_sym_position = sym_position;
d_sym_value_out = sym_value_out;
- d_nbits = (unsigned long)(log10(d_sym_value_out.size()) / log10(2));
+ d_nbits = (unsigned long)ceil(log10(d_sym_value_out.size()) / log10(2.0));
return true;
}
@@ -194,12 +239,16 @@ gr_ofdm_frame_sink::work (int noutput_items,
const char *sig = (const char *) input_items[1];
unsigned int j = 0;
unsigned int bytes=0;
+
+ // If the output is connected, send it the derotated symbols
+ if(output_items.size() >= 1)
+ d_derotated_output = (gr_complex *)output_items[0];
+ else
+ d_derotated_output = NULL;
if (VERBOSE)
fprintf(stderr,">>> Entering state machine\n");
-
- bytes = demapper(&in[0], d_bytes_out);
-
+
switch(d_state) {
case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt
@@ -212,6 +261,10 @@ gr_ofdm_frame_sink::work (int noutput_items,
break;
case STATE_HAVE_SYNC:
+ // only demod after getting the preamble signal; otherwise, the
+ // equalizer taps will screw with the PLL performance
+ bytes = demapper(&in[0], d_bytes_out);
+
if (VERBOSE) {
if(sig[0])
printf("ERROR -- Found SYNC in HAVE_SYNC\n");
@@ -258,6 +311,8 @@ gr_ofdm_frame_sink::work (int noutput_items,
break;
case STATE_HAVE_HEADER:
+ bytes = demapper(&in[0], d_bytes_out);
+
if (VERBOSE) {
if(sig[0])
printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen);
@@ -288,6 +343,6 @@ gr_ofdm_frame_sink::work (int noutput_items,
assert(0);
} // switch
-
+
return 1;
}
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
index f1c9b76fe..904373bba 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h
@@ -32,7 +32,8 @@ typedef boost::shared_ptr<gr_ofdm_frame_sink> gr_ofdm_frame_sink_sptr;
gr_ofdm_frame_sink_sptr
gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_tones);
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain=0.25, float freq_gain=0.25*0.25/4.0);
/*!
* \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs
@@ -47,7 +48,8 @@ class gr_ofdm_frame_sink : public gr_sync_block
friend gr_ofdm_frame_sink_sptr
gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_tones);
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
private:
enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER};
@@ -71,17 +73,26 @@ class gr_ofdm_frame_sink : public gr_sync_block
int d_packet_whitener_offset; // offset into whitener string to use
int d_packetlen_cnt; // how many so far
+ gr_complex * d_derotated_output; // Pointer to output stream to send deroated symbols out
+
std::vector<gr_complex> d_sym_position;
std::vector<unsigned char> d_sym_value_out;
+ std::vector<gr_complex> d_dfe;
unsigned int d_nbits;
unsigned char d_resid;
unsigned int d_nresid;
+ float d_phase;
+ float d_freq;
+ float d_phase_gain;
+ float d_freq_gain;
+ float d_eq_gain;
protected:
gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_tones);
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
void enter_search();
void enter_have_sync();
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
index 296eb6591..38ab50e97 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
+++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i
@@ -25,14 +25,16 @@ GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink);
gr_ofdm_frame_sink_sptr
gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_tones);
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain=0.25, float freq_gain=0.25*0.25/4);
class gr_ofdm_frame_sink : public gr_sync_block
{
protected:
gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
const std::vector<unsigned char> &sym_value_out,
- gr_msg_queue_sptr target_queue, unsigned int occupied_tones);
+ gr_msg_queue_sptr target_queue, unsigned int occupied_tones,
+ float phase_gain, float freq_gain);
public:
~gr_ofdm_frame_sink();
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
index 4ff55b5d8..f916977df 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc
@@ -54,8 +54,8 @@ gr_ofdm_mapper_bcv::gr_ofdm_mapper_bcv (const std::vector<gr_complex> &constella
{
if (!(d_occupied_carriers <= d_fft_length))
throw std::invalid_argument("gr_ofdm_mapper_bcv: occupied carriers must be <= fft_length");
-
- d_nbits = (unsigned long)(log10(d_constellation.size()) / log10(2));
+
+ d_nbits = (unsigned long)ceil(log10(d_constellation.size()) / log10(2.0));
}
gr_ofdm_mapper_bcv::~gr_ofdm_mapper_bcv(void)
diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
index 56b5d50a4..6216df791 100644
--- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
+++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
@@ -65,22 +65,26 @@ gr_ofdm_sampler::general_work (int noutput_items,
gr_complex *optr = (gr_complex *) output_items[0];
- int found=0;
+ int found=0, index=0;
int i=d_fft_length-1;
- while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
- if(trigger[i])
+ // FIXME: This is where we miss if the regeneration happens too soon.
+ //while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) {
+ while(i<std::min(ninput_items[0],ninput_items[1]) ) {
+ if(trigger[i]) {
found = 1;
+ index = i++;
+ }
else
i++;
}
-
+
if(found) {
- assert(i-d_fft_length+1 >= 0);
- for(int j=i-d_fft_length+1;j<=i;j++)
+ assert(index-d_fft_length+1 >= 0);
+ for(int j=index - d_fft_length + 1; j <= index; j++)
*optr++ = iptr[j];
- consume_each(i-d_fft_length+2);
+ consume_each(index - d_fft_length + 2);
//printf("OFDM Sampler found: ninput_items: %d/%d noutput_items: %d consumed: %d found: %d\n",
// ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+2), found);
}
diff --git a/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc
new file mode 100644
index 000000000..a84cf189f
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_peak_detector2_fb.h>
+#include <gr_io_signature.h>
+
+gr_peak_detector2_fb_sptr
+gr_make_peak_detector2_fb (float threshold_factor_rise,
+ int look_ahead, float alpha)
+{
+ return gr_peak_detector2_fb_sptr (new gr_peak_detector2_fb (threshold_factor_rise,
+ look_ahead, alpha));
+}
+
+gr_peak_detector2_fb::gr_peak_detector2_fb (float threshold_factor_rise,
+ int look_ahead, float alpha)
+ : gr_sync_block ("peak_detector2_fb",
+ gr_make_io_signature (1, 1, sizeof(float)),
+ gr_make_io_signature2 (1, 2, sizeof(char), sizeof(float))),
+ d_threshold_factor_rise(threshold_factor_rise),
+ d_look_ahead(look_ahead), d_alpha(alpha), d_avg(0.0f), d_found(false)
+{
+}
+
+int
+gr_peak_detector2_fb::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items) {
+ float *iptr = (float *) input_items[0];
+ char *optr = (char *) output_items[0];
+
+ assert(noutput_items >= 2);
+
+ memset(optr, 0, noutput_items*sizeof(char));
+
+ for (int i = 0; i < noutput_items; i++) {
+
+ if (!d_found) {
+ // Have not yet detected presence of peak
+ if (iptr[i] > d_avg * (1.0f + d_threshold_factor_rise)) {
+ d_found = true;
+ d_look_ahead_remaining = d_look_ahead;
+ d_peak_val = -(float)INFINITY;
+ }
+ else {
+ d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg;
+ }
+ }
+ else {
+ // Detected presence of peak
+ if (iptr[i] > d_peak_val) {
+ d_peak_val = iptr[i];
+ d_peak_ind = i;
+ }
+ else if (d_look_ahead_remaining <= 0) {
+ optr[d_peak_ind] = 1;
+ d_found = false;
+ d_avg = iptr[i];
+ }
+
+ // Have not yet located peak, loop and keep searching.
+ d_look_ahead_remaining--;
+ }
+
+ // Every iteration of the loop, write debugging signal out if
+ // connected:
+ if (output_items.size() == 2) {
+ float *sigout = (float *) output_items[1];
+ sigout[i] = d_avg;
+ }
+ } // loop
+
+ if (!d_found)
+ return noutput_items;
+
+ // else if detected presence, keep searching during the next call to work.
+ int tmp = d_peak_ind;
+ d_peak_ind = 1;
+
+ return tmp - 1;
+}
+
+
diff --git a/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h
new file mode 100644
index 000000000..e20c6c022
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h
@@ -0,0 +1,108 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_gr_peak_detector2_FB_H
+#define INCLUDED_gr_peak_detector2_FB_H
+
+#include <gr_sync_block.h>
+
+class gr_peak_detector2_fb;
+typedef boost::shared_ptr<gr_peak_detector2_fb> gr_peak_detector2_fb_sptr;
+
+gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float threshold_factor_rise = 7,
+ int look_ahead = 1000,
+ float alpha = 0.001);
+
+/*!
+ * \brief Detect the peak of a signal
+ * \ingroup block
+ *
+ * If a peak is detected, this block outputs a 1,
+ * or it outputs 0's. A separate debug output may be connected, to
+ * view the internal EWMA described below.
+ *
+ * \param threshold_factor_rise The threshold factor determins when a peak
+ * is present. An EWMA average of the signal is calculated and when the
+ * value of the signal goes over threshold_factor_rise*average, we
+ * call the peak.
+ * \param look_ahead The look-ahead value is used when the threshold is
+ * found to locate the peak within this range.
+ * \param alpha The gain value of a single-pole moving average filter
+ */
+
+class gr_peak_detector2_fb : public gr_sync_block
+{
+ friend gr_peak_detector2_fb_sptr
+ gr_make_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha);
+
+ gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha);
+
+private:
+ float d_threshold_factor_rise;
+ int d_look_ahead;
+ int d_look_ahead_remaining;
+ int d_peak_ind;
+ float d_peak_val;
+ float d_alpha;
+ float d_avg;
+ bool d_found;
+
+public:
+
+ /*! \brief Set the threshold factor value for the rise time
+ * \param thr new threshold factor
+ */
+ void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; }
+
+ /*! \brief Set the look-ahead factor
+ * \param look new look-ahead factor
+ */
+ void set_look_ahead(int look) { d_look_ahead = look; }
+
+ /*! \brief Set the running average alpha
+ * \param alpha new alpha for running average
+ */
+ void set_alpha(int alpha) { d_alpha = alpha; }
+
+ /*! \brief Get the threshold factor value for the rise time
+ * \return threshold factor
+ */
+ float threshold_factor_rise() { return d_threshold_factor_rise; }
+
+ /*! \brief Get the look-ahead factor value
+ * \return look-ahead factor
+ */
+ int look_ahead() { return d_look_ahead; }
+
+ /*! \brief Get the alpha value of the running average
+ * \return alpha
+ */
+ float alpha() { return d_alpha; }
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
+
+
diff --git a/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i
new file mode 100644
index 000000000..4b01435c8
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+GR_SWIG_BLOCK_MAGIC(gr,peak_detector2_fb)
+
+ gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float threshold_factor_rise = 7,
+ int look_ahead = 1000,
+ float alpha=0.001);
+
+class gr_peak_detector2_fb : public gr_sync_block
+{
+private:
+ gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha);
+
+public:
+ void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; }
+ void set_look_ahead(int look) { d_look_ahead = look; }
+ void set_alpha(int alpha) { d_avg_alpha = alpha; }
+
+ float threshold_factor_rise() { return d_threshold_factor_rise; }
+ int look_ahead() { return d_look_ahead; }
+ float alpha() { return d_avg_alpha; }
+};
+
+