diff options
author | trondeau | 2008-03-31 23:30:32 +0000 |
---|---|---|
committer | trondeau | 2008-03-31 23:30:32 +0000 |
commit | ce0a5f5d6df44cac93ba41a48b410cd3a6474b66 (patch) | |
tree | 44dcf7fe5eb713c3725704ff2cd304eed167ee30 /gnuradio-core/src/lib/general | |
parent | 52234f95fc81481d1e92328b25e90a3e26731dea (diff) | |
download | gnuradio-ce0a5f5d6df44cac93ba41a48b410cd3a6474b66.tar.gz gnuradio-ce0a5f5d6df44cac93ba41a48b410cd3a6474b66.tar.bz2 gnuradio-ce0a5f5d6df44cac93ba41a48b410cd3a6474b66.zip |
merging branch trondeau/ofdm r7971:8143. Fixing subcarriers and other issues to improve OFDM system operation. Not much more we can do with this than add channel coding and cleaning up.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@8144 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gnuradio-core/src/lib/general')
8 files changed, 145 insertions, 30 deletions
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 68bb029a2..b19b82abd 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006, 2007 Free Software Foundation, Inc. + * Copyright 2006,2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -66,7 +66,7 @@ gr_ofdm_frame_acquisition::gr_ofdm_frame_acquisition (unsigned occupied_carriers 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_known_phase_diff[i] = norm(d_known_symbol[i] - d_known_symbol[i+2]); } d_phase_lut = new gr_complex[(2*d_freq_shift_len+1) * MAX_NUM_SYMBOLS]; @@ -108,7 +108,7 @@ gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int zeros_on_left 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])); + d_symbol_phase_diff[i] = norm(symbol[i] - symbol[i+2]); } // sweep through all possible/allowed frequency offsets and select the best @@ -119,7 +119,7 @@ gr_ofdm_frame_acquisition::correlate(const gr_complex *symbol, int zeros_on_left for(j = 0; j < d_occupied_carriers; j++) { sum += (d_known_phase_diff[j] * d_symbol_phase_diff[i+j]); } - if(fabs(sum) > max) { + if(sum > max) { max = sum; index = i; } 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 a1ac66ff7..ab0c31a2c 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -110,16 +110,19 @@ unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in, carrier=gr_expj(d_phase); gr_complex accum_error = 0.0; - while(i < d_occupied_carriers) { + //while(i < d_occupied_carriers) { + while(i < d_subcarrier_map.size()) { if(d_nresid > 0) { d_partial_byte |= d_resid; d_byte_offset += d_nresid; d_nresid = 0; d_resid = 0; } - - while((d_byte_offset < 8) && (i < d_occupied_carriers)) { - gr_complex sigrot = in[i]*carrier*d_dfe[i]; + + //while((d_byte_offset < 8) && (i < d_occupied_carriers)) { + while((d_byte_offset < 8) && (i < d_subcarrier_map.size())) { + //gr_complex sigrot = in[i]*carrier*d_dfe[i]; + gr_complex sigrot = in[d_subcarrier_map[i]]*carrier*d_dfe[i]; if(d_derotated_output != NULL){ d_derotated_output[i] = sigrot; @@ -198,6 +201,59 @@ gr_ofdm_frame_sink::gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_positi 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) { + std::string carriers = "FE7F"; + + // A bit hacky to fill out carriers to occupied_carriers length + int diff = (d_occupied_carriers - 4*carriers.length()); + while(diff > 7) { + carriers.insert(0, "f"); + carriers.insert(carriers.length(), "f"); + diff -= 8; + } + + // if there's extras left to be processed + // divide remaining to put on either side of current map + // all of this is done to stick with the concept of a carrier map string that + // can be later passed by the user, even though it'd be cleaner to just do this + // on the carrier map itself + int diff_left=0; + int diff_right=0; + + // dictionary to convert from integers to ascii hex representation + char abc[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + if(diff > 0) { + char c[2] = {0,0}; + + diff_left = (int)ceil((float)diff/2.0f); // number of carriers to put on the left side + c[0] = abc[((1 << diff_left) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(0, c); + + diff_right = diff - diff_left; // number of carriers to put on the right side + c[0] = abc[(0xF^(1 << diff_left) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(carriers.length(), c); + } + + // It seemed like such a good idea at the time... + // because we are only dealing with the occupied_carriers + // at this point, the diff_left in the following compensates + // for any offset from the 0th carrier introduced + unsigned int i,j,k; + for(i = 0; i < (d_occupied_carriers/4)+diff_left; i++) { + char c = carriers[i]; + for(j = 0; j < 4; j++) { + k = (strtol(&c, NULL, 16) >> (3-j)) & 0x1; + if(k) { + d_subcarrier_map.push_back(4*i + j - diff_left); + } + } + } + + // make sure we stay in the limit currently imposed by the occupied_carriers + if(d_subcarrier_map.size() > d_occupied_carriers) { + throw std::invalid_argument("gr_ofdm_mapper_bcv: subcarriers allocated exceeds size of occupied carriers"); + } + 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)); 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 cc3d67bd5..91d559eb0 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h @@ -88,6 +88,8 @@ class gr_ofdm_frame_sink : public gr_sync_block float d_freq_gain; float d_eq_gain; + std::vector<int> d_subcarrier_map; + protected: gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position, const std::vector<unsigned char> &sym_value_out, 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 f916977df..0a3602cb2 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2007 Free Software Foundation, Inc. + * Copyright 2006,2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -54,6 +54,63 @@ 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"); + + // this is not the final form of this solution since we still use the occupied_tones concept, + // which would get us into trouble if the number of carriers we seek is greater than the occupied carriers. + // Eventually, we will get rid of the occupied_carriers concept. + std::string carriers = "FE7F"; + + // A bit hacky to fill out carriers to occupied_carriers length + int diff = (d_occupied_carriers - 4*carriers.length()); + while(diff > 7) { + carriers.insert(0, "f"); + carriers.insert(carriers.length(), "f"); + diff -= 8; + } + + // if there's extras left to be processed + // divide remaining to put on either side of current map + // all of this is done to stick with the concept of a carrier map string that + // can be later passed by the user, even though it'd be cleaner to just do this + // on the carrier map itself + int diff_left=0; + int diff_right=0; + + // dictionary to convert from integers to ascii hex representation + char abc[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + if(diff > 0) { + char c[2] = {0,0}; + + diff_left = (int)ceil((float)diff/2.0f); // number of carriers to put on the left side + c[0] = abc[((1 << diff_left) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(0, c); + + diff_right = diff - diff_left; // number of carriers to put on the right side + c[0] = abc[(0xF^(1 << diff_left) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(carriers.length(), c); + } + + // find out how many zeros to pad on the sides; the difference between the fft length and the subcarrier + // mapping size in chunks of four. This is the number to pack on the left and this number plus any + // residual nulls (if odd) will be packed on the right. + diff = (d_fft_length/4 - carriers.length())/2; + + unsigned int i,j,k; + for(i = 0; i < carriers.length(); i++) { + char c = carriers[i]; // get the current hex character from the string + for(j = 0; j < 4; j++) { // walk through all four bits + k = (strtol(&c, NULL, 16) >> (3-j)) & 0x1; // convert to int and extract next bit + if(k) { // if bit is a 1, + d_subcarrier_map.push_back(4*(i+diff) + j); // use this subcarrier + } + } + } + + // make sure we stay in the limit currently imposed by the occupied_carriers + if(d_subcarrier_map.size() > d_occupied_carriers) { + throw std::invalid_argument("gr_ofdm_mapper_bcv: subcarriers allocated exceeds size of occupied carriers"); + } d_nbits = (unsigned long)ceil(log10(d_constellation.size()) / log10(2.0)); } @@ -75,8 +132,6 @@ gr_ofdm_mapper_bcv::work(int noutput_items, gr_complex *out = (gr_complex *)output_items[0]; unsigned int i=0; - unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers; - unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0); //printf("OFDM BPSK Mapper: ninput_items: %d noutput_items: %d\n", ninput_items[0], noutput_items); @@ -107,8 +162,9 @@ gr_ofdm_mapper_bcv::work(int noutput_items, i = 0; unsigned char bits = 0; - while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) { - + //while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) { + while((d_msg_offset < d_msg->length()) && (i < d_subcarrier_map.size())) { + // need new data to process if(d_bit_offset == 0) { d_msgbytes = d_msg->msg()[d_msg_offset]; @@ -116,10 +172,11 @@ gr_ofdm_mapper_bcv::work(int noutput_items, } if(d_nresid > 0) { + // take the residual bits, fill out nbits with info from the new byte, and put them in the symbol d_resid |= (((1 << d_nresid)-1) & d_msgbytes) << (d_nbits - d_nresid); bits = d_resid; - out[i + zeros_on_left] = d_constellation[bits]; + out[d_subcarrier_map[i]] = d_constellation[bits]; i++; d_bit_offset += d_nresid; @@ -129,20 +186,16 @@ gr_ofdm_mapper_bcv::work(int noutput_items, // bits, d_resid, d_nresid, d_bit_offset); } else { - if((8 - d_bit_offset) >= d_nbits) { + if((8 - d_bit_offset) >= d_nbits) { // test to make sure we can fit nbits + // take the nbits number of bits at a time from the byte to add to the symbol bits = ((1 << d_nbits)-1) & (d_msgbytes >> d_bit_offset); d_bit_offset += d_nbits; - out[i + zeros_on_left] = d_constellation[bits]; + out[d_subcarrier_map[i]] = d_constellation[bits]; i++; - - /* - printf("mod bit: %x out: %.4f + j%.4f resid: %x nresid: %d bit_offset: %d\n", - bits, out[i-1 + zeros_on_left].real(), out[i-1 + zeros_on_left].imag(), - d_resid, d_nresid, d_bit_offset); - */ } - else { + else { // if we can't fit nbits, store them for the next + // saves d_nresid bits of this message where d_nresid < d_nbits unsigned int extra = 8-d_bit_offset; d_resid = ((1 << extra)-1) & (d_msgbytes >> d_bit_offset); d_bit_offset += extra; @@ -166,8 +219,10 @@ gr_ofdm_mapper_bcv::work(int noutput_items, d_resid = 0; } - while(i < d_occupied_carriers) { // finish filling out the symbol - out[i + zeros_on_left] = d_constellation[randsym()]; + //while(i < d_occupied_carriers) { // finish filling out the symbol + while(i < d_subcarrier_map.size()) { // finish filling out the symbol + out[d_subcarrier_map[i]] = d_constellation[randsym()]; + i++; } diff --git a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h index 010603b9c..6704c8b2a 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h +++ b/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.h @@ -69,6 +69,8 @@ class gr_ofdm_mapper_bcv : public gr_sync_block unsigned char d_resid; unsigned int d_nresid; + std::vector<int> d_subcarrier_map; + int randsym(); public: diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc index 931ea7a64..7defe3832 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2007,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -103,7 +103,6 @@ gr_ofdm_sampler::general_work (int noutput_items, case(STATE_FRAME): // use this state when we have processed a preamble and are getting the rest of the frames - //FIXME: add a timeout clause here to enter state STATE_NO_SIG after so many times here //FIXME: we could also have a power squelch system here to enter STATE_NO_SIG if no power is received // skip over fft length history and cyclic prefix @@ -113,6 +112,7 @@ gr_ofdm_sampler::general_work (int noutput_items, } if(d_timeout-- == 0) { + printf("TIMEOUT\n"); d_state = STATE_NO_SIG; } diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.h b/gnuradio-core/src/lib/general/gr_ofdm_sampler.h index 449ece748..916b11cf4 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.h +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.h @@ -30,7 +30,7 @@ typedef boost::shared_ptr<gr_ofdm_sampler> gr_ofdm_sampler_sptr; gr_ofdm_sampler_sptr gr_make_ofdm_sampler (unsigned int fft_length, unsigned int symbol_length, - unsigned int timeout=100); + unsigned int timeout=1000); /*! * \brief does the rest of the OFDM stuff diff --git a/gnuradio-core/src/lib/general/gr_ofdm_sampler.i b/gnuradio-core/src/lib/general/gr_ofdm_sampler.i index 6cf843bce..601330b07 100644 --- a/gnuradio-core/src/lib/general/gr_ofdm_sampler.i +++ b/gnuradio-core/src/lib/general/gr_ofdm_sampler.i @@ -24,7 +24,7 @@ GR_SWIG_BLOCK_MAGIC(gr,ofdm_sampler) gr_ofdm_sampler_sptr gr_make_ofdm_sampler (unsigned int fft_length, unsigned int symbol_length, - unsigned int timeout=100); + unsigned int timeout=1000); class gr_ofdm_sampler : public gr_sync_block { |