kopia lustrzana https://github.com/jamescoxon/dl-fldigi
PSK IMD
* add IMD generator * modified IMD computation for continuous operation vice only during DCDpull/4/head
rodzic
4fec333973
commit
4c9f1404ca
|
@ -316,9 +316,13 @@ static void cb_noiseDB(Fl_Counter2* o, void*) {
|
|||
progdefaults.s2n = o->value();
|
||||
}
|
||||
|
||||
Fl_Check_Button *btnOffsetOn=(Fl_Check_Button *)0;
|
||||
|
||||
Fl_Counter *ctrl_freq_offset=(Fl_Counter *)0;
|
||||
|
||||
Fl_Check_Button *btnOffsetOn=(Fl_Check_Button *)0;
|
||||
Fl_Check_Button *btn_imd_on=(Fl_Check_Button *)0;
|
||||
|
||||
Fl_Counter2 *xmtimd=(Fl_Counter2 *)0;
|
||||
|
||||
Fl_Group *tabUI=(Fl_Group *)0;
|
||||
|
||||
|
@ -5943,7 +5947,7 @@ Fl_Double_Window* ConfigureDialog() {
|
|||
inpMyAntenna->when(FL_WHEN_RELEASE);
|
||||
inpMyAntenna->labelsize(FL_NORMAL_SIZE);
|
||||
} // Fl_Input2* inpMyAntenna
|
||||
{ grpNoise = new Fl_Group(55, 231, 490, 114, _("Test Signal - Do NOT use with transmitter"));
|
||||
{ grpNoise = new Fl_Group(55, 231, 490, 143, _("Test Signal - Do NOT use with transmitter"));
|
||||
grpNoise->box(FL_ENGRAVED_FRAME);
|
||||
grpNoise->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
|
||||
grpNoise->hide();
|
||||
|
@ -5952,7 +5956,7 @@ Fl_Double_Window* ConfigureDialog() {
|
|||
btnNoiseOn->callback((Fl_Callback*)cb_btnNoiseOn);
|
||||
o->value(progdefaults.noise);
|
||||
} // Fl_Check_Button* btnNoiseOn
|
||||
{ Fl_Counter2* o = noiseDB = new Fl_Counter2(312, 264, 130, 21, _("dB"));
|
||||
{ Fl_Counter2* o = noiseDB = new Fl_Counter2(340, 264, 130, 21, _("dB"));
|
||||
noiseDB->box(FL_UP_BOX);
|
||||
noiseDB->color(FL_BACKGROUND_COLOR);
|
||||
noiseDB->selection_color(FL_INACTIVE_COLOR);
|
||||
|
@ -5969,16 +5973,35 @@ Fl_Double_Window* ConfigureDialog() {
|
|||
o->value(progdefaults.s2n);
|
||||
o->lstep(1);
|
||||
} // Fl_Counter2* noiseDB
|
||||
{ Fl_Counter* o = ctrl_freq_offset = new Fl_Counter(312, 304, 130, 21, _("freq-offset"));
|
||||
{ btnOffsetOn = new Fl_Check_Button(93, 307, 70, 15, _("Offset on"));
|
||||
btnOffsetOn->down_box(FL_DOWN_BOX);
|
||||
} // Fl_Check_Button* btnOffsetOn
|
||||
{ Fl_Counter* o = ctrl_freq_offset = new Fl_Counter(340, 304, 130, 21, _("freq-offset"));
|
||||
ctrl_freq_offset->tooltip(_("ONLY FOR TESTING !"));
|
||||
ctrl_freq_offset->minimum(-250);
|
||||
ctrl_freq_offset->maximum(250);
|
||||
ctrl_freq_offset->align(Fl_Align(FL_ALIGN_LEFT));
|
||||
o->lstep(10);
|
||||
} // Fl_Counter* ctrl_freq_offset
|
||||
{ btnOffsetOn = new Fl_Check_Button(93, 307, 70, 15, _("Offset on"));
|
||||
btnOffsetOn->down_box(FL_DOWN_BOX);
|
||||
} // Fl_Check_Button* btnOffsetOn
|
||||
{ btn_imd_on = new Fl_Check_Button(93, 342, 70, 15, _("ALC emulation on"));
|
||||
btn_imd_on->down_box(FL_DOWN_BOX);
|
||||
} // Fl_Check_Button* btn_imd_on
|
||||
{ Fl_Counter2* o = xmtimd = new Fl_Counter2(340, 339, 130, 21, _("ALC level"));
|
||||
xmtimd->box(FL_UP_BOX);
|
||||
xmtimd->color(FL_BACKGROUND_COLOR);
|
||||
xmtimd->selection_color(FL_INACTIVE_COLOR);
|
||||
xmtimd->labeltype(FL_NORMAL_LABEL);
|
||||
xmtimd->labelfont(0);
|
||||
xmtimd->labelsize(14);
|
||||
xmtimd->labelcolor(FL_FOREGROUND_COLOR);
|
||||
xmtimd->minimum(0.5);
|
||||
xmtimd->maximum(1);
|
||||
xmtimd->step(0.01);
|
||||
xmtimd->value(1);
|
||||
xmtimd->align(Fl_Align(FL_ALIGN_LEFT));
|
||||
xmtimd->when(FL_WHEN_CHANGED);
|
||||
o->lstep(.1);
|
||||
} // Fl_Counter2* xmtimd
|
||||
grpNoise->end();
|
||||
} // Fl_Group* grpNoise
|
||||
tabOperator->end();
|
||||
|
|
|
@ -366,7 +366,7 @@ static const char szProsigns[] = "~|%|&|+|=|{|}|<|>|[|]| ";} {}
|
|||
} {
|
||||
Fl_Group tabOperator {
|
||||
label Operator
|
||||
callback {progdefaults.changed = true;} open selected
|
||||
callback {progdefaults.changed = true;} open
|
||||
tooltip {Operator information} xywh {0 25 600 355} when 1
|
||||
} {
|
||||
Fl_Group {} {
|
||||
|
@ -427,8 +427,8 @@ progdefaults.changed = true;}
|
|||
class Fl_Input2
|
||||
}
|
||||
Fl_Group grpNoise {
|
||||
label {Test Signal - Do NOT use with transmitter} open
|
||||
xywh {55 231 490 114} box ENGRAVED_FRAME align 21 hide
|
||||
label {Test Signal - Do NOT use with transmitter} open selected
|
||||
xywh {55 231 490 143} box ENGRAVED_FRAME align 21 hide
|
||||
} {
|
||||
Fl_Check_Button btnNoiseOn {
|
||||
label {Noise on}
|
||||
|
@ -439,20 +439,30 @@ progdefaults.changed = true;}
|
|||
Fl_Counter noiseDB {
|
||||
label dB
|
||||
callback {progdefaults.s2n = o->value();}
|
||||
xywh {312 264 130 21} align 4 minimum -18 maximum 60 value 20
|
||||
xywh {340 264 130 21} align 4 minimum -18 maximum 60 value 20
|
||||
code0 {o->value(progdefaults.s2n);}
|
||||
code1 {o->lstep(1);}
|
||||
class Fl_Counter2
|
||||
}
|
||||
Fl_Counter ctrl_freq_offset {
|
||||
label {freq-offset}
|
||||
tooltip {ONLY FOR TESTING !} xywh {312 304 130 21} align 4 minimum -250 maximum 250
|
||||
code0 {o->lstep(10);}
|
||||
}
|
||||
Fl_Check_Button btnOffsetOn {
|
||||
label {Offset on}
|
||||
xywh {93 307 70 15} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Counter ctrl_freq_offset {
|
||||
label {freq-offset}
|
||||
tooltip {ONLY FOR TESTING !} xywh {340 304 130 21} align 4 minimum -250 maximum 250
|
||||
code0 {o->lstep(10);}
|
||||
}
|
||||
Fl_Check_Button btn_imd_on {
|
||||
label {ALC emulation on}
|
||||
xywh {93 342 70 15} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Counter xmtimd {
|
||||
label {ALC level}
|
||||
xywh {340 339 130 21} align 4 minimum 0.5 maximum 1 step 0.01 value 1
|
||||
code1 {o->lstep(.1);}
|
||||
class Fl_Counter2
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabUI {
|
||||
|
|
|
@ -32,9 +32,11 @@ extern Fl_Group *grpNoise;
|
|||
#include <FL/Fl_Check_Button.H>
|
||||
extern Fl_Check_Button *btnNoiseOn;
|
||||
extern Fl_Counter2 *noiseDB;
|
||||
extern Fl_Check_Button *btnOffsetOn;
|
||||
#include <FL/Fl_Counter.H>
|
||||
extern Fl_Counter *ctrl_freq_offset;
|
||||
extern Fl_Check_Button *btnOffsetOn;
|
||||
extern Fl_Check_Button *btn_imd_on;
|
||||
extern Fl_Counter2 *xmtimd;
|
||||
extern Fl_Group *tabUI;
|
||||
extern Fl_Tabs *tabsUI;
|
||||
extern Fl_Group *tabBrowser;
|
||||
|
|
|
@ -83,6 +83,10 @@ private:
|
|||
double *fir2c;
|
||||
Cmovavg *snfilt;
|
||||
Cmovavg *imdfilt;
|
||||
Cmovavg *e0_filt;
|
||||
Cmovavg *e1_filt;
|
||||
Cmovavg *e2_filt;
|
||||
bool displaysn;
|
||||
|
||||
double I1[NUM_FILTERS];
|
||||
double I2[NUM_FILTERS];
|
||||
|
@ -166,6 +170,9 @@ private:
|
|||
|
||||
double *tx_shape;
|
||||
int preamble;
|
||||
C_FIR_filter *xmtfilt;
|
||||
|
||||
void transmit(double *buf, int len);
|
||||
void tx_carriers();
|
||||
void tx_symbol(int sym);
|
||||
void tx_bit(int bit);
|
||||
|
|
104
src/psk/psk.cxx
104
src/psk/psk.cxx
|
@ -51,6 +51,8 @@
|
|||
#include "Viewer.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "confdialog.h"
|
||||
|
||||
extern waterfall *wf;
|
||||
|
||||
// Change the following for DCD low pass filter adjustment
|
||||
|
@ -153,6 +155,12 @@ void psk::tx_init(SoundBase *sc)
|
|||
vphase = 0;
|
||||
maxamp = 0;
|
||||
|
||||
double bw2 = 6.0 * bandwidth;
|
||||
double flo = (get_txfreq_woffset() - bw2);
|
||||
if (flo <= 0) flo = 0;
|
||||
double fhi = (get_txfreq_woffset() + bw2);
|
||||
if (fhi >= 0.48*samplerate) fhi = 0.48*samplerate;
|
||||
xmtfilt->init_bandpass (127, 1, flo/samplerate, fhi/samplerate);
|
||||
}
|
||||
|
||||
void psk::rx_init()
|
||||
|
@ -179,7 +187,6 @@ void psk::rx_init()
|
|||
else sigsearch = 0;
|
||||
put_MODEstatus(mode);
|
||||
resetSN_IMD();
|
||||
imdValid = false;
|
||||
afcmetric = 0.0;
|
||||
// interleaver, split incoming bit stream into two, one late by one bit
|
||||
rxbitstate = 0;
|
||||
|
@ -223,6 +230,9 @@ psk::~psk()
|
|||
}
|
||||
if (snfilt) delete snfilt;
|
||||
if (imdfilt) delete imdfilt;
|
||||
if (e0_filt) delete e0_filt;
|
||||
if (e1_filt) delete e1_filt;
|
||||
if (e2_filt) delete e2_filt;
|
||||
|
||||
if (pskviewer) delete pskviewer;
|
||||
if (evalpsk) delete evalpsk;
|
||||
|
@ -233,6 +243,8 @@ psk::~psk()
|
|||
if (Txinlv) delete Txinlv;
|
||||
|
||||
if (vestigial_sfft) delete vestigial_sfft;
|
||||
|
||||
if (xmtfilt) delete xmtfilt;
|
||||
}
|
||||
|
||||
psk::psk(trx_mode pskmode) : modem()
|
||||
|
@ -732,6 +744,9 @@ psk::psk(trx_mode pskmode) : modem()
|
|||
|
||||
snfilt = new Cmovavg(16);
|
||||
imdfilt = new Cmovavg(16);
|
||||
e0_filt = new Cmovavg(dcdbits / 2);
|
||||
e1_filt = new Cmovavg(dcdbits / 2);
|
||||
e2_filt = new Cmovavg(dcdbits / 2);
|
||||
|
||||
if (_disablefec) {
|
||||
enc = NULL;
|
||||
|
@ -827,6 +842,9 @@ psk::psk(trx_mode pskmode) : modem()
|
|||
vestigial_sfft = new sfft(sfft_size, bin - 5, bin + 6); // 11 bins
|
||||
for (int i = 0; i < 11; i++) sfft_bins[i] = cmplx(0,0);
|
||||
}
|
||||
|
||||
xmtfilt = new C_FIR_filter();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -1059,6 +1077,10 @@ int waitcount = 0;
|
|||
|
||||
void psk::findsignal()
|
||||
{
|
||||
put_Status1("");
|
||||
put_Status2("");
|
||||
put_status("");
|
||||
|
||||
int ftest, f1, f2;
|
||||
|
||||
if (sigsearch > 0) {
|
||||
|
@ -1171,7 +1193,6 @@ void psk::afc()
|
|||
phaseafc();
|
||||
}
|
||||
|
||||
|
||||
void psk::rx_symbol(cmplx symbol, int car)
|
||||
{
|
||||
int n;
|
||||
|
@ -1278,8 +1299,7 @@ void psk::rx_symbol(cmplx symbol, int car)
|
|||
dcdshreg = ( dcdshreg << (symbits+1) ) | bits;
|
||||
|
||||
int set_dcdON = -1; // 1 sets DCD on ; 0 sets DCD off ; -1 does neither (no-op)
|
||||
imdValid = false;
|
||||
//printf("\n%.8X", dcdshreg);
|
||||
|
||||
switch (dcdshreg) {
|
||||
|
||||
// bpsk DCD on
|
||||
|
@ -1360,11 +1380,12 @@ void psk::rx_symbol(cmplx symbol, int car)
|
|||
}
|
||||
}
|
||||
|
||||
displaysn = false;
|
||||
if ( 1 == set_dcdON ) {
|
||||
displaysn = true;
|
||||
dcd = true;
|
||||
acquire = 0;
|
||||
quality = cmplx (1.0, 0.0);
|
||||
imdValid = true;
|
||||
if (progdefaults.Pskmails2nreport && (mailserver || mailclient))
|
||||
s2n_sum = s2n_sum2 = s2n_ncount = 0.0;
|
||||
//printf("\n DCD ON!!");
|
||||
|
@ -1448,18 +1469,24 @@ void psk::rx_symbol(cmplx symbol, int car)
|
|||
}
|
||||
}
|
||||
|
||||
static double e0, e1, e2;
|
||||
|
||||
void psk::signalquality()
|
||||
{
|
||||
// double e0, e1, e2;
|
||||
e0 = e0_filt->run(m_Energy[0]);
|
||||
e1 = e1_filt->run(m_Energy[1]);
|
||||
e2 = e2_filt->run(m_Energy[2]);
|
||||
|
||||
if (m_Energy[1])
|
||||
snratio = snfilt->run(m_Energy[0]/m_Energy[1]);
|
||||
if (((e0 - e1) > 0) && (e1 > 0))
|
||||
snratio = (e0 - e1) / e1;
|
||||
else
|
||||
snratio = snfilt->run(1.0);
|
||||
snratio = 1000.0;
|
||||
|
||||
if (m_Energy[0] && imdValid)
|
||||
imdratio = imdfilt->run(m_Energy[2]/m_Energy[0]);
|
||||
if (((e0 - e1) > 0) && ((e2 - e1) > 0) )
|
||||
imdratio = (e2 - e1) / (e0 - e1);
|
||||
else
|
||||
imdratio = imdfilt->run(0.001);
|
||||
imdratio = 0.001;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1470,19 +1497,30 @@ void psk::update_syncscope()
|
|||
|
||||
display_metric(metric);
|
||||
|
||||
memset(msg1, 0, sizeof(msg1));
|
||||
memset(msg2, 0, sizeof(msg2));
|
||||
if (displaysn) {
|
||||
memset(msg1, 0, sizeof(msg1));
|
||||
memset(msg2, 0, sizeof(msg2));
|
||||
|
||||
s2n = 10.0*log10( snratio );
|
||||
snprintf(msg1, sizeof(msg1)-1, "s/n %2d dB", (int)(floor(s2n)));
|
||||
s2n = 10.0*log10( snratio );
|
||||
snprintf(msg1, sizeof(msg1), "s/n %2.0f dB", s2n);
|
||||
|
||||
imd = 10.0*log10( imdratio );
|
||||
snprintf(msg2, sizeof(msg2)-1, "imd %3d dB", (int)(floor(imd)));
|
||||
imd = 10.0*log10( imdratio );
|
||||
snprintf(msg2, sizeof(msg2), "imd %2.0f dB", imd);
|
||||
|
||||
if (imdValid) {
|
||||
put_Status1(msg1, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
|
||||
put_Status2(msg2, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
|
||||
put_Status1( msg1,
|
||||
progdefaults.StatusTimeout,
|
||||
progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
|
||||
put_Status2( msg2,
|
||||
progdefaults.StatusTimeout,
|
||||
progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
|
||||
}
|
||||
|
||||
//static char msg3[50];
|
||||
//memset(msg3, 0, sizeof(msg3));
|
||||
//snprintf(msg3, sizeof(msg3), "%10.3f, %10.3f, %10.3f",
|
||||
//e0, e1, e2);
|
||||
//put_status(msg3);
|
||||
|
||||
}
|
||||
|
||||
char bitstatus[100];
|
||||
|
@ -1675,6 +1713,14 @@ int psk::rx_process(const double *buf, int len)
|
|||
// transmit processes
|
||||
//=====================================================================
|
||||
|
||||
void psk::transmit(double *buf, int len)
|
||||
{
|
||||
// if (btn_imd_on->value())
|
||||
for (int i = 0; i < len; i++) xmtfilt->Irun(buf[i], buf[i]);
|
||||
|
||||
ModulateXmtr(buf, len);
|
||||
}
|
||||
|
||||
#define SVP_MASK 0xF
|
||||
#define SVP_COUNT (SVP_MASK + 1)
|
||||
|
||||
|
@ -1744,8 +1790,11 @@ void psk::tx_carriers()
|
|||
} else {
|
||||
outbuf[i] = (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car])) / numcarriers;
|
||||
}
|
||||
if (maxamp < fabs(outbuf[i]))
|
||||
maxamp = fabs(outbuf[i]);
|
||||
// create an imd value
|
||||
double maxmag = xmtimd->value();
|
||||
if (btn_imd_on->value())
|
||||
if (fabs(outbuf[i]) > maxmag)
|
||||
outbuf[i] = maxmag * (outbuf[i] < 0 ? -1 : 1);
|
||||
|
||||
phaseacc[car] += delta[car];
|
||||
if (phaseacc[car] > TWOPI) phaseacc[car] -= TWOPI;
|
||||
|
@ -1765,11 +1814,16 @@ void psk::tx_carriers()
|
|||
}
|
||||
}
|
||||
|
||||
maxamp = 0;
|
||||
for (int i = 0; i < symbollen; i++)
|
||||
if (maxamp < fabs(outbuf[i])) maxamp = fabs(outbuf[i]);
|
||||
maxamp *= 1.02;
|
||||
if (maxamp) {
|
||||
for (int i = 0; i < symbollen; i++) outbuf[i] *= (0.9 * maxamp);
|
||||
for (int i = 0; i < symbollen; i++)
|
||||
outbuf[i] /= maxamp;
|
||||
}
|
||||
|
||||
ModulateXmtr(outbuf, symbollen);
|
||||
transmit(outbuf, symbollen);
|
||||
}
|
||||
|
||||
void psk::tx_symbol(int sym)
|
||||
|
@ -2154,7 +2208,7 @@ void psk::initSN_IMD()
|
|||
m_NCount = 0;
|
||||
|
||||
COEF[0] = 2.0 * cos(TWOPI * 9 / GOERTZEL);
|
||||
COEF[1] = 2.0 * cos(TWOPI * 18 / GOERTZEL);
|
||||
COEF[1] = 2.0 * cos(TWOPI * 36 / GOERTZEL);
|
||||
COEF[2] = 2.0 * cos(TWOPI * 27 / GOERTZEL);
|
||||
}
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ double modem::sigmaN (double es_ovr_n0)
|
|||
case MODE_PSK125: case MODE_PSK250: case MODE_PSK500:
|
||||
case MODE_QPSK31: case MODE_QPSK63: case MODE_QPSK125: case MODE_QPSK250:
|
||||
case MODE_PSK125R: case MODE_PSK250R: case MODE_PSK500R:
|
||||
mode_factor *= 16;
|
||||
mode_factor = 400;
|
||||
break;
|
||||
case MODE_THROB1: case MODE_THROB2: case MODE_THROB4:
|
||||
case MODE_THROBX1: case MODE_THROBX2: case MODE_THROBX4:
|
||||
|
@ -431,13 +431,20 @@ double modem::gauss(double sigma) {
|
|||
// simulating the noise that is added to the signal.
|
||||
// return signal + noise, limiting value to +/- 1.0
|
||||
|
||||
//static double mag;
|
||||
|
||||
void modem::add_noise(double *buffer, int len)
|
||||
{
|
||||
double sigma = sigmaN(progdefaults.s2n);
|
||||
double sigma = sigmaN(noiseDB->value());
|
||||
double sn = 0;
|
||||
for (int n = 0; n < len; n++) {
|
||||
sn = (buffer[n] + gauss(sigma)) / (1.0 + 3.0 * sigma);
|
||||
buffer[n] = clamp(sn, -1.0, 1.0);
|
||||
// mag = fabs(buffer[n]);
|
||||
// if (btn_imd_on->value())
|
||||
// buffer[n] *= (1.0 - mag *xmtimd->value())/(1.0 - xmtimd->value());
|
||||
if (btnNoiseOn->value()) {
|
||||
sn = (buffer[n] + gauss(sigma)) / (1.0 + 3.0 * sigma);
|
||||
buffer[n] = clamp(sn, -1.0, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +476,7 @@ void modem::ModulateXmtr(double *buffer, int len)
|
|||
!(PERFORM_CPS_TEST || active_modem->XMLRPC_CPS_TEST))
|
||||
trx_xmit_wfall_queue(samplerate, buffer, (size_t)len);
|
||||
|
||||
if (withnoise && progdefaults.noise) add_noise(buffer, len);
|
||||
if (withnoise) add_noise(buffer, len);
|
||||
|
||||
double mult = pow(10, progdefaults.txlevel / 20.0);
|
||||
if (mult > 0.99) mult = 0.99;
|
||||
|
|
Ładowanie…
Reference in New Issue