/* -*- c++ -*- */
/*
- * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright 2007,2008 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
#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>
+#include <string.h>
#define VERBOSE 0
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
unsigned char *out)
{
unsigned int i=0, bytes_produced=0;
+ gr_complex carrier;
+
+ carrier=gr_expj(d_phase);
- while(i < d_occupied_carriers) {
+ gr_complex accum_error = 0.0;
+ //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)) {
+ 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;
+ }
+
+ 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++;
- 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++]);
if((8 - d_byte_offset) >= d_nbits) {
d_partial_byte |= bits << (d_byte_offset);
d_byte_offset += d_nbits;
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;
}
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)
{
+ 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_right) - 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));
set_sym_value_out(sym_position, sym_value_out);
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;
}
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
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");
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);
assert(0);
} // switch
-
+
return 1;
}