CW decoder update

* Cooperative programming effort, W1HKJ and AG1LE
  * Added matched filter implementation using FFT convolution filter
  * Added Self Organizing Map decoding.
  * Added adjustable upper/lower detection levels
  * Added level indicators on CW digiscope
  * combined new fft-convolution filter, SOM decoder & FIR filter
  * added configure controls for filter selection
  * modified CW digiscope display to show 9 dot intervals independent
    if WPM setting
  * increased CW_FIR length to 512
pull/2/head
David Freese 2012-05-28 18:11:14 -05:00
rodzic 92279e7a8d
commit c7f11f471a
13 zmienionych plików z 1121 dodań i 377 usunięć

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1101,6 +1101,49 @@ static void cb_sldrCWbandwidth(Fl_Value_Slider2* o, void*) {
progdefaults.changed = true;
}
Fl_Value_Output *valCWrcvWPM=(Fl_Value_Output *)0;
static void cb_valCWrcvWPM(Fl_Value_Output*, void*) {
progdefaults.changed = true;
}
Fl_Progress *prgsCWrcvWPM=(Fl_Progress *)0;
Fl_Check_Button *btnCWuseSOMdecoding=(Fl_Check_Button *)0;
static void cb_btnCWuseSOMdecoding(Fl_Check_Button* o, void*) {
progdefaults.CWuseSOMdecoding = o->value();
progdefaults.changed = true;
}
Fl_Counter2 *cntLower=(Fl_Counter2 *)0;
static void cb_cntLower(Fl_Counter2* o, void*) {
progdefaults.CWlower = o->value();
progdefaults.changed = true;
}
Fl_Counter2 *cntUpper=(Fl_Counter2 *)0;
static void cb_cntUpper(Fl_Counter2* o, void*) {
progdefaults.CWupper = o->value();
progdefaults.changed = true;
}
Fl_Check_Button *btnCWmfilt=(Fl_Check_Button *)0;
static void cb_btnCWmfilt(Fl_Check_Button* o, void*) {
progdefaults.CWmfilt = o->value();
progdefaults.changed = true;
}
Fl_Check_Button *btnCWuseFFTfilter=(Fl_Check_Button *)0;
static void cb_btnCWuseFFTfilter(Fl_Check_Button* o, void*) {
progdefaults.CWuse_fft_filter = o->value();
progdefaults.changed = true;
}
Fl_Check_Button *btnCWrcvTrack=(Fl_Check_Button *)0;
static void cb_btnCWrcvTrack(Fl_Check_Button* o, void*) {
@ -1115,14 +1158,6 @@ static void cb_cntCWrange(Fl_Counter2* o, void*) {
progdefaults.changed = true;
}
Fl_Value_Output *valCWrcvWPM=(Fl_Value_Output *)0;
static void cb_valCWrcvWPM(Fl_Value_Output*, void*) {
progdefaults.changed = true;
}
Fl_Progress *prgsCWrcvWPM=(Fl_Progress *)0;
Fl_Value_Slider2 *sldrCWxmtWPM=(Fl_Value_Slider2 *)0;
static void cb_sldrCWxmtWPM(Fl_Value_Slider2* o, void*) {
@ -3396,7 +3431,7 @@ Fl_Double_Window* ConfigureDialog() {
o->selection_color((Fl_Color)51);
o->labelsize(18);
o->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
{ tabsConfigure = new Fl_Tabs(-5, 0, 545, 372);
{ tabsConfigure = new Fl_Tabs(-5, 0, 553, 372);
tabsConfigure->color(FL_LIGHT1);
tabsConfigure->selection_color(FL_LIGHT1);
{ tabOperator = new Fl_Group(0, 25, 500, 345, _("Operator"));
@ -3509,7 +3544,7 @@ Fl_Double_Window* ConfigureDialog() {
} // Fl_Group* grpNoise
tabOperator->end();
} // Fl_Group* tabOperator
{ tabUI = new Fl_Group(0, 25, 506, 346, _("UI"));
{ tabUI = new Fl_Group(0, 25, 500, 346, _("UI"));
tabUI->hide();
{ tabsUI = new Fl_Tabs(0, 25, 506, 346);
tabsUI->selection_color(FL_LIGHT1);
@ -4169,13 +4204,12 @@ ab and newline are automatically included."));
} // Fl_Tabs* tabsUI
tabUI->end();
} // Fl_Group* tabUI
{ tabWaterfall = new Fl_Group(-2, 25, 501, 347, _("Waterfall"));
{ tabWaterfall = new Fl_Group(0, 25, 500, 347, _("Waterfall"));
tabWaterfall->hide();
{ tabsWaterfall = new Fl_Tabs(-2, 25, 501, 347);
tabsWaterfall->color(FL_LIGHT1);
tabsWaterfall->selection_color(FL_LIGHT1);
{ Fl_Group* o = new Fl_Group(-2, 50, 501, 320, _("Display"));
o->hide();
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("Display"));
{ Fl_Group* o = new Fl_Group(3, 56, 496, 190, _("Colors and cursors"));
o->box(FL_ENGRAVED_FRAME);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
@ -4370,7 +4404,8 @@ ab and newline are automatically included."));
} // Fl_Group* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(-2, 50, 500, 320, _("FFT Processing"));
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("FFT Processing"));
o->hide();
{ Fl_Group* o = new Fl_Group(3, 62, 490, 135);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Counter2* o = cntLowFreqCutoff = new Fl_Counter2(48, 72, 70, 20, _("Lower limit"));
@ -4480,7 +4515,7 @@ an merging"));
} // Fl_Group* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(-2, 50, 500, 320, _("Mouse"));
{ Fl_Group* o = new Fl_Group(0, 50, 500, 320, _("Mouse"));
o->hide();
{ Fl_Group* o = new Fl_Group(3, 62, 490, 170);
o->box(FL_ENGRAVED_FRAME);
@ -4529,20 +4564,20 @@ an merging"));
} // Fl_Tabs* tabsWaterfall
tabWaterfall->end();
} // Fl_Group* tabWaterfall
{ tabModems = new Fl_Group(-5, 25, 545, 347, _("Modems"));
{ tabModems = new Fl_Group(0, 25, 500, 347, _("Modems"));
tabModems->hide();
{ tabsModems = new Fl_Tabs(-5, 25, 545, 347);
{ tabsModems = new Fl_Tabs(0, 25, 500, 347);
tabsModems->selection_color(FL_LIGHT1);
tabsModems->align(Fl_Align(FL_ALIGN_TOP_RIGHT));
{ tabCW = new Fl_Group(0, 50, 504, 320, _("CW"));
{ tabsCW = new Fl_Tabs(0, 50, 504, 320);
{ tabCW = new Fl_Group(0, 50, 500, 320, _("CW"));
{ tabsCW = new Fl_Tabs(0, 50, 500, 320);
tabsCW->selection_color(FL_LIGHT1);
{ Fl_Group* o = new Fl_Group(0, 75, 500, 295, _("General"));
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
{ Fl_Group* o = new Fl_Group(5, 85, 490, 130, _("Receive"));
o->box(FL_ENGRAVED_FRAME);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
{ Fl_Value_Slider2* o = sldrCWbandwidth = new Fl_Value_Slider2(40, 115, 290, 20, _("Filter bandwidth"));
{ Fl_Value_Slider2* o = sldrCWbandwidth = new Fl_Value_Slider2(20, 149, 300, 20, _("Filter bandwidth"));
sldrCWbandwidth->tooltip(_("CW dsp filter bandwidth"));
sldrCWbandwidth->type(1);
sldrCWbandwidth->box(FL_DOWN_BOX);
@ -4553,24 +4588,96 @@ an merging"));
sldrCWbandwidth->labelsize(14);
sldrCWbandwidth->labelcolor(FL_FOREGROUND_COLOR);
sldrCWbandwidth->minimum(10);
sldrCWbandwidth->maximum(500);
sldrCWbandwidth->step(10);
sldrCWbandwidth->value(150);
sldrCWbandwidth->maximum(400);
sldrCWbandwidth->step(1);
sldrCWbandwidth->value(66);
sldrCWbandwidth->textsize(14);
sldrCWbandwidth->callback((Fl_Callback*)cb_sldrCWbandwidth);
sldrCWbandwidth->align(Fl_Align(FL_ALIGN_RIGHT));
sldrCWbandwidth->align(Fl_Align(FL_ALIGN_TOP_LEFT));
sldrCWbandwidth->when(FL_WHEN_CHANGED);
o->value(progdefaults.CWbandwidth);
o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE);
} // Fl_Value_Slider2* sldrCWbandwidth
{ Fl_Check_Button* o = btnCWrcvTrack = new Fl_Check_Button(40, 150, 80, 20, _("Tracking"));
{ valCWrcvWPM = new Fl_Value_Output(20, 188, 35, 20, _("Rx WPM"));
valCWrcvWPM->color(FL_BACKGROUND2_COLOR);
valCWrcvWPM->callback((Fl_Callback*)cb_valCWrcvWPM);
valCWrcvWPM->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Output* valCWrcvWPM
{ prgsCWrcvWPM = new Fl_Progress(56, 188, 264, 20);
prgsCWrcvWPM->tooltip(_("Tracked CW speed in WPM"));
prgsCWrcvWPM->color(FL_BACKGROUND_COLOR);
prgsCWrcvWPM->selection_color(FL_SELECTION_COLOR);
prgsCWrcvWPM->align(Fl_Align(FL_ALIGN_CENTER));
} // Fl_Progress* prgsCWrcvWPM
{ Fl_Check_Button* o = btnCWuseSOMdecoding = new Fl_Check_Button(16, 108, 125, 20, _("SOM decoding"));
btnCWuseSOMdecoding->tooltip(_("Self Organizing Mapping"));
btnCWuseSOMdecoding->down_box(FL_DOWN_BOX);
btnCWuseSOMdecoding->value(1);
btnCWuseSOMdecoding->callback((Fl_Callback*)cb_btnCWuseSOMdecoding);
o->value(progdefaults.CWuseSOMdecoding);
} // Fl_Check_Button* btnCWuseSOMdecoding
{ Fl_Counter2* o = cntLower = new Fl_Counter2(162, 108, 65, 20, _("Lower"));
cntLower->tooltip(_("Detector low threshold"));
cntLower->type(1);
cntLower->box(FL_UP_BOX);
cntLower->color(FL_BACKGROUND_COLOR);
cntLower->selection_color(FL_INACTIVE_COLOR);
cntLower->labeltype(FL_NORMAL_LABEL);
cntLower->labelfont(0);
cntLower->labelsize(14);
cntLower->labelcolor(FL_FOREGROUND_COLOR);
cntLower->minimum(0.01);
cntLower->maximum(0.99);
cntLower->step(0.01);
cntLower->value(0.45);
cntLower->callback((Fl_Callback*)cb_cntLower);
cntLower->align(Fl_Align(FL_ALIGN_TOP));
cntLower->when(FL_WHEN_CHANGED);
o->value(progdefaults.CWlower);
o->labelsize(FL_NORMAL_SIZE);
} // Fl_Counter2* cntLower
{ Fl_Counter2* o = cntUpper = new Fl_Counter2(255, 108, 65, 20, _("Upper"));
cntUpper->tooltip(_("Detector high threshold"));
cntUpper->type(1);
cntUpper->box(FL_UP_BOX);
cntUpper->color(FL_BACKGROUND_COLOR);
cntUpper->selection_color(FL_INACTIVE_COLOR);
cntUpper->labeltype(FL_NORMAL_LABEL);
cntUpper->labelfont(0);
cntUpper->labelsize(14);
cntUpper->labelcolor(FL_FOREGROUND_COLOR);
cntUpper->minimum(0.01);
cntUpper->maximum(0.99);
cntUpper->step(0.01);
cntUpper->value(0.55);
cntUpper->callback((Fl_Callback*)cb_cntUpper);
cntUpper->align(Fl_Align(FL_ALIGN_TOP));
cntUpper->when(FL_WHEN_CHANGED);
o->value(progdefaults.CWupper);
o->labelsize(FL_NORMAL_SIZE);
} // Fl_Counter2* cntUpper
{ Fl_Check_Button* o = btnCWmfilt = new Fl_Check_Button(330, 108, 80, 20, _("Matched Filter"));
btnCWmfilt->tooltip(_("Matched Filter bandwidth"));
btnCWmfilt->down_box(FL_DOWN_BOX);
btnCWmfilt->value(1);
btnCWmfilt->callback((Fl_Callback*)cb_btnCWmfilt);
o->value(progdefaults.CWmfilt);
} // Fl_Check_Button* btnCWmfilt
{ Fl_Check_Button* o = btnCWuseFFTfilter = new Fl_Check_Button(330, 134, 125, 20, _("FFT filter"));
btnCWuseFFTfilter->tooltip(_("FFT / FIR filter"));
btnCWuseFFTfilter->down_box(FL_DOWN_BOX);
btnCWuseFFTfilter->value(1);
btnCWuseFFTfilter->callback((Fl_Callback*)cb_btnCWuseFFTfilter);
o->value(progdefaults.CWuse_fft_filter);
} // Fl_Check_Button* btnCWuseFFTfilter
{ Fl_Check_Button* o = btnCWrcvTrack = new Fl_Check_Button(330, 160, 80, 20, _("Tracking"));
btnCWrcvTrack->tooltip(_("Automatic Rx speed tracking"));
btnCWrcvTrack->down_box(FL_DOWN_BOX);
btnCWrcvTrack->value(1);
btnCWrcvTrack->callback((Fl_Callback*)cb_btnCWrcvTrack);
o->value(progdefaults.CWtrack);
} // Fl_Check_Button* btnCWrcvTrack
{ Fl_Counter2* o = cntCWrange = new Fl_Counter2(225, 150, 65, 20, _("Tracking range (WPM)"));
{ Fl_Counter2* o = cntCWrange = new Fl_Counter2(330, 187, 65, 20, _("Range, WPM"));
cntCWrange->tooltip(_("Range +/- wpm"));
cntCWrange->type(1);
cntCWrange->box(FL_UP_BOX);
@ -4590,19 +4697,6 @@ an merging"));
o->value(progdefaults.CWrange);
o->labelsize(FL_NORMAL_SIZE);
} // Fl_Counter2* cntCWrange
{ valCWrcvWPM = new Fl_Value_Output(70, 185, 35, 20);
valCWrcvWPM->color(FL_BACKGROUND2_COLOR);
valCWrcvWPM->callback((Fl_Callback*)cb_valCWrcvWPM);
} // Fl_Value_Output* valCWrcvWPM
{ prgsCWrcvWPM = new Fl_Progress(105, 185, 250, 20);
prgsCWrcvWPM->tooltip(_("Tracked CW speed in WPM"));
prgsCWrcvWPM->color(FL_BACKGROUND_COLOR);
prgsCWrcvWPM->selection_color(FL_SELECTION_COLOR);
prgsCWrcvWPM->align(Fl_Align(FL_ALIGN_CENTER));
} // Fl_Progress* prgsCWrcvWPM
{ Fl_Box* o = new Fl_Box(360, 185, 70, 20, _("RX WPM"));
o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(5, 215, 490, 150, _("Transmit"));
@ -5319,7 +5413,7 @@ an merging"));
} // Fl_Group* o
tabContestia->end();
} // Fl_Group* tabContestia
{ tabPSK = new Fl_Group(-4, 50, 521, 322, _("PSK"));
{ tabPSK = new Fl_Group(0, 50, 500, 322, _("PSK"));
tabPSK->hide();
{ tabsPSK = new Fl_Tabs(-4, 50, 521, 322);
tabsPSK->selection_color(FL_LIGHT1);

Wyświetl plik

@ -132,7 +132,7 @@ static const char szProsigns[] = "~|%|&|+|=|{|}|<|>|[|]| ";} {}
xywh {729 57 500 400} type Double color 45 selection_color 51 labelsize 18 align 80 non_modal visible
} {
Fl_Tabs tabsConfigure {open
xywh {-5 0 545 372} color 50 selection_color 50
xywh {-5 0 553 372} color 50 selection_color 50
} {
Fl_Group tabOperator {
label Operator
@ -217,7 +217,7 @@ progdefaults.changed = true;}
}
Fl_Group tabUI {
label UI open
xywh {0 25 506 346} hide
xywh {0 25 500 346} hide
} {
Fl_Tabs tabsUI {open
xywh {0 25 506 346} selection_color 50
@ -1019,14 +1019,14 @@ WF_UI();}
}
Fl_Group tabWaterfall {
label Waterfall open
xywh {-2 25 501 347} hide
xywh {0 25 500 347} hide
} {
Fl_Tabs tabsWaterfall {open
xywh {-2 25 501 347} color 50 selection_color 50
} {
Fl_Group {} {
label Display open
xywh {-2 50 501 320} hide
xywh {0 50 500 320}
} {
Fl_Group {} {
label {Colors and cursors} open
@ -1267,7 +1267,7 @@ progdefaults.changed = true;}
}
Fl_Group {} {
label {FFT Processing} open
xywh {-2 50 500 320}
xywh {0 50 500 320} hide
} {
Fl_Group {} {open
xywh {3 62 490 135} box ENGRAVED_FRAME
@ -1337,7 +1337,7 @@ progdefaults.changed = true;}
}
Fl_Group {} {
label Mouse open
xywh {-2 50 500 320} hide
xywh {0 50 500 320} hide
} {
Fl_Group {} {open
xywh {3 62 490 170} box ENGRAVED_FRAME
@ -1388,17 +1388,17 @@ behaves inside the waterfall} xywh {13 196 150 22} down_box BORDER_BOX align 8
}
Fl_Group tabModems {
label Modems open
xywh {-5 25 545 347} hide
xywh {0 25 500 347} hide
} {
Fl_Tabs tabsModems {open
xywh {-5 25 545 347} selection_color 50 align 9
xywh {0 25 500 347} selection_color 50 align 9
} {
Fl_Group tabCW {
label CW open
xywh {0 50 504 320}
xywh {0 50 500 320}
} {
Fl_Tabs tabsCW {open
xywh {0 50 504 320} selection_color 50
xywh {0 50 500 320} selection_color 50
} {
Fl_Group {} {
label General open
@ -1412,38 +1412,74 @@ behaves inside the waterfall} xywh {13 196 150 22} down_box BORDER_BOX align 8
label {Filter bandwidth}
callback {progdefaults.CWbandwidth = (int)o->value();
progdefaults.changed = true;}
tooltip {CW dsp filter bandwidth} xywh {40 115 290 20} type Horizontal align 8 minimum 10 maximum 500 step 10 value 150 textsize 14
tooltip {CW dsp filter bandwidth} xywh {20 149 300 20} type Horizontal align 5 minimum 10 maximum 400 step 1 value 66 textsize 14
code0 {o->value(progdefaults.CWbandwidth);}
code1 {o->labelsize(FL_NORMAL_SIZE); o->textsize(FL_NORMAL_SIZE);}
class Fl_Value_Slider2
}
Fl_Value_Output valCWrcvWPM {
label {Rx WPM}
callback {progdefaults.changed = true;}
xywh {20 188 35 20} color 7 align 5
}
Fl_Progress prgsCWrcvWPM {
tooltip {Tracked CW speed in WPM} xywh {56 188 264 20} color 49 selection_color 15 align 0
}
Fl_Check_Button btnCWuseSOMdecoding {
label {SOM decoding}
callback {progdefaults.CWuseSOMdecoding = o->value();
progdefaults.changed = true;}
tooltip {Self Organizing Mapping} xywh {16 108 125 20} down_box DOWN_BOX value 1
code0 {o->value(progdefaults.CWuseSOMdecoding);}
}
Fl_Counter cntLower {
label Lower
callback {progdefaults.CWlower = o->value();
progdefaults.changed = true;}
tooltip {Detector low threshold} xywh {162 108 65 20} type Simple align 1 minimum 0.01 maximum 0.99 step 0.01 value 0.45
code0 {o->value(progdefaults.CWlower);}
code1 {o->labelsize(FL_NORMAL_SIZE);}
class Fl_Counter2
}
Fl_Counter cntUpper {
label Upper
callback {progdefaults.CWupper = o->value();
progdefaults.changed = true;}
tooltip {Detector high threshold} xywh {255 108 65 20} type Simple align 1 minimum 0.01 maximum 0.99 step 0.01 value 0.55
code0 {o->value(progdefaults.CWupper);}
code1 {o->labelsize(FL_NORMAL_SIZE);}
class Fl_Counter2
}
Fl_Check_Button btnCWmfilt {
label {Matched Filter}
callback {progdefaults.CWmfilt = o->value();
progdefaults.changed = true;}
tooltip {Matched Filter bandwidth} xywh {330 108 80 20} down_box DOWN_BOX value 1
code0 {o->value(progdefaults.CWmfilt);}
}
Fl_Check_Button btnCWuseFFTfilter {
label {FFT filter}
callback {progdefaults.CWuse_fft_filter = o->value();
progdefaults.changed = true;}
tooltip {FFT / FIR filter} xywh {330 134 125 20} down_box DOWN_BOX value 1
code0 {o->value(progdefaults.CWuse_fft_filter);}
}
Fl_Check_Button btnCWrcvTrack {
label Tracking
callback {progdefaults.CWtrack = o->value();
progdefaults.changed = true;}
tooltip {Automatic Rx speed tracking} xywh {40 150 80 20} down_box DOWN_BOX value 1
tooltip {Automatic Rx speed tracking} xywh {330 160 80 20} down_box DOWN_BOX value 1
code0 {o->value(progdefaults.CWtrack);}
}
Fl_Counter cntCWrange {
label {Tracking range (WPM)}
label {Range, WPM}
callback {progdefaults.CWrange = (int)o->value();
progdefaults.changed = true;}
tooltip {Range +/- wpm} xywh {225 150 65 20} type Simple align 8 minimum 5 maximum 25 step 1 value 10
tooltip {Range +/- wpm} xywh {330 187 65 20} type Simple align 8 minimum 5 maximum 25 step 1 value 10
code0 {o->value(progdefaults.CWrange);}
code1 {o->labelsize(FL_NORMAL_SIZE);}
class Fl_Counter2
}
Fl_Value_Output valCWrcvWPM {
callback {progdefaults.changed = true;}
xywh {70 185 35 20} color 7
}
Fl_Progress prgsCWrcvWPM {
tooltip {Tracked CW speed in WPM} xywh {105 185 250 20} color 49 selection_color 15 align 0
}
Fl_Box {} {
label {RX WPM}
xywh {360 185 70 20} align 20
}
}
Fl_Group {} {
label Transmit open
@ -2123,7 +2159,7 @@ progdefaults.changed = true;}
}
Fl_Group tabPSK {
label PSK open
xywh {-4 50 521 322} hide
xywh {0 50 500 322} hide
} {
Fl_Tabs tabsPSK {open
xywh {-4 50 521 322} selection_color 50

Wyświetl plik

@ -5522,6 +5522,48 @@ void set_zdata(complex *zarray, int len)
wf->wfscope->zdata(zarray, len);
}
void set_scope_xaxis_1(double y1)
{
if (digiscope)
digiscope->xaxis_1(y1);
wf->wfscope->xaxis_1(y1);
}
void set_scope_xaxis_2(double y2)
{
if (digiscope)
digiscope->xaxis_2(y2);
wf->wfscope->xaxis_2(y2);
}
void set_scope_yaxis_1(double x1)
{
if (digiscope)
digiscope->yaxis_1(x1);
wf->wfscope->yaxis_1(x1);
}
void set_scope_yaxis_2(double x2)
{
if (digiscope)
digiscope->yaxis_2(x2);
wf->wfscope->yaxis_2(x2);
}
void set_scope_clear_axis()
{
if (digiscope) {
digiscope->xaxis_1(0);
digiscope->xaxis_2(0);
digiscope->yaxis_1(0);
digiscope->yaxis_2(0);
}
wf->wfscope->xaxis_1(0);
wf->wfscope->xaxis_2(0);
wf->wfscope->yaxis_1(0);
wf->wfscope->yaxis_2(0);
}
// raw buffer functions can ONLY be called by FLMAIN_TID
//======================================================================

Wyświetl plik

@ -28,6 +28,7 @@
// ----------------------------------------------------------------------------
#include <config.h>
#include <memory.h>
#include <cmath>
#include "misc.h"
@ -52,10 +53,31 @@ fftfilt::fftfilt(double f1, double f2, int len)
ovlbuf[i].re = ovlbuf[i].im = 0.0;
inptr = 0;
create_filter(f1, f2);
}
fftfilt::fftfilt(double f, int len)
{
filterlen = len;
fft = new Cfft(filterlen);
ift = new Cfft(filterlen);
ovlbuf = new complex[filterlen/2];
filter = new complex[filterlen];
filtdata = new complex[filterlen];
for (int i = 0; i < filterlen; i++)
filter[i].re = filter[i].im =
filtdata[i].re = filtdata[i].im = 0.0;
for (int i = 0; i < filterlen/2; i++)
ovlbuf[i].re = ovlbuf[i].im = 0.0;
inptr = 0;
create_lpf(f);
}
fftfilt::~fftfilt()
{
if (fft) delete fft;
@ -75,7 +97,7 @@ void fftfilt::create_filter(double f1, double f2)
// initialize the filter to zero
for (int i = 0; i < filterlen; i++)
filter[i].re = filter[i].im = 0.0;
filter[i].re = filter[i].im = 0.0;
// create the filter shape coefficients by fft
// filter values initialized to the impulse response h(t)
@ -99,20 +121,52 @@ void fftfilt::create_filter(double f1, double f2)
}
void fftfilt::create_lpf(double f)
{
int len = filterlen / 2 + 1;
double t, h, x, it;
Cfft *tmpfft;
tmpfft = new Cfft(filterlen);
// initialize the filter to zero
for (int i = 0; i < filterlen; i++)
filter[i].re = filter[i].im = 0.0;
// create the filter shape coefficients by fft
// filter values initialized to the impulse response h(t)
for (int i = 0; i < len; i++) {
it = (double) i;
t = it - (len - 1) / 2.0;
h = it / (len - 1);
x = f * sinc(2 * f * t);
x *= blackman(h); // windowed by Blackman function
x *= filterlen; // scaled for unity in passband
filter[i].re = x;
}
// perform the complex forward fft to obtain H(w)
tmpfft->cdft(filter);
// start outputs after 2 full passes are complete
pass = 2;
delete tmpfft;
}
/*
* Filter with fast convolution (overlap-add algorithm).
*/
int fftfilt::run(const complex& in, complex **out)
{
// collect filterlen/2 input samples
const int filterlen_div2 = filterlen / 2 ;
filtdata[inptr++] = in;
if (inptr < filterlen / 2)
if (inptr < filterlen_div2)
return 0;
if (pass) --pass; // filter output is not stable until 2 passes
// zero the rest of the input data
for (int i = filterlen / 2 ; i < filterlen; i++)
for (int i = filterlen_div2 ; i < filterlen; i++)
filtdata[i].re = filtdata[i].im = 0.0;
// FFT transpose to the frequency domain
@ -127,15 +181,15 @@ int fftfilt::run(const complex& in, complex **out)
ift->icdft(filtdata);
// overlap and add
for (int i = 0; i < filterlen / 2; i++) {
filtdata[i].re += ovlbuf[i].re;
filtdata[i].im += ovlbuf[i].im;
for (int i = 0; i < filterlen_div2; i++) {
filtdata[i] += ovlbuf[i];
}
*out = filtdata;
// save the second half for overlapping
for (int i = 0; i < filterlen / 2; i++)
ovlbuf[i] = filtdata[i + filterlen / 2];
// Memcpy is allowed because complex are POD objects.
memcpy( ovlbuf, filtdata + filterlen_div2, sizeof( ovlbuf[0] ) * filterlen_div2 );
// clear inbuf pointer
inptr = 0;
@ -143,5 +197,5 @@ int fftfilt::run(const complex& in, complex **out)
// signal the caller there is filterlen/2 samples ready
if (pass) return 0;
return filterlen / 2;
return filterlen_div2;
}

Wyświetl plik

@ -161,12 +161,17 @@ extern Fl_Tabs *tabsModems;
extern Fl_Group *tabCW;
extern Fl_Tabs *tabsCW;
extern Fl_Value_Slider2 *sldrCWbandwidth;
extern Fl_Check_Button *btnCWrcvTrack;
extern Fl_Counter2 *cntCWrange;
#include <FL/Fl_Value_Output.H>
extern Fl_Value_Output *valCWrcvWPM;
#include <FL/Fl_Progress.H>
extern Fl_Progress *prgsCWrcvWPM;
extern Fl_Check_Button *btnCWuseSOMdecoding;
extern Fl_Counter2 *cntLower;
extern Fl_Counter2 *cntUpper;
extern Fl_Check_Button *btnCWmfilt;
extern Fl_Check_Button *btnCWuseFFTfilter;
extern Fl_Check_Button *btnCWrcvTrack;
extern Fl_Counter2 *cntCWrange;
extern Fl_Value_Slider2 *sldrCWxmtWPM;
extern Fl_Counter2 *cntCWdefWPM;
#include <FL/Fl_Counter.H>

Wyświetl plik

@ -166,6 +166,9 @@
ELEM_(bool, StartAtSweetSpot, "STARTATSWEETSPOT", \
"Always start new modems at sweet spot frequencies", \
false) \
ELEM_(bool, CWOffset, "CWOFFSET", \
"Select if waterfall should compensate for BFO offset in CW", \
false) \
ELEM_(bool, CWIsLSB, "CWISLSB", \
"Select if BFO is injected as LSB instead of USB", \
false) \
@ -324,9 +327,27 @@
ELEM_(int, CWbandwidth, "CWBANDWIDTH", \
"Filter bandwidth (Hz)", \
150) \
ELEM_(double, CWlower, "CWLOWER", \
"Detector hysterisis, lower threshold", \
0.4) \
ELEM_(double, CWupper, "CWUPPER", \
"Detector hysterisis, upper threshold", \
0.6) \
ELEM_(int, CWmfiltlen, "CWMFILTLEN", \
"Matched Filter length", \
100) \
ELEM_(bool, CWtrack, "CWTRACK", \
"Automatic receive speed tracking", \
true) \
ELEM_(bool, CWmfilt, "CWMFILT", \
"Matched Filter in use", \
false) \
ELEM_(bool, CWuse_fft_filter, "CWUSEFFTFILTER", \
"Use FFT overlap and add convolution filter", \
false) \
ELEM_(bool, CWuseSOMdecoding, "CWUSESOMDECODING", \
"Self Organizing Map decoding", \
false) \
ELEM_(int, CWrange, "CWRANGE", \
"Tracking range for CWTRACK (WPM)", \
10) \
@ -457,6 +478,57 @@
ELEM_(double, ThorCWI, "THORCWI", \
"CWI threshold (CWI detection and suppression)", \
0.0) \
ELEM_(bool, THOR_PREAMBLE, "THORPREAMBLE", \
"Detect THOR preamble (and flush Rx pipeline)", \
true) \
ELEM_(bool, THOR_SOFTSYMBOLS, "THORSOFTSYMBOLS", \
"Enable Soft-symbol decoding", \
true) \
ELEM_(bool, THOR_SOFTBITS, "THORSOFTBITS", \
"Enable Soft-bit decoding", \
true) \
/* PACKET */ \
ELEM_(int, PKT_BAUD_SELECT, "PKTBAUDSELECT", \
"Packet baud rate. Values are as follows:\n" \
" 0: 1200 (V/UHF); 1: 300 (HF); 2: 2400 (V/UHF)", \
0) /* 1200 baud (V/UHF) default. */ \
ELEM_(double, PKT_LOSIG_RXGAIN, "LOSIGRXGAIN", \
"Signal gain for lower frequency (Mark) tone (in dB)", \
0.0) \
ELEM_(double, PKT_HISIG_RXGAIN, "HISIGRXGAIN", \
"Signal gain for higher frequency (Space) tone (in dB)", \
0.0) \
ELEM_(double, PKT_LOSIG_TXGAIN, "LOSIGTXGAIN", \
"Signal gain for Mark (lower frequency) tone (in dB)", \
0.0) \
ELEM_(double, PKT_HISIG_TXGAIN, "HISIGTXGAIN", \
"Signal gain for Space (higher frequency) tone (in dB)", \
0.0) \
ELEM_(bool, PKT_PreferXhairScope, "PKTPREFERXHAIRSCOPE", \
"Default to syncscope (detected symbol scope)", \
false) ELEM_(bool, PKT_AudioBoost, "PKTAUDIOBOOST", \
"No extra input gain (similar to Mic Boost) by default", \
false) \
\
ELEM_(bool, PKT_RXTimestamp, "PKTRXTIMESTAMP", \
"No timestamps on RX packets by default", \
false) \
\
ELEM_(bool, PKT_expandMicE, "PKTEXPANDMICE", \
"decode received Mic-E data", \
false) \
ELEM_(bool, PKT_expandPHG, "PKTEXPANDPHG", \
"decode received PHG data", \
false) \
ELEM_(bool, PKT_expandCmp, "PKTEXPANDCMP", \
"decode received Compressed Position data", \
false) \
ELEM_(bool, PKT_unitsSI, "PKTUNITSSI", \
"display decoded data in SI units", \
false) \
ELEM_(bool, PKT_unitsEnglish, "PKTUNITSENGLISH", \
"display decoded data in English units", \
false) \
/* DOMINOEX */ \
ELEM_(double, DOMINOEX_BW, "DOMINOEXBW", \
"Filter bandwidth factor (bandwidth relative to signal width)", \
@ -546,7 +618,7 @@
{255, 255, 255, 255}) \
ELEM_(RGBI, rttymarkRGBI, "RTTYMARKRGBI", \
"Color of RTTY MARK freq marker (RGBI)", \
{255, 128, 0, 255}) \
{255, 120, 0, 255}) \
ELEM_(int, feldfontnbr, "FELDFONTNBR", \
"Index of raster font used for transmission", \
4) \
@ -1301,9 +1373,29 @@
ELEM_(int, wefax_filter, "WEFAXFILTER", \
"Input filter for image reception", \
0) \
/* NAVTEX configuration items */ \
ELEM_(bool, NVTX_AdifLog, "NAVTEXADIFLOG", \
"Logs Navtex messages in Adig log file", \
ELEM_(bool, WEFAX_EmbeddedGui, "WEFAXEMBEDDEDGUI", \
"Embedded GUI", \
true) \
ELEM_(bool, WEFAX_HideTx, "WEFAXHIDETX", \
"Hide transmission window", \
true) \
ELEM_(int, WEFAX_Shift, "WEFAXSHIFT", \
"Shift (Standard 800Hz)", \
800 ) \
ELEM_(int, WEFAX_MaxRows, "WEFAXMAXROWS", \
"Received fax maximum number of rows", \
2900 ) \
ELEM_(int, WEFAX_NoiseMargin, "WEFAXNOISEMARGIN", \
"Pixel margin for noise removal", \
1 ) \
ELEM_(int, WEFAX_NoiseThreshold, "WEFAXNOISETHRESHOLD", \
"Threshold level for noise detection and removal", \
5 ) \
ELEM_(int, WEFAX_SaveMonochrome, "WEFAXSAVEMONOCHROME", \
"Save fax image as monochrome", \
true ) \
ELEM_(bool, WEFAX_AdifLog, "WEFAXADIFLOG", \
"Logs wefax file names in Adif log file", \
false) \
/* WX fetch from NOAA */ \
ELEM_(std::string, wx_sta, "WX_STA", \

Wyświetl plik

@ -28,18 +28,24 @@
#ifndef _CW_H
#define _CW_H
#include <cstring>
#include <string>
#include "modem.h"
#include "filters.h"
#include "fftfilt.h"
//#include "mfilt.h" //AG1LE: added this
#include "mbuffer.h"
#define CWSampleRate 8000
#define CWMaxSymLen 4096
#define KNUM 128
#define CWMaxSymLen 4096 // AG1LE: - was 4096
#define KNUM 122
// decimation ratio for the receiver
//#define DEC_RATIO 8
//#define CW_FIRLEN 32
//#define CW_FIRLEN 128
//#define CW_FIRLEN 122
//#define CW_FIRLEN 256
//#define CW_FIRLEN 512
// Limits on values of CW send and timing parameters
@ -47,8 +53,8 @@
//#define CW_MAX_SPEED 100 // Highest WPM allowed
// CW function return status codes.
#define CW_SUCCESS 0
#define CW_ERROR -1
#define CW_SUCCESS 0
#define CW_ERROR -1
#define ASC_NUL '\0' // End of string
#define ASC_SPACE ' ' // ASCII space char
@ -70,6 +76,8 @@
#define TRACKING_FILTER_SIZE 16
#define MAX_PIPE_SIZE (22 * CWSampleRate * 12 / 800)
enum CW_RX_STATE {
RS_IDLE = 0,
RS_IN_TONE,
@ -84,16 +92,43 @@ enum CW_EVENT {
};
class cw : public modem {
protected:
int symbollen; // length of a dot in sound samples (tx)
int fsymlen; // length of extra interelement space (farnsworth)
double phaseacc; // used by NCO for rx/tx tones
unsigned int smpl_ctr; // sample counter for timing cw rx
double agc_peak; // threshold for tone detection
C_FIR_filter *cwfilter;
Cmovavg *bitfilter;
Cmovavg *trackingfilter;
#define CLRCOUNT 16
#define DEC_RATIO 16
#define CW_FIRLEN 512
// Maximum number of signs (dit or dah) in a Morse char.
#define WGT_SIZE 7
struct SOM_TABLE {
char chr; /* The character(s) represented */
const char *prt; /* The printable representation of the character */
float wgt[WGT_SIZE]; /* Dot-dash weight vector */
};
protected:
int symbollen; // length of a dot in sound samples (tx)
int fsymlen; // length of extra interelement space (farnsworth)
double phaseacc; // used by NCO for rx/tx tones
double FFTphase;
double FIRphase;
double FFTvalue;
double FIRvalue;
unsigned int smpl_ctr; // sample counter for timing cw rx
double agc_peak; // threshold for tone detection
int FilterFFTLen;
bool use_matched_filter;
bool use_fft_filter;
double upper_threshold;
double lower_threshold;
C_FIR_filter *hilbert; // Hilbert filter precedes sinc filter
fftfilt *cw_FFT_filter; // sinc / matched filter
C_FIR_filter *cw_FIR_filter; // linear phase finite impulse response filter
Cmovavg *bitfilter;
Cmovavg *trackingfilter;
int bitfilterlen;
@ -101,8 +136,9 @@ protected:
CW_RX_STATE old_cw_receive_state;
CW_EVENT cw_event; // functions used by cw process routine
double pipe[CWMaxSymLen]; // storage for sync scope data
mbuffer<double, CWMaxSymLen, 2> scopedata;
double pipe[MAX_PIPE_SIZE+1]; // storage for sync scope data
double clearpipe[MAX_PIPE_SIZE+1];
mbuffer<double, MAX_PIPE_SIZE + 1, 4> scopedata;
int pipeptr;
int pipesize;
bool scope_clear;
@ -112,23 +148,23 @@ protected:
int cw_bandwidth;
int cw_squelch;
int cw_send_speed; // Initially 18 WPM
int cw_receive_speed; // Initially 18 WPM
int cw_receive_speed; // Initially 18 WPM
bool usedefaultWPM; // use default WPM
int cw_upper_limit;
int cw_lower_limit;
long int cw_noise_spike_threshold; // Initially ignore any tone < 10mS
long int cw_noise_spike_threshold; // Initially ignore any tone < 10mS
int cw_in_sync; // Synchronization flag
// Sending parameters:
long int cw_send_dot_length; // Length of a send Dot, in Usec
long int cw_send_dash_length; // Length of a send Dash, in Usec
long int cw_send_dot_length; // Length of a send Dot, in Usec
long int cw_send_dash_length; // Length of a send Dash, in Usec
int lastsym; // last symbol sent
double risetime; // leading/trailing edge rise time (msec)
int knum; // number of samples on edges
int QSKshape; // leading/trailing edge shape factor
double qskbuf[OUTBUFSIZE]; // signal array for qsk drive
double risetime; // leading/trailing edge rise time (msec)
int knum; // number of samples on edges
int QSKshape; // leading/trailing edge shape factor
double qskbuf[OUTBUFSIZE]; // signal array for qsk drive
double qskphase; //
bool firstelement;
@ -142,10 +178,11 @@ protected:
#define RECEIVE_CAPACITY 256 // Way longer than any representation
char rx_rep_buf[RECEIVE_CAPACITY];
int cw_rr_current; // Receive buffer current location
unsigned int cw_rr_start_timestamp; // Tone start timestamp
unsigned int cw_rr_end_timestamp; // Tone end timestamp
unsigned int cw_rr_start_timestamp; // Tone start timestamp
unsigned int cw_rr_end_timestamp; // Tone end timestamp
long int cw_adaptive_receive_threshold; // 2-dot threshold for adaptive speed
long int cw_adaptive_receive_threshold; // 2-dot threshold for adaptive speed
int in_replay; //AG1LE: if we have replay even, set to 1 otherwise = 0 ;
// Receive adaptive speed tracking.
double dot_tracking;
@ -157,6 +194,7 @@ protected:
void clear_syncscope();
void update_Status();
void sync_parameters();
void reset_rx_filter();
int handle_event(int cw_event, const char **c);
int usec_diff(unsigned int earlier, unsigned int later);
void send_symbol(int symbol, int len);
@ -166,7 +204,16 @@ protected:
void update_tracking(int dot, int dash);
void makeshape();
complex mixer(complex in);
static const SOM_TABLE som_table[];
float cw_buffer[512];
int cw_ptr;
int clrcount;
bool use_paren;
std::string prosigns;
public:
cw();
~cw();
@ -174,12 +221,20 @@ public:
void rx_init();
void tx_init(SoundBase *sc);
void restart() {};
int rx_process(const double *buf, int len);
void rx_FFTprocess(const double *buf, int len);
void rx_FIRprocess(const double *buf, int len);
void decode_stream(double);
int tx_process();
void incWPM();
void decWPM();
void toggleWPM();
int normalize(float *v, int n, int twodots);
const char *find_winner (float *inbuf, int twodots);
};
#endif

Wyświetl plik

@ -67,6 +67,7 @@ private:
double _phase;
double _quality;
double _flo, _fhi, _amp;
double _x1, _x2, _y1, _y2;
bool _highlight;
scope_mode phase_mode;
@ -89,6 +90,11 @@ public:
void rtty(double flo, double fhi, double amp);
void mode(scope_mode md);
scope_mode mode() { return _mode;};
void xaxis_1(double y1) { _y1 = y1; }
void xaxis_2(double y2) { _y2 = y2; }
void yaxis_1(double x1) { _x1 = x1; }
void yaxis_2(double x2) { _x2 = x2; }
void clear_axis() { _x1 = _x2 = _y1 = _y2 = 0; }
};
#endif

Wyświetl plik

@ -22,8 +22,10 @@ protected:
int pass;
public:
fftfilt(double f1, double f2, int len);
fftfilt(double f, int len);
~fftfilt();
void create_filter(double f1, double f2);
void create_lpf(double f);
int run(const complex& in, complex **out);
};

Wyświetl plik

@ -179,6 +179,12 @@ extern void set_rtty(double, double, double);
extern void set_video(double *, int, bool = true);
extern void set_zdata(complex *, int);
extern void set_scope_xaxis_1(double y1);
extern void set_scope_xaxis_2(double y2);
extern void set_scope_yaxis_1(double x1);
extern void set_scope_yaxis_2(double x2);
extern void set_scope_clear_axis();
extern void set_CWwpm();
extern void put_rx_char(unsigned int data, int style = FTextBase::RECV);
extern void put_sec_char( char chr );

Wyświetl plik

@ -139,6 +139,7 @@ public:
virtual void decWPM() {};
virtual void toggleWPM() {};
virtual void sync_parameters() {};
virtual void reset_rx_filter(bool) {};
virtual void update_Status() {};
// for waterfall id transmission
@ -200,6 +201,9 @@ extern modem *mfsk64_modem;
extern modem *wefax576_modem;
extern modem *wefax288_modem;
extern modem *navtex_modem;
extern modem *sitorb_modem;
extern modem *mt63_500_modem;
extern modem *mt63_1000_modem;
extern modem *mt63_2000_modem;
@ -231,6 +235,7 @@ extern modem *psk250r_modem;
extern modem *psk500r_modem;
extern modem *rtty_modem;
extern modem *pkt_modem;
extern modem *olivia_modem;
extern modem *contestia_modem;
@ -239,10 +244,14 @@ extern modem *thor4_modem;
extern modem *thor5_modem;
extern modem *thor8_modem;
extern modem *thor11_modem;
//extern modem *tsor11_modem;
extern modem *thor16_modem;
extern modem *thor22_modem;
extern modem *dominoex44_modem;
extern modem *thor44_modem;
extern modem *dominoex88_modem;
extern modem *thor88_modem;
extern modem *dominoex4_modem;
extern modem *dominoex5_modem;
extern modem *dominoex8_modem;

Wyświetl plik

@ -52,6 +52,7 @@ Digiscope::Digiscope (int X, int Y, int W, int H) :
_highlight = false;
_len = MAX_LEN;
_zptr = 0;
_x1 = _x2 = _y1 = _y2;
phase_mode = PHASE1;
}
@ -138,11 +139,9 @@ void Digiscope::data(double *data, int len, bool scale)
max = MAX(max, _buf[i]);
min = MIN(min, _buf[i]);
}
if (max == min) max *= 1.001;
for (int i = 0; i < _len; i++)
if (_buf[i] > 0.001) // threshold
_buf[i] = (_buf[i] - min) / (max - min);
else
_buf[i] = 0.0;
_buf[i] = (_buf[i] - min) / (max - min);
}
REQ_DROP(&Digiscope::redraw, this);
FL_UNLOCK_D();
@ -336,10 +335,42 @@ void Digiscope::draw_scope()
for (int i = 0; i < npts; i++)
fl_vertex( (double)i / npts, _buf[i * _len / npts] );
fl_end_line();
// x & y axis'
if (_x1) {
fl_color(FL_WHITE);
fl_begin_line();
fl_vertex(_x1, 0.0);
fl_vertex(_x1, 1.0);
fl_end_line();
}
if (_x2) {
fl_color(FL_YELLOW);
fl_begin_line();
fl_vertex(_x2, 0.0);
fl_vertex(_x2, 1.0);
fl_end_line();
}
if (_y1) {
fl_color(FL_WHITE);
fl_begin_line();
fl_vertex(0.0, _y1);
fl_vertex(1.0, _y1);
fl_end_line();
}
if (_y2) {
fl_color(FL_YELLOW);
fl_begin_line();
fl_vertex(0.0, _y2);
fl_vertex(1.0, _y2);
fl_end_line();
}
fl_pop_matrix();
fl_pop_clip();
}
void Digiscope::draw_xy()
{
fl_clip(x()+2,y()+2,w()-4,h()-4);