Changeset 7324

Show
Ignore:
Timestamp:
01/02/08 10:35:35
Author:
trondeau
Message:

Merging ofdm2 branch -r7047:7321 into trunk. This updates the OFDM code to hier_block2 in blks2impl and removed from blksimpl. The new code
implements a decision feedback sync loop to lock the phase/freq, removes two unnecessary premables and performs frame sync and equalization off
single preamble symbol. Also adds/updates Python plotting tools and a branchless clip algorithm in gr_math.h.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gnuradio/trunk/AUTHORS

    r5957 r7324  
    1212Johnathan Corgan <jcorgan@corganenterprises.com>  Build system, ongoing stuff, release manager 
    1313Bdale Garbee <bdale@gag.com>           Debian release packages 
     14Tom Rondeau <trondeau@vt.edu>          Mostly digital waveforms and a little bit of trouble 
  • gnuradio/trunk/gnuradio-core/src/lib/general/Makefile.am

    r6044 r7324  
    9797        gr_null_sink.cc                 \ 
    9898        gr_null_source.cc               \ 
    99         gr_ofdm_correlator.cc         \ 
     99        gr_ofdm_frame_acquisition.cc  \ 
    100100        gr_ofdm_cyclic_prefixer.cc      \ 
    101101        gr_ofdm_demapper_vcb.cc         \ 
     
    110110        gr_pa_2x2_phase_combiner.cc     \ 
    111111        gr_packet_sink.cc               \ 
     112        gr_peak_detector2_fb.cc         \ 
    112113        gr_phase_modulator_fc.cc        \ 
    113114        gr_pll_carriertracking_cc.cc    \ 
     
    240241        gr_null_sink.h                  \ 
    241242        gr_null_source.h                \ 
    242         gr_ofdm_correlator.h          \ 
     243        gr_ofdm_frame_acquisition.h   \ 
    243244        gr_ofdm_cyclic_prefixer.h       \ 
    244245        gr_ofdm_demapper_vcb.h          \ 
     
    253254        gr_pa_2x2_phase_combiner.h      \ 
    254255        gr_packet_sink.h                \ 
     256        gr_peak_detector2_fb.h          \ 
    255257        gr_phase_modulator_fc.h         \ 
    256258        gr_pll_carriertracking_cc.h     \ 
     
    384386        gr_null_sink.i                  \ 
    385387        gr_null_source.i                \ 
    386         gr_ofdm_correlator.i          \ 
     388        gr_ofdm_frame_acquisition.i   \ 
    387389        gr_ofdm_cyclic_prefixer.i       \ 
    388390        gr_ofdm_demapper_vcb.i          \ 
     
    397399        gr_pa_2x2_phase_combiner.i      \ 
    398400        gr_packet_sink.i                \ 
     401        gr_peak_detector2_fb.i          \ 
    399402        gr_phase_modulator_fc.i         \ 
    400403        gr_pll_carriertracking_cc.i     \ 
  • gnuradio/trunk/gnuradio-core/src/lib/general/general.i

    r6113 r7324  
    9494#include <gr_probe_avg_mag_sqrd_f.h> 
    9595#include <gr_probe_signal_f.h> 
    96 #include <gr_ofdm_correlator.h> 
     96#include <gr_ofdm_frame_acquisition.h> 
    9797#include <gr_ofdm_cyclic_prefixer.h> 
    9898#include <gr_ofdm_bpsk_demapper.h> 
     
    129129#include <gr_glfsr_source_b.h> 
    130130#include <gr_glfsr_source_f.h> 
     131#include <gr_peak_detector2_fb.h> 
    131132%} 
    132133 
     
    202203%include "gr_probe_avg_mag_sqrd_f.i" 
    203204%include "gr_probe_signal_f.i" 
    204 %include "gr_ofdm_correlator.i" 
     205%include "gr_ofdm_frame_acquisition.i" 
    205206%include "gr_ofdm_cyclic_prefixer.i" 
    206207%include "gr_ofdm_bpsk_demapper.i" 
     
    237238%include "gr_glfsr_source_b.i" 
    238239%include "gr_glfsr_source_f.i" 
     240%include "gr_peak_detector2_fb.i" 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_math.h

    r6851 r7324  
    6565} 
    6666 
     67 
     68/* This bounds x by +/- clip without a branch */ 
     69 
     70static inline float gr_branchless_clip(float x, float clip) 
     71{ 
     72  float x1 = fabsf(x+clip); 
     73  float x2 = fabsf(x-clip); 
     74  x1 -= x2; 
     75  return 0.5*x1; 
     76} 
     77 
     78 
     79 
    6780#endif /* _GR_MATH_H_ */ 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_acquisition.cc

    r7320 r7324  
    116116  int index = 0; 
    117117  float max = 0, sum=0; 
    118   for(i = 0; i < d_fft_length - d_occupied_carriers; i++) { 
     118  for(i = zeros_on_left - d_freq_shift_len; i < zeros_on_left + d_freq_shift_len; i+=2) { 
    119119    sum = 0; 
    120120    for(j = 0; j < d_occupied_carriers; j++) { 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.cc

    r6113 r7324  
    2727#include <gr_ofdm_frame_sink.h> 
    2828#include <gr_io_signature.h> 
     29#include <gr_expj.h> 
     30#include <gr_math.h> 
     31#include <math.h> 
    2932#include <cstdio> 
    3033#include <stdexcept> 
     34#include <iostream> 
    3135 
    3236#define VERBOSE 0 
     
    5660  d_header = 0; 
    5761  d_headerbytelen_cnt = 0; 
     62 
     63  // Resetting PLL 
     64  d_freq = 0.0; 
     65  d_phase = 0.0; 
     66  fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); 
    5867} 
    5968 
     
    97106{ 
    98107  unsigned int i=0, bytes_produced=0; 
    99  
     108  gr_complex carrier; 
     109 
     110  carrier=gr_expj(d_phase); 
     111 
     112  gr_complex accum_error = 0.0; 
    100113  while(i < d_occupied_carriers) { 
    101114    if(d_nresid > 0) { 
     
    107120 
    108121    while((d_byte_offset < 8) && (i < d_occupied_carriers)) { 
    109       //fprintf(stderr, "%f+j%f  = %d\n", in[i].real(), in[i].imag(), slicer(in[i]));  
    110       unsigned char bits = slicer(in[i++]); 
     122      gr_complex sigrot = in[i]*carrier*d_dfe[i]; 
     123       
     124      if(d_derotated_output != NULL){ 
     125        d_derotated_output[i] = sigrot; 
     126      } 
     127       
     128      unsigned char bits = slicer(sigrot); 
     129 
     130      gr_complex closest_sym = d_sym_position[bits]; 
     131       
     132      accum_error += sigrot * conj(closest_sym); 
     133 
     134      // FIX THE FOLLOWING STATEMENT 
     135      if (norm(sigrot)> 0.001) d_dfe[i] +=  d_eq_gain*(closest_sym/sigrot-d_dfe[i]); 
     136       
     137      i++; 
     138 
    111139      if((8 - d_byte_offset) >= d_nbits) { 
    112140        d_partial_byte |= bits << (d_byte_offset); 
     
    131159    } 
    132160  } 
    133  
     161  //std::cerr << "accum_error " << accum_error << std::endl; 
     162 
     163  float angle = arg(accum_error); 
     164 
     165  d_freq = d_freq - d_freq_gain*angle; 
     166  d_phase = d_phase + d_freq - d_phase_gain*angle; 
     167  if (d_phase >= 2*M_PI) d_phase -= 2*M_PI; 
     168  if (d_phase <0) d_phase += 2*M_PI; 
     169     
     170  //if(VERBOSE) 
     171  //  std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << std::endl; 
     172   
    134173  return bytes_produced; 
    135174} 
     
    139178gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,  
    140179                        const std::vector<unsigned char> &sym_value_out, 
    141                         gr_msg_queue_sptr target_queue, unsigned int occupied_carriers) 
     180                        gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, 
     181                        float phase_gain, float freq_gain) 
    142182{ 
    143183  return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(sym_position, sym_value_out, 
    144                                                         target_queue, occupied_carriers)); 
     184                                                        target_queue, occupied_carriers, 
     185                                                        phase_gain, freq_gain)); 
    145186} 
    146187 
     
    148189gr_ofdm_frame_sink::gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,  
    149190                                       const std::vector<unsigned char> &sym_value_out, 
    150                                        gr_msg_queue_sptr target_queue, unsigned int occupied_carriers) 
     191                                       gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, 
     192                                       float phase_gain, float freq_gain) 
    151193  : gr_sync_block ("ofdm_frame_sink", 
    152194                   gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)), 
    153                    gr_make_io_signature (0, 0, 0)), 
     195                   gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)), 
    154196    d_target_queue(target_queue), d_occupied_carriers(occupied_carriers),  
    155197    d_byte_offset(0), d_partial_byte(0), 
    156     d_resid(0), d_nresid(0) 
     198    d_resid(0), d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain), 
     199    d_eq_gain(0.05) 
    157200{ 
    158201  d_bytes_out = new unsigned char[d_occupied_carriers]; 
     202  d_dfe.resize(occupied_carriers); 
     203  fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); 
    159204 
    160205  set_sym_value_out(sym_position, sym_value_out); 
     
    180225  d_sym_position  = sym_position; 
    181226  d_sym_value_out = sym_value_out; 
    182   d_nbits = (unsigned long)(log10(d_sym_value_out.size()) / log10(2)); 
     227  d_nbits = (unsigned long)ceil(log10(d_sym_value_out.size()) / log10(2.0)); 
    183228 
    184229  return true; 
     
    195240  unsigned int j = 0; 
    196241  unsigned int bytes=0; 
     242 
     243  // If the output is connected, send it the derotated symbols 
     244  if(output_items.size() >= 1) 
     245    d_derotated_output = (gr_complex *)output_items[0]; 
     246  else 
     247    d_derotated_output = NULL; 
    197248   
    198249  if (VERBOSE) 
    199250    fprintf(stderr,">>> Entering state machine\n"); 
    200    
    201   bytes = demapper(&in[0], d_bytes_out); 
    202    
     251 
    203252  switch(d_state) { 
    204253       
     
    213262 
    214263  case STATE_HAVE_SYNC: 
     264    // only demod after getting the preamble signal; otherwise, the  
     265    // equalizer taps will screw with the PLL performance 
     266    bytes = demapper(&in[0], d_bytes_out); 
     267     
    215268    if (VERBOSE) { 
    216269      if(sig[0]) 
     
    259312       
    260313  case STATE_HAVE_HEADER: 
     314    bytes = demapper(&in[0], d_bytes_out); 
     315 
    261316    if (VERBOSE) { 
    262317      if(sig[0]) 
     
    289344     
    290345  } // switch 
    291    
     346 
    292347  return 1; 
    293348} 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.h

    r6113 r7324  
    3333gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,  
    3434                         const std::vector<unsigned char> &sym_value_out, 
    35                          gr_msg_queue_sptr target_queue, unsigned int occupied_tones); 
     35                         gr_msg_queue_sptr target_queue, unsigned int occupied_tones, 
     36                         float phase_gain=0.25, float freq_gain=0.25*0.25/4.0); 
    3637 
    3738/*! 
     
    4849  gr_make_ofdm_frame_sink (const std::vector<gr_complex> &sym_position,  
    4950                           const std::vector<unsigned char> &sym_value_out, 
    50                            gr_msg_queue_sptr target_queue, unsigned int occupied_tones); 
     51                           gr_msg_queue_sptr target_queue, unsigned int occupied_tones, 
     52                           float phase_gain, float freq_gain); 
    5153 
    5254 private: 
     
    7274  int                d_packetlen_cnt;           // how many so far 
    7375 
     76  gr_complex * d_derotated_output;  // Pointer to output stream to send deroated symbols out 
     77 
    7478  std::vector<gr_complex>    d_sym_position; 
    7579  std::vector<unsigned char> d_sym_value_out; 
     80  std::vector<gr_complex>    d_dfe; 
    7681  unsigned int d_nbits; 
    7782 
    7883  unsigned char d_resid; 
    7984  unsigned int d_nresid; 
     85  float d_phase; 
     86  float d_freq; 
     87  float d_phase_gain; 
     88  float d_freq_gain; 
     89  float d_eq_gain; 
    8090 
    8191 protected: 
    8292  gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,  
    8393                     const std::vector<unsigned char> &sym_value_out, 
    84                      gr_msg_queue_sptr target_queue, unsigned int occupied_tones); 
     94                     gr_msg_queue_sptr target_queue, unsigned int occupied_tones, 
     95                     float phase_gain, float freq_gain); 
    8596 
    8697  void enter_search(); 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_frame_sink.i

    r6113 r7324  
    2626gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,  
    2727                        const std::vector<unsigned char> &sym_value_out, 
    28                         gr_msg_queue_sptr target_queue, unsigned int occupied_tones); 
     28                        gr_msg_queue_sptr target_queue, unsigned int occupied_tones, 
     29                        float phase_gain=0.25, float freq_gain=0.25*0.25/4); 
    2930 
    3031class gr_ofdm_frame_sink : public gr_sync_block 
     
    3334  gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,  
    3435                     const std::vector<unsigned char> &sym_value_out, 
    35                      gr_msg_queue_sptr target_queue, unsigned int occupied_tones); 
     36                     gr_msg_queue_sptr target_queue, unsigned int occupied_tones, 
     37                     float phase_gain, float freq_gain); 
    3638 
    3739 public: 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_mapper_bcv.cc

    r6113 r7324  
    5555  if (!(d_occupied_carriers <= d_fft_length)) 
    5656    throw std::invalid_argument("gr_ofdm_mapper_bcv: occupied carriers must be <= fft_length"); 
    57  
    58   d_nbits = (unsigned long)(log10(d_constellation.size()) / log10(2)); 
     57   
     58  d_nbits = (unsigned long)ceil(log10(d_constellation.size()) / log10(2.0)); 
    5959} 
    6060 
  • gnuradio/trunk/gnuradio-core/src/lib/general/gr_ofdm_sampler.cc

    r6113 r7324  
    6666  gr_complex *optr = (gr_complex *) output_items[0]; 
    6767 
    68   int found=0
     68  int found=0, index=0
    6969 
    7070  int i=d_fft_length-1; 
    7171 
    72   while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) { 
    73     if(trigger[i]) 
     72  // FIXME: This is where we miss if the regeneration happens too soon. 
     73  //while(!found && i<std::min(ninput_items[0],ninput_items[1]) ) { 
     74  while(i<std::min(ninput_items[0],ninput_items[1]) ) { 
     75    if(trigger[i]) { 
    7476      found = 1; 
     77      index = i++; 
     78    } 
    7579    else 
    7680      i++; 
    7781  } 
    78  
     82   
    7983  if(found) { 
    80     assert(i-d_fft_length+1 >= 0); 
    81     for(int j=i-d_fft_length+1;j<=i;j++) 
     84    assert(index-d_fft_length+1 >= 0); 
     85    for(int j=index - d_fft_length + 1; j <= index; j++) 
    8286      *optr++ = iptr[j]; 
    83     consume_each(i-d_fft_length+2); 
     87    consume_each(index - d_fft_length + 2); 
    8488    //printf("OFDM Sampler found:  ninput_items: %d/%d   noutput_items: %d  consumed: %d   found: %d\n",  
    8589    //   ninput_items[0], ninput_items[1], noutput_items, (i-d_fft_length+2), found); 
  • gnuradio/trunk/gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am

    r6649 r7324  
    4141        nbfm_rx.py              \ 
    4242        nbfm_tx.py              \ 
     43        ofdm.py                 \ 
     44        ofdm_receiver.py        \ 
     45        ofdm_sync_fixed.py      \ 
     46        ofdm_sync_pn.py         \ 
     47        ofdm_sync_pnac.py       \ 
     48        ofdm_sync_ml.py         \ 
    4349        pkt.py                  \ 
    4450        psk.py                  \ 
  • gnuradio/trunk/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am

    r6044 r7324  
    4141        nbfm_rx.py              \ 
    4242        nbfm_tx.py              \ 
    43         ofdm.py                 \ 
    44         ofdm_receiver.py        \ 
    45         ofdm_sync_fixed.py      \ 
    46         ofdm_sync_ml.py         \ 
    47         ofdm_sync_pnac.py       \ 
    48         ofdm_sync_pn.py         \ 
    4943        pkt.py                  \ 
    5044        psk.py                  \ 
  • gnuradio/trunk/gnuradio-core/src/utils/gr_plot_char.py

    r7320 r7324  
    6868         
    6969    def get_data(self): 
    70         self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//4)) 
     70        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell())) 
    7171        f = scipy.fromfile(self.hfile, dtype=scipy.int8, count=self.block_length) 
    7272        #print "Read in %d items" % len(self.f) 
  • gnuradio/trunk/gnuradio-core/src/utils/gr_plot_const.py

    r6044 r7324  
    2121#  
    2222 
    23 import pylab, math 
     23import scipy 
    2424from pylab import * 
    25 import struct, sy
     25from matplotlib.font_manager import fontManager, FontPropertie
    2626from optparse import OptionParser 
    2727 
    28 import gr_read_binary 
     28matplotlib.interactive(True) 
     29matplotlib.use('TkAgg') 
    2930 
    30 class zoom: 
    31     def __init__(self, xdata, reals, imags, sp_iq, sp_const, plot_const, manager): 
    32         self.sp_iq = sp_iq 
    33         self.sp_const = sp_const 
    34         self.xaxis = xdata 
    35         self.reals = reals 
    36         self.imags = imags 
    37         self.plot_const = plot_const 
    38         self.manager = manager 
     31class draw_constellation: 
     32    def __init__(self, filename, options): 
     33        self.hfile = open(filename, "r") 
     34        self.block_length = options.block 
     35        self.start = options.start 
     36        self.sample_rate = options.sample_rate 
     37 
     38        self.axis_font_size = 16 
     39        self.label_font_size = 18 
     40        self.title_font_size = 20 
     41 
     42        # Setup PLOT 
     43        self.fig = figure(1, figsize=(16, 9), facecolor='w') 
     44        rcParams['xtick.labelsize'] = self.axis_font_size 
     45        rcParams['ytick.labelsize'] = self.axis_font_size 
     46         
     47        self.text_file     = figtext(0.10, 0.95, ("File: %s" % filename), weight="heavy", size=16) 
     48        self.text_file_pos = figtext(0.10, 0.90, "File Position: ", weight="heavy", size=16) 
     49        self.text_block    = figtext(0.40, 0.90, ("Block Size: %d" % self.block_length), 
     50                                     weight="heavy", size=16)         
     51        self.text_sr       = figtext(0.60, 0.90, ("Sample Rate: %.2f" % self.sample_rate), 
     52                                     weight="heavy", size=16) 
     53        self.make_plots() 
     54 
     55        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True) 
     56        self.button_left = Button(self.button_left_axes, "<") 
     57        self.button_left_callback = self.button_left.on_clicked(self.button_left_click) 
     58 
     59        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True) 
     60        self.button_right = Button(self.button_right_axes, ">") 
     61        self.button_right_callback = self.button_right.on_clicked(self.button_right_click) 
    3962 
    4063        self.xlim = self.sp_iq.get_xlim() 
    41             
    42     def __call__(self, event): 
     64 
     65        self.manager = get_current_fig_manager() 
     66        connect('draw_event', self.zoom) 
     67        connect('key_press_event', self.click) 
     68        show() 
     69 
     70    def get_data(self): 
     71        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//8)) 
     72        iq = scipy.fromfile(self.hfile, dtype=scipy.complex64, count=self.block_length) 
     73        #print "Read in %d items" % len(iq) 
     74        if(len(iq) == 0): 
     75            print "End of File" 
     76        else: 
     77            self.reals = [r.real for r in iq] 
     78            self.imags = [i.imag for i in iq] 
     79 
     80            self.time = [i*(1/self.sample_rate) for i in range(len(self.reals))] 
     81             
     82    def make_plots(self): 
     83        # if specified on the command-line, set file pointer 
     84        self.hfile.seek(16*self.start, 1) 
     85 
     86        self.get_data() 
     87         
     88        # Subplot for real and imaginary parts of signal 
     89        self.sp_iq = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.4, 0.6]) 
     90        self.sp_iq.set_title(("I&Q"), fontsize=self.title_font_size, fontweight="bold") 
     91        self.sp_iq.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold") 
     92        self.sp_iq.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, fontweight="bold") 
     93        self.plot_iq = plot(self.time, self.reals, 'bo-', self.time, self.imags, 'ro-') 
     94        self.sp_iq.axis([min(self.time), max(self.time), 
     95                         1.5*min([min(self.reals), min(self.imags)]), 
     96                         1.5*max([max(self.reals), max(self.imags)])]) 
     97 
     98        # Subplot for constellation plot 
     99        self.sp_const = self.fig.add_subplot(2,2,1, position=[0.575, 0.2, 0.4, 0.6]) 
     100        self.sp_const.set_title(("Constellation"), fontsize=self.title_font_size, fontweight="bold") 
     101        self.sp_const.set_xlabel("Inphase", fontsize=self.label_font_size, fontweight="bold") 
     102        self.sp_const.set_ylabel("Qaudrature", fontsize=self.label_font_size, fontweight="bold") 
     103        self.plot_const = plot(self.reals, self.imags, 'bo') 
     104        self.sp_const.axis([-2, 2, -2, 2]) 
     105 
     106        draw() 
     107 
     108    def update_plots(self): 
     109        self.plot_iq[0].set_data([self.time, self.reals]) 
     110        self.plot_iq[1].set_data([self.time, self.imags]) 
     111        self.sp_iq.axis([min(self.time), max(self.time), 
     112                         1.5*min([min(self.reals), min(self.imags)]), 
     113                         1.5*max([max(self.reals), max(self.imags)])]) 
     114 
     115        self.plot_const[0].set_data([self.reals, self.imags]) 
     116        self.sp_const.axis([-2, 2, -2, 2]) 
     117        draw() 
     118         
     119    def zoom(self, event): 
    43120        newxlim = self.sp_iq.get_xlim() 
    44  
    45121        if(newxlim != self.xlim): 
    46122            self.xlim = newxlim 
    47             r = self.reals[int(self.xlim[0]) : int(self.xlim[1])] 
    48             i = self.imags[int(self.xlim[0]) : int(self.xlim[1])] 
     123            r = self.reals[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))] 
     124            i = self.imags[int(ceil(self.xlim[0])) : int(ceil(self.xlim[1]))] 
    49125 
    50126            self.plot_const[0].set_data(r, i) 
    51127            self.sp_const.axis([-2, 2, -2, 2]) 
    52128            self.manager.canvas.draw() 
     129            draw() 
     130 
     131    def click(self, event): 
     132        forward_valid_keys = [" ", "down", "right"] 
     133        backward_valid_keys = ["up", "left"] 
     134 
     135        if(find(event.key, forward_valid_keys)): 
     136            self.step_forward() 
    53137             
     138        elif(find(event.key, backward_valid_keys)): 
     139            self.step_backward() 
     140 
     141    def button_left_click(self, event): 
     142        self.step_backward() 
     143 
     144    def button_right_click(self, event): 
     145        self.step_forward() 
     146 
     147    def step_forward(self): 
     148        self.get_data() 
     149        self.update_plots() 
     150 
     151    def step_backward(self): 
     152        # Step back in file position 
     153        if(self.hfile.tell() >= 16*self.block_length ): 
     154            self.hfile.seek(-16*self.block_length, 1) 
     155        else: 
     156            self.hfile.seek(-self.hfile.tell(),1) 
     157        self.get_data() 
     158        self.update_plots() 
     159         
     160             
     161 
     162#FIXME: there must be a way to do this with a Python builtin 
     163def find(item_in, list_search): 
     164    for l in list_search: 
     165        if item_in == l: 
     166            return True 
     167    return False 
     168 
    54169def main(): 
    55     usage="%prog: [options] output_filename" 
    56     parser = OptionParser(conflict_handler="resolve", usage=usage) 
    57     parser.add_option("-s", "--size", type="int", default=None, 
    58                       help="Specify the number of points to plot [default=%default]") 
    59     parser.add_option("", "--skip", type="int", default=None, 
    60                       help="Specify the number of points to skip [default=%default]") 
     170    usage="%prog: [options] input_filename" 
     171    description = "Takes a GNU Radio complex binary file and displays the I&Q data versus time and the constellation plot (I vs. Q). You can set the block size to specify how many points to read in at a time and the start position in the file. By default, the system assumes a sample rate of 1, so in time, each sample is plotted versus the sample number. To set a true time axis, set the sample rate (-R or --sample-rate) to the sample rate used when capturing the samples." 
    61172 
     173    parser = OptionParser(conflict_handler="resolve", usage=usage, description=description) 
     174    parser.add_option("-B", "--block", type="int", default=1000, 
     175                      help="Specify the block size [default=%default]") 
     176    parser.add_option("-s", "--start", type="int", default=0, 
     177                      help="Specify where to start in the file [default=%default]") 
     178    parser.add_option("-R", "--sample-rate", type="float", default=1.0, 
     179                      help="Set the sampler rate of the data [default=%default]") 
     180     
    62181    (options, args) = parser.parse_args () 
    63182    if len(args) != 1: 
     
    66185    filename = args[0] 
    67186 
    68     iq = gr_read_binary.read_complex_binary(filename) 
    69  
    70     if(options.skip is None): 
    71         options.skip = 0 
    72      
    73     if((options.size is None) or ((options.skip+options.size) > len(iq[0]))): 
    74         options.size = len(iq[0]) - options.skip 
    75  
    76     reals = iq[0][options.skip : options.skip + options.size] 
    77     imags = iq[1][options.skip : options.skip + options.size] 
    78     x = range(options.skip, options.skip + options.size) 
    79      
    80     # PLOT 
    81     f = figure(1, figsize=(16, 12), facecolor='w') 
    82     rcParams['xtick.labelsize'] = 16 
    83     rcParams['ytick.labelsize'] = 16 
    84  
    85     # Subplot for real and imaginary parts of signal 
    86     sp1 = f.add_subplot(2,1,1) 
    87     sp1.set_title(("I&Q"), fontsize=26, fontweight="bold") 
    88     sp1.set_xlabel("Time (s)", fontsize=20, fontweight="bold") 
    89     sp1.set_ylabel("Amplitude (V)", fontsize=20, fontweight="bold") 
    90     plot(x, reals, 'bo-', x, imags, 'ro-') 
    91  
    92     # Subplot for constellation plot 
    93     sp2 = f.add_subplot(2,1,2) 
    94     sp2.set_title(("Constellation"), fontsize=26, fontweight="bold") 
    95     sp2.set_xlabel("Inphase", fontsize=20, fontweight="bold") 
    96     sp2.set_ylabel("Qaudrature", fontsize=20, fontweight="bold") 
    97     p2 = plot(reals, imags, 'bo') 
    98     sp2.axis([-2, 2, -2, 2]) 
    99      
    100     manager = get_current_fig_manager() 
    101     zm = zoom(x, reals, imags, sp1, sp2, p2, manager) 
    102     connect('draw_event', zm) 
    103      
    104     show() 
     187    dc = draw_constellation(filename, options) 
    105188 
    106189if __name__ == "__main__": 
  • gnuradio/trunk/gnuradio-core/src/utils/gr_plot_float.py

    r6044 r7324  
    2121#  
    2222 
    23 import pylab, math 
     23import scipy 
    2424from pylab import * 
    25 import struct, sys 
    2625from optparse import OptionParser 
    2726 
    28 import gr_read_binary 
     27matplotlib.interactive(True) 
     28matplotlib.use('TkAgg') 
     29 
     30class draw_fft_c: 
     31    def __init__(self, filename, options): 
     32        self.hfile = open(filename, "r") 
     33        self.block_length = options.block 
     34        self.start = options.start 
     35        self.sample_rate = options.sample_rate 
     36 
     37        self.axis_font_size = 16 
     38        self.label_font_size = 18 
     39        self.title_font_size = 20 
     40        self.text_size = 22 
     41 
     42        # Setup PLOT 
     43        self.fig = figure(1, figsize=(16, 9), facecolor='w') 
     44        rcParams['xtick.labelsize'] = self.axis_font_size 
     45        rcParams['ytick.labelsize'] = self.axis_font_size 
     46         
     47        self.text_file     = figtext(0.10, 0.94, ("File: %s" % filename), weight="heavy", size=self.text_size) 
     48        self.text_file_pos = figtext(0.10, 0.88, "File Position: ", weight="heavy", size=self.text_size) 
     49        self.text_block    = figtext(0.40, 0.88, ("Block Size: %d" % self.block_length), 
     50                                     weight="heavy", size=self.text_size) 
     51        self.text_sr       = figtext(0.60, 0.88, ("Sample Rate: %.2f" % self.sample_rate), 
     52                                     weight="heavy", size=self.text_size) 
     53        self.make_plots() 
     54 
     55        self.button_left_axes = self.fig.add_axes([0.45, 0.01, 0.05, 0.05], frameon=True) 
     56        self.button_left = Button(self.button_left_axes, "<") 
     57        self.button_left_callback = self.button_left.on_clicked(self.button_left_click) 
     58 
     59        self.button_right_axes = self.fig.add_axes([0.50, 0.01, 0.05, 0.05], frameon=True) 
     60        self.button_right = Button(self.button_right_axes, ">") 
     61        self.button_right_callback = self.button_right.on_clicked(self.button_right_click) 
     62 
     63        self.xlim = self.sp_f.get_xlim() 
     64 
     65        self.manager = get_current_fig_manager() 
     66        connect('key_press_event', self.click) 
     67        show() 
     68         
     69    def get_data(self): 
     70        self.text_file_pos.set_text("File Position: %d" % (self.hfile.tell()//4)) 
     71        f = scipy.fromfile(self.hfile, dtype=scipy.float32, count=self.block_length) 
     72        #print "Read in %d items" % len(self.f) 
     73        if(len(f) == 0): 
     74            print "End of File" 
     75        else: 
     76            self.f = f 
     77            self.time = [i*(1/self.sample_rate) for i in range(len(self.f))] 
     78         
     79    def make_plots(self): 
     80        # if specified on the command-line, set file pointer 
     81        self.hfile.seek(8*self.start, 1) 
     82 
     83        self.get_data() 
     84         
     85        # Subplot for real and imaginary parts of signal 
     86        self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 0.6]) 
     87        self.sp_f.set_title(("Amplitude"), fontsize=self.title_font_size, fontweight="bold") 
     88        self.sp_f.set_xlabel("Time (s)", fontsize=self.label_font_size, fontweight="bold") 
     89        self.sp_f.set_ylabel("Amplitude (V)", fontsize=self.label_font_size, fontweight="bold") 
     90        self.plot_f = plot(self.time, self.f, 'bo-') 
     91        self.sp_f.set_ylim([1.5*min(self.f), 
     92                            1.5*max(self.f)]) 
     93 
     94        draw() 
     95 
     96    def update_plots(self): 
     97        self.plot_f[0].set_data([self.time, self.f]) 
     98        self.sp_f.set_ylim([1.5*min(self.f), 
     99                            1.5*max(self.f)]) 
     100        draw() 
     101         
     102    def click(self, event): 
     103        forward_valid_keys = [" ", "down", "right"] 
     104        backward_valid_keys = ["up", "left"] 
     105 
     106        if(find(event.key, forward_valid_keys)): 
     107            self.step_forward() 
     108             
     109        elif(find(event.key, backward_valid_keys)): 
     110            self.step_backward() 
     111 
     112    def button_left_click(self, event): 
     113        self.step_backward() 
     114 
     115    def button_right_click(self, event): 
     116        self.step_forward() 
     117 
     118    def step_forward(self): 
     119        self.get_data() 
     120        self.update_plots() 
     121 
     122    def step_backward(self): 
     123        # Step back in file position 
     124        if(self.hfile.tell() >= 8*self.block_length ): 
     125            self.hfile.seek(-8*self.block_length, 1) 
     126        else: 
     127            self.hfile.seek(-self.hfile.tell(),1) 
     128        self.get_data() 
     129        self.update_plots() 
     130         
     131             
     132 
     133#FIXME: there must be a way to do this with a Python builtin 
     134def find(item_in, l