diff options
Diffstat (limited to 'gnuradio-core/src/lib/general')
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; } +}; + + |