From 42ad2adb86981f4488edbe33169683f787b807c3 Mon Sep 17 00:00:00 2001 From: trondeau Date: Wed, 6 Feb 2008 15:54:54 +0000 Subject: Merging trondeau/ofdmfix into branch at -r7582:7586. This allows for over-the-air OFDM. Works with all modulations and tested both send and receive on different computers/USRPs. Misses a few packets, so it's not perfect. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@7587 221aa14e-8319-0410-a670-987f0aec2ac5 --- .../src/lib/general/gr_ofdm_frame_acquisition.cc | 78 +++++++++++++--------- gnuradio-core/src/lib/general/gr_ofdm_sampler.cc | 3 +- 2 files changed, 47 insertions(+), 34 deletions(-) (limited to 'gnuradio-core/src/lib/general') diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc index 0fa6a3d3e..40a0ed852 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc @@ -48,7 +48,7 @@ gr_ofdm_frame_acquisition::gr_ofdm_frame_acquisition (unsigned occupied_carriers const std::vector &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_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), @@ -101,44 +101,64 @@ gr_ofdm_frame_acquisition::coarse_freq_comp(int freq_delta, int 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; + 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; 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]); + + while(!found && ((unsigned)abs(search_delta) <= d_freq_shift_len)) { + h_sqrd = gr_complex(0.0,0.0); + power = 0.0F; + + //FIXME: power calculation doesn't really make sense + for(i = 0; i < d_occupied_carriers; i++) { + h_sqrd += (d_known_phase_diff[i] * d_symbol_phase_diff[i+zeros_on_left+search_delta]); + power += d_known_phase_diff[i]*d_known_phase_diff[i]; } - if(fabs(sum) > max) { - max = sum; - index = i; + + 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)); } - } - - 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]); + //FIXME: these threshold values are arbitrary, although the decision metric is very good + // even at very low SNR + if((h_sqrd.real() > 0.95*power) && (h_sqrd.real() < 1.1*power)) { + found = true; + d_coarse_freq = search_delta; + d_phase_count = 1; + + //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)); + + if(VERBOSE) { + printf("CORR: Found, bin %d\tdB\tcorr power fraction %f\n", + search_delta, h_sqrd.real()/power); + } + break; + } + else { + if(search_delta <= 0) + search_delta = (-search_delta) + 2; + else + search_delta = -search_delta; } } - - return true; //FIXME: don't need ot return anything now + return found; } + void gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, int zeros_on_left) { @@ -184,7 +204,6 @@ gr_ofdm_frame_acquisition::general_work(int noutput_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]; @@ -193,19 +212,15 @@ gr_ofdm_frame_acquisition::general_work(int noutput_items, 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]; - } - + found = correlate(symbol, zeros_on_left); 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) @@ -217,7 +232,6 @@ gr_ofdm_frame_acquisition::general_work(int noutput_items, d_phase_count = 1; } - consume(0,1); - consume(1,ninput_items[1]); + consume_each(1); return 1; } diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc index 6216df791..c52945656 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc @@ -70,8 +70,7 @@ gr_ofdm_sampler::general_work (int noutput_items, int i=d_fft_length-1; // FIXME: This is where we miss if the regeneration happens too soon. - //while(!found && i