1 // ---------------------------------------------------------------------------- 2 // Waterfall Spectrum Analyzer Widget 3 // Copyright (C) 2006-2010 Dave Freese, W1HKJ 4 // Copyright (C) 2008 Stelios Bounanos, M0GLD 5 // 6 // This file is part of fldigi. 7 // 8 // Fldigi is free software: you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation, either version 3 of the License, or 11 // (at your option) any later version. 12 // 13 // Fldigi is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with fldigi. If not, see <http://www.gnu.org/licenses/>. 20 // ---------------------------------------------------------------------------- 21 22 #ifndef _WF_H 23 #define _WF_H 24 25 #include <FL/Fl_Widget.H> 26 #include <FL/Fl_Group.H> 27 #include <FL/Fl_Button.H> 28 #include <FL/Fl_Light_Button.H> 29 #include <FL/Fl_Menu_Button.H> 30 #include <FL/Fl_Counter.H> 31 #include <FL/Fl_Box.H> 32 33 #include "gfft.h" 34 #include "fldigi-config.h" 35 #include "digiscope.h" 36 #include "flslider2.h" 37 38 #include <samplerate.h> 39 40 enum { 41 WF_FFT_RECTANGULAR, WF_FFT_BLACKMAN, WF_FFT_HAMMING, 42 WF_FFT_HANNING, WF_FFT_TRIANGULAR 43 }; 44 45 #define WF_FFTLEN 8192 46 #define WF_SAMPLERATE 8000 47 #define WF_BLOCKSIZE 512 48 49 struct RGB { 50 uchar R; 51 uchar G; 52 uchar B; 53 }; 54 55 struct RGBI { 56 uchar R; 57 uchar G; 58 uchar B; 59 uchar I; 60 }; 61 62 // you can change the basic fft processing type by a simple change in the 63 // following typedef. change to float if you need to skimp on cpu cycles. 64 65 typedef double wf_fft_type; 66 //typedef float wf_fft_type; 67 68 typedef std::complex<wf_fft_type> wf_cpx_type; 69 70 extern RGBI mag2RGBI[256]; 71 extern RGB palette[9]; 72 73 enum WFmode { 74 WATERFALL, 75 SPECTRUM, 76 SCOPE, 77 NUM_WF_MODES 78 }; 79 80 #define MAG_1 1 81 #define MAG_2 2 82 #define MAG_4 3 83 84 enum WFspeed { PAUSE = 0, FAST = 1, NORMAL = 2, SLOW = 4 }; 85 86 extern void do_qsy(bool); 87 88 class WFdisp : public Fl_Widget { 89 public: 90 91 WFdisp (int x, int y, int w, int h, char *lbl = 0); 92 ~WFdisp (); 93 int wfmag(); 94 int setMag(int m); 95 void setOffset(int v); 96 Mode(WFmode M)97 void Mode(WFmode M) { 98 mode = M; 99 } Mode()100 WFmode Mode() { 101 return mode; 102 } cursorFreq(int xpos)103 int cursorFreq(int xpos) { 104 return (offset + step * xpos); 105 } Ampspan(double AmpSpn)106 void Ampspan(double AmpSpn) { 107 ampspan = (int)AmpSpn; 108 } Ampspan()109 double Ampspan() { 110 return ampspan; 111 } Bandwidth(int bw)112 void Bandwidth (int bw) { 113 bandwidth = bw; 114 makeMarker(); 115 } Bandwidth()116 int Bandwidth () { 117 return bandwidth; 118 } Overload(int ovr)119 void Overload(int ovr) { 120 if (overload == ovr) return; 121 overload = ovr; 122 } 123 AudioPeak()124 double AudioPeak() { return peakaudio; } 125 Speed()126 WFspeed Speed() { return wfspeed;} Speed(WFspeed rate)127 void Speed(WFspeed rate) { 128 wfspeed = rate; 129 dispcnt = 1.0 * WF_BLOCKSIZE / WF_SAMPLERATE; 130 } 131 Mag()132 int Mag() { return mag;} Mag(int m)133 void Mag(int m) { setMag(m);} Offset()134 int Offset() { return offset;} Offset(int v)135 void Offset(int v) { setOffset(v);} 136 137 void initmaps(); 138 void draw(); 139 int handle(int event); 140 void update_sigmap(); 141 void update_waterfall(); 142 void checkoffset(); 143 void slew(int); 144 void movetocenter(); 145 void carrier(int cf); 146 int carrier(); 147 inline void makeNotch_(int notch_frequency); 148 inline void makeMarker_(int width, const RGB* color, int freq, const RGB* clrMin, RGB* clrM, const RGB* clrMax); 149 void make_fmt_marker (); 150 void makeMarker(); 151 void process_analog(wf_fft_type *sig, int len); 152 void processFFT(); 153 void sig_data(double *sig, int len); 154 void handle_sig_data(); rfcarrier(long long f)155 void rfcarrier(long long f) { 156 rfc = f; 157 } USB(bool b)158 void USB(bool b) { 159 usb = b; 160 } USB()161 bool USB() {return usb;}; rfcarrier()162 long long rfcarrier() { return rfc;}; 163 updateMarker()164 void updateMarker() { 165 drawMarker();}; 166 int peakFreq(int f0, int delta); 167 double powerDensity(double f0, double bw); 168 double powerDensityMaximum(int bw_nb, const int (*bw)[2]) const ; 169 170 void setPrefilter(int v); 171 void setcolors(); dFreq()172 double dFreq() {return dfreq;} 173 void defaultColors(); 174 175 private: 176 int disp_width; 177 int image_width; 178 int scale_width; 179 int RGBwidth; 180 int RGBsize; 181 int image_height; 182 int image_area; 183 int sig_image_area; 184 int mag; 185 int magset; 186 WFmode mode; 187 bool overload; 188 bool usb; 189 long long rfc; 190 int offset; 191 int sigoffset; 192 int step; 193 int carrierfreq; 194 int bandwidth; 195 int wfspdcnt; 196 float dispcnt; 197 float dispdec; 198 int ampspan; 199 double peakaudio; 200 double dfreq; 201 bool centercarrier; 202 bool cursormoved; 203 WFspeed wfspeed; 204 // int srate; 205 RGBI *fft_img; 206 RGB *markerimage; 207 RGB RGBmarker; 208 RGB RGBcursor; 209 RGBI RGBInotch; 210 211 wf_fft_type *fftwindow; 212 213 uchar *scaleimage; 214 uchar *fft_sig_img; 215 uchar *sig_img; 216 uchar *scline; 217 218 wf_cpx_type *wfbuf; 219 220 short int *fft_db; 221 int ptrFFTbuff; 222 wf_fft_type *circbuff; 223 int ptrCB; 224 wf_fft_type *pwr; 225 g_fft<wf_fft_type> *wfft; 226 int prefilter; 227 228 229 int checkMag(); 230 void checkWidth(); 231 void initMarkers(); 232 void makeScale(); 233 void drawScale(); 234 void drawMarker(); 235 236 int log2disp(int v); 237 void drawcolorWF(); 238 void drawgrayWF(); 239 void drawspectrum(); 240 void drawsignal(); 241 242 // resample 243 SRC_STATE* src_state; 244 SRC_DATA src_data; 245 int genptr; 246 float insamples[WF_BLOCKSIZE * 2]; 247 float outsamples[WF_BLOCKSIZE * 16]; 248 float *buf; 249 int srclen; 250 251 protected: 252 public: 253 bool wantcursor; 254 int cursorpos; 255 256 int newcarrier; 257 int oldcarrier; 258 bool tmp_carrier; Pwr(int i)259 double Pwr(int i) { 260 if ( i > 0 && i < IMAGE_WIDTH) return pwr[i]; 261 return 0.0; 262 } 263 }; 264 265 class waterfall: public Fl_Group { 266 friend void x1_cb(Fl_Widget *w, void* v); 267 friend void slew_left(Fl_Widget *w, void * v); 268 friend void slew_right(Fl_Widget *w, void * v); 269 friend void center_cb(Fl_Widget *w, void *v); 270 friend void carrier_cb(Fl_Widget *w, void *v); 271 friend void mode_cb(Fl_Widget *w, void *v); 272 friend void set_wf_mode(void); 273 friend void ampspan_cb(Fl_Widget *w, void *v); 274 friend void qsy_cb(Fl_Widget *w, void *v); 275 friend void rate_cb(Fl_Widget *w, void *v); 276 friend void btnMem_cb(Fl_Widget *w, void *v); 277 public: 278 waterfall(int x, int y, int w, int h, char *lbl= 0); ~waterfall()279 ~waterfall(){}; 280 void show_scope(bool on); 281 void opmode(); sig_data(double * sig,int len)282 void sig_data(double *sig, int len) { 283 wfdisp->sig_data(sig, len); 284 } handle_sig_data()285 void handle_sig_data() {wfdisp->handle_sig_data();} Overload(bool ovr)286 void Overload(bool ovr) { 287 wfdisp->Overload(ovr); 288 } carrier()289 int carrier() { 290 return wfdisp->carrier(); 291 } 292 void carrier(int f); 293 void rfcarrier(long long cf); 294 long long rfcarrier(); tmp_carrier(void)295 bool tmp_carrier(void) { return wfdisp->tmp_carrier; } 296 void set_XmtRcvBtn(bool val); 297 void USB(bool b); 298 bool USB(); Reverse(bool v)299 void Reverse( bool v) { reverse = v;} Reverse()300 bool Reverse() { return reverse;} 301 xmtrcv_selection_color(Fl_Color clr)302 void xmtrcv_selection_color(Fl_Color clr) {xmtrcv->selection_color(clr);} reverse_selection_color(Fl_Color clr)303 void reverse_selection_color(Fl_Color clr) {btnRev->selection_color(clr);} xmtlock_selection_color(Fl_Color clr)304 void xmtlock_selection_color(Fl_Color clr) {xmtlock->selection_color(clr);} 305 Bandwidth(int bw)306 void Bandwidth(int bw) 307 { 308 wfdisp->Bandwidth(bw); 309 } peakFreq(int f0,int delta)310 int peakFreq(int f0, int delta) 311 { 312 return (wfdisp->peakFreq(f0, delta)); 313 } powerDensity(double f0,double bw)314 double powerDensity(double f0, double bw) 315 { 316 return (wfdisp->powerDensity(f0,bw)); 317 } 318 powerDensityMaximum(int bw_nb,const int (* bw)[2])319 double powerDensityMaximum(int bw_nb, const int (*bw)[2]) const 320 { 321 return (wfdisp->powerDensityMaximum(bw_nb,bw)); 322 } 323 324 int Speed(); 325 void Speed(int rate); 326 int Mag(); 327 void Mag(int m); 328 int Offset(); 329 void Offset(int v); 330 int Carrier(); 331 void Carrier(int f); 332 draw_fmt_marker()333 void draw_fmt_marker() { wfdisp->make_fmt_marker(); } 334 movetocenter()335 void movetocenter() { wfdisp->movetocenter();} redraw_marker()336 void redraw_marker() { wfdisp->makeMarker(); } setPrefilter(int v)337 void setPrefilter(int v) {wfdisp->setPrefilter(v);} 338 setcolors()339 void setcolors() { wfdisp->setcolors(); } 340 void setRefLevel(); 341 void setAmpSpan(); dFreq()342 double dFreq() { return wfdisp->dFreq();} 343 setQSY(bool on)344 void setQSY(bool on) { 345 if (on) 346 qsy->activate(); 347 else 348 qsy->deactivate(); 349 } Pwr(int i)350 double Pwr(int i) { return wfdisp->Pwr(i); } 351 352 int handle(int event); 353 354 void insert_text(bool check = false); 355 356 enum { WF_NOP, WF_AFC_BW, WF_SIGNAL_SEARCH, WF_SQUELCH, 357 WF_CARRIER, WF_MODEM, WF_SCROLL }; 358 static const char* wf_wheel_action[7]; 359 void handle_mouse_wheel(int what, int d); 360 361 Fl_Button *btnRev; 362 Fl_Counter2 *wfcarrier; 363 Fl_Counter2 *wfRefLevel; 364 Fl_Counter2 *wfAmpSpan; 365 Fl_Light_Button *xmtrcv; 366 Fl_Light_Button *xmtlock; 367 Fl_Button *qsy; 368 369 void UI_select(bool); 370 371 Digiscope *wfscope; 372 373 private: 374 int wf_dim; 375 WFdisp *wfdisp; 376 Fl_Group *rs1; 377 Fl_Button *mode; 378 Fl_Button *x1; 379 Fl_Button *left; 380 Fl_Button *center; 381 Fl_Button *right; 382 Fl_Button *wfrate; 383 Fl_Button *btnMem; 384 Fl_Menu_Button *mbtnMem; 385 int buttonrow; 386 bool reverse; 387 }; 388 389 #endif 390