Merge with upstream

pull/2/head
Stelios Bounanos 2008-04-28 18:30:32 +01:00
commit 92fa4ad9ea
16 zmienionych plików z 287 dodań i 300 usunięć

Wyświetl plik

@ -36,6 +36,13 @@ Change Log:
2) fading fixed length vector display
3) fading variable length vector display; length proportional to
signal quality.
18) Completely new DominoEX decoder - similar in theory to ZL2AFP
DominoEX, which has FFT bin resolution 4x the tone spacing. No AFC is
required for proper tracking of the Rx signal.
19) Removed ZOH and Linear interpolator choices from the resampling choice
menu under Sound Card configuration.
20) Fixed a bug in the global.cxx structures. Missing field in "CW"
definition.
2.10.3)
1) Corrected memory leak bug.

Wyświetl plik

@ -9,7 +9,7 @@ dnl major and minor must be integers; patch may
dnl contain other characters or be empty
m4_define(FLDIGI_MAJOR, [2])
m4_define(FLDIGI_MINOR, [11])
m4_define(FLDIGI_PATCH, [S])
m4_define(FLDIGI_PATCH, [U])
AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com])

Wyświetl plik

@ -881,8 +881,9 @@ Fl_Group *tabDomEX=(Fl_Group *)0;
Fl_Input *txtSecondary=(Fl_Input *)0;
static void cb_txtSecondary(Fl_Input*, void*) {
progdefaults.changed = true;
static void cb_txtSecondary(Fl_Input* o, void*) {
progdefaults.secText = o->value();
progdefaults.changed = true;
}
Fl_Button *btnRestartDomEX=(Fl_Button *)0;
@ -895,7 +896,15 @@ resetDOMEX();
Fl_Counter *valDominoEX_BW=(Fl_Counter *)0;
static void cb_valDominoEX_BW(Fl_Counter* o, void*) {
progdefaults.DOMINOEX_BW=o->value();
progdefaults.DOMINOEX_BW = o->value();
resetDOMEX();
progdefaults.changed = true;
}
Fl_Check_Button *valDominoEX_FILTER=(Fl_Check_Button *)0;
static void cb_valDominoEX_FILTER(Fl_Check_Button* o, void*) {
progdefaults.DOMINOEX_FILTER = o->value();
progdefaults.changed = true;
}
@ -1669,6 +1678,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
{ tabAudio = new Fl_Group(0, 50, 400, 170, "Audio devices");
tabAudio->color((Fl_Color)51);
tabAudio->selection_color((Fl_Color)51);
tabAudio->hide();
{ AudioOSS = new Fl_Group(5, 58, 391, 35);
AudioOSS->box(FL_ENGRAVED_FRAME);
{ btnAudioIO[0] = new Fl_Round_Button(5, 63, 100, 25, "OSS");
@ -1727,7 +1737,6 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
{ tabAudioOpt = new Fl_Group(0, 50, 400, 170, "Audio settings");
tabAudioOpt->color((Fl_Color)51);
tabAudioOpt->selection_color((Fl_Color)51);
tabAudioOpt->hide();
{ Fl_Spinner* o = cntRxRateCorr = new Fl_Spinner(5, 160, 85, 25, "RX ppm");
cntRxRateCorr->value(1);
cntRxRateCorr->callback((Fl_Callback*)cb_cntRxRateCorr);
@ -2019,24 +2028,30 @@ l with your sound hardware.");
{ tabDomEX = new Fl_Group(0, 50, 400, 170, "DomEX");
tabDomEX->color((Fl_Color)51);
tabDomEX->selection_color((Fl_Color)51);
tabDomEX->hide();
{ txtSecondary = new Fl_Input(20, 75, 360, 44, "Secondary Text");
txtSecondary->type(4);
txtSecondary->callback((Fl_Callback*)cb_txtSecondary);
txtSecondary->align(FL_ALIGN_TOP_LEFT);
txtSecondary->when(FL_WHEN_CHANGED);
} // Fl_Input* txtSecondary
{ btnRestartDomEX = new Fl_Button(300, 172, 79, 28, "Restart");
btnRestartDomEX->callback((Fl_Callback*)cb_btnRestartDomEX);
btnRestartDomEX->hide();
} // Fl_Button* btnRestartDomEX
{ Fl_Counter* o = valDominoEX_BW = new Fl_Counter(25, 134, 63, 21, "BW factor:");
valDominoEX_BW->type(1);
valDominoEX_BW->minimum(1);
valDominoEX_BW->maximum(3);
valDominoEX_BW->maximum(2);
valDominoEX_BW->step(0.1);
valDominoEX_BW->value(2);
valDominoEX_BW->callback((Fl_Callback*)cb_valDominoEX_BW);
o->value(progdefaults.DOMINOEX_BW);
} // Fl_Counter* valDominoEX_BW
{ Fl_Check_Button* o = valDominoEX_FILTER = new Fl_Check_Button(107, 136, 83, 19, "Filter ON");
valDominoEX_FILTER->down_box(FL_DOWN_BOX);
valDominoEX_FILTER->callback((Fl_Callback*)cb_valDominoEX_FILTER);
o->value(progdefaults.DOMINOEX_FILTER);
} // Fl_Check_Button* valDominoEX_FILTER
tabDomEX->end();
} // Fl_Group* tabDomEX
{ tabFeld = new Fl_Group(0, 50, 400, 170, "Feld");
@ -2250,6 +2265,7 @@ l with your sound hardware.");
{ tabRTTY = new Fl_Group(0, 50, 400, 170, "RTTY");
tabRTTY->color((Fl_Color)51);
tabRTTY->selection_color((Fl_Color)51);
tabRTTY->hide();
{ Fl_Choice* o = selShift = new Fl_Choice(48, 60, 77, 22, "Shift");
selShift->down_box(FL_BORDER_BOX);
selShift->callback((Fl_Callback*)cb_selShift);
@ -2374,10 +2390,10 @@ l with your sound hardware.");
} // Fl_Group* tabModems
tabsConfigure->end();
} // Fl_Tabs* tabsConfigure
{ btnCloseConfig = new Fl_Return_Button(285, 225, 100, 25, "Close");
{ btnCloseConfig = new Fl_Return_Button(285, 222, 100, 25, "Close");
btnCloseConfig->callback((Fl_Callback*)cb_btnCloseConfig);
} // Fl_Return_Button* btnCloseConfig
{ btnSaveConfig = new Fl_Button(15, 225, 100, 25, "Save Config");
{ btnSaveConfig = new Fl_Button(15, 222, 100, 25, "Save Config");
btnSaveConfig->callback((Fl_Callback*)cb_btnSaveConfig);
} // Fl_Button* btnSaveConfig
o->end();

Wyświetl plik

@ -661,7 +661,7 @@ o->label((inpQRZuserpassword->type() & FL_SECRET_INPUT) ? "Show" : "Hide");}
} {
Fl_Group tabAudio {
label {Audio devices} open
xywh {0 50 400 170} color 51 selection_color 51
xywh {0 50 400 170} color 51 selection_color 51 hide
} {
Fl_Group AudioOSS {open
xywh {5 58 391 35} box ENGRAVED_FRAME
@ -743,7 +743,7 @@ resetSoundCard();}
}
Fl_Group tabAudioOpt {
label {Audio settings} open
xywh {0 50 400 170} color 51 selection_color 51 hide
xywh {0 50 400 170} color 51 selection_color 51
} {
Fl_Spinner cntRxRateCorr {
label {RX ppm}
@ -1037,26 +1037,35 @@ progdefaults.changed = true;}
}
Fl_Group tabDomEX {
label DomEX open
xywh {0 50 400 170} color 51 selection_color 51 hide
xywh {0 50 400 170} color 51 selection_color 51
} {
Fl_Input txtSecondary {
label {Secondary Text}
callback {progdefaults.changed = true;}
xywh {20 75 360 44} type Multiline align 5
callback {progdefaults.secText = o->value();
progdefaults.changed = true;}
xywh {20 75 360 44} type Multiline align 5 when 1
}
Fl_Button btnRestartDomEX {
label Restart
callback {progdefaults.storeDefaults();
resetDOMEX();}
xywh {300 172 79 28}
xywh {300 172 79 28} hide
}
Fl_Counter valDominoEX_BW {
label {BW factor:}
callback {progdefaults.DOMINOEX_BW=o->value();
callback {progdefaults.DOMINOEX_BW = o->value();
resetDOMEX();
progdefaults.changed = true;}
xywh {25 134 63 21} type Simple minimum 1 maximum 3 step 0.1 value 2
xywh {25 134 63 21} type Simple minimum 1 maximum 2 step 0.1 value 2
code0 {o->value(progdefaults.DOMINOEX_BW);}
}
Fl_Check_Button valDominoEX_FILTER {
label {Filter ON}
callback {progdefaults.DOMINOEX_FILTER = o->value();
progdefaults.changed = true;} selected
xywh {107 136 83 19} down_box DOWN_BOX
code0 {o->value(progdefaults.DOMINOEX_FILTER);}
}
}
Fl_Group tabFeld {
label Feld open
@ -1289,7 +1298,7 @@ progdefaults.changed = true;}
}
Fl_Group tabRTTY {
label RTTY open
xywh {0 50 400 170} color 51 selection_color 51
xywh {0 50 400 170} color 51 selection_color 51 hide
} {
Fl_Choice selShift {
label Shift
@ -1327,7 +1336,7 @@ resetRTTY();} open
label Stop
callback {progdefaults.changed = true;
progdefaults.storeDefaults();
resetRTTY();} open selected
resetRTTY();} open
xywh {48 158 77 22} down_box BORDER_BOX when 1
code0 {o->add(szStopBits);}
} {}
@ -1423,12 +1432,12 @@ progdefaults.changed = true;}
Fl_Return_Button btnCloseConfig {
label Close
callback {closeDialog();}
xywh {285 225 100 25}
xywh {285 222 100 25}
}
Fl_Button btnSaveConfig {
label {Save Config}
callback {progdefaults.saveDefaults();}
xywh {15 225 100 25}
xywh {15 222 100 25}
}
}
}

Wyświetl plik

@ -1727,7 +1727,7 @@ void put_sec_char( char chr )
{
if (chr >= ' ' && chr <= 'z') {
strSecText.append(1, chr);
if (strSecText.length() > 60)
if (strSecText.length() > 50)
strSecText.erase(0,1);
FL_LOCK_D();
REQ(static_cast<void (Fl_Box::*)(const char *)>(&Fl_Box::label), StatusBar, strSecText.c_str());
@ -1930,7 +1930,7 @@ void resetDOMEX() {
md == MODE_DOMINOEX16 ||
md == MODE_DOMINOEX22 ) {
trx_reset();
// trx_reset();
active_modem->restart();
}
}

Wyświetl plik

@ -1,12 +1,11 @@
//
// dominoex.cxx -- DominoEX modem
// dominoex.cxx -- DominoEX modem
//
// Copyright (C) 2001, 2002, 2003
// Tomi Manninen (oh2bns@sral.fi)
// Copyright (C) 2008
// David Freese (w1hkj@w1hkj.com)
// based on code in gmfsk
// Copyright (C) 2006
// Hamish Moffatt (hamish@debian.org)
// Copyright (C) 2006
// David Freese (w1hkj@w1hkj.com)
// 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
@ -40,10 +39,6 @@
using namespace std;
#define RESOLUTION 1
#define AFC_COUNT 64
char dommsg[80];
void dominoex::tx_init(SoundBase *sc)
@ -52,7 +47,7 @@ void dominoex::tx_init(SoundBase *sc)
txstate = TX_STATE_PREAMBLE;
txprevtone = 0;
counter = 0;
phaseacc = 0.0;
txphase = 0;
videoText();
}
@ -63,8 +58,7 @@ void dominoex::rx_init()
met1 = 0.0;
met2 = 0.0;
counter = 0;
phaseacc = 0.0;
freqerr = 0.0;
phase[0] = phase[1] = phase[2] = phase[3] = 0.0;
put_MODEstatus(mode);
put_sec_char(0);
}
@ -72,25 +66,17 @@ void dominoex::rx_init()
void dominoex::restart()
{
double flo, fhi, bw, cf;
// basetone is always 1000 Hz
// mid frequency is always 1000 Hz + bandwidth / 2
bw = bandwidth * progdefaults.DOMINOEX_BW;
cf = 1000.0 + bandwidth / 2.0;
flo = (cf - bw/2) / samplerate;
fhi = (cf + bw/2) / samplerate;
if (filt)
filt->init_bandpass (127, 1, flo, fhi);
strSecXmtText = txtSecondary->value();
if (strSecXmtText.length() == 0)
strSecXmtText = "fldigi "PACKAGE_VERSION" ";
cf = BASEFREQ + bandwidth / 2.0;
flo = (cf - 0.8 * bw) / samplerate;
fhi = (cf + 0.8 * bw) / samplerate;
for (int i = 0; i < NUMFFTS; i++)
if (filt[i])
filt[i]->init_bandpass (127, 1, flo, fhi);
prev1symbol = prev2symbol = 0;
prev1vector = prev2vector = complex(0.0, 0.0);
}
@ -99,116 +85,103 @@ void dominoex::init()
modem::init();
restart();
rx_init();
strSecXmtText = txtSecondary->value();
if (strSecXmtText.length() == 0)
strSecXmtText = "fldigi "PACKAGE_VERSION" ";
set_scope_mode(Digiscope::DOMDATA);
}
dominoex::~dominoex()
{
if (binsfft) delete binsfft;
if (hilbert) delete hilbert;
for (int i = 0; i < NUMFFTS; i++) {
if (binsfft[i]) delete binsfft[i];
if (filt[i]) delete filt[i];
}
if (pipe) delete [] pipe;
if (filt) delete filt;
}
dominoex::dominoex(trx_mode md)
{
double cf, bw, flo, fhi;
numtones = DOMNUMTONES;
int basetone, lotone, hitone;
mode = md;
switch (mode) {
// 8kHz modes
case MODE_DOMINOEX4:
symlen = 2048;
basetone = 256; // = 1000 * symlen / samplerate
doublespaced = 1;
samplerate = 8000;
break;
case MODE_DOMINOEX8:
symlen = 1024;
basetone = 128; // = 1000 * symlen / samplerate
doublespaced = 1;
samplerate = 8000;
break;
case MODE_DOMINOEX16:
symlen = 512;
basetone = 64; // = 1000 * symlen / samplerate
doublespaced = 0;
samplerate = 8000;
break;
// 11.025 kHz modes
case MODE_DOMINOEX5:
symlen = 2048;
basetone = 186; // 1001.3 Hz
doublespaced = 1;
samplerate = 11025;
break;
case MODE_DOMINOEX11:
symlen = 1024;
basetone = 93; // 1001.3 Hz
doublespaced = 0;
samplerate = 11025;
break;
case MODE_DOMINOEX22:
symlen = 512;
basetone = 46; // 990 Hz
doublespaced = 0;
samplerate = 11025;
break;
// 8kHz modes
case MODE_DOMINOEX4:
symlen = 2048;
doublespaced = 1;
samplerate = 8000;
break;
case MODE_DOMINOEX16:
symlen = 512;
doublespaced = 0;
samplerate = 8000;
break;
case MODE_DOMINOEX8:
default:
// case MODE_DOMINOEX8:
symlen = 1024;
basetone = 128; // 1000 Hz
doublespaced = 1;
samplerate = 8000;
}
basetone = (int)floor(BASEFREQ * symlen / samplerate + 0.5);
lotone = basetone - NUMTONES * (doublespaced ? 2 : 1);
hitone = basetone + 2 * NUMTONES * (doublespaced ? 2 : 1);
tonespacing = (double) (samplerate * ((doublespaced) ? 2 : 1)) / symlen;
// binsfft = new sfft( symlen,
// basetone - numtones*(doublespaced?2:1),
// basetone + 2*numtones*(doublespaced ? 2 : 1) );
//exp
binsfft = new sfft( RESOLUTION * symlen,
RESOLUTION * (basetone - numtones*(doublespaced ? 2 : 1)),
RESOLUTION * (basetone + 2*numtones*(doublespaced ? 2 : 1)) );
bandwidth = NUMTONES * tonespacing;
hilbert = new C_FIR_filter();
hilbert->init_hilbert(37, 1);
afcfilt = new Cmovavg(AFC_COUNT);
for (int i = 0; i < NUMFFTS; i++) {
binsfft[i] = new sfft (symlen, lotone, hitone);
filt[i] = new C_FIR_filter();
}
twosym = 2 * symlen;
pipe = new domrxpipe[twosym];
scopedata.alloc(twosym);
videodata.alloc(RESOLUTION * numtones * 6);
videodata.alloc((4 * NUMTONES * 3 * (doublespaced?2:1) ));
pipeptr = 0;
symcounter = 0;
metric = 0.0;
bandwidth = numtones * tonespacing;
bw = bandwidth * progdefaults.DOMINOEX_BW;
cf = 1000.0 + bandwidth / 2.0;
flo = (cf - bw/2) / samplerate;
fhi = (cf + bw/2) / samplerate;
filt = new C_FIR_filter();
filt->init_bandpass (127, 1, flo, fhi);
fragmentsize = symlen;
s2n = 0.0;
prev1symbol = prev2symbol = 0;
prev1vector = prev2vector = complex(0.0, 0.0);
init();
}
@ -216,19 +189,20 @@ dominoex::dominoex(trx_mode md)
//=====================================================================
// rx modules
complex dominoex::mixer(complex in, double f)
complex dominoex::mixer(int n, complex in)
{
complex z;
// Basetone is always 1000 Hz
f -= (1000.0 + bandwidth/2);
z.re = cos(phaseacc);
z.im = sin(phaseacc);
double f;
// 4 mixers are supported each separated by 1/4 bin size
f = frequency - BASEFREQ - bandwidth/2 + (samplerate / symlen) * (n / 4.0);
z.re = cos(phase[n]);
z.im = sin(phase[n]);
z = z * in;
phaseacc -= twopi * f / samplerate;
if (phaseacc > M_PI)
phaseacc -= twopi;
else if (phaseacc < M_PI)
phaseacc += twopi;
phase[n] -= twopi * f / samplerate;
if (phase[n] > M_PI)
phase[n] -= twopi;
else if (phase[n] < M_PI)
phase[n] += twopi;
return z;
}
@ -242,20 +216,19 @@ void dominoex::recvchar(int c)
put_rx_char(c & 0xFF);
}
void dominoex::decodesymbol(unsigned char curtone, unsigned char prevtone)
void dominoex::decodesymbol()
{
int c, sym, ch;
int diff;
// Decode the IFK+ sequence, which results in a single nibble
diff = curtone - prevtone;
diff = currsymbol - prev1symbol;
if (reverse) diff = -diff;
diff /= 4; // 4 sets of interleaved bins
if (doublespaced) diff /= 2;
diff /= RESOLUTION;
diff -= 2;
if (diff < 0) diff += numtones;
if (diff < 0) diff += NUMTONES;
c = diff;
// If the new symbol is the start of a new character (MSB is low), complete the previous character
@ -283,13 +256,12 @@ void dominoex::decodesymbol(unsigned char curtone, unsigned char prevtone)
}
int dominoex::harddecode(complex *in)
int dominoex::harddecode()
{
double x, max = 0.0;
int symbol = 0;
int count = RESOLUTION * numtones * 3 *(doublespaced?2:1);
for (int i = 0; i < count; i++) {
x = in[i].mag();
for (int i = 0; i < (4 * NUMTONES * 3 * (doublespaced?2:1) ); i++) {
x = pipe[pipeptr].vector[i].mag();
if (x > max) {
max = x;
symbol = i;
@ -298,43 +270,44 @@ int dominoex::harddecode(complex *in)
return symbol;
}
void dominoex::update_syncscope(complex *bins)
void dominoex::update_syncscope()
{
double max = 0, min = 1e6, range, mag;
int numbins = RESOLUTION * (numtones * 3 * (doublespaced ? 2 : 1)); //exp
// dom waterfall
for (int i = 0; i < numbins; i++ ) {
mag = bins[i].mag();
if (max < mag) max = mag;
if (min > mag) min = mag;
}
range = max - min;
memset(videodata, 0, numbins * sizeof(double));
for (int i = 0; i < numbins; i++ ) {
if (range > 2) {
mag = (bins[i].mag() - min) / range;
mag = 1 + log10(mag);
if (mag < 0) mag = 0;
} else
mag = 0;
videodata[i] = 255*mag;
}
double max = 0, min = 1e6, range, mag;
// dom waterfall
memset(videodata, 0, (4 * NUMTONES * 3 * (doublespaced?2:1) ) * sizeof(double));
if (!progStatus.sqlonoff || metric >= progStatus.sldrSquelchValue) {
set_video(videodata, numbins);
videodata.next(); // change buffers
for (int i = 0; i < (4 * NUMTONES * 3 * (doublespaced?2:1) ); i++ ) {
mag = pipe[pipeptr].vector[i].mag();
if (max < mag) max = mag;
if (min > mag) min = mag;
}
range = max - min;
for (int i = 0; i < (4 * NUMTONES * 3 * (doublespaced?2:1) ); i++ ) {
if (range > 2) {
mag = (pipe[pipeptr].vector[i].mag() - min) / range;
mag = 1 + log10(mag);
if (mag < 0) mag = 0;
} else
mag = 0;
videodata[i] = 255*mag;
}
}
set_video(videodata, (4 * NUMTONES * 3 * (doublespaced?2:1) ));
videodata.next();
// dom symbol synch data
memset(scopedata, 0, twosym * sizeof(double));
if (!progStatus.sqlonoff || metric >= progStatus.sldrSquelchValue) {
for (int i = 0, j = 0; i < twosym; i++) {
for (unsigned int i = 0, j = 0; i < twosym; i++) {
j = (pipeptr + i + 1) % (twosym);
scopedata[i] = pipe[j].vector[prev1symbol].mag();
}
set_scope(scopedata, twosym);
scopedata.next(); // change buffers
}
set_scope(scopedata, twosym);
scopedata.next();
}
void dominoex::synchronize()
@ -347,7 +320,7 @@ void dominoex::synchronize()
if (prev1symbol == prev2symbol)
return;
for (int i = 0, j = pipeptr; i < twosym; i++) {
for (unsigned int i = 0, j = pipeptr; i < twosym; i++) {
val = (pipe[j].vector[prev1symbol]).mag();
if (val > max) {
max = val;
@ -355,112 +328,65 @@ void dominoex::synchronize()
}
j = (j + 1) % twosym;
}
synccounter += (int) floor(1.0 * (syn - symlen) / numtones + 0.5);
synccounter += (int) floor(1.0 * (syn - symlen) / NUMTONES + 0.5);
}
void dominoex::reset_afc() {
freqerr = 0.0;
// for (int i = 0; i < AFC_COUNT; i++) afcfilt->run(0.0);
afcfilt->reset();
return;
}
void dominoex::afc()
void dominoex::eval_s2n()
{
complex z;
complex vec1, vec2;
double f, fsym, err;
double ds = doublespaced ? 2 : 1;
if (currsymbol != prev1symbol && prev1symbol != prev2symbol) {
sig = pipe[pipeptr].vector[currsymbol].mag();
noise = pipe[pipeptr].vector[prev2symbol].mag();
if (sigsearch) {
reset_afc();
sigsearch = 0;
}
if (noise < 1.0e-6) noise = 1e-6;
s2n = decayavg( s2n, sig / noise, 8);
vec1 = pipe[pipeptr].vector[currsymbol];
if (pipeptr == 0)
vec2 = pipe[2*symlen].vector[currsymbol];
else
vec2 = pipe[pipeptr - 1].vector[currsymbol];
// z = prevvector % currvector;
z = vec2 % vec1;
f = z.arg() * samplerate / twopi;
fsym = (currsymbol/RESOLUTION - numtones * ds) * samplerate / symlen;
fsym += 1000;
err = fsym - f;
// freqerr = afcfilt->run(err / numtones);
freqerr = decayavg(freqerr, err / numtones, 32);
//std::cout << currsymbol << ", " << fsym << ", " << f << ", " << err << ", " << freqerr << std::endl;
if (progStatus.afconoff && (metric > progStatus.sldrSquelchValue || progStatus.sqlonoff == false)) {
set_freq(frequency - freqerr);
metric = 20*log10(s2n);
display_metric(metric);
snprintf(dommsg, sizeof(dommsg), "s/n %3.0f dB", metric);
put_Status1(dommsg);
}
}
void dominoex::eval_s2n(complex curr, complex n)
{
sig = curr.mag(); // signal + noise energy
noise = n.mag();// + 1e-10; // noise energy
if (noise < 1e-20) noise = 1e-20;
s2n = decayavg( s2n, sig / noise, 8);
metric = 20*log10(s2n);
display_metric(metric);
snprintf(dommsg, sizeof(dommsg), "s/n %3.0f dB", metric);
put_Status1(dommsg);
}
int testcount = 2;
int dominoex::rx_process(const double *buf, int len)
{
complex z, *bins, noise;
complex zref, z, *bins;
while (len) {
// create analytic signal...shift in frequency to base band & bandpass filter
z.re = z.im = *buf++;
hilbert->run(z, z);
z = mixer(z, frequency);
filt->run(z, z);
// feed it to the sliding FFT
bins = binsfft->run(z);
// create analytic signal
zref.re = zref.im = *buf++;
hilbert->run(zref, zref);
// copy current vector to the pipe
for (int i = 0; i < RESOLUTION * numtones * 3 * (doublespaced?2:1); i++) {
pipe[pipeptr].vector[i] = bins[i];
// process 4 sets of sliding FFTs spaced at 1/4 bin intervals each of which
// is a matched filter for the current symbol length
for (int n = 0; n < 4; n++) {
// shift in frequency to base band & bandpass filter
z = mixer(n, zref);
if (progdefaults.DOMINOEX_FILTER)
filt[n]->run(z, z);
// feed it to the sliding FFTs
bins = binsfft[n]->run(z);
// copy current vector to the pipe interleaving the FFT vectors
for (int i = 0; i < NUMTONES * 3 * (doublespaced ? 2 : 1); i++) {
pipe[pipeptr].vector[n + 4 * i] = bins[i];
}
}
if (--synccounter <= 0) {
synccounter = symlen;
currsymbol = harddecode(bins);
//std::cout << currsymbol << " "; std::cout.flush();
currvector = bins[currsymbol];
// decode symbol
decodesymbol(currsymbol, prev1symbol);
// update the scope
// update_syncscope(bins);
// symbol sync
currsymbol = harddecode();
decodesymbol();
synchronize();
// update the scope
update_syncscope(bins);
// frequency tracking
afc();
eval_s2n(currvector, bins[RESOLUTION * (numtones + 2) * (doublespaced ? 2 : 1)]);
update_syncscope();
eval_s2n();
prev2symbol = prev1symbol;
prev2vector = prev1vector;
prev1symbol = currsymbol;
prev1vector = currvector;
}
pipeptr++;
if (pipeptr >= twosym)
pipeptr = 0;
--len;
}
return 0;
@ -486,22 +412,22 @@ void dominoex::sendsymbol(int sym)
int tone;
double f, phaseincr;
tone = (txprevtone + 2 + sym) % numtones;
tone = (txprevtone + 2 + sym) % NUMTONES;
txprevtone = tone;
if (reverse)
tone = (numtones - 1) - tone;
tone = (NUMTONES - 1) - tone;
f = tone * tonespacing + get_txfreq_woffset() - bandwidth / 2;
phaseincr = twopi * f / samplerate;
for (int i = 0; i < symlen; i++) {
outbuf[i] = cos(phaseacc);
phaseacc -= phaseincr;
if (phaseacc > M_PI)
phaseacc -= twopi;
else if (phaseacc < M_PI)
phaseacc += twopi;
outbuf[i] = cos(txphase);
txphase -= phaseincr;
if (txphase > M_PI)
txphase -= twopi;
else if (txphase < M_PI)
txphase += twopi;
}
ModulateXmtr(outbuf, symlen);

Wyświetl plik

@ -46,8 +46,7 @@ const char *state_names[] = {
// Elements are in enum trx_mode order. Mode name video-id uses the
// first string (sname), so its length should be a multiple of 2.
const struct mode_info_t mode_info[NUM_MODES] = {
{ MODE_CW, &cw_modem, "CW", "CW", "CW" },
{ MODE_CW, &cw_modem, "CW", "CW", "CW", "CW" },
{ MODE_DOMINOEX4, &dominoex4_modem, "DomEX4", "DominoEX 4", "DOMINOEX4", "DOMINO" }, // These aren't Domino FEC, right?
{ MODE_DOMINOEX5, &dominoex5_modem, "DomEX5", "DominoEX 5", "DOMINOEX5", "DOMINO" },
{ MODE_DOMINOEX8, &dominoex8_modem, "DomEX8", "DominoEX 8", "DOMINOEX8", "DOMINO" },

Wyświetl plik

@ -140,6 +140,7 @@ extern Fl_Group *tabDomEX;
extern Fl_Input *txtSecondary;
extern Fl_Button *btnRestartDomEX;
extern Fl_Counter *valDominoEX_BW;
extern Fl_Check_Button *valDominoEX_FILTER;
extern Fl_Group *tabFeld;
#include "fontdef.h"
extern Fl_Choice *selHellFont;

Wyświetl plik

@ -26,7 +26,6 @@ struct configuration {
int ServerOffset;
double ACQsn;
// RTTY
// double rtty_squelch;
int rtty_shift;
int rtty_baud;
int rtty_bits;
@ -38,9 +37,6 @@ struct configuration {
bool rtty_autocrlf;
int rtty_autocount;
int rtty_afcspeed;
// bool afconoff;
// bool sqlonoff;
// double sldrSquelchValue;
bool useFSKkeyline; // use RTS for FSK
bool useFSKkeylineDTR; // use DTR for FSK
bool FSKisLSB;
@ -79,6 +75,7 @@ struct configuration {
bool olivia8bit;
// DOMINOEX
double DOMINOEX_BW;
bool DOMINOEX_FILTER;
// MT63
bool mt63_8bit;
int mt63_interleave;

Wyświetl plik

@ -38,11 +38,12 @@
using namespace std;
#define MAXRESOLUTION 4
#define DOMNUMTONES 18
#define NUMTONES 18
#define NUMFFTS 4
#define BASEFREQ 1000.0
struct domrxpipe {
complex vector[MAXRESOLUTION * DOMNUMTONES * 6]; /* numtones <= 18 */
complex vector[NUMFFTS * NUMTONES * 6];
};
class dominoex : public modem {
@ -56,10 +57,9 @@ public:
};
protected:
// common variables
double phaseacc;
double phase[4];
double txphase;
int symlen;
int numtones;
int basetone;
int doublespaced;
double tonespacing;
int counter;
@ -67,9 +67,8 @@ protected:
// rx variables
C_FIR_filter *hilbert;
C_FIR_filter *filt;
sfft *binsfft;
Cmovavg *afcfilt;
C_FIR_filter *filt[NUMFFTS];
sfft *binsfft[NUMFFTS];
domrxpipe *pipe;
unsigned int pipeptr;
@ -78,8 +77,6 @@ protected:
mbuffer<double, 0, 2> videodata;
complex currvector;
complex prev1vector;
complex prev2vector;
int currsymbol;
int prev1symbol;
@ -105,15 +102,15 @@ protected:
string strSecXmtText;
private:
complex mixer(complex in, double f);
complex mixer(int n, complex in);
void recvchar(int c);
void decodesymbol(unsigned char curtone, unsigned char prevtone);
int harddecode(complex *in);
void update_syncscope(complex *);
void decodesymbol();
int harddecode();
void update_syncscope();
void synchronize();
void afc();
void reset_afc();
void eval_s2n(complex, complex);
void eval_s2n();
void sendsymbol(int sym);
void sendchar(unsigned char c, int secondary);
void sendidle();

Wyświetl plik

@ -525,9 +525,12 @@ void mfsk::afc()
void mfsk::eval_s2n(complex c, complex n)
{
sig = c.mag(); // signal + noise energy
noise = n.mag() + 1e-10; // noise energy
noise = n.mag() + 1e-20; // noise energy
s2n = decayavg( s2n, fabs((sig - noise) / noise), 8);
if (metric > progStatus.sldrSquelchValue)
s2n = decayavg( s2n, fabs(sig / noise), 16 );
else
s2n = decayavg( s2n, 1.0, 16 );
}
int mfsk::rx_process(const double *buf, int len)
@ -601,7 +604,7 @@ int mfsk::rx_process(const double *buf, int len)
// frequency tracking
afc();
eval_s2n(currvector, bins[numtones + 2]);
eval_s2n(currvector, bins[(currsymbol + numtones/2) % numtones]);
// decode symbol
softdecode(bins);
// symbol sync

Wyświetl plik

@ -80,6 +80,7 @@ configuration progdefaults = {
false, // bool olivia8bit
// DOMINOEX
2.0, // double DOMINOEX_BW;
false, // bool DOMINOEX_FILTER
// MT63
false, // bool mt63_8bit;
32, // int mt63_interleave;
@ -241,7 +242,7 @@ enum TAG { \
CWTRACK, CWRISETIME, CWDASH2DOT,
XQSK, CWPRE, CWPOST, CWID, CWIDWPM,
OLIVIATONES, OLIVIABW, OLIVIASMARGIN, OLIVIASINTEG, OLIVIA8BIT,
DOMINOEXBW,
DOMINOEXBW, DOMINOEXFILTER,
FELDFONTNBR, FELDIDLE,
WFPREFILTER,
USECURSORLINES, USECURSORCENTERLINE, USEBWTRACKS,
@ -381,6 +382,7 @@ void configuration::writeDefaultsXML()
writeXMLint(f, "OLIVIASINTEG", oliviasinteg);
writeXMLbool(f, "OLIVIA8BIT", olivia8bit);
writeXMLdbl(f, "DOMINOEXBW", DOMINOEX_BW);
writeXMLbool(f, "DOMINOEXFILTER", DOMINOEX_FILTER);
writeXMLint(f, "FELDFONTNBR", feldfontnbr);
writeXMLbool(f, "FELDIDLE", FELD_IDLE);
@ -670,6 +672,9 @@ bool configuration::readDefaultsXML()
case DOMINOEXBW :
DOMINOEX_BW = atof(xml->getNodeData());
break;
case DOMINOEXFILTER :
DOMINOEX_FILTER = atoi(xml->getNodeData());
break;
case FELDFONTNBR :
feldfontnbr = atoi(xml->getNodeData());
break;
@ -1018,6 +1023,7 @@ bool configuration::readDefaultsXML()
else if (!strcmp("OLIVIASINTEG", nodeName)) tag = OLIVIASINTEG;
else if (!strcmp("OLIVIA8BIT", nodeName)) tag = OLIVIA8BIT;
else if (!strcmp("DOMINOEXBW", nodeName)) tag = DOMINOEXBW;
else if (!strcmp("DOMINOEXFILTER", nodeName)) tag = DOMINOEXFILTER;
else if (!strcmp("FELDFONTNBR", nodeName)) tag = FELDFONTNBR;
else if (!strcmp("FELDIDLE", nodeName)) tag = FELDIDLE;
else if (!strcmp("WFPREFILTER", nodeName)) tag = WFPREFILTER;
@ -1226,6 +1232,7 @@ int configuration::setDefaults() {
txtSecondary->value(secText.c_str());
valDominoEX_BW->value(DOMINOEX_BW);
valDominoEX_FILTER->value(DOMINOEX_FILTER);
for (int i = 0; i < 5; i++) {
btnPTT[i]->value(0);

Wyświetl plik

@ -6,6 +6,7 @@
#include "status.h"
#include "configuration.h"
#include "fl_digi.h"
#include "versions.h"
#include "waterfall.h"
@ -115,10 +116,16 @@ void status::saveLastState()
scopeW = scopeview->w();
scopeH = scopeview->h();
}
string str = PACKAGE_NAME;
str.append(" ");
str.append(PACKAGE_VERSION);
string deffname = HomeDir;
deffname.append("fldigi.status");
ofstream deffile(deffname.c_str(), ios::out);
deffile << str.c_str() << endl;
deffile << lastmode << endl;
deffile << mainX << endl;
deffile << mainY << endl;
@ -154,43 +161,51 @@ void status::saveLastState()
void status::loadLastState()
{
char line[255];
string str = PACKAGE_NAME;
str.append(" ");
str.append(PACKAGE_VERSION);
string deffname = HomeDir;
deffname.append("fldigi.status");
ifstream deffile(deffname.c_str(), ios::in);
if (deffile) {
deffile >> lastmode;
deffile >> mainX;
deffile >> mainY;
deffile >> mainW;
deffile >> mainH;
deffile >> rigShown;
deffile >> rigX;
deffile >> rigY;
deffile >> RxTextHeight;
deffile >> carrier;
deffile >> mag;
deffile >> speed;
deffile >> reflevel;
deffile >> ampspan;
deffile >> VIEWERnchars;
deffile >> VIEWERxpos;
deffile >> VIEWERypos;
deffile >> VIEWERvisible;
deffile >> LOGenabled;
deffile >> sldrSquelchValue;
deffile >> afconoff;
deffile >> sqlonoff;
deffile >> RcvMixer;
deffile >> XmtMixer;
deffile >> scopeX;
deffile >> scopeY;
deffile >> scopeVisible;
deffile >> scopeW;
deffile >> scopeH;
deffile.close();
progdefaults.wfRefLevel = reflevel;
progdefaults.wfAmpSpan = ampspan;
bLastStateRead = true;
deffile.getline(line, 255);
if (str == line) {
deffile >> lastmode;
deffile >> mainX;
deffile >> mainY;
deffile >> mainW;
deffile >> mainH;
deffile >> rigShown;
deffile >> rigX;
deffile >> rigY;
deffile >> RxTextHeight;
deffile >> carrier;
deffile >> mag;
deffile >> speed;
deffile >> reflevel;
deffile >> ampspan;
deffile >> VIEWERnchars;
deffile >> VIEWERxpos;
deffile >> VIEWERypos;
deffile >> VIEWERvisible;
deffile >> LOGenabled;
deffile >> sldrSquelchValue;
deffile >> afconoff;
deffile >> sqlonoff;
deffile >> RcvMixer;
deffile >> XmtMixer;
deffile >> scopeX;
deffile >> scopeY;
deffile >> scopeVisible;
deffile >> scopeW;
deffile >> scopeH;
deffile.close();
progdefaults.wfRefLevel = reflevel;
progdefaults.wfAmpSpan = ampspan;
bLastStateRead = true;
}
}
}

Wyświetl plik

@ -1062,7 +1062,7 @@ void SoundPort::src_data_reset(int mode)
rbsize = ceil2((unsigned)(2 * CHANNELS * SCBLOCKSIZE *
MAX(req_sample_rate, sd[0].dev_sample_rate) /
MIN(req_sample_rate, sd[0].dev_sample_rate)));
rbsize = MAX(rbsize, 4096);
rbsize = 2 * MAX(rbsize, 4096);
#ifndef NDEBUG
cerr << "input rbsize=" << rbsize << endl;
#endif

Wyświetl plik

@ -193,8 +193,11 @@ static void sound_init_options(void)
menuOutSampleRate->menu(sample_rate_menu);
const char* cname;
for (int i = 0; (cname = src_get_name(i)); i++)
for (int i = 0; (cname = src_get_name(i)); i++) {
if (strstr( cname, "ZOH") != 0) continue;
if (strstr( cname, "Linear") != 0) continue;
menuSampleConverter->add(cname);
}
menuSampleConverter->value(progdefaults.sample_converter);
menuSampleConverter->tooltip(src_get_description(progdefaults.sample_converter));

Wyświetl plik

@ -407,7 +407,14 @@ void Digiscope::draw()
case XHAIRS : draw_xy(); break;
case DOMDATA : draw_scope(); break;
case BLANK :
default: break;
default:
fl_clip(x()+2,y()+2,w()-4,h()-4);
fl_color(FL_BLACK);
fl_rectf(x()+2,y()+2,w()-4,h()-4);
fl_push_matrix();
fl_pop_matrix();
fl_pop_clip();
break;
}
}
}