diff --git a/ChangeLog b/ChangeLog index ca6a738e..84660ac3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ Change Log: +2.10 1) Added history (ctrl-Left-click in waterfall). Available after tracking + has started. This does not start a new signal acquisition. + 2) Psk and ViewPsk use shared signal detection class + 2.09 1) Modified src/Makefile.am for FreeBSD name space clash 2) Added psk multi-channel viewer with regex search capability 3) Rewrote audio capture/playback/generate routines to use the diff --git a/configure.ac b/configure.ac index e3732dc7..b9f04f13 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ AC_COPYRIGHT([Copyright (C) 2007 Stelios Bounanos, M0GLD (m0gld AT enotty DOT net)]) AC_PREREQ(2.61) -AC_INIT([fldigi], [2.09], [w1hkj AT w1hkj DOT com]) +AC_INIT([fldigi], [2.10A], [w1hkj AT w1hkj DOT com]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([-Wall foreign std-options 1.9.6]) AM_MAINTAINER_MODE diff --git a/src/Makefile.am b/src/Makefile.am index f6ebaf55..65c41331 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -154,6 +154,7 @@ fldigi_SOURCES += \ include/viewpsk.h \ include/pskcoeff.h \ include/pskvaricode.h \ + include/pskeval.h \ include/ptt.h \ include/qrunner.h \ include/qrzcall.h \ @@ -217,6 +218,7 @@ fldigi_SOURCES += \ psk/pskcoeff.cxx \ psk/pskvaricode.cxx \ psk/viewpsk.cxx \ + psk/pskeval.cxx \ qrunner/fqueue.h \ qrunner/qrunner.cxx \ rigcontrol/FreqControl.cxx \ diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index b15df0f3..df6739d1 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -965,8 +965,8 @@ Fl_Menu_Item menu_[] = { {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, {"Rig", 0, (Fl_Callback*)cb_mnuRig, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, -{"Viewer", 0, (Fl_Callback*)cb_mnuViewer, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, +{"Viewer", 0, (Fl_Callback*)cb_mnuViewer, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {" ", 0, 0, 0, FL_MENU_INACTIVE, FL_NORMAL_LABEL, 0, 14, 0}, {"Help", 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, diff --git a/src/include/modem.h b/src/include/modem.h index 443cfaec..7df4c931 100644 --- a/src/include/modem.h +++ b/src/include/modem.h @@ -89,7 +89,7 @@ public: double get_squelch() { return squelch; } void set_sqlchOnOff(bool val) {squelchon = val;} bool get_sqlchOnOff() { return squelchon;} - void set_afcOnOff(bool val) {afcon = val;} + void set_afcOnOff(int val) {afcon = val;} bool get_afcOnOff() { return afcon;} // void set_mode(trx_mode); diff --git a/src/include/psk.h b/src/include/psk.h index ebd829a7..46e66fad 100644 --- a/src/include/psk.h +++ b/src/include/psk.h @@ -37,7 +37,7 @@ #define PipeLen (64) #define SNTHRESHOLD 2.0 -#define AFCDECAY 8 +#define AFCDECAYSLOW 8 //===================================================================== class psk : public modem { @@ -53,6 +53,7 @@ private: C_FIR_filter *fir1; C_FIR_filter *fir2; +// C_FIR_filter *fir3; double *fir1c; double *fir2c; @@ -69,6 +70,7 @@ private: int dcd; int dcdbits; complex quality; + void rx_symbol(complex symbol); void rx_bit(int bit); void rx_qpsk(int bits); @@ -78,6 +80,8 @@ private: double I11, I12, I21, I22, I31, I32; double snratio, s2n, imdratio, imd; double E1, E2, E3; + double twopi; + // complex thirdorder; // tx variables & functions double *tx_shape; @@ -91,6 +95,7 @@ private: void findsignal(); void phaseafc(); void afc(); + void coreafc(); public: psk(trx_mode mode); diff --git a/src/include/pskeval.h b/src/include/pskeval.h new file mode 100644 index 00000000..fb319a74 --- /dev/null +++ b/src/include/pskeval.h @@ -0,0 +1,51 @@ +// ---------------------------------------------------------------------------- +// pskeval.cxx -- psk signal evaluator +// +// Copyright (C) 2008 +// Dave Freese, W1HKJ +// +// This file is part of fldigi. Adapted from code contained in gmfsk source code +// distribution. +// +// fldigi is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// fldigi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with fldigi; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ---------------------------------------------------------------------------- + +#ifndef _PSKEVAL_H +#define _PSKEVAL_H + +#include "complex.h" +#include "trx.h" +#include "filters.h" +#include "fldigi-config.h" +#include "waterfall.h" + +#define FLOWER 200 +#define FUPPER 4000 + +class pskeval { +private: + double sigpwr[FFT_LEN]; + double sigavg; + double bw; +public: + pskeval(); + ~pskeval(); + void clear(); + void setbw(double w) { bw = w;} + void sigdensity(); + double sigpeak(int &f, int f1, int f2); +}; + +#endif diff --git a/src/include/trx.h b/src/include/trx.h index a88f1125..5ef64a54 100644 --- a/src/include/trx.h +++ b/src/include/trx.h @@ -53,4 +53,6 @@ extern modem *active_modem; extern cSound *scard; +extern bool bHistory; + #endif diff --git a/src/include/viewpsk.h b/src/include/viewpsk.h index 61b985db..0e2ae207 100644 --- a/src/include/viewpsk.h +++ b/src/include/viewpsk.h @@ -1,7 +1,7 @@ // ---------------------------------------------------------------------------- -// psk.h -- psk modem +// viewpsk.h -- psk modem // -// Copyright (C) 2006 +// Copyright (C) 2008 // Dave Freese, W1HKJ // // This file is part of fldigi. Adapted from code contained in gmfsk source code diff --git a/src/psk/psk.cxx b/src/psk/psk.cxx index 3e883979..0defcd9d 100644 --- a/src/psk/psk.cxx +++ b/src/psk/psk.cxx @@ -30,11 +30,13 @@ #include #include +#include #include "psk.h" #include "waterfall.h" #include "configuration.h" #include "viewpsk.h" +#include "pskeval.h" extern waterfall *wf; @@ -47,6 +49,7 @@ extern waterfall *wf; // Change the following for DCD low pass filter adjustment #define SQLCOEFF 0.01 +#define SQLDECAY 100 //===================================================================== @@ -56,6 +59,7 @@ extern waterfall *wf; char pskmsg[80]; viewpsk *pskviewer = (viewpsk *)0; +pskeval *evalpsk = (pskeval *)0; void psk::tx_init(cSound *sc) { @@ -86,6 +90,8 @@ void psk::restart() { if (!pskviewer) pskviewer = new viewpsk(mode); else pskviewer->restart(mode); + if (!evalpsk) evalpsk = new pskeval; + evalpsk->setbw(bandwidth); } void psk::init() @@ -107,6 +113,8 @@ psk::~psk() psk::psk(trx_mode pskmode) : modem() { mode = pskmode; + + twopi = 2.0 * M_PI; switch (mode) { case MODE_BPSK31: @@ -172,6 +180,7 @@ psk::psk(trx_mode pskmode) : modem() wsincfilt(fir1c, 1.0 / symbollen, true); // creates fir1c matched sin(x)/x filter w blackman wsincfilt(fir2c, 1.0 / 16.0, true); // creates fir2c matched sin(x)/x filter w blackman + // wsincfilt(fir1c, 1.0 / symbollen, false); // creates fir1c matched sin(x)/x filter w hamming // wsincfilt(fir2c, 1.0 / 16.0, false); // creates fir2c matched sin(x)/x filter w hamming // wsincfilt(fir2c, 1.0 / 22.0, false); // 1/22 with Hamming window @@ -185,6 +194,7 @@ psk::psk(trx_mode pskmode) : modem() fir2 = new C_FIR_filter(); fir2->init(FIRLEN, 1, fir2c, fir2c); + if (_qpsk) { enc = new encoder(K, POLY1, POLY2); dec = new viterbi(K, POLY1, POLY2); @@ -330,31 +340,40 @@ void psk::findsignal() } } else { // normal signal search - searchBW = progdefaults.SearchRange; - ftest = wf->peakFreq((int)(frequency), searchBW); - sigpwr = wf->powerDensity(ftest, bandwidth); - noise = wf->powerDensity(ftest + 2 * bandwidth / 2, bandwidth / 2) + - wf->powerDensity(ftest - 2 * bandwidth / 2, bandwidth / 2) + 1e-20; - if (sigpwr/noise > SNTHRESHOLD) { // larger than the detection threshold) - frequency = ftest; - set_freq(frequency); - freqerr = 0.0; - } + int ftest; + int f1 = (int)(frequency - progdefaults.SearchRange/2); + int f2 = (int)(frequency + progdefaults.SearchRange/2); + if (evalpsk->sigpeak(ftest, f1, f2) > SNTHRESHOLD ){//SNTHRESHOLD) { + frequency = ftest; + set_freq(frequency); + freqerr = 0.0; + } +// searchBW = progdefaults.SearchRange; +// ftest = wf->peakFreq((int)(frequency), searchBW); +// sigpwr = wf->powerDensity(ftest, bandwidth); +// noise = wf->powerDensity(ftest + 2 * bandwidth / 2, bandwidth / 2) + +// wf->powerDensity(ftest - 2 * bandwidth / 2, bandwidth / 2) + 1e-20; +// if (sigpwr/noise > SNTHRESHOLD) { // larger than the detection threshold) +// frequency = ftest; +// set_freq(frequency); +// freqerr = 0.0; +// } } } + } void psk::phaseafc() { double error; - error = (phase - bits * M_PI / 2); - if (error < M_PI / 2) - error += 2 * M_PI; - if (error > M_PI / 2) - error -= 2 * M_PI; - error *= ((samplerate / (symbollen * 2 * M_PI)/16)); + error = (phase - bits * M_PI / 2.0); + if (error < -M_PI/2.0) + error += twopi; + if (error > M_PI/2.0) + error -= twopi; + error *= ((samplerate / twopi) / (16.0 * symbollen)); if (fabs(error) < bandwidth) { - freqerr = decayavg( freqerr, error, AFCDECAY); + freqerr = decayavg( freqerr, error, AFCDECAYSLOW); frequency -= freqerr; set_freq (frequency); } @@ -378,7 +397,7 @@ void psk::rx_symbol(complex symbol) prevsymbol = symbol; if (phase < 0) - phase += 2 * M_PI; + phase += twopi; if (_qpsk) { bits = ((int) (phase / M_PI_2 + 0.5)) & 3; n = 4; @@ -389,9 +408,9 @@ void psk::rx_symbol(complex symbol) // simple low pass filter for quality of signal // quality.re = 0.02 * cos(n * phase) + 0.98 * quality.re; // quality.im = 0.02 * sin(n * phase) + 0.98 * quality.im; - quality.re = SQLCOEFF * cos(n * phase) + (1.0 - SQLCOEFF) * quality.re; - quality.im = SQLCOEFF * sin(n * phase) + (1.0 - SQLCOEFF) * quality.im; - + quality.re = decayavg(quality.re, cos(n*phase), SQLDECAY); + quality.im = decayavg(quality.im, cos(n*phase), SQLDECAY); + metric = 100.0 * quality.norm(); dcdshreg = (dcdshreg << 2) | bits; @@ -460,11 +479,15 @@ char bitstatus[100]; int psk::rx_process(const double *buf, int len) { double delta; - complex z; + complex z, z2;//, z3; - if (pskviewer) pskviewer->rx_process(buf, len); - - delta = 2.0 * M_PI * frequency / samplerate; + if (pskviewer && !bHistory) pskviewer->rx_process(buf, len); + if (evalpsk) evalpsk->sigdensity(); + + if (afcon == 2) + sigsearch = 0; + + delta = twopi * frequency / samplerate; signalquality(); @@ -474,27 +497,30 @@ int psk::rx_process(const double *buf, int len) buf++; phaseacc += delta; if (phaseacc > M_PI) - phaseacc -= 2.0 * M_PI; + phaseacc -= twopi; // Filter and downsample // by 16 (psk31, qpsk31) // by 8 (psk63, qpsk63) // by 4 (psk125, qpsk125) +// by 2 (psk250, qpsk250) // first filter if (fir1->run( z, z )) { // fir1 returns true every Nth sample // final filter - fir2->run( z, z ); // fir3 returns value on every sample - + fir2->run( z, z2 ); // fir2 returns value on every sample + +// fir3->run( z, z3); +// coreafc(z3); + int idx = (int) bitclk; double sum = 0.0; double ampsum = 0.0; - syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * z.mag(); + syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * z2.mag(); for (int i = 0; i < 8; i++) { sum += (syncbuf[i] - syncbuf[i+8]); ampsum += (syncbuf[i] + syncbuf[i+8]); } // added correction as per PocketDigi -// vastly improved performance with synchronous interference !! sum = (ampsum == 0 ? 0 : sum / ampsum); bitclk -= sum / 5.0; @@ -503,7 +529,7 @@ int psk::rx_process(const double *buf, int len) if (bitclk < 0) bitclk += 16.0; if (bitclk >= 16.0) { bitclk -= 16.0; - rx_symbol(z); + rx_symbol(z2); update_syncscope(); afc(); } diff --git a/src/psk/pskeval.cxx b/src/psk/pskeval.cxx new file mode 100644 index 00000000..7f01cd80 --- /dev/null +++ b/src/psk/pskeval.cxx @@ -0,0 +1,89 @@ +// ---------------------------------------------------------------------------- +// pskeval.cxx -- psk signal evaluator +// +// Copyright (C) 2008 +// Dave Freese, W1HKJ +// +// This file is part of fldigi. Adapted from code contained in gmfsk source code +// distribution. +// +// fldigi is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// fldigi is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with fldigi; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// ---------------------------------------------------------------------------- + +#include "pskeval.h" + +//============================================================================= +//========================== psk signal evaluation ============================ +//============================================================================= + +double alpha = 0.125; + +pskeval::pskeval() { + bw = 31.25; + clear(); +} + +pskeval::~pskeval() { +} + +//static int evalcount = 1; + +void pskeval::sigdensity() { + double sig = 0.0; + double val; + int ihbw = (int)(bw / 2 + 0.5) + 1; + int ibw = 2 * ihbw; + int fstart = FLOWER + ibw; + double *vals = new double[ibw + 1]; + for (int i = 0; i < ibw + 1; i++) vals[i] = 0.0; + int j = -1; + sigavg = 0.0; + for (int i = FLOWER; i < IMAGE_WIDTH; i++) { + j++; + if (j == ibw + 1) j = 0; + val = wf->Pwr(i); + if (i >= fstart) { + sigpwr[i - ihbw - 1] = (1-alpha)*sigpwr[i - ihbw - 1] + alpha * sig; +// sigpwr[i - ihbw - 1] = sig; + sig -= vals[j]; + } + vals[j] = val; + sig += val; + sigavg += val; + } + sigavg /= (FFT_LEN - FLOWER); + if (sigavg == 0) sigavg = 1e-20; +// if (evalcount++ < 100) { +// for (int i = FLOWER; i < IMAGE_WIDTH; i++) +// std::cout << i << "," << sigpwr[i] / sigavg << std::endl; +// std::cout.flush(); +// } +} + +double pskeval::sigpeak(int &f, int f1, int f2) +{ + double peak = 0; + f = (f1 + f2) / 2; + for (int i = f1; i <= f2; i++) + if (sigpwr[i] > peak) { + peak = sigpwr[i]; + f = i; + } + return peak / sigavg / bw; +} + +void pskeval::clear() { + for (int i = 0; i < FFT_LEN; i++) sigpwr[i] = 0.0; +} diff --git a/src/psk/viewpsk.cxx b/src/psk/viewpsk.cxx index d9e7e05e..08c897a9 100644 --- a/src/psk/viewpsk.cxx +++ b/src/psk/viewpsk.cxx @@ -34,6 +34,7 @@ #include #include "viewpsk.h" +#include "pskeval.h" #include "pskcoeff.h" #include "pskvaricode.h" #include "waterfall.h" @@ -42,6 +43,7 @@ #include "qrunner.h" extern waterfall *wf; +extern pskeval *evalpsk; //===================================================================== // Change the following for DCD low pass filter adjustment @@ -144,22 +146,20 @@ void viewpsk::restart(trx_mode pskmode) init(); } -int sigcnt = 0; //============================================================================= //========================== viewpsk signal evaluation ======================== //============================================================================= void viewpsk::sigdensity() { - sigcnt++; double sig = 0.0; double val; int hbw = (int)(bandwidth / 2); int twohbw = 2 * hbw; - int flower = progdefaults.VIEWERstart - 50; //nomfreq[0] - 50; - int fupper = flower + 100 * progdefaults.VIEWERchannels + 100; //nomfreq[MAXCHANNELS-1] + 50; + int flower = progdefaults.VIEWERstart - 50; + int fupper = flower + 100 * progdefaults.VIEWERchannels + 100; double *vals = new double[twohbw + 1]; int j = -1; sigavg = 0.0; -// sigmin = 1e6; + sigmin = 1e6; for (int i = flower - hbw; i < fupper + hbw; i++) { j++; if (j == twohbw + 1) j = 0; @@ -171,14 +171,9 @@ void viewpsk::sigdensity() { vals[j] = val; sig += val; sigavg += val; -// if (sig && sig < sigmin) sigmin = sig; + if (sig > 0 && sig < sigmin) sigmin = sig; } - sigavg /= (fupper - flower - 100); -//if (sigcnt == 32) -// for (int i = flower; i <= fupper; i++) -// std::cout << i << ", " << sigpwr[i] / sigavg << std::endl; - } double viewpsk::sigpeak(int &f, int f1, int f2) @@ -205,7 +200,7 @@ void viewpsk::rx_bit(int ch, int bit) if ((shreg[ch] & 3) == 0) { c = psk_varicode_decode(shreg[ch] >> 2); shreg[ch] = 0; -// if (c != -1) { + if (c == '\n') c = ' '; if (c >= ' ' && c <= 'z') { REQ(&viewaddchr, ch, (int)frequency[ch], c); timeout[ch] = now + progdefaults.VIEWERtimeout; @@ -215,36 +210,21 @@ void viewpsk::rx_bit(int ch, int bit) void viewpsk::findsignal(int ch) { -// double ftest, sigpwr, noise; if (waitcount[ch] > 0) { waitcount[ch]--; return; } -// ftest = wf->peakFreq((int)(frequency[ch]), VSEARCHWIDTH + (int)(bandwidth / 2)); -// sigpwr = wf->powerDensity(ftest, bandwidth); -// noise = wf->powerDensity(ftest + 2 * bandwidth, bandwidth / 2) + -// wf->powerDensity(ftest - 2 * bandwidth, bandwidth / 2) + 1e-20; - -// if (sigpwr/noise > VSNTHRESHOLD) { // larger than the search threshold -// if (ftest - nomfreq[ch] > VSEARCHWIDTH) ftest = nomfreq[ch] + VSEARCHWIDTH; -// if (ftest - nomfreq[ch] < -VSEARCHWIDTH) ftest = nomfreq[ch] - VSEARCHWIDTH; -// frequency[ch] = ftest; -// } else { // less than the detection threshold -// frequency[ch] = nomfreq[ch]; -// sigsearch[ch] = VSIGSEARCH; -// } - int ftest; - int f1 = (int)(nomfreq[ch] - VSEARCHWIDTH); - int f2 = (int)(nomfreq[ch] + VSEARCHWIDTH); - if (sigpeak(ftest, f1, f2) > VSNTHRESHOLD) { - frequency[ch] = ftest; - sigsearch[ch] = 0; - } - else - frequency[ch] = nomfreq[ch]; - freqerr[ch] = 0.0; -// } + int ftest; + int f1 = (int)(nomfreq[ch] - VSEARCHWIDTH); + int f2 = (int)(nomfreq[ch] + VSEARCHWIDTH); + if (evalpsk->sigpeak(ftest, f1, f2) > VSNTHRESHOLD) { + frequency[ch] = ftest; + sigsearch[ch] = 0; + } + else + frequency[ch] = nomfreq[ch]; + freqerr[ch] = 0.0; } void viewpsk::afc(int ch) @@ -322,7 +302,7 @@ int viewpsk::rx_process(const double *buf, int len) complex z[MAXCHANNELS]; now = time(NULL); - sigdensity(); +// sigdensity(); while (len-- > 0) { // process all CHANNELS (25) @@ -369,34 +349,10 @@ int viewpsk::rx_process(const double *buf, int len) REQ( &viewclearchannel, channel); timeout[channel] = -1; } -// if (sigpwr[(int)(frequency[channel])] / sigmin < VSNTHRESHOLD) if (sigpwr[(int)(frequency[channel])] / sigavg < VSNTHRESHOLD) sigsearch[channel] = 1; if (sigsearch[channel]) findsignal(channel); - -/* if (sigsearch[channel]) - findsignal(channel); - else { - if (waitcount[channel] > 0) { - --waitcount[channel]; - if (waitcount[channel] == 0) { -// sigsearch[channel] = VSIGSEARCH; - sigsearch[channel] = 1; - } - } - else { -// double E1 = wf->powerDensity(frequency[channel], bandwidth); -// double E2 = wf->powerDensity(frequency[channel] - 2 * bandwidth, bandwidth/2) + -// wf->powerDensity(frequency[channel] + 2 * bandwidth, bandwidth/2); -// if ( E1/ E2 <= VSNTHRESHOLD) { - if (sigpwr[(int)(frequency[channel])] / sigavg < VSNTHRESHOLD) { - waitcount[channel] = VWAITCOUNT; - sigsearch[channel] = 0; - } - } - } -*/ } return 0; } diff --git a/src/trx/trx.cxx b/src/trx/trx.cxx index 6a824252..8f485fca 100644 --- a/src/trx/trx.cxx +++ b/src/trx/trx.cxx @@ -73,6 +73,11 @@ short int *sidata; // is used asynchronously by the GUI thread. mbuffer _trx_scdbl; +#define HISTSIZE 1024 * SCBLOCKSIZE +double histbuff[HISTSIZE]; +size_t numinbuff = 0; +bool bHistory = false; + static int dummy = 0; static bool trxrunning = false; #include "tune.cxx" @@ -117,9 +122,25 @@ void trx_trx_receive_loop() if (numread == -1 || (trx_state != STATE_RX)) break; if (numread > 0) { - REQ(&waterfall::sig_data, wf, _trx_scdbl.c_array(), numread); - active_modem->rx_process(_trx_scdbl, numread); - _trx_scdbl.next(); // change buffers + + if (bHistory) { + active_modem->set_afcOnOff(0); + active_modem->rx_process( histbuff, numinbuff ); + active_modem->set_afcOnOff(1); + bHistory = false; + } + + active_modem->rx_process(_trx_scdbl, numread); + + if (numinbuff + numread > HISTSIZE) { + memcpy( &histbuff[0], &histbuff[numread], (numinbuff - numread)*sizeof(double)); + numinbuff -= numread; + } + for (int n = 0; n < numread; n++) + histbuff[numinbuff++] = _trx_scdbl[n]; + + REQ(&waterfall::sig_data, wf, _trx_scdbl.c_array(), numread); + _trx_scdbl.next(); // change buffers } } if (!scard->full_duplex()) diff --git a/src/waterfall/waterfall.cxx b/src/waterfall/waterfall.cxx index 9d8ace5f..bfc45c2b 100644 --- a/src/waterfall/waterfall.cxx +++ b/src/waterfall/waterfall.cxx @@ -630,9 +630,11 @@ void WFdisp::update_waterfall() { p4 = p3; for (int col = 0; col < disp_width; col++) { if (step == 4) - sig = MAX( MAX ( MAX ( *p2, *(p2+1) ), *(p2+2) ), *(p2+3) ); + // sig = MAX( MAX ( MAX ( *p2, *(p2+1) ), *(p2+2) ), *(p2+3) ); + sig = (*p2+ *(p2+1)+ *(p2+2)+ *(p2+3))/4; else if (step == 2) - sig = MAX( *p2, *(p2 + 1) ); + // sig = MAX( *p2, *(p2 + 1) ); + sig = (*p2 + *(p2 + 1))/2; else sig = *p2; *p4 = mag2RGBI[ sig ]; @@ -1405,12 +1407,16 @@ int WFdisp::handle(int event) } // fall through case FL_LEFT_MOUSE: - newcarrier = cursorFreq(xpos); - active_modem->set_freq(newcarrier); - if (!(Fl::event_state() & FL_SHIFT)) - active_modem->set_sigsearch(SIGSEARCH); - redrawCursor(); - restoreFocus(); + if ((Fl::event_state() & FL_CTRL)) + bHistory = true; + else { + newcarrier = cursorFreq(xpos); + active_modem->set_freq(newcarrier); + if (!(Fl::event_state() & FL_SHIFT)) + active_modem->set_sigsearch(SIGSEARCH); + redrawCursor(); + restoreFocus(); + } break; case FL_MIDDLE_MOUSE: if (event == FL_DRAG)