Merge branch 'qtupdate'
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_ofdm_sampler.cc
index 02897bb6b112c639eb881d8a830e88f60e7c0f33..7f6b2b01c984a6d5064a9d91fbdb5005146989e7 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright 2007,2008,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
 #include <gr_ofdm_sampler.h>
 #include <gr_io_signature.h>
 #include <gr_expj.h>
+#include <cstdio>
 
 gr_ofdm_sampler_sptr
 gr_make_ofdm_sampler (unsigned int fft_length, 
-                     unsigned int symbol_length)
+                     unsigned int symbol_length,
+                     unsigned int timeout)
 {
-  return gr_ofdm_sampler_sptr (new gr_ofdm_sampler (fft_length, symbol_length));
+  return gr_ofdm_sampler_sptr (new gr_ofdm_sampler (fft_length, symbol_length, timeout));
 }
 
 gr_ofdm_sampler::gr_ofdm_sampler (unsigned int fft_length, 
-                                 unsigned int symbol_length)
+                                 unsigned int symbol_length,
+                                 unsigned int timeout)
   : gr_block ("ofdm_sampler",
              gr_make_io_signature2 (2, 2, sizeof (gr_complex), sizeof(char)),
-             gr_make_io_signature (1, 1, sizeof (gr_complex)*fft_length)),
-    d_fft_length(fft_length), d_symbol_length(symbol_length)
+             gr_make_io_signature2 (2, 2, sizeof (gr_complex)*fft_length, sizeof(char)*fft_length)),
+    d_state(STATE_NO_SIG), d_timeout_max(timeout), d_fft_length(fft_length), d_symbol_length(symbol_length)
 {
+  set_relative_rate(1.0/(double) fft_length);   // buffer allocator hint
 }
 
 void
 gr_ofdm_sampler::forecast (int noutput_items, gr_vector_int &ninput_items_required)
 {
   // FIXME do we need more
-  int nreqd  = (noutput_items-1) * d_symbol_length + d_fft_length;
+  //int nreqd  = (noutput_items-1) * d_symbol_length + d_fft_length;
+  int nreqd  = d_symbol_length + d_fft_length;
   unsigned ninputs = ninput_items_required.size ();
   for (unsigned i = 0; i < ninputs; i++)
     ninput_items_required[i] = nreqd;
 }
 
+
 int
 gr_ofdm_sampler::general_work (int noutput_items,
                               gr_vector_int &ninput_items,
                               gr_vector_const_void_star &input_items,
                               gr_vector_void_star &output_items)
 {
-  gr_complex *iptr = (gr_complex *) input_items[0];
-  char *trigger = (char *) input_items[1];
+  const gr_complex *iptr = (const gr_complex *) input_items[0];
+  const char *trigger = (const char *) input_items[1];
 
   gr_complex *optr = (gr_complex *) output_items[0];
+  char *outsig = (char *) output_items[1];
+
+  //FIXME: we only process a single OFDM symbol at a time; after the preamble, we can 
+  // process a few at a time as long as we always look out for the next preamble.
 
-  int found=0;
+  unsigned int index=d_fft_length;  // start one fft length into the input so we can always look back this far
 
-  int i=d_fft_length-1;
+  outsig[0] = 0; // set output to no signal by default
 
-  while(!found && i<std::min(ninput_items[0],ninput_items[1]) )
-    if(trigger[i])
-      found = 1;
+  // Search for a preamble trigger signal during the next symbol length
+  while((d_state != STATE_PREAMBLE) && (index <= (d_symbol_length+d_fft_length))) {
+    if(trigger[index]) {
+      outsig[0] = 1; // tell the next block there is a preamble coming
+      d_state = STATE_PREAMBLE;
+    }
     else
-      i++;
-
-  if(found) {
-    assert(i-d_fft_length+1 >= 0);
-    for(int j=i-d_fft_length+1;j<=i;j++)
-      *optr++ = iptr[j];
-    consume_each(i-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);
+      index++;
   }
-  else {
-    consume_each(i-d_fft_length+1);
-    //printf("OFDM Sampler not 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+1), found);
- }
+  
+  unsigned int i, pos, ret;
+  switch(d_state) {
+  case(STATE_PREAMBLE):
+    // When we found a preamble trigger, get it and set the symbol boundary here
+    for(i = (index - d_fft_length + 1); i <= index; i++) {
+      *optr++ = iptr[i];
+    }
+    
+    d_timeout = d_timeout_max; // tell the system to expect at least this many symbols for a frame
+    d_state = STATE_FRAME;
+    consume_each(index - d_fft_length + 1); // consume up to one fft_length away to keep the history
+    ret = 1;
+    break;
+    
+  case(STATE_FRAME):
+    // use this state when we have processed a preamble and are getting the rest of the frames
+    //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
+    pos = d_symbol_length;         // keeps track of where we are in the input buffer
+    while(pos < d_symbol_length + d_fft_length) {
+      *optr++ = iptr[pos++];
+    }
 
+    if(d_timeout-- == 0) {
+      printf("TIMEOUT\n");
+      d_state = STATE_NO_SIG;
+    }
+
+    consume_each(d_symbol_length); // jump up by 1 fft length and the cyclic prefix length
+    ret = 1;
+    break;
+
+  case(STATE_NO_SIG):
+  default:
+    consume_each(index-d_fft_length); // consume everything we've gone through so far leaving the fft length history
+    ret = 0;
+    break;
+  }
 
-  return found;
+  return ret;
 }