[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r7317 - gnuradio/branches/developers/trondeau/ofdm2/gn
From: |
trondeau |
Subject: |
[Commit-gnuradio] r7317 - gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general |
Date: |
Tue, 1 Jan 2008 07:03:26 -0700 (MST) |
Author: trondeau
Date: 2008-01-01 07:03:25 -0700 (Tue, 01 Jan 2008)
New Revision: 7317
Modified:
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
Log:
uses known-symbol with alternating 0 bins (from Schmidl and Cox sync routine)
to do frame acquisition finding integer frequency offset, and equalizer.
Equalizer is calculated against known symbol for all non-zero bins and linearly
interpolates for zero bins. Frequency offset calculation doesn't work for
certain (odd, I think) integer frequency offsets, which I think is a rotation
problem in the way I'm calculating the correlation.
Modified:
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
===================================================================
---
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
2008-01-01 13:58:14 UTC (rev 7316)
+++
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc
2008-01-01 14:03:25 UTC (rev 7317)
@@ -27,6 +27,7 @@
#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)
@@ -35,42 +36,37 @@
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_symbol1,
- const std::vector<gr_complex> &known_symbol2,
+ 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_symbol1, known_symbol2,
-
max_fft_shift_len));
+
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_symbol1,
- const
std::vector<gr_complex> &known_symbol2,
+ const
std::vector<gr_complex> &known_symbol,
unsigned int
max_fft_shift_len)
: gr_block ("ofdm_frame_acquisition",
- gr_make_io_signature (1, 1, sizeof(gr_complex)*fft_length),
+ 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_symbol1(known_symbol1),
- d_known_symbol2(known_symbol2),
+ d_known_symbol(known_symbol),
d_coarse_freq(0),
d_phase_count(0)
{
- d_diff_corr_factor.resize(d_occupied_carriers);
+ d_symbol_phase_diff.resize(d_fft_length);
+ d_known_phase_diff.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++;
+
+ 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];
@@ -91,7 +87,7 @@
{
unsigned ninputs = ninput_items_required.size ();
for (unsigned i = 0; i < ninputs; i++)
- ninput_items_required[i] = 2;
+ ninput_items_required[i] = 1;
}
gr_complex
@@ -102,91 +98,81 @@
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_frame_acquisition::correlate(const gr_complex *previous, const
gr_complex *current,
- int zeros_on_left)
+gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int
zeros_on_left)
{
- unsigned int i = 0;
- int search_delta = 0;
- bool found = false;
+ unsigned int i = 0, j = 0;
- 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]));
+ }
- 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
+ int index = 0;
+ float max = 0, sum=0;
+ for(i = 0; i < d_fft_length - d_occupied_carriers; i++) {
+ sum = 0;
+ for(j = 0; j < d_occupied_carriers; j++) {
+ //sum += fabs(d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
+ sum += (d_known_phase_diff[j] * d_symbol_phase_diff[i+j]);
}
-
-#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()));
+ if(fabs(sum) > max) {
+ max = sum;
+ index = i;
+ }
+ }
- // 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()));
- }
+ printf("Corr: %.4f\n", max);
+ d_coarse_freq = index - zeros_on_left;
-#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;
- }
+ if(0) {
+ fprintf(stderr, "Coarse Freq Offset: %d\n", d_coarse_freq);
+ fprintf(stderr, "Known: ");
+ for(i = 0; i < 18; i++)
+ fprintf(stderr, "%+.4f ", d_known_phase_diff[i]);
+ fprintf(stderr, "\nSymbol: ");
+ for(i = 0; i < 18; i++)
+ fprintf(stderr, "%+.4f ",
d_symbol_phase_diff[zeros_on_left+d_coarse_freq+i]);
+ fprintf(stderr, "\n");
}
- return found;
+
+ return true; //FIXME: don't need ot return anything now
}
void
-gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *previous,
const gr_complex *current,
- int zeros_on_left)
+gr_ofdm_frame_acquisition::calculate_equalizer(const gr_complex *symbol, 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]));
+ // 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);
}
-#if VERBOSE
- fprintf(stderr, "\n");
-#endif
+
+ // 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(0) {
+ for(i = 0; i < d_occupied_carriers; i++) {
+ fprintf(stderr, "%+.4f + j%+.4f ", d_hestimate[i].real(),
d_hestimate[i].imag());
+ }
+ fprintf(stderr, "\n");
+ }
}
int
@@ -195,37 +181,40 @@
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];
+ 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];
- 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);
+ int found = 0;
+ for(int i = 0; i < ninput_items[1]; i++) {
+ found += trigger[i];
+ }
+
+ if(found) {
+ correlate(symbol, zeros_on_left);
+ calculate_equalizer(symbol, 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];
+ 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_each(1);
+ consume(0,1);
+ consume(1,ninput_items[1]);
return 1;
}
Modified:
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
===================================================================
---
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
2008-01-01 13:58:14 UTC (rev 7316)
+++
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.h
2008-01-01 14:03:25 UTC (rev 7317)
@@ -33,8 +33,7 @@
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_symbol1,
- const std::vector<gr_complex> &known_symbol2,
+ const std::vector<gr_complex> &known_symbol,
unsigned int max_fft_shift_len=10);
/*!
@@ -71,32 +70,30 @@
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_symbol1,
- const std::vector<gr_complex> &known_symbol2,
+ const std::vector<gr_complex> &known_symbol,
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_symbol1,
- const std::vector<gr_complex> &known_symbol2,
+ 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
Modified:
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
===================================================================
---
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
2008-01-01 13:58:14 UTC (rev 7316)
+++
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.i
2008-01-01 14:03:25 UTC (rev 7317)
@@ -28,8 +28,7 @@
gr_make_ofdm_frame_acquisition (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,
+ const std::vector<gr_complex> &known_symbol,
unsigned int max_fft_shift_len=4);
class gr_ofdm_frame_acquisition : public gr_sync_decimator
@@ -38,8 +37,7 @@
gr_ofdm_frame_acquisition (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,
+ const std::vector<gr_complex> &known_symbol,
unsigned int max_fft_shift_len);
public:
Modified:
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
===================================================================
---
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
2008-01-01 13:58:14 UTC (rev 7316)
+++
gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc
2008-01-01 14:03:25 UTC (rev 7317)
@@ -65,22 +65,26 @@
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);
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r7317 - gnuradio/branches/developers/trondeau/ofdm2/gnuradio-core/src/lib/general,
trondeau <=