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