From da36c7bd9168e31173d9855562014d63d5959de3 Mon Sep 17 00:00:00 2001 From: David Freese Date: Sat, 19 Oct 2013 07:43:31 -0500 Subject: [PATCH] WF fft * Changed Waterfall fft from Cfft to g_fft --- src/include/dtmf.h | 6 ++-- src/include/gfft.h | 2 +- src/include/waterfall.h | 48 +++++++++----------------- src/misc/configuration.cxx | 11 +++--- src/waterfall/waterfall.cxx | 69 ++++++++++++++++++------------------- 5 files changed, 60 insertions(+), 76 deletions(-) diff --git a/src/include/dtmf.h b/src/include/dtmf.h index 9fdbec6a..fb4f4cad 100644 --- a/src/include/dtmf.h +++ b/src/include/dtmf.h @@ -3,8 +3,8 @@ #include "filters.h" class cDTMF { -public: -#define N 240 // 30 msec interval at 8000 sps +private: +//#define N 240 // 30 msec interval at 8000 sps #define RANGE 0.5 /* any thing higher than RANGE*peak is "on" */ #define THRESH 1000 /* 6 dB s/n for detection */ @@ -43,7 +43,7 @@ public: cDTMF() { for (int i = 0; i < 4; i++) filt[i] = new goertzel(240, row[i], 8000); for (int i = 0; i < 4; i++) filt[i+4] = new goertzel(240, col[i], 8000); - for (int i = 0; i < N; i++) data[i] = 0; + for (int i = 0; i < 240; i++) data[i] = 0; dtmfchars.clear(); framesize = 240; // 8000 sr default silence_time = 0; diff --git a/src/include/gfft.h b/src/include/gfft.h index 6f015388..eaadf3db 100644 --- a/src/include/gfft.h +++ b/src/include/gfft.h @@ -75,7 +75,7 @@ private: short *BRLow; void fftInit(); - int ConvertFFTSize(int N); + int ConvertFFTSize(int); // base fft methods void riffts1(FFT_TYPE *ioptr, int M, FFT_TYPE *Utbl, short *BRLow); diff --git a/src/include/waterfall.h b/src/include/waterfall.h index 148c352e..1d9cc5fd 100644 --- a/src/include/waterfall.h +++ b/src/include/waterfall.h @@ -30,7 +30,7 @@ #include #include -#include "fft.h" +#include "gfft.h" #include "fldigi-config.h" #include "digiscope.h" #include "flslider2.h" @@ -40,22 +40,9 @@ enum { WF_FFT_HANNING, WF_FFT_TRIANGULAR }; -/* -#ifdef HAVE_DFFTW_H -# include -#endif -#ifdef HAVE_FFTW_H -# include -#endif -*/ - -#define FFT_LEN 4096 -//8192 -//2048 -//4096 - +#define FFT_LEN 8192 #define SC_SMPLRATE 8000 -#define WFBLOCKSIZE 512 +#define WFBLOCKSIZE 512 struct RGB { uchar R; @@ -70,7 +57,13 @@ struct RGBI { uchar I; }; -extern RGBI mag2RGBI[256]; +// you can change the basic fft processing type by a simple change in the +// following typedef. change to float if you need to skimp on cpu cycles. + +typedef double wf_fft_type; +typedef std::complex wf_cpx_type; + +extern RGBI mag2RGBI[256]; extern RGB palette[9]; enum WFmode { @@ -149,7 +142,6 @@ public: void initmaps(); void draw(); -// void resize (int, int, int, int); int handle(int event); void update_sigmap(); void update_waterfall(); @@ -161,7 +153,7 @@ public: inline void makeNotch_(int notch_frequency); inline void makeMarker_(int width, const RGB* color, int freq, const RGB* clrMin, RGB* clrM, const RGB* clrMax); void makeMarker(); - void process_analog(double *sig, int len); + void process_analog(wf_fft_type *sig, int len); void processFFT(); void sig_data( double *sig, int len, int sr ); void rfcarrier(long long f) { @@ -173,8 +165,6 @@ public: bool USB() {return usb;}; long long rfcarrier() { return rfc;}; -// void useBands(bool b) { usebands = b;}; - void updateMarker() { drawMarker();}; int peakFreq(int f0, int delta); @@ -202,7 +192,6 @@ private: bool overload; bool usb; long long rfc; -// bool usebands; int offset; int sigoffset; int step; @@ -220,24 +209,24 @@ private: WFspeed wfspeed; int srate; RGBI *fft_img; -// RGBI mag2RGBI[256]; RGB *markerimage; RGB RGBmarker; RGB RGBcursor; RGBI RGBInotch; - double *fftout; double *fftwindow; uchar *scaleimage; uchar *fft_sig_img; uchar *sig_img; uchar *scline; + wf_cpx_type *wfbuf; + short int *fft_db; int ptrFFTbuff; - double *circbuff; + wf_fft_type *circbuff; int ptrCB; - double *pwr; - Cfft *wfft; + wf_fft_type *pwr; + g_fft *wfft; int prefilter; @@ -271,7 +260,6 @@ public: class waterfall: public Fl_Group { friend void x1_cb(Fl_Widget *w, void* v); -// friend void slew_cb(Fl_Widget *w, void * v); friend void slew_left(Fl_Widget *w, void * v); friend void slew_right(Fl_Widget *w, void * v); friend void center_cb(Fl_Widget *w, void *v); @@ -351,10 +339,6 @@ public: qsy->activate(); else qsy->deactivate(); -// wfdisp->useBands(!on); - } - void setXMLRPC(bool on) { -// wfdisp->useBands(!on); } double Pwr(int i) { return wfdisp->Pwr(i); } diff --git a/src/misc/configuration.cxx b/src/misc/configuration.cxx index c3f5f3cf..e91cbf93 100644 --- a/src/misc/configuration.cxx +++ b/src/misc/configuration.cxx @@ -787,11 +787,12 @@ void configuration::initInterface() } #endif } else if (chkUSEXMLRPCis) { - wf->setXMLRPC(1); - rigCAT_init(false); - wf->USB(true); - wf->setQSY(0); - riginitOK = true; + if (rigCAT_init(false)) { + LOG_VERBOSE("%s", "using XMLRPC"); + wf->USB(true); + wf->setQSY(0); + riginitOK = true; + } } if (riginitOK == false) { diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index 830c6112..856534ca 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -129,17 +129,16 @@ WFdisp::WFdisp (int x0, int y0, int w0, int h0, char *lbl) : scline = new uchar[scale_width]; fft_sig_img = new uchar[image_area]; sig_img = new uchar[sig_image_area]; - pwr = new double[IMAGE_WIDTH]; + pwr = new wf_fft_type[IMAGE_WIDTH]; fft_db = new short int[image_area]; tmp_fft_db = new short int[image_area]; - circbuff = new double[FFT_LEN * 2]; - fftout = new double[FFT_LEN * 2]; - wfft = new Cfft(FFT_LEN); - fftwindow = new double[FFT_LEN * 2]; + circbuff = new wf_fft_type[FFT_LEN]; + wfbuf = new wf_cpx_type[FFT_LEN]; + wfft = new g_fft(FFT_LEN); + fftwindow = new double[FFT_LEN]; setPrefilter(progdefaults.wfPreFilter); - for (int i = 0; i < FFT_LEN*2; i++) - circbuff[i] = fftout[i] = 0.0; + memset(circbuff, 0, FFT_LEN * sizeof(*circbuff)); mag = 1; step = 4; @@ -481,11 +480,11 @@ double WFdisp::powerDensityMaximum(int bw_nb, const int (*bw)[2]) const void WFdisp::setPrefilter(int v) { switch (v) { - case WF_FFT_RECTANGULAR: RectWindow(fftwindow, FFT_LEN*2); break; - case WF_FFT_BLACKMAN: BlackmanWindow(fftwindow, FFT_LEN*2); break; - case WF_FFT_HAMMING: HammingWindow(fftwindow, FFT_LEN*2); break; - case WF_FFT_HANNING: HanningWindow(fftwindow, FFT_LEN*2); break; - case WF_FFT_TRIANGULAR: TriangularWindow(fftwindow, FFT_LEN*2); break; + case WF_FFT_RECTANGULAR: RectWindow(fftwindow, FFT_LEN); break; + case WF_FFT_BLACKMAN: BlackmanWindow(fftwindow, FFT_LEN); break; + case WF_FFT_HAMMING: HammingWindow(fftwindow, FFT_LEN); break; + case WF_FFT_HANNING: HanningWindow(fftwindow, FFT_LEN); break; + case WF_FFT_TRIANGULAR: TriangularWindow(fftwindow, FFT_LEN); break; } prefilter = v; } @@ -502,30 +501,31 @@ void WFdisp::processFFT() { if (prefilter != progdefaults.wfPreFilter) setPrefilter(progdefaults.wfPreFilter); - const double scale = ( (double)SC_SMPLRATE / srate ) * ( FFT_LEN / 2000.0 ); + wf_fft_type scale = ( 1.0 * SC_SMPLRATE / srate ) * ( FFT_LEN / 8000.0); if (dispcnt == 0) { int step = 8 / progdefaults.latency; - int last_i = FFT_LEN * 2 / step; + memset(wfbuf, 0, FFT_LEN * sizeof(*wfbuf)); + int last_i = FFT_LEN / step; for (int i = 0; i < last_i; i++) - fftout[i] = fftwindow[i * step] * circbuff[i] * step; - /// Zeroes only the last elements. - memset (fftout + last_i , 0, ( FFT_LEN*2 - last_i ) *sizeof(double)); + wfbuf[i] = wf_cpx_type(fftwindow[i * step] * circbuff[i] * step, 0); + wfft->ComplexFFT(wfbuf); - wfft->rdft(fftout); FL_LOCK_D(); - const int log2disp100 = log2disp(-100); - for (int i = 0; i <= progdefaults.LowFreqCutoff; i++) { - pwr[i] = 0.0; - fft_db[ptrFFTbuff * IMAGE_WIDTH + i] = log2disp100; - } + static const int log2disp100 = log2disp(-100); + static const double pscale = 4.0 / (FFT_LEN * FFT_LEN); + memset(pwr, 0, progdefaults.LowFreqCutoff * sizeof(wf_fft_type)); + memset(&fft_db[ptrFFTbuff * IMAGE_WIDTH], + log2disp100, + progdefaults.LowFreqCutoff * sizeof(*fft_db)); + + int n = 0; for (int i = progdefaults.LowFreqCutoff + 1; i < IMAGE_WIDTH; i++) { - int n = (int)(scale * i) & ~1 ; // Even number. - double pw = fftout[n]*fftout[n] + fftout[n+1]*fftout[n+1]; - pwr[i] = pw; - int ffth = (int)(10.0 * log10(pw + 1e-10) ); + n = round(scale * i); + pwr[i] = norm(wfbuf[n]) * pscale;; + int ffth = round(10.0 * log10(pwr[i] + 1e-10) ); fft_db[ptrFFTbuff * IMAGE_WIDTH + i] = log2disp(ffth); } @@ -559,7 +559,7 @@ FL_UNLOCK_D(); } --dispcnt; } -void WFdisp::process_analog (double *sig, int len) { +void WFdisp::process_analog (wf_fft_type *sig, int len) { int h1, h2, h3; int sigy, sigpixel, ynext, graylevel; h1 = h()/8 - 1; @@ -580,7 +580,7 @@ FL_LOCK_D(); ynext = (int)(h2 * sig[cbc]); if (ynext < -h2) ynext = -h2; if (ynext > h2) ynext = h2; - cbc = (cbc + 1) % (FFT_LEN *2); + cbc = (cbc + 1) % (FFT_LEN); for (; sigy < ynext; sigy++) sig_img[sigpixel -= IMAGE_WIDTH] = graylevel; for (; sigy > ynext; sigy--) sig_img[sigpixel += IMAGE_WIDTH] = graylevel; sig_img[sigpixel++] = graylevel; @@ -604,7 +604,7 @@ void WFdisp::sig_data( double *sig, int len, int sr ) // if sound card sampling rate changed reset the waterfall buffer if (srate != sr) { srate = sr; - memset (circbuff, 0, FFT_LEN * 2 * sizeof(double)); + memset(circbuff, 0, FFT_LEN * sizeof(*circbuff)); ptrCB = 0; } @@ -613,18 +613,17 @@ void WFdisp::sig_data( double *sig, int len, int sr ) double overval, peak = 0.0; memmove((void*)circbuff, (void*)(circbuff + len), - (size_t)((FFT_LEN *2 - len)*sizeof(double))); - memmove((void*)(circbuff + (FFT_LEN*2-len)), - (void*)sig, - (size_t)(len*sizeof(double))); + (size_t)((FFT_LEN - len)*sizeof(wf_fft_type))); + for (int i = 0; i < len; i++) { + circbuff[FFT_LEN - len + i] = sig[i]; overval = fabs(sig[i]); if (overval > peak) peak = overval; } peakaudio = 0.1 * peak + 0.9 * peakaudio; } if (mode == SCOPE) - process_analog(circbuff, FFT_LEN * 2); + process_analog(circbuff, FFT_LEN); else processFFT();