Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

VrPointSink.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*-
00002  *
00003  *  Copyright 1999 Massachusetts Institute of Technology
00004  * 
00005  *  Permission to use, copy, modify, distribute, and sell this software and its
00006  *  documentation for any purpose is hereby granted without fee, provided that
00007  *  the above copyright notice appear in all copies and that both that
00008  *  copyright notice and this permission notice appear in supporting
00009  *  documentation, and that the name of M.I.T. not be used in advertising or
00010  *  publicity pertaining to distribution of the software without specific,
00011  *  written prior permission.  M.I.T. makes no representations about the
00012  *  suitability of this software for any purpose.  It is provided "as is"
00013  *  without express or implied warranty.
00014  * 
00015  */
00016 
00017 /*
00018  * Interface to a Virtual Radio sink connected to a GUI for a constellation plot.
00019  * VrPointSink inherits from VrSink, whereas VrGUI inherits from QWidget.
00020  */
00021 
00022 #ifndef _VRPOINTSINK_H_
00023 #define _VRPOINTSINK_H_
00024 
00025 #include <VrSink.h>
00026 #include "VrGUI.h"
00027 
00028 #define DEBUG1 0
00029 #define DEBUG2 0
00030 
00031 extern "C" {
00032 #include <dlfcn.h>
00033 #include <float.h>
00034 #include <math.h>
00035            }
00036 
00037 #define XAXIS_NAME                      "In-phase"
00038 #define YAXIS_NAME                      "Quadrature"
00039 
00040 enum PointSinkState { TRIGGER_SETTING, TRIGGER_WAITING, DISPLAYING, SKIPPING };
00041 
00042 class VrPointSink : public VrSink<VrComplex> {
00043 
00044  public:
00045   virtual const char *name() { return "VrPointSink"; }
00046   virtual void initialize();
00047   void clear() {display->clear(); }
00048   void set_persistent(int arg_persistent) {display->set_persistent(arg_persistent); }
00049   virtual int work(VrSampleRange output, 
00050                    VrSampleRange inputs[], void *i[]);
00051   static const int maxnPoints = 1000;   // number of points to plot
00052   VrPointSink(VrGUILayout *layout,
00053         int arg_min, int arg_max, int arg_nPoints = maxnPoints, int arg_no_wait = 0);
00054   //void ~VrPointSink();
00055   void setRun(int r) {run = r;};
00056   void setSkip(int arg_inc, int arg_between);
00057   void setPoints(int arg_nPoints);
00058         static const int divisions = 10;        // number of x-axis divisions
00059 
00060  private:
00061   double    tpd;        // time per x-axis division (microseconds)
00062   double    samplingFrequency;  // samples/microsecond
00063   int       samplesAvailable;   // for work procedure
00064   int       skipWork;
00065   int       skipIncrement;
00066   int       skipBetween;
00067   int       nPoints;    // max number of points to plot
00068   int       current_nPoints;    // number of points to plot
00069   int       run;
00070 
00071   VrGUIPlot     *display;
00072   int       ymin, ymax;         // possible range of sample values
00073   int       xmin, xmax;         // possible range of sample values
00074   VrComplex sampleValue;        // value of last sample
00075   double    trigger;            // amplitude to trigger new display
00076 
00077   PointSinkState state;         // how next sample will be used
00078   PointSinkState prevState;     // how last sample was used
00079                                 // TRIGGER_SETTING, TRIGGER_WAITING
00080   double maxAmplitude;          // base for setting new trigger
00081   int    triggerCount;          // samples to check before resetting trigger
00082                                 // DISPLAYING
00083   int    nextPoint;             // index of next point to generate for graph
00084   double *xValues;
00085   double *yValues;
00086   int no_wait;
00087   int first_time_collect;
00088 
00089   //  void setTrigger(iType *i[]);
00090   //  void findTrigger(iType *i[]);
00091   void collectData(VrComplex *i[]);
00092   void skipData(VrComplex *i[]);
00093 
00094 };
00095 
00096 /*****************************************************************************
00097  * Implementation of template (C++ requires it to be in .h file).
00098  ****************************************************************************/
00099 
00100 
00101 /*
00102  * Creates a new VrPointSink.
00103  */
00104 VrPointSink::VrPointSink(VrGUILayout *layout,
00105         int arg_min, int arg_max, int arg_nPoints, int arg_no_wait)
00106 {
00107   nPoints = arg_nPoints;
00108   current_nPoints = nPoints;
00109   yValues = new double[nPoints+1];
00110   xValues = new double[nPoints];
00111   no_wait = arg_no_wait;
00112   ymin = arg_min;
00113   ymax = arg_max;
00114   xmin = 3*arg_min/2;
00115   xmax = 3*arg_max/2;
00116   //trigger = ymax/TRIGGER_SENSITIVITY; // set high to force recomputation
00117   display = new VrGUIPlot (layout, XAXIS_NAME, YAXIS_NAME, 0,
00118                 xmin, xmax, ymin, ymax, nPoints, divisions);
00119   setOptimalSize(nPoints);
00120 }
00121 
00122 void
00123 VrPointSink::initialize()
00124 {
00125   samplingFrequency = getInputSamplingFrequencyN(0)/1000000;
00126   setSkip(1,0);
00127   run =1 ;
00128 }
00129 
00130 int
00131 VrPointSink::work(VrSampleRange output, 
00132                            VrSampleRange inputs[], void *ai[])
00133 {
00134   VrComplex **i = (VrComplex **)ai;
00135   sync(output.index);
00136   samplesAvailable = output.size;
00137   while (samplesAvailable > 0) {
00138     switch (state) {
00139      case TRIGGER_SETTING:
00140       break;
00141      case TRIGGER_WAITING:
00142       break;
00143      case DISPLAYING:
00144       collectData(i);
00145       break;
00146      case SKIPPING:
00147       skipData(i);
00148       break;
00149     }
00150   }
00151   return output.size;
00152 }
00153 
00154 #if 0
00155 /*
00156  * Records maximum amplitude of signal seen in TRIGGER_SAMPLES settings.
00157  */
00158 void
00159 VrPointSink::setTrigger(iType *i[]) {
00160   if (prevState != state) {
00161     #if DEBUG1
00162     cerr << "Setting trigger value." << endl;
00163     #endif
00164     prevState = state;
00165     triggerCount = TRIGGER_SAMPLES;
00166     maxAmplitude = (double)ymin;
00167   }
00168   if (triggerCount-- <= 0) {
00169     trigger = TRIGGER_SENSITIVITY*maxAmplitude;
00170     state = TRIGGER_WAITING;
00171   } else {
00172     
00173     sampleValue = (int)*i[0]++;
00174     samplesAvailable--;
00175     if (sampleValue > maxAmplitude) maxAmplitude = (double)sampleValue;
00176   }
00177 } 
00178 
00179 /*
00180  * If triggerCount > 0, gets the next sample and compares it with both the
00181  * last sample and the trigger.  Sets the state to DISPLAYING if it is
00182  * greater than both.  Sets the state to TRIGGER_SETTING if triggerCount = 0.
00183  */
00184 void
00185 VrPointSink::findTrigger(iType *i[]) {
00186   if (prevState != state) {
00187     #if DEBUG1
00188     cerr << "Waiting for trigger value." << endl;
00189     #endif
00190     prevState = state;
00191     triggerCount = TRIGGER_SAMPLES;
00192     sampleValue = ymax;
00193   }
00194   if (triggerCount-- <= 0) {
00195     state = TRIGGER_SETTING;
00196   } else {
00197     int lastValue = sampleValue;
00198     sampleValue = (int)*i[0]++;
00199     samplesAvailable--;
00200     if (sampleValue > trigger && sampleValue > lastValue) state = DISPLAYING;
00201   }
00202 }
00203 #endif
00204 
00205 /*
00206  * Acquires the next point to plot on the graph.  Displays the graph when
00207  * all points are acquired.
00208  */
00209 void
00210 VrPointSink::collectData(VrComplex *i[]) {
00211   //cout << "collect data: " << nextPoint << "  " << current_nPoints << endl;
00212   if (first_time_collect) {
00213     #if DEBUG1
00214     cerr << "Acquiring data." << endl;
00215     #endif
00216     prevState = state;
00217     nextPoint = 0;
00218     skipWork = skipIncrement + skipBetween;
00219         first_time_collect = 0;
00220   }
00221   if (nextPoint <= current_nPoints)  {
00222     // Fix: have source skip proper number of values instead of using a loop
00223     while (skipWork > 0) {
00224       if (samplesAvailable-- <= 0) return;
00225       sampleValue = *i[0]++;   // Fix: eliminate loop? just bump counter?
00226       skipWork--;
00227     }
00228     xValues[nextPoint] = real(sampleValue);
00229     yValues[nextPoint++] = imag(sampleValue);
00230     skipWork = skipIncrement;
00231   }
00232   if (nextPoint >= current_nPoints)  {
00233     if (run) display->data(xValues, yValues, current_nPoints);  // mlw
00234         first_time_collect = 1;
00235         if (!no_wait)
00236         state = SKIPPING;
00237   }
00238 }
00239 void
00240 VrPointSink::setSkip(int arg_inc, int arg_between)
00241 {
00242   skipIncrement = arg_inc;
00243   skipBetween = arg_between;
00244 
00245   state = TRIGGER_WAITING;
00246   if (no_wait)
00247         state = DISPLAYING;
00248   first_time_collect = 1;
00249   triggerCount = 0;
00250 }
00251 void
00252 VrPointSink::setPoints(int arg_nPoints)
00253 {
00254   if (arg_nPoints < nPoints)
00255         current_nPoints = arg_nPoints;
00256   //  else
00257   //    printf (stderr, "setPoints %d exceeds max %d\n", arg_nPoints, nPoints);
00258 }
00259 
00260 void
00261 VrPointSink::skipData(VrComplex *i[]) {
00262   if (prevState != state) {
00263     prevState = state;
00264     #if DEBUG1
00265     cerr << "Skipping data." << endl;
00266     #endif
00267   }
00268   state = TRIGGER_WAITING;
00269   // Fix: tell the scheduler to ignore some number of samples
00270 }
00271 #if 0
00272 
00273 void
00274 VrPointSink::~VrPointSink()
00275 {
00276   delete[] xValues;
00277   delete[] yValues;
00278 }
00279 
00280 #endif
00281 #endif
00282 
00283 
00284 
00285 

Generated on Tue Mar 15 23:55:34 2005 for GNU Radio by  doxygen 1.4.0