kopia lustrzana https://github.com/jamescoxon/dl-fldigi
MT63 transmit bug fix
1. MT63 tx buffer was not correctly initialized at the start of each transmission. 2. Added Rx Integration length selector to MT63 configuration. 3. Added lowest / highest preamble tones as a signal acquisition aid. User can enable lowest, both or none.pull/2/head
rodzic
52fb02e33d
commit
cf4c6710fa
|
@ -818,6 +818,27 @@ static void cb_btnMT63_8bit(Fl_Check_Button* o, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *btnMT63_rx_integration=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnMT63_rx_integration(Fl_Check_Button* o, void*) {
|
||||
progdefaults.mt63_rx_integration = o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *btnMT63_usetones=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnMT63_usetones(Fl_Check_Button* o, void*) {
|
||||
progdefaults.mt63_usetones = o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *btnMT63_upper_lower=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnMT63_upper_lower(Fl_Check_Button* o, void*) {
|
||||
progdefaults.mt63_twotones = o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Group *tabOlivia=(Fl_Group *)0;
|
||||
|
||||
Fl_Choice *mnuOlivia_Bandwidth=(Fl_Choice *)0;
|
||||
|
@ -2123,6 +2144,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
{ tabOperator = new Fl_Group(0, 25, 500, 345, _("Operator"));
|
||||
tabOperator->callback((Fl_Callback*)cb_tabOperator);
|
||||
tabOperator->when(FL_WHEN_CHANGED);
|
||||
tabOperator->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 35, 490, 165, _("Station"));
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
@ -2707,11 +2729,11 @@ an merging"));
|
|||
tabWaterfall->end();
|
||||
} // Fl_Group* tabWaterfall
|
||||
{ tabModems = new Fl_Group(0, 25, 500, 345, _("Modems"));
|
||||
tabModems->hide();
|
||||
{ tabsModems = new Fl_Tabs(0, 25, 500, 345);
|
||||
tabsModems->selection_color(FL_LIGHT1);
|
||||
tabsModems->align(FL_ALIGN_TOP_RIGHT);
|
||||
{ tabCW = new Fl_Group(0, 50, 500, 320, _("CW"));
|
||||
tabCW->hide();
|
||||
{ tabsCW = new Fl_Tabs(0, 50, 500, 320);
|
||||
tabsCW->selection_color(FL_LIGHT1);
|
||||
{ Fl_Group* o = new Fl_Group(0, 75, 500, 295, _("General"));
|
||||
|
@ -3076,8 +3098,7 @@ an merging"));
|
|||
tabFeld->end();
|
||||
} // Fl_Group* tabFeld
|
||||
{ tabMT63 = new Fl_Group(0, 50, 500, 320, _("MT-63"));
|
||||
tabMT63->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 85);
|
||||
{ Fl_Group* o = new Fl_Group(5, 60, 490, 184);
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
{ Fl_Check_Button* o = btnmt63_interleave = new Fl_Check_Button(150, 78, 185, 20, _("64-bit (long) interleave"));
|
||||
|
@ -3087,12 +3108,30 @@ an merging"));
|
|||
btnmt63_interleave->callback((Fl_Callback*)cb_btnmt63_interleave);
|
||||
o->value(0);if (progdefaults.mt63_interleave == 64) o->value(1);
|
||||
} // Fl_Check_Button* btnmt63_interleave
|
||||
{ Fl_Check_Button* o = btnMT63_8bit = new Fl_Check_Button(150, 113, 205, 20, _("8-bit extended characters"));
|
||||
{ Fl_Check_Button* o = btnMT63_8bit = new Fl_Check_Button(150, 114, 205, 20, _("8-bit extended characters"));
|
||||
btnMT63_8bit->tooltip(_("Enable this for Latin-1 accented characters"));
|
||||
btnMT63_8bit->down_box(FL_DOWN_BOX);
|
||||
btnMT63_8bit->callback((Fl_Callback*)cb_btnMT63_8bit);
|
||||
o->value(progdefaults.mt63_8bit);
|
||||
} // Fl_Check_Button* btnMT63_8bit
|
||||
{ Fl_Check_Button* o = btnMT63_rx_integration = new Fl_Check_Button(150, 151, 167, 15, _("Long Rx Integration"));
|
||||
btnMT63_rx_integration->tooltip(_("Enable for very weak signals"));
|
||||
btnMT63_rx_integration->down_box(FL_DOWN_BOX);
|
||||
btnMT63_rx_integration->callback((Fl_Callback*)cb_btnMT63_rx_integration);
|
||||
o->value(progdefaults.mt63_rx_integration);
|
||||
} // Fl_Check_Button* btnMT63_rx_integration
|
||||
{ Fl_Check_Button* o = btnMT63_usetones = new Fl_Check_Button(150, 183, 133, 15, _("Use start tones"));
|
||||
btnMT63_usetones->tooltip(_("Xmt startup tones in first / last frequency bins"));
|
||||
btnMT63_usetones->down_box(FL_DOWN_BOX);
|
||||
btnMT63_usetones->callback((Fl_Callback*)cb_btnMT63_usetones);
|
||||
o->value(progdefaults.mt63_usetones);
|
||||
} // Fl_Check_Button* btnMT63_usetones
|
||||
{ Fl_Check_Button* o = btnMT63_upper_lower = new Fl_Check_Button(150, 215, 136, 15, _("Upper && Lower"));
|
||||
btnMT63_upper_lower->tooltip(_("Select for two / clear for only lower tone"));
|
||||
btnMT63_upper_lower->down_box(FL_DOWN_BOX);
|
||||
btnMT63_upper_lower->callback((Fl_Callback*)cb_btnMT63_upper_lower);
|
||||
o->value(progdefaults.mt63_twotones);
|
||||
} // Fl_Check_Button* btnMT63_upper_lower
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
tabMT63->end();
|
||||
|
|
|
@ -80,15 +80,15 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
code {} {}
|
||||
Fl_Window {} {
|
||||
label {Fldigi configuration} open
|
||||
xywh {326 139 500 400} type Double color 45 selection_color 51 labelsize 18 align 80 visible
|
||||
xywh {536 199 500 400} type Double color 45 selection_color 51 labelsize 18 align 80 visible
|
||||
} {
|
||||
Fl_Tabs tabsConfigure {open
|
||||
xywh {0 0 505 372} color 50 selection_color 50
|
||||
} {
|
||||
Fl_Group tabOperator {
|
||||
label Operator
|
||||
callback {progdefaults.changed = true;} open selected
|
||||
xywh {0 25 500 345} when 1
|
||||
callback {progdefaults.changed = true;} open
|
||||
xywh {0 25 500 345} when 1 hide
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label Station open
|
||||
|
@ -699,14 +699,14 @@ behaves inside the waterfall} xywh {15 196 150 22} down_box BORDER_BOX align 8
|
|||
}
|
||||
Fl_Group tabModems {
|
||||
label Modems open
|
||||
xywh {0 25 500 345} hide
|
||||
xywh {0 25 500 345}
|
||||
} {
|
||||
Fl_Tabs tabsModems {open
|
||||
xywh {0 25 500 345} selection_color 50 align 9
|
||||
} {
|
||||
Fl_Group tabCW {
|
||||
label CW open
|
||||
xywh {0 50 500 320}
|
||||
xywh {0 50 500 320} hide
|
||||
} {
|
||||
Fl_Tabs tabsCW {open
|
||||
xywh {0 50 500 320} selection_color 50
|
||||
|
@ -830,14 +830,14 @@ progdefaults.changed = true;}
|
|||
label {Dash to dot ratio}
|
||||
callback {progdefaults.CWdash2dot=o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Dash to dot ratio} xywh {240 114 64 20} type Simple align 8 minimum 2.5 maximum 4 step 0.1 value 3
|
||||
tooltip {Dash to dot ratio} xywh {240 114 64 20} type Simple align 8 minimum 2.5 maximum 4 value 3
|
||||
code0 {o->value(progdefaults.CWdash2dot);}
|
||||
}
|
||||
Fl_Counter cntCWrisetime {
|
||||
label {Edge timing}
|
||||
callback {progdefaults.CWrisetime=o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Leading and Trailing edge risetimes (msec)} xywh {240 145 65 20} type Simple align 8 minimum 0 maximum 15 step 0.1 value 4
|
||||
tooltip {Leading and Trailing edge risetimes (msec)} xywh {240 145 65 20} type Simple align 8 minimum 0 maximum 15 value 4
|
||||
code0 {o->value(progdefaults.CWrisetime);}
|
||||
}
|
||||
Fl_Choice mnuQSKshape {
|
||||
|
@ -927,7 +927,7 @@ progdefaults.changed = true;}
|
|||
callback {progdefaults.DOMINOEX_BW = o->value();
|
||||
resetDOMEX();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Filter bandwidth relative to signal width} xywh {156 141 63 20} type Simple align 8 minimum 1 maximum 2 step 0.1 value 1.5
|
||||
tooltip {Filter bandwidth relative to signal width} xywh {156 141 63 20} type Simple align 8 minimum 1 maximum 2 value 1.5
|
||||
code0 {o->value(progdefaults.DOMINOEX_BW);}
|
||||
}
|
||||
Fl_Check_Button chkDominoEX_FEC {
|
||||
|
@ -941,7 +941,7 @@ progdefaults.changed = true;}
|
|||
label {CWI threshold}
|
||||
callback {progdefaults.DomCWI = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {CWI detection and suppression} xywh {15 207 260 20} type Horizontal align 1 step 0.01 textsize 14
|
||||
tooltip {CWI detection and suppression} xywh {15 207 260 20} type Horizontal align 1 textsize 14
|
||||
code0 {o->value(progdefaults.DomCWI);}
|
||||
}
|
||||
Fl_Counter valDominoEX_PATHS {
|
||||
|
@ -1025,10 +1025,10 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group tabMT63 {
|
||||
label {MT-63} open
|
||||
xywh {0 50 500 320} hide
|
||||
xywh {0 50 500 320}
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {5 60 490 85} box ENGRAVED_FRAME align 21
|
||||
xywh {5 60 490 184} box ENGRAVED_FRAME align 21
|
||||
} {
|
||||
Fl_Check_Button btnmt63_interleave {
|
||||
label {64-bit (long) interleave}
|
||||
|
@ -1044,9 +1044,30 @@ progdefaults.changed = true;}
|
|||
label {8-bit extended characters}
|
||||
callback {progdefaults.mt63_8bit = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Enable this for Latin-1 accented characters} xywh {150 113 205 20} down_box DOWN_BOX
|
||||
tooltip {Enable this for Latin-1 accented characters} xywh {150 114 205 20} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.mt63_8bit);}
|
||||
}
|
||||
Fl_Check_Button btnMT63_rx_integration {
|
||||
label {Long Rx Integration}
|
||||
callback {progdefaults.mt63_rx_integration = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Enable for very weak signals} xywh {150 151 167 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.mt63_rx_integration);}
|
||||
}
|
||||
Fl_Check_Button btnMT63_usetones {
|
||||
label {Use start tones}
|
||||
callback {progdefaults.mt63_usetones = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Xmt startup tones in first / last frequency bins} xywh {150 183 133 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.mt63_usetones);}
|
||||
}
|
||||
Fl_Check_Button btnMT63_upper_lower {
|
||||
label {Upper && Lower}
|
||||
callback {progdefaults.mt63_twotones = o->value();
|
||||
progdefaults.changed = true;} selected
|
||||
tooltip {Select for two / clear for only lower tone} xywh {150 215 136 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.mt63_twotones);}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabOlivia {
|
||||
|
@ -1402,7 +1423,7 @@ progdefaults.changed = true;}
|
|||
callback {progdefaults.THOR_BW = o->value();
|
||||
resetTHOR();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Filter bandwidth relative to signal width} xywh {156 141 63 20} type Simple align 8 minimum 1 maximum 2 step 0.1 value 1.5
|
||||
tooltip {Filter bandwidth relative to signal width} xywh {156 141 63 20} type Simple align 8 minimum 1 maximum 2 value 1.5
|
||||
code0 {o->value(progdefaults.THOR_BW);}
|
||||
}
|
||||
Fl_Check_Button valTHOR_SOFT {
|
||||
|
@ -1416,7 +1437,7 @@ progdefaults.changed = true;}
|
|||
label {CWI threshold}
|
||||
callback {progdefaults.ThorCWI = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {CWI detection and suppression} xywh {15 218 260 20} type Horizontal align 1 step 0.01 textsize 14
|
||||
tooltip {CWI detection and suppression} xywh {15 218 260 20} type Horizontal align 1 textsize 14
|
||||
code0 {o->value(progdefaults.ThorCWI);}
|
||||
}
|
||||
Fl_Counter valTHOR_PATHS {
|
||||
|
@ -2191,7 +2212,7 @@ progdefaults.changed = true;}
|
|||
label PCM
|
||||
callback {setPCMvolume(o->value());
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Set the sound card PCM level} xywh {15 167 340 20} type Horizontal selection_color 15 align 8 step 0.01 value 0.8 textsize 14
|
||||
tooltip {Set the sound card PCM level} xywh {15 167 340 20} type Horizontal selection_color 15 align 8 value 0.8 textsize 14
|
||||
code0 {extern void setPCMvolume(double);}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,9 @@ extern Fl_Check_Button *btnHellXmtWidth;
|
|||
extern Fl_Group *tabMT63;
|
||||
extern Fl_Check_Button *btnmt63_interleave;
|
||||
extern Fl_Check_Button *btnMT63_8bit;
|
||||
extern Fl_Check_Button *btnMT63_rx_integration;
|
||||
extern Fl_Check_Button *btnMT63_usetones;
|
||||
extern Fl_Check_Button *btnMT63_upper_lower;
|
||||
extern Fl_Group *tabOlivia;
|
||||
extern Fl_Choice *mnuOlivia_Bandwidth;
|
||||
extern Fl_Choice *mnuOlivia_Tones;
|
||||
|
|
|
@ -143,6 +143,9 @@
|
|||
/* MT63 */ \
|
||||
ELEM_(bool, mt63_8bit, "MT638BIT", false) \
|
||||
ELEM_(int, mt63_interleave, "MT63INTERLEAVE", 64) /* long interleave */ \
|
||||
ELEM_(bool, mt63_rx_integration, "MT63INTEGRATION", false) \
|
||||
ELEM_(bool, mt63_twotones, "MT63TWOTONES", true) \
|
||||
ELEM_(bool, mt63_usetones, "MT63USETONES", true) \
|
||||
/* Waterfall & UI */ \
|
||||
ELEM_(uchar, red, "", 0) \
|
||||
ELEM_(uchar, green, "", 255) \
|
||||
|
|
|
@ -22,7 +22,7 @@ class modem : public morse {
|
|||
protected:
|
||||
trx_mode mode;
|
||||
SoundBase *scard;
|
||||
|
||||
|
||||
bool stopflag;
|
||||
int fragmentsize;
|
||||
int samplerate;
|
||||
|
@ -57,7 +57,7 @@ protected:
|
|||
|
||||
bool historyON;
|
||||
Digiscope::scope_mode scopemode;
|
||||
|
||||
|
||||
int scptr;
|
||||
|
||||
unsigned cap;
|
||||
|
@ -76,7 +76,7 @@ public:
|
|||
virtual void set1(int, int){};
|
||||
virtual void set2(int, int){};
|
||||
virtual void makeTxViewer(int W, int H){};
|
||||
|
||||
|
||||
virtual void searchDown() {};
|
||||
virtual void searchUp() {};
|
||||
|
||||
|
@ -109,12 +109,12 @@ public:
|
|||
void set_samplerate(int);
|
||||
void init_queues();
|
||||
int get_echo_char();
|
||||
|
||||
|
||||
void ModulateXmtr(double *, int);
|
||||
void ModulateStereo(double *, double *, int);
|
||||
|
||||
|
||||
void videoText();
|
||||
|
||||
|
||||
void set_stopflag(bool b) { stopflag = b;};
|
||||
|
||||
unsigned get_cap(void) { return cap; }
|
||||
|
@ -132,15 +132,15 @@ public:
|
|||
virtual void incWPM() {};
|
||||
virtual void decWPM() {};
|
||||
virtual void toggleWPM() {};
|
||||
|
||||
|
||||
// for waterfall id transmission
|
||||
private:
|
||||
|
||||
|
||||
static int wfid_mask[];
|
||||
static double wfid_w[];
|
||||
static double wfid_txpulse[];
|
||||
static double wfid_outbuf[];
|
||||
|
||||
|
||||
void wfid_make_pulse();
|
||||
void wfid_make_tones();
|
||||
void wfid_send(long int);
|
||||
|
@ -149,7 +149,7 @@ private:
|
|||
|
||||
void wfid_sendchar(char c);
|
||||
void wfid_sendchars(std::string s);
|
||||
|
||||
|
||||
double PTTnco();
|
||||
|
||||
public:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Copyright (C) 2006
|
||||
// Dave Freese, W1HKJ
|
||||
//
|
||||
// This file is part of fldigi. Adapted from code contained in gmfsk source code
|
||||
// This file is part of fldigi. Adapted from code contained in gmfsk source code
|
||||
// distribution.
|
||||
// Copyright (C) 2005
|
||||
// Tomi Manninen (oh2bns@sral.fi)
|
||||
|
@ -37,6 +37,7 @@ private:
|
|||
int Interleave;
|
||||
int flush;
|
||||
int escape;
|
||||
bool long_integral;
|
||||
|
||||
MT63tx *Tx;
|
||||
MT63rx *Rx;
|
||||
|
@ -47,7 +48,7 @@ private:
|
|||
bool flushbuffer;
|
||||
double FEC_offset;
|
||||
double FEC_snr;
|
||||
|
||||
|
||||
public:
|
||||
mt63(trx_mode mode);
|
||||
~mt63();
|
||||
|
@ -57,7 +58,7 @@ public:
|
|||
void restart();
|
||||
int rx_process(const double *buf, int len);
|
||||
int tx_process();
|
||||
|
||||
|
||||
void rx_flush();
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* mt63base.h -- MT63 transmitter and receiver in C++ for LINUX
|
||||
*
|
||||
* Copyright (c) 2007, 2008 Dave Freese, W1HKJ
|
||||
*
|
||||
*
|
||||
* base class for use by fldigi
|
||||
* modified from original
|
||||
* excluded CW_ID which is a part of the base modem class for fldigi
|
||||
|
@ -57,7 +57,7 @@ How to use this class:
|
|||
// Date: 05-NOV-1999
|
||||
|
||||
class MT63encoder
|
||||
{
|
||||
{
|
||||
public:
|
||||
MT63encoder();
|
||||
~MT63encoder();
|
||||
|
@ -180,7 +180,7 @@ public:
|
|||
~MT63tx();
|
||||
void Free(void);
|
||||
int Preset(int BandWidth=1000, int LongInterleave=0);//, char *ID=NULL);
|
||||
int SendTune(void);
|
||||
int SendTune(bool twotones);
|
||||
int SendChar(char ch);
|
||||
int SendJam(void);
|
||||
int SendSilence(void);
|
||||
|
@ -280,7 +280,7 @@ private:
|
|||
int DecimateRatio; // decimation/interpolation after/before filter
|
||||
|
||||
// how the bits of one block are placed on data carriers
|
||||
int *InterleavePattern;
|
||||
int *InterleavePattern;
|
||||
int DataInterleave; // data interleave depth
|
||||
|
||||
int DataCarriers; // number of carriers
|
||||
|
@ -308,9 +308,9 @@ private:
|
|||
|
||||
dspCmpx *SyncPhCorr; // dspPhase corrections for the sync. processor
|
||||
|
||||
dspCmpx *CorrelMid[4],
|
||||
dspCmpx *CorrelMid[4],
|
||||
*CorrelOut[4]; // correlation integrator
|
||||
double *dspPowerMid,
|
||||
double *dspPowerMid,
|
||||
*dspPowerOut; // carrier dspPower integrator
|
||||
dspCmpx *CorrelNorm[4]; // normalized correlation
|
||||
double W1, W2, W5; // correlation integrator weights
|
||||
|
@ -341,9 +341,9 @@ private:
|
|||
double SyncSymbShift; // current smoothed symbol time shift
|
||||
|
||||
// here starts the data decoder
|
||||
void DataProcess( dspCmpx *EvenSlice,
|
||||
dspCmpx *OddSlice,
|
||||
double FreqOfs,
|
||||
void DataProcess( dspCmpx *EvenSlice,
|
||||
dspCmpx *OddSlice,
|
||||
double FreqOfs,
|
||||
int TimeDist);
|
||||
|
||||
int DataScanMargin; // +/- data carriers to scan for best FEC match
|
||||
|
|
638
src/mt63/dsp.cxx
638
src/mt63/dsp.cxx
Plik diff jest za duży
Load Diff
|
@ -31,8 +31,7 @@
|
|||
#include "mt63.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static int IntegLen = 32; // integration period for sync./data tracking
|
||||
bool startflag = true;
|
||||
|
||||
void mt63::tx_init(SoundBase *sb)
|
||||
{
|
||||
|
@ -41,11 +40,14 @@ void mt63::tx_init(SoundBase *sb)
|
|||
set_freq(500.0 + bandwidth / 2.0);
|
||||
flush = Tx->DataInterleave;
|
||||
videoText();
|
||||
startflag = true;
|
||||
}
|
||||
|
||||
void mt63::rx_init()
|
||||
{
|
||||
Rx->Preset((int)bandwidth, Interleave == 64 ? 1 : 0, IntegLen);
|
||||
Rx->Preset( (int)bandwidth,
|
||||
Interleave == 64 ? 1 : 0,
|
||||
long_integral ? 32 : 16 );
|
||||
set_freq(500.0 + bandwidth / 2.0);
|
||||
InpLevel->Preset(64.0, 0.75);
|
||||
escape = 0;
|
||||
|
@ -59,7 +61,24 @@ int mt63::tx_process()
|
|||
double maxval = 0;
|
||||
|
||||
rx_flush();
|
||||
|
||||
|
||||
if (startflag == true) {
|
||||
startflag = false;
|
||||
for (int i = 0; i < Tx->DataInterleave; i++) Tx->SendChar(0);
|
||||
if (progdefaults.mt63_usetones) {
|
||||
double maxval = 0.0;
|
||||
for (int i = 0; i < Tx->DataInterleave / 2; i++) {
|
||||
Tx->SendTune( progdefaults.mt63_twotones );
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++)
|
||||
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
|
||||
maxval = fabs(Tx->Comb.Output.Data[i]);
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++)
|
||||
Tx->Comb.Output.Data[i] /= maxval;
|
||||
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c = get_tx_char();
|
||||
if (c == 0x03) {
|
||||
stopflag = true;
|
||||
|
@ -68,7 +87,7 @@ int mt63::tx_process()
|
|||
}
|
||||
|
||||
if (c == -1 || stopflag == true) c = 0;
|
||||
|
||||
|
||||
if (stopflag && flush-- == 0) {
|
||||
stopflag = false;
|
||||
Tx->SendJam();
|
||||
|
@ -86,7 +105,7 @@ int mt63::tx_process()
|
|||
c = '.';
|
||||
|
||||
put_echo_char(c);
|
||||
|
||||
|
||||
if (c > 127) {
|
||||
c &= 127;
|
||||
Tx->SendChar(127);
|
||||
|
@ -99,12 +118,12 @@ int mt63::tx_process()
|
|||
}
|
||||
|
||||
Tx->SendChar(c);
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++)
|
||||
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
|
||||
maxval = fabs(Tx->Comb.Output.Data[i]);
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
|
||||
Tx->Comb.Output.Data[i] /= maxval;
|
||||
}
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++)
|
||||
if (fabs(Tx->Comb.Output.Data[i]) > maxval)
|
||||
maxval = fabs(Tx->Comb.Output.Data[i]);
|
||||
for (int i = 0; i < Tx->Comb.Output.Len; i++) {
|
||||
Tx->Comb.Output.Data[i] /= maxval;
|
||||
}
|
||||
ModulateXmtr((Tx->Comb.Output.Data), Tx->Comb.Output.Len);
|
||||
|
||||
return 0;
|
||||
|
@ -125,21 +144,26 @@ int mt63::rx_process(const double *buf, int len)
|
|||
Interleave = progdefaults.mt63_interleave;
|
||||
restart();
|
||||
}
|
||||
|
||||
if (long_integral != progdefaults.mt63_rx_integration) {
|
||||
long_integral = progdefaults.mt63_rx_integration;
|
||||
restart();
|
||||
}
|
||||
|
||||
if (InpBuff->EnsureSpace(len) == -1) {
|
||||
fprintf(stderr, "mt63_rxprocess: buffer error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
InpBuff->Data[i] = buf[i];
|
||||
InpBuff->Len = len;
|
||||
|
||||
InpBuff->Len = len;
|
||||
InpLevel->Process(InpBuff);
|
||||
|
||||
|
||||
Rx->Process(InpBuff);
|
||||
|
||||
snr = Rx->FEC_SNR();
|
||||
|
||||
|
||||
if (progStatus.sqlonoff && snr < progStatus.sldrSquelchValue) {
|
||||
put_Status1("");
|
||||
put_Status2("");
|
||||
|
@ -152,12 +176,12 @@ int mt63::rx_process(const double *buf, int len)
|
|||
display_metric(snr);
|
||||
|
||||
double s2n = 10.0*log10( snr == 0 ? 0.001 : snr);
|
||||
snprintf(msg1, sizeof(msg1), "s/n %2d dB", (int)(floor(s2n)));
|
||||
snprintf(msg1, sizeof(msg1), "s/n %2d dB", (int)(floor(s2n)));
|
||||
put_Status1(msg1);
|
||||
|
||||
snprintf(msg2, sizeof(msg2), "f/o %+4.1f Hz", Rx->TotalFreqOffset());
|
||||
put_Status2(msg2, 5, STATUS_CLEAR);
|
||||
|
||||
|
||||
for (i = 0; i < Rx->Output.Len; i++) {
|
||||
c = Rx->Output.Data[i];
|
||||
|
||||
|
@ -182,7 +206,7 @@ int mt63::rx_process(const double *buf, int len)
|
|||
put_rx_char(c);
|
||||
}
|
||||
flushbuffer = true;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -193,7 +217,7 @@ void mt63::rx_flush()
|
|||
int dlen = 0;
|
||||
|
||||
if (!flushbuffer) return;
|
||||
|
||||
|
||||
if (emptyBuff->EnsureSpace(len) == -1) {
|
||||
flushbuffer = false;
|
||||
return;
|
||||
|
@ -233,7 +257,7 @@ void mt63::rx_flush()
|
|||
dlen = Rx->Output.Len;
|
||||
}
|
||||
flushbuffer = false;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -250,11 +274,9 @@ void mt63::restart()
|
|||
fprintf(stderr, "mt63_txinit: init failed\n");
|
||||
flush = Tx->DataInterleave;
|
||||
|
||||
// Rx->Preset( int BandWidth = 1000,
|
||||
// int LongInterleave = 0,
|
||||
// int Integ = 16,
|
||||
// void (*Display)(double *Spectra, int Len) = NULL);
|
||||
err = Rx->Preset((int)bandwidth, Interleave == 64 ? 1 : 0, IntegLen);
|
||||
err = Rx->Preset( (int)bandwidth,
|
||||
Interleave == 64 ? 1 : 0,
|
||||
long_integral ? 32 : 16);
|
||||
if (err)
|
||||
fprintf(stderr, "mt63_rxinit: init failed\n");
|
||||
InpLevel->Preset(64.0, 0.75);
|
||||
|
@ -282,6 +304,7 @@ mt63::mt63 (trx_mode mt63_mode) : modem()
|
|||
break;
|
||||
}
|
||||
Interleave = progdefaults.mt63_interleave;
|
||||
long_integral = progdefaults.mt63_rx_integration;
|
||||
|
||||
Tx = new MT63tx;
|
||||
Rx = new MT63rx;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* mt63base.cc -- MT63 transmitter and receiver in C++ for LINUX
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2007, 2008 Dave Freese, W1HKJ
|
||||
*
|
||||
*
|
||||
* base class for use by fldigi
|
||||
* modified from original
|
||||
* excluded CW_ID which is a part of the base modem class for fldigi
|
||||
|
@ -52,22 +52,22 @@
|
|||
// MT63 transmitter code
|
||||
|
||||
MT63tx::MT63tx()
|
||||
{
|
||||
TxVect = NULL;
|
||||
dspPhaseCorr = NULL;
|
||||
{
|
||||
TxVect = NULL;
|
||||
dspPhaseCorr = NULL;
|
||||
}
|
||||
|
||||
MT63tx::~MT63tx()
|
||||
{
|
||||
free(TxVect);
|
||||
free(dspPhaseCorr);
|
||||
{
|
||||
free(TxVect);
|
||||
free(dspPhaseCorr);
|
||||
}
|
||||
|
||||
void MT63tx::Free(void)
|
||||
{
|
||||
{
|
||||
free(TxVect);
|
||||
TxVect = NULL;
|
||||
free(dspPhaseCorr);
|
||||
free(dspPhaseCorr);
|
||||
dspPhaseCorr = NULL;
|
||||
Encoder.Free();
|
||||
FFT.Free();
|
||||
|
@ -77,10 +77,10 @@ void MT63tx::Free(void)
|
|||
}
|
||||
|
||||
int MT63tx::Preset(int BandWidth, int LongInterleave)
|
||||
{
|
||||
{
|
||||
int i, p, step, incr, mask;
|
||||
|
||||
switch(BandWidth) {
|
||||
switch(BandWidth) {
|
||||
case 500:
|
||||
FirstDataCarr = 256;
|
||||
AliasShapeI = Alias_k5_I;
|
||||
|
@ -102,7 +102,7 @@ int MT63tx::Preset(int BandWidth, int LongInterleave)
|
|||
AliasFilterLen = Alias_2k_Len;
|
||||
DecimateRatio = 2;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -115,13 +115,13 @@ int MT63tx::Preset(int BandWidth, int LongInterleave)
|
|||
CarrMarkCode = 0x16918BBEL;
|
||||
CarrMarkdspAmpl = 0; // WindowLen/32;
|
||||
|
||||
if (LongInterleave) {
|
||||
DataInterleave = 64;
|
||||
InterleavePattern = LongIntlvPatt;
|
||||
if (LongInterleave) {
|
||||
DataInterleave = 64;
|
||||
InterleavePattern = LongIntlvPatt;
|
||||
}
|
||||
else {
|
||||
DataInterleave = 32;
|
||||
InterleavePattern = ShortIntlvPatt;
|
||||
else {
|
||||
DataInterleave = 32;
|
||||
InterleavePattern = ShortIntlvPatt;
|
||||
}
|
||||
|
||||
if (dspRedspAllocArray(&TxVect, DataCarriers))
|
||||
|
@ -147,27 +147,27 @@ int MT63tx::Preset(int BandWidth, int LongInterleave)
|
|||
// Here we only compute indexes to the FFT twiddle factors
|
||||
// so the actual vector is FFT.Twiddle[TxVect[i]]
|
||||
|
||||
for (step = 0, incr = 1, p = 0, i = 0; i < DataCarriers; i++) {
|
||||
TxVect[i] = p;
|
||||
step += incr;
|
||||
p = (p + step) & mask;
|
||||
for (step = 0, incr = 1, p = 0, i = 0; i < DataCarriers; i++) {
|
||||
TxVect[i] = p;
|
||||
step += incr;
|
||||
p = (p + step) & mask;
|
||||
}
|
||||
|
||||
// compute dspPhase correction between successive FFTs separated by SymbolSepar
|
||||
// Like above we compute indexes to the FFT.Twiddle[]
|
||||
|
||||
incr = (SymbolSepar * DataCarrSepar) & mask;
|
||||
for (p = (SymbolSepar * FirstDataCarr) & mask, i = 0; i < DataCarriers; i++) {
|
||||
dspPhaseCorr[i] = p;
|
||||
for (p = (SymbolSepar * FirstDataCarr) & mask, i = 0; i < DataCarriers; i++) {
|
||||
dspPhaseCorr[i] = p;
|
||||
p = (p + incr) & mask;
|
||||
}
|
||||
return 0;
|
||||
Error:
|
||||
Free();
|
||||
Error:
|
||||
Free();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MT63tx::SendTune(void)
|
||||
int MT63tx::SendTune(bool twotones)
|
||||
{
|
||||
int i, c, r, mask;
|
||||
double dspAmpl;
|
||||
|
@ -178,7 +178,7 @@ int MT63tx::SendTune(void)
|
|||
for (i = 0; i < DataCarriers; i++)
|
||||
TxVect[i] = (TxVect[i] + dspPhaseCorr[i]) & mask;
|
||||
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
WindowBuff.Data[i].im = WindowBuff.Data[i].re = 0.0;
|
||||
|
||||
i = 0;
|
||||
|
@ -187,18 +187,19 @@ int MT63tx::SendTune(void)
|
|||
WindowBuff.Data[r].re = dspAmpl * FFT.Twiddle[TxVect[i]].re;
|
||||
WindowBuff.Data[r].im = (-dspAmpl) * FFT.Twiddle[TxVect[i]].im;
|
||||
|
||||
i = DataCarriers - 1;
|
||||
c = FirstDataCarr + i * DataCarrSepar;
|
||||
c &= mask;
|
||||
r = WindowLen + FFT.BitRevIdx[c];
|
||||
WindowBuff.Data[r].re = dspAmpl * FFT.Twiddle[TxVect[i]].re;
|
||||
WindowBuff.Data[r].im = (-dspAmpl) * FFT.Twiddle[TxVect[i]].im;
|
||||
|
||||
// inverse FFT: WindowBuff is already scrmabled
|
||||
if (twotones) {
|
||||
i = DataCarriers - 1;
|
||||
c = FirstDataCarr + i * DataCarrSepar;
|
||||
c &= mask;
|
||||
r = WindowLen + FFT.BitRevIdx[c];
|
||||
WindowBuff.Data[r].re = dspAmpl * FFT.Twiddle[TxVect[i]].re;
|
||||
WindowBuff.Data[r].im = (-dspAmpl) * FFT.Twiddle[TxVect[i]].im;
|
||||
}
|
||||
// inverse FFT: WindowBuff is already scrambled
|
||||
FFT.CoreProc(WindowBuff.Data);
|
||||
FFT.CoreProc(WindowBuff.Data + WindowLen);
|
||||
// negate the imaginary part for the IFFT
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
WindowBuff.Data[i].im *= (-1.0);
|
||||
|
||||
Window.Process(&WindowBuff);
|
||||
|
@ -237,7 +238,7 @@ int MT63tx::SendChar(char ch)
|
|||
}
|
||||
|
||||
int MT63tx::SendJam(void)
|
||||
{
|
||||
{
|
||||
int i,mask,left,right;
|
||||
|
||||
mask = FFT.Size-1;
|
||||
|
@ -245,7 +246,7 @@ int MT63tx::SendJam(void)
|
|||
right = 3 * (FFT.Size / 4);
|
||||
for (i = 0; i < DataCarriers; i++) {
|
||||
if (rand() & 0x100) // turn left 90 degrees
|
||||
TxVect[i] = (TxVect[i] + dspPhaseCorr[i] + left) & mask;
|
||||
TxVect[i] = (TxVect[i] + dspPhaseCorr[i] + left) & mask;
|
||||
else // turn right 90 degrees
|
||||
TxVect[i] = (TxVect[i] + dspPhaseCorr[i] + right) & mask;
|
||||
}
|
||||
|
@ -255,33 +256,33 @@ int MT63tx::SendJam(void)
|
|||
}
|
||||
|
||||
int MT63tx::ProcessTxVect(void)
|
||||
{
|
||||
{
|
||||
int i, c, r, mask;
|
||||
|
||||
mask = FFT.Size - 1;
|
||||
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
WindowBuff.Data[i].im = WindowBuff.Data[i].re = 0.0;
|
||||
|
||||
for ( c = FirstDataCarr, i = 0;
|
||||
i < DataCarriers;
|
||||
i += 2, c = (c + 2 * DataCarrSepar) & mask) {
|
||||
for ( c = FirstDataCarr, i = 0;
|
||||
i < DataCarriers;
|
||||
i += 2, c = (c + 2 * DataCarrSepar) & mask) {
|
||||
r = FFT.BitRevIdx[c];
|
||||
WindowBuff.Data[r].re = TxdspAmpl*FFT.Twiddle[TxVect[i]].re;
|
||||
WindowBuff.Data[r].im = (-TxdspAmpl)*FFT.Twiddle[TxVect[i]].im;
|
||||
WindowBuff.Data[r].im = (-TxdspAmpl)*FFT.Twiddle[TxVect[i]].im;
|
||||
}
|
||||
for ( c = FirstDataCarr + DataCarrSepar, i = 1;
|
||||
i < DataCarriers;
|
||||
for ( c = FirstDataCarr + DataCarrSepar, i = 1;
|
||||
i < DataCarriers;
|
||||
i += 2, c = (c + 2 * DataCarrSepar) & mask) {
|
||||
r = WindowLen + FFT.BitRevIdx[c];
|
||||
WindowBuff.Data[r].re = TxdspAmpl * FFT.Twiddle[TxVect[i]].re;
|
||||
WindowBuff.Data[r].im = (-TxdspAmpl) * FFT.Twiddle[TxVect[i]].im;
|
||||
WindowBuff.Data[r].im = (-TxdspAmpl) * FFT.Twiddle[TxVect[i]].im;
|
||||
}
|
||||
FFT.CoreProc(WindowBuff.Data);
|
||||
FFT.CoreProc(WindowBuff.Data + WindowLen);
|
||||
|
||||
// negate the imaginary part for the IFFT
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
for (i = 0; i < 2 * WindowLen; i++)
|
||||
WindowBuff.Data[i].im *= (-1.0);
|
||||
|
||||
// we could be faster by avoiding Scramble and using the FFT.RevIdx[]
|
||||
|
@ -294,7 +295,7 @@ int MT63tx::ProcessTxVect(void)
|
|||
}
|
||||
|
||||
int MT63tx::SendSilence(void)
|
||||
{
|
||||
{
|
||||
Window.ProcessSilence(2);
|
||||
Comb.Process(&Window.Output);
|
||||
return 0;
|
||||
|
@ -304,7 +305,7 @@ int MT63tx::SendSilence(void)
|
|||
// Character encoder and block interleave for the MT63 modem
|
||||
|
||||
MT63encoder::MT63encoder()
|
||||
{
|
||||
{
|
||||
IntlvPipe = NULL;
|
||||
WalshBuff = NULL;
|
||||
Output = NULL;
|
||||
|
@ -320,12 +321,12 @@ MT63encoder::~MT63encoder()
|
|||
}
|
||||
|
||||
void MT63encoder::Free()
|
||||
{
|
||||
{
|
||||
free(IntlvPipe);
|
||||
free(WalshBuff);
|
||||
free(Output);
|
||||
free(IntlvPatt);
|
||||
IntlvPipe = NULL;
|
||||
IntlvPipe = NULL;
|
||||
WalshBuff = NULL;
|
||||
Output = NULL;
|
||||
IntlvPatt = NULL;
|
||||
|
@ -341,10 +342,10 @@ int MT63encoder::Preset(int Carriers, int Intlv, int *Pattern, int PreFill)
|
|||
IntlvSize = IntlvLen * DataCarriers;
|
||||
if (IntlvLen) {
|
||||
if (dspRedspAllocArray(&IntlvPipe, IntlvSize)) goto Error;
|
||||
if (PreFill)
|
||||
for (i = 0; i < IntlvSize; i++)
|
||||
if (PreFill)
|
||||
for (i = 0; i < IntlvSize; i++)
|
||||
IntlvPipe[i] = rand() & 1;
|
||||
else
|
||||
else
|
||||
dspClearArray(IntlvPipe,IntlvSize);
|
||||
if (dspRedspAllocArray(&IntlvPatt, DataCarriers)) goto Error;
|
||||
IntlvPtr = 0;
|
||||
|
@ -360,21 +361,21 @@ int MT63encoder::Preset(int Carriers, int Intlv, int *Pattern, int PreFill)
|
|||
}
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
Error:
|
||||
Free();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MT63encoder::Process(char code) // encode an ASCII character "code"
|
||||
{
|
||||
{
|
||||
int i, k;
|
||||
code &= CodeMask;
|
||||
for (i = 0; i < DataCarriers; i++)
|
||||
for (i = 0; i < DataCarriers; i++)
|
||||
WalshBuff[i] = 0;
|
||||
if (code < DataCarriers)
|
||||
if (code < DataCarriers)
|
||||
WalshBuff[(int)code] = 1.0;
|
||||
else WalshBuff[code-DataCarriers] = (-1.0);
|
||||
|
||||
|
||||
dspWalshInvTrans(WalshBuff, DataCarriers);
|
||||
|
||||
if (IntlvLen) {
|
||||
|
@ -382,7 +383,7 @@ int MT63encoder::Process(char code) // encode an ASCII character "code"
|
|||
IntlvPipe[IntlvPtr + i] = (WalshBuff[i] < 0.0);
|
||||
for (i = 0; i < DataCarriers; i++) {
|
||||
k = IntlvPtr + IntlvPatt[i];
|
||||
if (k >= IntlvSize)
|
||||
if (k >= IntlvSize)
|
||||
k -= IntlvSize;
|
||||
Output[i] = IntlvPipe[k+i];
|
||||
}
|
||||
|
@ -390,7 +391,7 @@ int MT63encoder::Process(char code) // encode an ASCII character "code"
|
|||
if (IntlvPtr >= IntlvSize)
|
||||
IntlvPtr -= IntlvSize;
|
||||
} else
|
||||
for (i = 0; i < DataCarriers; i++)
|
||||
for (i = 0; i < DataCarriers; i++)
|
||||
Output[i] = (WalshBuff[i] < 0.0);
|
||||
|
||||
return 0;
|
||||
|
@ -402,7 +403,7 @@ int MT63encoder::Process(char code) // encode an ASCII character "code"
|
|||
// MT63 decoder and deinterleaver
|
||||
|
||||
MT63decoder::MT63decoder()
|
||||
{
|
||||
{
|
||||
IntlvPipe = NULL;
|
||||
IntlvPatt = NULL;
|
||||
WalshBuff = NULL;
|
||||
|
@ -438,11 +439,11 @@ void MT63decoder::Free()
|
|||
}
|
||||
|
||||
int MT63decoder::Preset(int Carriers, int Intlv, int *Pattern, int Margin, int Integ)
|
||||
{
|
||||
{
|
||||
int i,p;
|
||||
|
||||
if (!dspPowerOf2(Carriers)) goto Error;
|
||||
DataCarriers = Carriers;
|
||||
DataCarriers = Carriers;
|
||||
ScanLen = 2 * Margin + 1;
|
||||
ScanSize = DataCarriers + 2 * Margin;
|
||||
|
||||
|
@ -458,7 +459,7 @@ int MT63decoder::Preset(int Carriers, int Intlv, int *Pattern, int Margin, int I
|
|||
for (p = 0, i = 0; i < DataCarriers; i++) {
|
||||
IntlvPatt[i] = p * ScanSize; // printf(" %2d",p);
|
||||
p += Pattern[i];
|
||||
if (p >= IntlvLen) p -= IntlvLen;
|
||||
if (p >= IntlvLen) p -= IntlvLen;
|
||||
}
|
||||
// printf("\n");
|
||||
|
||||
|
@ -497,13 +498,13 @@ int MT63decoder::Process(double *data)
|
|||
for (i = 0; i < DataCarriers; i++) {
|
||||
k = IntlvPtr - ScanSize - IntlvPatt[i];
|
||||
if (k < 0) k += IntlvSize;
|
||||
if ((s & 1) && (i & 1)) {
|
||||
k += ScanSize;
|
||||
if ((s & 1) && (i & 1)) {
|
||||
k += ScanSize;
|
||||
if (k >= IntlvSize) k-=IntlvSize;
|
||||
}
|
||||
WalshBuff[i] = IntlvPipe[k + s + i];
|
||||
WalshBuff[i] = IntlvPipe[k + s + i];
|
||||
// printf(" %4d",k/ScanSize);
|
||||
}
|
||||
}
|
||||
// printf("\n");
|
||||
dspWalshTrans(WalshBuff, DataCarriers);
|
||||
Min = dspFindMin(WalshBuff, DataCarriers, MinPos);
|
||||
|
@ -518,7 +519,7 @@ int MT63decoder::Process(double *data)
|
|||
WalshBuff[MinPos] = 0.0;
|
||||
}
|
||||
Noise = dspRMS(WalshBuff, DataCarriers);
|
||||
if (Noise > 0.0)
|
||||
if (Noise > 0.0)
|
||||
SNR = Sig/Noise;
|
||||
else SNR = 0.0;
|
||||
dspLowPass2(SNR, DecodeSnrMid[s], DecodeSnrOut[s], W1, W2, W5);
|
||||
|
@ -529,7 +530,7 @@ int MT63decoder::Process(double *data)
|
|||
}
|
||||
IntlvPtr += ScanSize;
|
||||
if (IntlvPtr >= IntlvSize) IntlvPtr = 0;
|
||||
DecodePtr += ScanLen;
|
||||
DecodePtr += ScanLen;
|
||||
if (DecodePtr >= DecodeSize) DecodePtr = 0;
|
||||
Max = dspFindMax(DecodeSnrOut, ScanLen, MaxPos);
|
||||
Output = DecodePipe[DecodePtr + MaxPos];
|
||||
|
@ -547,13 +548,13 @@ int MT63decoder::Process(double *data)
|
|||
// MT63 receiver code
|
||||
|
||||
MT63rx::MT63rx()
|
||||
{
|
||||
{
|
||||
int s;
|
||||
|
||||
FFTbuff = NULL;
|
||||
FFTbuff2 = NULL;
|
||||
|
||||
for (s = 0; s < 4; s++)
|
||||
for (s = 0; s < 4; s++)
|
||||
SyncPipe[s] = NULL;
|
||||
SyncPhCorr = NULL;
|
||||
for (s = 0; s < 4; s++) {
|
||||
|
@ -588,16 +589,16 @@ MT63rx::MT63rx()
|
|||
}
|
||||
|
||||
MT63rx::~MT63rx()
|
||||
{
|
||||
{
|
||||
int s;
|
||||
|
||||
free(FFTbuff);
|
||||
free(FFTbuff2);
|
||||
|
||||
for (s = 0; s < 4; s++)
|
||||
for (s = 0; s < 4; s++)
|
||||
free(SyncPipe[s]);
|
||||
free(SyncPhCorr);
|
||||
for (s = 0; s < 4; s++) {
|
||||
for (s = 0; s < 4; s++) {
|
||||
free(CorrelMid[s]);
|
||||
free(CorrelOut[s]);
|
||||
}
|
||||
|
@ -631,7 +632,7 @@ MT63rx::~MT63rx()
|
|||
void MT63rx::Free(void)
|
||||
{
|
||||
int s;
|
||||
FFT.Free();
|
||||
FFT.Free();
|
||||
InpSplit.Free();
|
||||
TestOfs.Free();
|
||||
ProcLine.Free();
|
||||
|
@ -641,11 +642,11 @@ void MT63rx::Free(void)
|
|||
free(FFTbuff2);
|
||||
FFTbuff2 = NULL;
|
||||
|
||||
for (s = 0; s < 4; s++) {
|
||||
free(SyncPipe[s]);
|
||||
for (s = 0; s < 4; s++) {
|
||||
free(SyncPipe[s]);
|
||||
SyncPipe[s] = NULL;
|
||||
}
|
||||
free(SyncPhCorr);
|
||||
free(SyncPhCorr);
|
||||
SyncPhCorr = NULL;
|
||||
for (s = 0; s < 4; s++) {
|
||||
free(CorrelMid[s]);
|
||||
|
@ -700,13 +701,13 @@ void MT63rx::Free(void)
|
|||
|
||||
Decoder.Free();
|
||||
|
||||
free(SpectradspPower);
|
||||
free(SpectradspPower);
|
||||
SpectradspPower = NULL;
|
||||
}
|
||||
|
||||
int MT63rx::Preset(int BandWidth, int LongInterleave, int Integ,
|
||||
void (*Display)(double *Spectra, int Len))
|
||||
{
|
||||
{
|
||||
int err,s,i,c;
|
||||
|
||||
switch(BandWidth) {
|
||||
|
@ -809,9 +810,9 @@ int MT63rx::Preset(int BandWidth, int LongInterleave, int Integ,
|
|||
SyncPtr = 0;
|
||||
|
||||
if (dspRedspAllocArray(&SyncPhCorr, ScanLen)) goto Error;
|
||||
|
||||
|
||||
for (c = (ScanFirst * SymbolSepar) & WindowLenMask, i = 0; i < ScanLen; i++) {
|
||||
SyncPhCorr[i].re = FFT.Twiddle[c].re * FFT.Twiddle[c].re -
|
||||
SyncPhCorr[i].re = FFT.Twiddle[c].re * FFT.Twiddle[c].re -
|
||||
FFT.Twiddle[c].im * FFT.Twiddle[c].im;
|
||||
SyncPhCorr[i].im = 2 * FFT.Twiddle[c].re * FFT.Twiddle[c].im;
|
||||
c = (c + SymbolSepar) & WindowLenMask;
|
||||
|
@ -915,7 +916,7 @@ int MT63rx::Preset(int BandWidth, int LongInterleave, int Integ,
|
|||
if (dspRedspAllocArray(&DatadspPhase, DataScanLen)) goto Error;
|
||||
if (dspRedspAllocArray(&DatadspPhase2, DataScanLen)) goto Error;
|
||||
|
||||
err = Decoder.Preset(DataCarriers, DataInterleave,
|
||||
err = Decoder.Preset(DataCarriers, DataInterleave,
|
||||
InterleavePattern, DataScanMargin, IntegLen);
|
||||
if (err) goto Error;
|
||||
|
||||
|
@ -935,7 +936,7 @@ Error:
|
|||
}
|
||||
|
||||
int MT63rx::Process(double_buff *Input)
|
||||
{
|
||||
{
|
||||
int s1,s2;
|
||||
|
||||
// TestOfs.Omega+=(-0.005*(2.0*M_PI/512)); // simulate frequency drift
|
||||
|
@ -955,7 +956,7 @@ int MT63rx::Process(double_buff *Input)
|
|||
// printf("SyncSymbConf=%5.2f, SyncLock=%d, SyncProcPtr=%d, SyncPtr=%d, SymbPtr=%d, SyncSymbShift=%5.1f, SyncFreqOfs=%5.2f =>",
|
||||
// SyncSymbConf,SyncLocked,SyncProcPtr,SyncPtr,SymbPtr,SyncSymbShift,SyncFreqOfs);
|
||||
if (SyncPtr == SymbPtr) {
|
||||
s1 = SyncProcPtr - ProcdspDelay +
|
||||
s1 = SyncProcPtr - ProcdspDelay +
|
||||
((int)SyncSymbShift - SymbPtr * SyncStep);
|
||||
s2 = s1 + SymbolSepar / 2;
|
||||
// printf(" SdspAmple at %d,%d (SyncProcPtr-%d), time diff.=%d\n",s1,s2,SyncProcPtr-s1,s1-DataProcPtr);
|
||||
|
@ -975,7 +976,7 @@ void MT63rx::DoCorrelSum(dspCmpx *Correl1, dspCmpx *Correl2, dspCmpx *Aver)
|
|||
{
|
||||
dspCmpx sx;
|
||||
int i, s, d;
|
||||
|
||||
|
||||
s = 2 * DataCarrSepar;
|
||||
d = DataCarriers * DataCarrSepar;
|
||||
sx.re = sx.im = 0.0;
|
||||
|
@ -1027,8 +1028,8 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
FFT.CoreProc(FFTbuff);
|
||||
|
||||
if (SpectraDisplay) {
|
||||
for ( i = 0,
|
||||
j = FirstDataCarr + (DataCarriers / 2) * DataCarrSepar -
|
||||
for ( i = 0,
|
||||
j = FirstDataCarr + (DataCarriers / 2) * DataCarrSepar -
|
||||
WindowLen / 2;
|
||||
(i < WindowLen) && ( j <WindowLen); i++,j++)
|
||||
SpectradspPower[i] = dspPower(FFTbuff[j]);
|
||||
|
@ -1049,11 +1050,11 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
if (P > 0.0) {
|
||||
dI = (I * I - Q * Q) / A;
|
||||
dQ = (2 * I * Q) / A;
|
||||
} else {
|
||||
} else {
|
||||
dI = dQ = 0.0;
|
||||
}
|
||||
dspLowPass2(P, dspPowerMid[i], dspPowerOut[i], W1p, W2p, W5p);
|
||||
pI = PrevSlice[i].re * SyncPhCorr[i].re -
|
||||
pI = PrevSlice[i].re * SyncPhCorr[i].re -
|
||||
PrevSlice[i].im * SyncPhCorr[i].im;
|
||||
pQ = PrevSlice[i].re * SyncPhCorr[i].im +
|
||||
PrevSlice[i].im * SyncPhCorr[i].re;
|
||||
|
@ -1070,8 +1071,8 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
for (i = 0; i < ScanLen; i++) {
|
||||
if (dspPowerOut[i] > 0.0) {
|
||||
CorrelNorm[s][i].re = CorrelOut[s][i].re / dspPowerOut[i];
|
||||
CorrelNorm[s][i].im = CorrelOut[s][i].im / dspPowerOut[i];
|
||||
} else
|
||||
CorrelNorm[s][i].im = CorrelOut[s][i].im / dspPowerOut[i];
|
||||
} else
|
||||
CorrelNorm[s][i].im = CorrelNorm[s][i].re = 0.0;
|
||||
}
|
||||
}
|
||||
|
@ -1087,11 +1088,11 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
CorrelNorm[s][i].im=CorrelOut[s][i].im/P; }
|
||||
} else
|
||||
{ for (s=0; s<SymbolDiv; s++)
|
||||
CorrelNorm[s][i].re=CorrelNorm[s][i].im=0.0; }
|
||||
CorrelNorm[s][i].re=CorrelNorm[s][i].im=0.0; }
|
||||
}
|
||||
*/
|
||||
// make a sum for each possible carrier positions
|
||||
for (s = 0; s < SymbolDiv; s++) {
|
||||
for (s = 0; s < SymbolDiv; s++) {
|
||||
s2 = (s + SymbolDiv / 2) & (SymbolDiv - 1);
|
||||
for (k = 0; k < 2 * DataCarrSepar; k++)
|
||||
DoCorrelSum( CorrelNorm[s] + k,
|
||||
|
@ -1100,9 +1101,9 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
}
|
||||
// symbol-shift dspPhase fitting
|
||||
for (i = 0; i < FitLen; i++) {
|
||||
SymbFit[i].re = dspAmpl(CorrelAver[0][i]) -
|
||||
SymbFit[i].re = dspAmpl(CorrelAver[0][i]) -
|
||||
dspAmpl(CorrelAver[2][i]);
|
||||
SymbFit[i].im = dspAmpl(CorrelAver[1][i]) -
|
||||
SymbFit[i].im = dspAmpl(CorrelAver[1][i]) -
|
||||
dspAmpl(CorrelAver[3][i]);
|
||||
}
|
||||
|
||||
|
@ -1112,13 +1113,13 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
// printf("[%2d,%2d]",j,SymbFitPos);
|
||||
k = (j - SymbFitPos) / DataCarrSepar;
|
||||
if (k > 1)
|
||||
j -= (k - 1) * DataCarrSepar;
|
||||
else if (k < (-1))
|
||||
j -= (k - 1) * DataCarrSepar;
|
||||
else if (k < (-1))
|
||||
j -= (k + 1) * DataCarrSepar;
|
||||
SymbFitPos = j;
|
||||
// printf(" => %2d",j);
|
||||
if (P > 0.0) {
|
||||
SymbConf = dspAmpl(SymbFit[j]) +
|
||||
SymbConf = dspAmpl(SymbFit[j]) +
|
||||
0.5 * (dspAmpl(SymbFit[j + 1]) + dspAmpl(SymbFit[j - 1]));
|
||||
SymbConf *= 0.5;
|
||||
I = SymbFit[j].re + 0.5 * (SymbFit[j - 1].re + SymbFit[j + 1].re);
|
||||
|
@ -1158,13 +1159,13 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
F0 = i + dspPhase(I, Q) / (2.0 * M_PI) * A - FreqOfs;
|
||||
Fl = F0 - A;
|
||||
Fu = F0 + A;
|
||||
if (fabs(Fl) < fabs(F0))
|
||||
if (fabs(Fl) < fabs(F0))
|
||||
FreqOfs += (fabs(Fu) < fabs(Fl)) ? Fu : Fl;
|
||||
else
|
||||
else
|
||||
FreqOfs += (fabs(Fu) < fabs(F0)) ? Fu : F0;
|
||||
// printf(" => (%5.2f,%5.2f,%5.2f) => %5.2f",Fl,F0,Fu,FreqOfs);
|
||||
|
||||
} else {
|
||||
} else {
|
||||
SymbTime.re = SymbTime.im = 0.0;
|
||||
SymbConf = 0.0;
|
||||
SymbShift = 0.0;
|
||||
|
@ -1211,16 +1212,16 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
F0 = FreqOfs - FreqPipe[TrackPipePtr];
|
||||
Fl = F0 - A;
|
||||
Fu = F0 + A;
|
||||
if (fabs(Fl) < fabs(F0))
|
||||
if (fabs(Fl) < fabs(F0))
|
||||
FreqOfs += (fabs(Fu) < fabs(Fl)) ? A : -A;
|
||||
else
|
||||
else
|
||||
FreqOfs += (fabs(Fu) < fabs(F0)) ? A : 0.0;
|
||||
}
|
||||
|
||||
// printf(" => [%+5.2f,%+5.2f], %5.2f",SymbTime.re,SymbTime.im,FreqOfs);
|
||||
|
||||
TrackPipePtr += 1;
|
||||
if (TrackPipePtr >= TrackPipeLen)
|
||||
if (TrackPipePtr >= TrackPipeLen)
|
||||
TrackPipePtr -= TrackPipeLen;
|
||||
SymbPipe[TrackPipePtr] = SymbTime; // put SymbTime and FreqOfs into pipes
|
||||
FreqPipe[TrackPipePtr] = FreqOfs; // for averaging
|
||||
|
@ -1251,7 +1252,7 @@ void MT63rx::SyncProcess(dspCmpx *Slice)
|
|||
SyncFreqOfs = AverFreq;
|
||||
if (SymbConf > 0.0) {
|
||||
SymbShift = dspPhase(AverSymb) / (2 * M_PI) * SymbolSepar;
|
||||
if (SymbShift < 0.0)
|
||||
if (SymbShift < 0.0)
|
||||
SymbShift += SymbolSepar;
|
||||
SymbPtr = (int)floor((dspPhase(AverSymb) / (2 * M_PI)) * SymbolDiv);
|
||||
if (SymbPtr < 0)
|
||||
|
@ -1353,12 +1354,12 @@ void MT63rx::DataProcess(dspCmpx *EvenSlice, dspCmpx *OddSlice, double FreqOfs,
|
|||
// printf("%3d,%2d: [%8.5f,%8.5f] / %8.5f\n",
|
||||
// c,i,FFTbuff[c].re,FFTbuff[c].im,DataPwrOut[i]);
|
||||
dspLowPass2( dspPower(FFTbuff[c]),
|
||||
DataPwrMid[i],
|
||||
DataPwrMid[i],
|
||||
DataPwrOut[i], dW1, dW2, dW5);
|
||||
RefDataSlice[i++] = FFTbuff[c];
|
||||
c = (c + DataCarrSepar) & WindowLenMask;
|
||||
p = (p + incr) & WindowLenMask;
|
||||
|
||||
|
||||
Phas = FFT.Twiddle[p];
|
||||
CdspcmpxMultAxB(Dtmp, RefDataSlice[i], Phas);
|
||||
CdspcmpxMultAxBs(DataVect[i], FFTbuff2[c], Dtmp);
|
||||
|
@ -1374,7 +1375,7 @@ void MT63rx::DataProcess(dspCmpx *EvenSlice, dspCmpx *OddSlice, double FreqOfs,
|
|||
|
||||
P = (-TimeDist * 2 * M_PI * FreqOfs) / WindowLen;
|
||||
Freq.re = cos(P);
|
||||
Freq.im = sin(P);
|
||||
Freq.im = sin(P);
|
||||
for (i = 0; i < DataScanLen; i++) {
|
||||
CdspcmpxMultAxB(Ftmp, DataVect[i], Freq);
|
||||
// dspLowPass2(dspPower(Ftmp),DataPwrMid[i],DataPwrOut[i],dW1,dW2,dW5);
|
||||
|
@ -1391,12 +1392,12 @@ void MT63rx::DataProcess(dspCmpx *EvenSlice, dspCmpx *OddSlice, double FreqOfs,
|
|||
for (i = 0; i < DataScanLen; i++) {
|
||||
if (DataPwrOut[i] > 0.0) {
|
||||
P = DataVect[i].re / DataPwrOut[i];
|
||||
if (P > 1.0)
|
||||
P = 1.0;
|
||||
else if (P < (-1.0))
|
||||
if (P > 1.0)
|
||||
P = 1.0;
|
||||
else if (P < (-1.0))
|
||||
P = (-1.0);
|
||||
DatadspPhase[i] = P;
|
||||
} else
|
||||
} else
|
||||
DatadspPhase[i] = 0.0;
|
||||
}
|
||||
Decoder.Process(DatadspPhase);
|
||||
|
@ -1429,7 +1430,7 @@ void MT63rx::DataProcess(dspCmpx *EvenSlice, dspCmpx *OddSlice, double FreqOfs,
|
|||
*/
|
||||
}
|
||||
|
||||
int MT63rx::SYNC_LockStatus(void) {
|
||||
int MT63rx::SYNC_LockStatus(void) {
|
||||
return SyncLocked;
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1459,7 @@ int MT63rx::FEC_CarrOffset(void) {
|
|||
}
|
||||
|
||||
double MT63rx::TotalFreqOffset(void) {
|
||||
return ( SyncFreqOfs + DataCarrSepar * Decoder.CarrOfs) *
|
||||
return ( SyncFreqOfs + DataCarrSepar * Decoder.CarrOfs) *
|
||||
(8000.0 / DecimateRatio) / WindowLen;
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue