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

VrScopeSink.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 an oscilloscope.
00019  * VrScopeSink inherits from VrSink, whereas VrGUI inherits from QWidget.
00020  */
00021 
00022 #ifndef _VRSCOPESINK_H_
00023 #define _VRSCOPESINK_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 TRIGGER_SAMPLES         6000    // samples to check for new trigger
00038 #define TRIGGER_SENSITIVITY     0.9         // fraction of maximum value seen in signal
00039 #define XAXIS_NAME                      "Time divisions"
00040 #define YAXIS_NAME                      "Amplitude"
00041 
00042 enum ScopeSinkState { TRIGGER_SETTING, TRIGGER_WAITING, DISPLAYING, SKIPPING };
00043 
00044 template<class iType> 
00045 class VrScopeSink : public VrSink<iType> {
00046 
00047  public:
00048   virtual const char *name() { return "VrScopeSink"; }
00049   virtual void initialize();
00050   void clear() {display->clear(); }
00051   void set_persistent(int arg_persistent) {display->set_persistent(arg_persistent); }
00052   virtual int work3(VrSampleRange output, 
00053                     VrSampleRange inputs[], void *i[]);
00054   static const int maxnPoints = 1000;   // number of points to plot
00055   VrScopeSink(VrGUILayout *layout, float arg_default,
00056         int arg_min, int arg_max, int arg_nPoints = maxnPoints, int arg_no_wait = 0);
00057   ~VrScopeSink();
00058   void setScale(float arg_scale);
00059   void setRun(int r) {run = r;};
00060   void setSkip(int arg_inc, int arg_between);
00061   void setPoints(int arg_nPoints);
00062         static const int divisions = 10;        // number of x-axis divisions
00063 
00064  private:
00065   double    tpd;        // time per x-axis division (microseconds)
00066   double   *amplitude;          // amplitudes to plot on y-axis
00067   double    samplingFrequency;  // samples/microsecond
00068   int       samplesAvailable;   // for work procedure
00069   int       skipWork;
00070   int       skipIncrement;
00071   int       skipBetween;
00072   int       nPoints;    // max number of points to plot
00073   int       current_nPoints;    // number of points to plot
00074   int       run;
00075 
00076   VrGUIPlot     *display;
00077   int       ymin, ymax;         // possible range of sample values
00078   int       sampleValue;        // value of last sample
00079   double    trigger;            // amplitude to trigger new display
00080 
00081   ScopeSinkState state;         // how next sample will be used
00082   ScopeSinkState prevState;     // how last sample was used
00083                                 // TRIGGER_SETTING, TRIGGER_WAITING
00084   double maxAmplitude;          // base for setting new trigger
00085   int    triggerCount;          // samples to check before resetting trigger
00086                                 // DISPLAYING
00087   int    nextPoint;             // index of next point to generate for graph
00088   double *xValues;
00089   int no_wait;
00090   int first_time_collect;
00091 
00092   void setTrigger(iType *i[]);
00093   void findTrigger(iType *i[]);
00094   void collectData(iType *i[]);
00095   void skipData(iType *i[]);
00096 
00097 };
00098 
00099 /*****************************************************************************
00100  * Implementation of template (C++ requires it to be in .h file).
00101  ****************************************************************************/
00102 
00103 
00104 /*
00105  * Creates a new VrScopeSink.
00106  */
00107 template<class iType>
00108 VrScopeSink<iType>::VrScopeSink(VrGUILayout *layout, float arg_default,
00109         int arg_min, int arg_max, int arg_nPoints, int arg_no_wait)
00110 {
00111   nPoints = arg_nPoints;
00112   current_nPoints = nPoints;
00113   amplitude = new double[nPoints+1];
00114   xValues = new double[nPoints];
00115   for (int i = 0; i < nPoints; i++)
00116                 xValues[i] = i;
00117   no_wait = arg_no_wait;
00118   ymin = arg_min;
00119   ymax = arg_max;
00120   trigger = ymax/TRIGGER_SENSITIVITY; // set high to force recomputation
00121   display = new VrGUIPlot (layout, XAXIS_NAME, YAXIS_NAME, 1,
00122                 0, nPoints, ymin, ymax, nPoints, divisions);
00123   tpd = arg_default;
00124   setOptimalSize(nPoints);
00125 }
00126 
00127 template<class iType> void
00128 VrScopeSink<iType>::initialize()
00129 {
00130   samplingFrequency = getInputSamplingFrequencyN(0)/1000000;
00131   setScale(tpd);
00132   run =1 ;
00133 }
00134 
00135 template<class iType> int
00136 VrScopeSink<iType>::work3(VrSampleRange output, 
00137                           VrSampleRange inputs[], void *ai[])
00138 {
00139   iType **i = (iType **)ai;
00140   sync(output.index);
00141   samplesAvailable = output.size;
00142   while (samplesAvailable > 0) {
00143     switch (state) {
00144     case TRIGGER_SETTING:
00145       setTrigger(i);
00146       break;
00147     case TRIGGER_WAITING:
00148       findTrigger(i);
00149       break;
00150     case DISPLAYING:
00151       collectData(i);
00152       break;
00153     case SKIPPING:
00154       skipData(i);
00155       break;
00156     }
00157   }
00158   return output.size;
00159 }
00160 
00161 /*
00162  * Records maximum amplitude of signal seen in TRIGGER_SAMPLES settings.
00163  */
00164 template<class iType> void
00165 VrScopeSink<iType>::setTrigger(iType *i[]) {
00166   if (prevState != state) {
00167     #if DEBUG1
00168     cerr << "Setting trigger value." << endl;
00169     #endif
00170     prevState = state;
00171     triggerCount = TRIGGER_SAMPLES;
00172     maxAmplitude = (double)ymin;
00173   }
00174   if (triggerCount-- <= 0) {
00175     trigger = TRIGGER_SENSITIVITY*maxAmplitude;
00176     state = TRIGGER_WAITING;
00177   } else {
00178     
00179     sampleValue = (int)*i[0]++;
00180     samplesAvailable--;
00181     if (sampleValue > maxAmplitude) maxAmplitude = (double)sampleValue;
00182   }
00183 } 
00184 
00185 /*
00186  * If triggerCount > 0, gets the next sample and compares it with both the
00187  * last sample and the trigger.  Sets the state to DISPLAYING if it is
00188  * greater than both.  Sets the state to TRIGGER_SETTING if triggerCount = 0.
00189  */
00190 template<class iType> void
00191 VrScopeSink<iType>::findTrigger(iType *i[]) {
00192   if (prevState != state) {
00193     #if DEBUG1
00194     cerr << "Waiting for trigger value." << endl;
00195     #endif
00196     prevState = state;
00197     triggerCount = TRIGGER_SAMPLES;
00198     sampleValue = ymax;
00199   }
00200   if (triggerCount-- <= 0) {
00201     state = TRIGGER_SETTING;
00202   } else {
00203     int lastValue = sampleValue;
00204     sampleValue = (int)*i[0]++;
00205     samplesAvailable--;
00206     if (sampleValue > trigger && sampleValue > lastValue) state = DISPLAYING;
00207   }
00208 }
00209 
00210 /*
00211  * Acquires the next point to plot on the graph.  Displays the graph when
00212  * all points are acquired.
00213  */
00214 template<class iType> void
00215 VrScopeSink<iType>::collectData(iType *i[]) {
00216   //cout << "collect data: " << nextPoint << "  " << current_nPoints << endl;
00217   if (first_time_collect) {
00218     #if DEBUG1
00219     cerr << "Acquiring data." << endl;
00220     #endif
00221     prevState = state;
00222     nextPoint = 0;
00223     skipWork = skipIncrement + skipBetween;
00224         first_time_collect = 0;
00225   }
00226   //  cout << skipWork << endl;
00227   if (nextPoint <= current_nPoints)  {
00228     // Fix: have source skip proper number of values instead of using a loop
00229     while (skipWork > 0) {
00230       if (samplesAvailable-- <= 0) return;
00231       sampleValue = (int)*i[0]++;   // Fix: eliminate loop? just bump counter?
00232       skipWork--;
00233     }
00234     amplitude[nextPoint++] = (double)sampleValue;
00235     //cout << "read " << sampleValue << " from " << (int) i[0]-1 << endl;
00236     //cout << (double) sampleValue << endl;
00237     skipWork = skipIncrement;
00238     //cout << skipWork << " " << skipIncrement << endl;
00239   }
00240   if (nextPoint >= current_nPoints)  {
00241     //cout << "display" << cout ;
00242     if (run) display->data(xValues, amplitude, current_nPoints);  // mlw
00243         first_time_collect = 1;
00244         if (!no_wait)
00245         state = SKIPPING;
00246   }
00247 }
00248 template<class iType> void
00249 VrScopeSink<iType>::setScale(float arg_scale)
00250 {
00251   tpd = arg_scale;
00252   //  skipIncrement = (int) (((double)tpd*divisions*samplingFrequency)/current_nPoints);
00253   skipBetween = 0;
00254   state = TRIGGER_WAITING;
00255   if (no_wait)
00256         state = DISPLAYING;
00257   first_time_collect = 1;
00258   triggerCount = 0;
00259 }
00260 template<class iType> void
00261 VrScopeSink<iType>::setSkip(int arg_inc, int arg_between)
00262 {
00263   skipIncrement = arg_inc;
00264   skipBetween = arg_between;
00265   //  cout << "setting:  " << skipIncrement << " " << skipBetween << endl;
00266 
00267   state = TRIGGER_WAITING;
00268   if (no_wait)
00269         state = DISPLAYING;
00270   first_time_collect = 1;
00271   triggerCount = 0;
00272 }
00273 template<class iType> void
00274 VrScopeSink<iType>::setPoints(int arg_nPoints)
00275 {
00276   if (arg_nPoints < nPoints)
00277         current_nPoints = arg_nPoints;
00278   else
00279         printf (stderr, "setPoints %d exceeds max %d\n", arg_nPoints, nPoints);
00280 }
00281 
00282 template<class iType> void
00283 VrScopeSink<iType>::skipData(iType *i[]) {
00284   if (prevState != state) {
00285     prevState = state;
00286     #if DEBUG1
00287     cerr << "Skipping data." << endl;
00288     #endif
00289   }
00290   state = TRIGGER_WAITING;
00291   // Fix: tell the scheduler to ignore some number of samples
00292 }
00293 
00294 template<class iType> 
00295 VrScopeSink<iType>::~VrScopeSink()
00296 {
00297   delete[] amplitude;
00298 }
00299 #endif
00300 
00301 
00302 

Generated on Wed Mar 23 12:30:26 2005 for GNU Radio by  doxygen 1.4.0