Main Page | Namespace List | Class Hierarchy | Class List | 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 Aug 4 02:22:05 2004 for GNU Radio by doxygen 1.3.8