kopia lustrzana https://github.com/jamescoxon/dl-fldigi
Upstream version 1.35J
rodzic
9621790078
commit
e37ebe13a4
|
@ -1,5 +1,14 @@
|
|||
Change Log:
|
||||
|
||||
1.35 1) Increased TxPPM to +/- 50000 to match the RxPPM range
|
||||
2) Changed all audio i/o to separate 2 channel control (stereo)
|
||||
3) Added right channel CW QRQ signal
|
||||
4) Added right channel pseudo FSK signal
|
||||
5) Added position and size of main dialog to state memory
|
||||
6) Added status and position of rig control dialog to state memory
|
||||
7) Added PSKmail tab and control to allow disabling the automatic
|
||||
return to the PSK sweet spot if running a mail server
|
||||
8) Added "Save To" menu item on received text popup menu.
|
||||
1.34 1) Cleaned up unused code segments
|
||||
2) Modified CW decoder to allow setting upper and lower limits on
|
||||
Tx WPM
|
||||
|
|
|
@ -43,6 +43,7 @@ void cw::tx_init(cSound *sc)
|
|||
scard = sc;
|
||||
phaseacc = 0;
|
||||
lastsym = 0;
|
||||
qrqphase = 0;
|
||||
}
|
||||
|
||||
void cw::rx_init()
|
||||
|
@ -62,6 +63,8 @@ void cw::init()
|
|||
trackingfilter->reset();
|
||||
cw_adaptive_receive_threshold = (long int)trackingfilter->run(2 * cw_send_dot_length);
|
||||
put_cwRcvWPM(cw_send_speed);
|
||||
for (int i = 0; i < OUTBUFSIZE; i++)
|
||||
outbuf[i] = qrqbuf[i] = 0.0;
|
||||
rx_init();
|
||||
}
|
||||
|
||||
|
@ -83,8 +86,8 @@ cw::cw() : morse(), modem()
|
|||
|
||||
mode = MODE_CW;
|
||||
freqlock = false;
|
||||
frequency = 800;
|
||||
tx_frequency = 800;
|
||||
frequency = progdefaults.CWsweetspot;
|
||||
tx_frequency = get_txfreq_woffset();
|
||||
risetime = progdefaults.CWrisetime;
|
||||
// keyshape = new double[KNUM];
|
||||
|
||||
|
@ -518,28 +521,51 @@ inline double cw::nco(double freq)
|
|||
return sin(phaseacc);
|
||||
}
|
||||
|
||||
inline double cw::qrqnco()
|
||||
{
|
||||
qrqphase += 2.0 * M_PI * 1600.0 / samplerate;
|
||||
|
||||
if (qrqphase > M_PI)
|
||||
qrqphase -= 2.0 * M_PI;
|
||||
|
||||
return sin(qrqphase);
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// send_symbol()
|
||||
// Sends a part of a morse character (one dot duration) of either
|
||||
// sound at the correct freq or silence. Rise and fall time is controlled
|
||||
// with a raised cosine shape.
|
||||
//
|
||||
// Left channel contains the shaped A2 CW waveform
|
||||
// Right channel contains a square wave burst of 1600 Hz that is used
|
||||
// to trigger a QRQ switch. Right channel has pre and post timings for
|
||||
// proper switching of the QRQ switch before and after the A2 element.
|
||||
// If the Pre + Post timing exceeds the interelement spacing then the
|
||||
// Pre and / or Post is only applied at the beginning and end of the
|
||||
// character.
|
||||
//=======================================================================
|
||||
|
||||
|
||||
void cw::send_symbol(int currsym)
|
||||
void cw::send_symbol(int bits)
|
||||
{
|
||||
double freq;
|
||||
int sample = 0, i;
|
||||
int delta = 0;
|
||||
int keydown;
|
||||
int keyup;
|
||||
int kpre;
|
||||
int kpost;
|
||||
int duration = 0;
|
||||
int symlen = 0;
|
||||
double dsymlen = 0.0;
|
||||
int currsym = bits & 1;
|
||||
|
||||
freq = get_txfreq_woffset();
|
||||
|
||||
freq = tx_frequency;
|
||||
|
||||
if ((currsym == 1) && (lastsym == 0)) phaseacc = 0.0;
|
||||
if ((currsym == 1) && (lastsym == 0)) {
|
||||
phaseacc = 0.0;
|
||||
// qrqphase = 0.0;
|
||||
}
|
||||
|
||||
if ((currsym == 1 && lastsym == 0) || (currsym == 0 && lastsym == 1))
|
||||
delta = (int) (symbollen * (progdefaults.CWweight - 50) / 100.0);
|
||||
|
@ -559,34 +585,78 @@ void cw::send_symbol(int currsym)
|
|||
|
||||
keydown = symlen - knum + delta;
|
||||
keyup = symlen - knum - delta;
|
||||
|
||||
if (currsym == 1) {
|
||||
|
||||
kpre = (int)(progdefaults.CWpre * 8);
|
||||
kpost = (int)(progdefaults.CWpost * 8);
|
||||
|
||||
if ( (kpre + kpost) > keyup) {
|
||||
kpre = keyup / 2;
|
||||
kpost = keyup - kpre;
|
||||
}
|
||||
if (bits == 4) {
|
||||
kpost = (int)(progdefaults.CWpost * 8);
|
||||
if (kpost > keyup)
|
||||
kpost = keyup;
|
||||
}
|
||||
if (firstelement) {
|
||||
kpre = (int)(progdefaults.CWpre * 8);
|
||||
kpost = 0;
|
||||
if (kpre > keydown)
|
||||
kpre = keydown;
|
||||
}
|
||||
|
||||
if (currsym == 1) { // keydown
|
||||
for (i = 0; i < knum; i++, sample++) {
|
||||
if (lastsym == 0)
|
||||
outbuf[sample] = nco(freq) * keyshape[i];
|
||||
else
|
||||
outbuf[sample] = nco(freq);
|
||||
qrqbuf[sample] = qrqnco();
|
||||
}
|
||||
for (i = 0; i < keydown; i++, sample++) {
|
||||
outbuf[sample] = nco(freq);
|
||||
qrqbuf[sample] = qrqnco();
|
||||
}
|
||||
duration = knum + keydown;
|
||||
} else {
|
||||
}
|
||||
else { // keyup
|
||||
for (i = knum - 1; i >= 0; i--, sample++) {
|
||||
if (lastsym == 1)
|
||||
if (lastsym == 1) {
|
||||
outbuf[sample] = nco(freq) * keyshape[i];
|
||||
else
|
||||
} else {
|
||||
outbuf[sample] = 0.0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < keyup; i++, sample++) {
|
||||
outbuf[sample] = 0.0;
|
||||
}
|
||||
|
||||
sample -= (knum + keyup);
|
||||
|
||||
for (i = 0; i < knum + kpost ; i++, sample++) {
|
||||
if (bits > 2 && lastsym == 1)
|
||||
qrqbuf[sample] = qrqnco();
|
||||
else
|
||||
qrqbuf[sample] = 0.0;
|
||||
}
|
||||
for (i = 0; i < (keyup - kpre - kpost); i++, sample++)
|
||||
qrqbuf[sample] = 0.0;
|
||||
for (i = 0; i < kpre; i++, sample++)
|
||||
if (bits > 4)
|
||||
qrqbuf[sample] = qrqnco();
|
||||
else
|
||||
qrqbuf[sample] = 0.0;
|
||||
|
||||
duration = knum + keyup;
|
||||
}
|
||||
|
||||
ModulateXmtr(outbuf, duration);
|
||||
if (progdefaults.QSK)
|
||||
ModulateStereo(outbuf, qrqbuf, duration);
|
||||
else
|
||||
ModulateXmtr(outbuf, duration);
|
||||
|
||||
lastsym = currsym;
|
||||
firstelement = false;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
|
@ -603,32 +673,32 @@ void cw::send_ch(int ch)
|
|||
// last char already had 2 elements of inter-character spacing
|
||||
|
||||
if ((ch == ' ') || (ch == '\n')) {
|
||||
// cout << " ";
|
||||
firstelement = false;
|
||||
send_symbol(0);
|
||||
send_symbol(0);
|
||||
send_symbol(0);
|
||||
send_symbol(0);
|
||||
send_symbol(0);
|
||||
put_echo_char(ch);
|
||||
// cout << endl; cout.flush();
|
||||
return;
|
||||
}
|
||||
|
||||
// convert character code to a morse representation
|
||||
if ((ch < 256) && (ch >= 0))
|
||||
if ((ch < 256) && (ch >= 0)) {
|
||||
code = tx_lookup(ch); //cw_tx_lookup(ch);
|
||||
else
|
||||
firstelement = true;
|
||||
} else {
|
||||
code = 0x04; // two extra dot spaces
|
||||
firstelement = false;
|
||||
}
|
||||
|
||||
// loop sending out binary bits of cw character
|
||||
|
||||
// cout << (char) ch << " " << progdefaults.CWdash2dot << " === ";
|
||||
|
||||
while (code > 1) {
|
||||
send_symbol(code & 1);
|
||||
send_symbol(code);// & 1);
|
||||
code = code >> 1;
|
||||
Fl::awake();
|
||||
}
|
||||
// cout << endl; cout.flush();
|
||||
|
||||
if (ch != 0)
|
||||
put_echo_char(ch);
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ void rtty::rx_init()
|
|||
rxstate = RTTY_RX_STATE_IDLE;
|
||||
rxmode = LETTERS;
|
||||
phaseacc = 0;
|
||||
FSKphaseacc = 0;
|
||||
for (int i = 0; i < RTTYMaxSymLen; i++ ) {
|
||||
bbfilter[i] = 0.0;
|
||||
}
|
||||
|
@ -117,12 +118,10 @@ void rtty::restart()
|
|||
case 4 : rtty_parity = PARITY_ONE; break;
|
||||
default : rtty_parity = PARITY_NONE; break;
|
||||
}
|
||||
msb = progdefaults.rtty_msbfirst;
|
||||
rtty_stop = progdefaults.rtty_stop;
|
||||
|
||||
txmode = LETTERS;
|
||||
rxmode = LETTERS;
|
||||
msb = chkMsbFirst->value();
|
||||
symbollen = (int) (samplerate / rtty_baud + 0.5);
|
||||
set_bandwidth(shift);
|
||||
|
||||
|
@ -273,9 +272,6 @@ int rtty::decode_char()
|
|||
|
||||
data = rxdata & ((1 << nbits) - 1);
|
||||
|
||||
if (msb)
|
||||
data = bitreverse(data, nbits);
|
||||
|
||||
if (nbits == 5)
|
||||
return baudot_dec(data);
|
||||
|
||||
|
@ -543,14 +539,23 @@ double rtty::nco(double freq)
|
|||
{
|
||||
phaseacc += twopi * freq / samplerate;
|
||||
|
||||
// if (freq == 0.0)
|
||||
// return 0.0;
|
||||
if (phaseacc > M_PI)
|
||||
phaseacc -= twopi;
|
||||
|
||||
return cos(phaseacc);
|
||||
}
|
||||
|
||||
double rtty::FSKnco()
|
||||
{
|
||||
FSKphaseacc += twopi * 1600 / samplerate;
|
||||
|
||||
if (FSKphaseacc > M_PI)
|
||||
FSKphaseacc -= twopi;
|
||||
|
||||
return sin(FSKphaseacc);
|
||||
|
||||
}
|
||||
|
||||
void rtty::send_symbol(int symbol)
|
||||
{
|
||||
double freq;
|
||||
|
@ -561,13 +566,21 @@ void rtty::send_symbol(int symbol)
|
|||
symbol = !symbol;
|
||||
|
||||
if (symbol)
|
||||
freq = tx_frequency + shift / 2.0;
|
||||
freq = get_txfreq_woffset() + shift / 2.0;
|
||||
else
|
||||
freq = tx_frequency - shift / 2.0;
|
||||
for (int i = 0; i < symbollen; i++)
|
||||
freq = get_txfreq_woffset() - shift / 2.0;
|
||||
for (int i = 0; i < symbollen; i++) {
|
||||
outbuf[i] = nco(freq);
|
||||
if (symbol)
|
||||
FSKbuf[i] = FSKnco();
|
||||
else
|
||||
FSKbuf[i] = 0.0;
|
||||
}
|
||||
|
||||
ModulateXmtr(outbuf, symbollen);
|
||||
if (progdefaults.PseudoFSK)
|
||||
ModulateStereo(outbuf, FSKbuf, symbollen);
|
||||
else
|
||||
ModulateXmtr(outbuf, symbollen);
|
||||
}
|
||||
|
||||
void rtty::send_stop()
|
||||
|
@ -578,19 +591,26 @@ void rtty::send_stop()
|
|||
invert = !invert;
|
||||
|
||||
if (invert)
|
||||
freq = tx_frequency - shift / 2.0;
|
||||
freq = get_txfreq_woffset() - shift / 2.0;
|
||||
else
|
||||
freq = tx_frequency + shift / 2.0;
|
||||
freq = get_txfreq_woffset() + shift / 2.0;
|
||||
|
||||
for (int i = 0; i < stoplen; i++)
|
||||
for (int i = 0; i < stoplen; i++) {
|
||||
outbuf[i] = nco(freq);
|
||||
|
||||
ModulateXmtr(outbuf, stoplen);
|
||||
if (invert)
|
||||
FSKbuf[i] = FSKnco();
|
||||
else
|
||||
FSKbuf[i] = 0.0;
|
||||
}
|
||||
if (progdefaults.PseudoFSK)
|
||||
ModulateStereo(outbuf, FSKbuf, stoplen);
|
||||
else
|
||||
ModulateXmtr(outbuf, stoplen);
|
||||
}
|
||||
|
||||
void rtty::send_char(int c)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
if (nbits == 5) {
|
||||
if (c == LETTERS)
|
||||
|
@ -602,8 +622,7 @@ void rtty::send_char(int c)
|
|||
send_symbol(0);
|
||||
// data bits
|
||||
for (i = 0; i < nbits; i++) {
|
||||
j = (msb) ? (nbits - 1 - i) : i;
|
||||
send_symbol((c >> j) & 1);
|
||||
send_symbol((c >> i) & 1);
|
||||
}
|
||||
// parity bit
|
||||
if (rtty_parity != PARITY_NONE)
|
||||
|
|
|
@ -469,6 +469,13 @@ static void cb_cntTxRateCorr(Fl_Spinner* o, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Spinner *cntTxOffset=(Fl_Spinner *)0;
|
||||
|
||||
static void cb_cntTxOffset(Fl_Spinner* o, void*) {
|
||||
progdefaults.TxOffset = (int)o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Value_Input *valCWsweetspot=(Fl_Value_Input *)0;
|
||||
|
||||
static void cb_valCWsweetspot(Fl_Value_Input* o, void*) {
|
||||
|
@ -543,6 +550,8 @@ Fl_Value_Slider *sldrCWxmtWPM=(Fl_Value_Slider *)0;
|
|||
|
||||
static void cb_sldrCWxmtWPM(Fl_Value_Slider* o, void*) {
|
||||
progdefaults.CWspeed = (int)o->value();
|
||||
cntPreTiming->maximum((int)(2400/o->value())/2.0);
|
||||
cntPostTiming->maximum((int)(2400/o->value())/2.0);
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
|
@ -596,6 +605,29 @@ static void cb_cntCWdefWPM(Fl_Counter* o, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Group *tabCWQSK=(Fl_Group *)0;
|
||||
|
||||
Fl_Check_Button *btnQSK=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnQSK(Fl_Check_Button* o, void*) {
|
||||
progdefaults.QSK=o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Counter *cntPreTiming=(Fl_Counter *)0;
|
||||
|
||||
static void cb_cntPreTiming(Fl_Counter* o, void*) {
|
||||
progdefaults.CWpre=o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Counter *cntPostTiming=(Fl_Counter *)0;
|
||||
|
||||
static void cb_cntPostTiming(Fl_Counter* o, void*) {
|
||||
progdefaults.CWpost=o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Group *tabDomEX=(Fl_Group *)0;
|
||||
|
||||
Fl_Input *txtSecondary=(Fl_Input *)0;
|
||||
|
@ -702,6 +734,12 @@ resetOLIVIA();
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *btnPSKmailSweetSpot=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_btnPSKmailSweetSpot(Fl_Check_Button* o, void*) {
|
||||
progdefaults.PSKmailSweetSpot = o->value();
|
||||
}
|
||||
|
||||
Fl_Group *tabRTTY=(Fl_Group *)0;
|
||||
|
||||
Fl_Choice *selShift=(Fl_Choice *)0;
|
||||
|
@ -734,10 +772,11 @@ static void cb_selStopBits(Fl_Choice*, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *chkMsbFirst=(Fl_Check_Button *)0;
|
||||
Fl_Check_Button *chkPseudoFSK=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_chkMsbFirst(Fl_Check_Button*, void*) {
|
||||
progdefaults.changed = true;
|
||||
static void cb_chkPseudoFSK(Fl_Check_Button* o, void*) {
|
||||
progdefaults.PseudoFSK = o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Button *btnRestartRtty=(Fl_Button *)0;
|
||||
|
@ -1109,7 +1148,6 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
{ Fl_Group* o = tabSoundCard = new Fl_Group(0, 25, 400, 195, "SndCrd");
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)51);
|
||||
o->hide();
|
||||
{ Fl_Group* o = new Fl_Group(0, 27, 400, 190);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
{ Fl_Group* o = new Fl_Group(5, 35, 395, 115, "Mixer");
|
||||
|
@ -1160,11 +1198,18 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
{ Fl_Spinner* o = cntTxRateCorr = new Fl_Spinner(294, 185, 75, 24, "TX ppm:");
|
||||
o->callback((Fl_Callback*)cb_cntTxRateCorr);
|
||||
o->step(1);
|
||||
o->minimum(-5000);
|
||||
o->maximum(5000);
|
||||
o->minimum(-50000);
|
||||
o->maximum(50000);
|
||||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Spinner* o = cntTxOffset = new Fl_Spinner(172, 185, 45, 24, "Tx offset:");
|
||||
o->callback((Fl_Callback*)cb_cntTxOffset);
|
||||
o->value(progdefaults.TxOffset);
|
||||
o->step(1);
|
||||
o->minimum(-50);
|
||||
o->maximum(50);
|
||||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Group* o = new Fl_Group(0, 25, 400, 195, "Misc");
|
||||
|
@ -1215,6 +1260,7 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
{ Fl_Group* o = tabModems = new Fl_Group(0, 25, 401, 195, "Modems");
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)51);
|
||||
o->hide();
|
||||
{ Fl_Tabs* o = tabsModems = new Fl_Tabs(0, 25, 401, 195);
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)10);
|
||||
|
@ -1222,6 +1268,7 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
{ Fl_Group* o = tabCW = new Fl_Group(0, 50, 400, 170, "CW");
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)51);
|
||||
o->hide();
|
||||
{ Fl_Group* o = new Fl_Group(1, 60, 398, 155);
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
{ Fl_Value_Slider* o = sldrCWbandwidth = new Fl_Value_Slider(65, 65, 325, 20, "BW");
|
||||
|
@ -1338,6 +1385,35 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Group* o = tabCWQSK = new Fl_Group(0, 50, 400, 170, "QSK");
|
||||
o->hide();
|
||||
{ Fl_Check_Button* o = btnQSK = new Fl_Check_Button(35, 75, 175, 15, "QSK on right channel");
|
||||
o->down_box(FL_DOWN_BOX);
|
||||
o->callback((Fl_Callback*)cb_btnQSK);
|
||||
o->value(progdefaults.QSK);
|
||||
}
|
||||
{ Fl_Counter* o = cntPreTiming = new Fl_Counter(25, 109, 64, 21, "Pre Timing");
|
||||
o->type(1);
|
||||
o->minimum(0);
|
||||
o->maximum(50);
|
||||
o->step(0.5);
|
||||
o->value(4);
|
||||
o->callback((Fl_Callback*)cb_cntPreTiming);
|
||||
o->value(progdefaults.CWpre);
|
||||
o->maximum((int)(2400/progdefaults.CWspeed)/2.0);
|
||||
}
|
||||
{ Fl_Counter* o = cntPostTiming = new Fl_Counter(125, 109, 64, 21, "Post Timing");
|
||||
o->type(1);
|
||||
o->minimum(0);
|
||||
o->maximum(50);
|
||||
o->step(0.5);
|
||||
o->value(4);
|
||||
o->callback((Fl_Callback*)cb_cntPostTiming);
|
||||
o->value(progdefaults.CWpre);
|
||||
o->maximum((int)(2400/progdefaults.CWspeed)/2.0);
|
||||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Group* o = tabDomEX = new Fl_Group(0, 50, 401, 170, "DomEX");
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)51);
|
||||
|
@ -1441,6 +1517,15 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Group* o = new Fl_Group(0, 50, 400, 170, "PSKmail");
|
||||
{ Fl_Check_Button* o = btnPSKmailSweetSpot = new Fl_Check_Button(25, 75, 155, 15, "use PSK sweetspot");
|
||||
o->down_box(FL_DOWN_BOX);
|
||||
o->value(1);
|
||||
o->callback((Fl_Callback*)cb_btnPSKmailSweetSpot);
|
||||
o->value(progdefaults.PSKmailSweetSpot);
|
||||
}
|
||||
o->end();
|
||||
}
|
||||
{ Fl_Group* o = tabRTTY = new Fl_Group(0, 50, 400, 170, "RTTY");
|
||||
o->color((Fl_Color)51);
|
||||
o->selection_color((Fl_Color)51);
|
||||
|
@ -1470,24 +1555,24 @@ static char *szBaudRates = "300|600|1200|2400|4800|9600|19200|38400|57600|115200
|
|||
o->callback((Fl_Callback*)cb_selStopBits);
|
||||
o->add(szStopBits);
|
||||
}
|
||||
{ Fl_Check_Button* o = chkMsbFirst = new Fl_Check_Button(15, 126, 120, 24, "Send msb first");
|
||||
{ Fl_Check_Button* o = chkPseudoFSK = new Fl_Check_Button(15, 126, 120, 24, "PseudoFSK");
|
||||
o->down_box(FL_DOWN_BOX);
|
||||
o->callback((Fl_Callback*)cb_chkMsbFirst);
|
||||
o->hide();
|
||||
o->callback((Fl_Callback*)cb_chkPseudoFSK);
|
||||
o->value(progdefaults.PseudoFSK);
|
||||
}
|
||||
{ Fl_Button* o = btnRestartRtty = new Fl_Button(300, 180, 79, 28, "Restart");
|
||||
o->callback((Fl_Callback*)cb_btnRestartRtty);
|
||||
}
|
||||
{ Fl_Check_Button* o = btnCRCRLF = new Fl_Check_Button(16, 155, 115, 15, "CR-CR-LF");
|
||||
{ Fl_Check_Button* o = btnCRCRLF = new Fl_Check_Button(15, 155, 115, 15, "CR-CR-LF");
|
||||
o->down_box(FL_DOWN_BOX);
|
||||
o->callback((Fl_Callback*)cb_btnCRCRLF);
|
||||
o->when(FL_WHEN_RELEASE_ALWAYS);
|
||||
}
|
||||
{ Fl_Check_Button* o = btnAUTOCRLF = new Fl_Check_Button(16, 184, 125, 15, "AutoCRLF");
|
||||
{ Fl_Check_Button* o = btnAUTOCRLF = new Fl_Check_Button(15, 184, 125, 15, "AutoCRLF");
|
||||
o->down_box(FL_DOWN_BOX);
|
||||
o->callback((Fl_Callback*)cb_btnAUTOCRLF);
|
||||
}
|
||||
{ Fl_Counter* o = cntrAUTOCRLF = new Fl_Counter(142, 181, 65, 20, "after:");
|
||||
{ Fl_Counter* o = cntrAUTOCRLF = new Fl_Counter(150, 181, 65, 20, "after:");
|
||||
o->type(1);
|
||||
o->minimum(68);
|
||||
o->maximum(80);
|
||||
|
|
|
@ -461,7 +461,7 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group tabSoundCard {
|
||||
label SndCrd open
|
||||
xywh {0 25 400 195} color 51 selection_color 51 hide
|
||||
xywh {0 25 400 195} color 51 selection_color 51
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {0 27 400 190} align 21
|
||||
|
@ -549,10 +549,20 @@ progdefaults.changed = true;}
|
|||
progdefaults.changed = true;}
|
||||
xywh {294 185 75 24}
|
||||
code0 {o->step(1);}
|
||||
code1 {o->minimum(-5000);}
|
||||
code2 {o->maximum(5000);}
|
||||
code1 {o->minimum(-50000);}
|
||||
code2 {o->maximum(50000);}
|
||||
}
|
||||
}
|
||||
Fl_Spinner cntTxOffset {
|
||||
label {Tx offset:}
|
||||
callback {progdefaults.TxOffset = (int)o->value();
|
||||
progdefaults.changed = true;} selected
|
||||
xywh {172 185 45 24}
|
||||
code0 {o->value(progdefaults.TxOffset);}
|
||||
code1 {o->step(1);}
|
||||
code2 {o->minimum(-50);}
|
||||
code3 {o->maximum(50);}
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label Misc open
|
||||
|
@ -600,14 +610,14 @@ progdefaults.changed = true;}
|
|||
}
|
||||
Fl_Group tabModems {
|
||||
label Modems open
|
||||
xywh {0 25 401 195} color 51 selection_color 51
|
||||
xywh {0 25 401 195} color 51 selection_color 51 hide
|
||||
} {
|
||||
Fl_Tabs tabsModems {open
|
||||
xywh {0 25 401 195} color 51 selection_color 10 align 9
|
||||
} {
|
||||
Fl_Group tabCW {
|
||||
label CW open
|
||||
xywh {0 50 400 170} color 51 selection_color 51
|
||||
xywh {0 50 400 170} color 51 selection_color 51 hide
|
||||
} {
|
||||
Fl_Group {} {open
|
||||
xywh {1 60 398 155} box ENGRAVED_FRAME
|
||||
|
@ -644,6 +654,8 @@ progdefaults.changed = true;}
|
|||
Fl_Value_Slider sldrCWxmtWPM {
|
||||
label TxWPM
|
||||
callback {progdefaults.CWspeed = (int)o->value();
|
||||
cntPreTiming->maximum((int)(2400/o->value())/2.0);
|
||||
cntPostTiming->maximum((int)(2400/o->value())/2.0);
|
||||
progdefaults.changed = true;}
|
||||
xywh {65 135 325 20} type {Horz Knob} color 215 align 4 minimum 5 maximum 100 step 1 value 20 textsize 14
|
||||
code0 {o->value(progdefaults.CWspeed);}
|
||||
|
@ -694,12 +706,40 @@ progdefaults.changed = true;}
|
|||
Fl_Counter cntCWdefWPM {
|
||||
label Default
|
||||
callback {progdefaults.defCWspeed = (int)o->value();
|
||||
progdefaults.changed = true;} selected
|
||||
progdefaults.changed = true;}
|
||||
xywh {65 160 64 21} type Simple align 4 minimum 5 maximum 200 step 1 value 18
|
||||
code0 {o->value(progdefaults.defCWspeed);}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabCWQSK {
|
||||
label QSK open
|
||||
xywh {0 50 400 170} hide
|
||||
} {
|
||||
Fl_Check_Button btnQSK {
|
||||
label {QSK on right channel}
|
||||
callback {progdefaults.QSK=o->value();
|
||||
progdefaults.changed = true;}
|
||||
xywh {35 75 175 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.QSK);}
|
||||
}
|
||||
Fl_Counter cntPreTiming {
|
||||
label {Pre Timing}
|
||||
callback {progdefaults.CWpre=o->value();
|
||||
progdefaults.changed = true;}
|
||||
xywh {25 109 64 21} type Simple minimum 0 maximum 50 step 0.5 value 4
|
||||
code0 {o->value(progdefaults.CWpre);}
|
||||
code1 {o->maximum((int)(2400/progdefaults.CWspeed)/2.0);}
|
||||
}
|
||||
Fl_Counter cntPostTiming {
|
||||
label {Post Timing}
|
||||
callback {progdefaults.CWpost=o->value();
|
||||
progdefaults.changed = true;}
|
||||
xywh {125 109 64 21} type Simple minimum 0 maximum 50 step 0.5 value 4
|
||||
code0 {o->value(progdefaults.CWpre);}
|
||||
code1 {o->maximum((int)(2400/progdefaults.CWspeed)/2.0);}
|
||||
}
|
||||
}
|
||||
Fl_Group tabDomEX {
|
||||
label DomEX open
|
||||
xywh {0 50 401 170} color 51 selection_color 51 hide
|
||||
|
@ -817,6 +857,17 @@ progdefaults.changed = true;}
|
|||
xywh {300 172 79 28}
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label PSKmail open
|
||||
xywh {0 50 400 170}
|
||||
} {
|
||||
Fl_Check_Button btnPSKmailSweetSpot {
|
||||
label {use PSK sweetspot}
|
||||
callback {progdefaults.PSKmailSweetSpot = o->value();}
|
||||
xywh {25 75 155 15} down_box DOWN_BOX value 1
|
||||
code0 {o->value(progdefaults.PSKmailSweetSpot);}
|
||||
}
|
||||
}
|
||||
Fl_Group tabRTTY {
|
||||
label RTTY open
|
||||
xywh {0 50 400 170} color 51 selection_color 51 hide
|
||||
|
@ -851,10 +902,12 @@ progdefaults.changed = true;}
|
|||
xywh {179 122 77 24} down_box BORDER_BOX
|
||||
code0 {o->add(szStopBits);}
|
||||
} {}
|
||||
Fl_Check_Button chkMsbFirst {
|
||||
label {Send msb first}
|
||||
callback {progdefaults.changed = true;}
|
||||
xywh {15 126 120 24} down_box DOWN_BOX hide
|
||||
Fl_Check_Button chkPseudoFSK {
|
||||
label PseudoFSK
|
||||
callback {progdefaults.PseudoFSK = o->value();
|
||||
progdefaults.changed = true;}
|
||||
xywh {15 126 120 24} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.PseudoFSK);}
|
||||
}
|
||||
Fl_Button btnRestartRtty {
|
||||
label Restart
|
||||
|
@ -865,17 +918,17 @@ resetRTTY();}
|
|||
Fl_Check_Button btnCRCRLF {
|
||||
label {CR-CR-LF}
|
||||
callback {progdefaults.changed = true;}
|
||||
xywh {16 155 115 15} down_box DOWN_BOX when 6
|
||||
xywh {15 155 115 15} down_box DOWN_BOX when 6
|
||||
}
|
||||
Fl_Check_Button btnAUTOCRLF {
|
||||
label AutoCRLF
|
||||
callback {progdefaults.changed = true;}
|
||||
xywh {16 184 125 15} down_box DOWN_BOX
|
||||
xywh {15 184 125 15} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Counter cntrAUTOCRLF {
|
||||
label {after:}
|
||||
callback {progdefaults.changed = true;}
|
||||
xywh {142 181 65 20} type Simple align 4 minimum 68 maximum 80 step 1 value 72
|
||||
xywh {150 181 65 20} type Simple align 4 minimum 68 maximum 80 step 1 value 72
|
||||
}
|
||||
Fl_Check_Button btnRTTY_USB {
|
||||
label {RTTY is USB}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
// generated by Fast Light User Interface Designer (fluid) version 1.0107
|
||||
|
||||
#ifndef Config_h
|
||||
#define Config_h
|
||||
#include <FL/Fl.H>
|
||||
#include "globals.h"
|
||||
#include "modem.h"
|
||||
#include "configuration.h"
|
||||
extern Fl_Double_Window *dlgConfig;
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Tabs.H>
|
||||
extern Fl_Tabs *tabsConfigure;
|
||||
#include <FL/Fl_Group.H>
|
||||
extern Fl_Group *tabOperator;
|
||||
#include <FL/Fl_Input.H>
|
||||
extern Fl_Input *inpMyCallsign;
|
||||
extern Fl_Input *inpMyName;
|
||||
extern Fl_Input *inpMyQth;
|
||||
extern Fl_Input *inpMyLocator;
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
extern Fl_Check_Button *btnUseLeadingZeros;
|
||||
#include <FL/Fl_Value_Input.H>
|
||||
extern Fl_Value_Input *nbrContestStart;
|
||||
extern Fl_Value_Input *nbrContestDigits;
|
||||
extern Fl_Group *tabWaterfall;
|
||||
extern Fl_Check_Button *btnBlackman;
|
||||
extern Fl_Check_Button *btnHamming;
|
||||
extern Fl_Check_Button *btnHanning;
|
||||
extern Fl_Check_Button *btnTriangular;
|
||||
extern Fl_Check_Button *btnUseCursorLines;
|
||||
extern Fl_Check_Button *btnUseBWTracks;
|
||||
extern Fl_Check_Button *btnUseCursorCenterLine;
|
||||
extern Fl_Check_Button *btnViewXmtSignal;
|
||||
#include "colorbox.h"
|
||||
extern colorbox *Palette;
|
||||
#include <FL/Fl_Button.H>
|
||||
extern Fl_Button *btnColor[9];
|
||||
extern Fl_Button *btnLoadPalette;
|
||||
extern Fl_Button *btnSavePalette;
|
||||
extern Fl_Group *tabInterface;
|
||||
#include <FL/Fl_Round_Button.H>
|
||||
extern Fl_Input *inpTTYdev;
|
||||
extern Fl_Round_Button *btnRTSptt;
|
||||
extern Fl_Round_Button *btnDTRptt;
|
||||
extern Fl_Round_Button *btnRTSplusV;
|
||||
extern Fl_Round_Button *btnDTRplusV;
|
||||
#include <FL/Fl_Box.H>
|
||||
extern Fl_Round_Button *btnPTT[5];
|
||||
extern Fl_Check_Button *chkUSEHAMLIB;
|
||||
extern Fl_Check_Button *chkUSEMEMMAP;
|
||||
extern Fl_ComboBox *cboHamlibRig;
|
||||
extern Fl_Input *inpRIGdev;
|
||||
#include <FL/Fl_Choice.H>
|
||||
extern Fl_Choice *mnuBaudRate;
|
||||
extern Fl_Check_Button *chkUSERIGCAT;
|
||||
extern Fl_Button *btnInit_Interface;
|
||||
extern Fl_Check_Button *btnQRZnotavailable;
|
||||
extern Fl_Check_Button *btnQRZsocket;
|
||||
extern Fl_Check_Button *btnQRZcdrom;
|
||||
extern Fl_Group *tabSoundCard;
|
||||
extern Fl_Round_Button *btnDsp[2];
|
||||
#include <FL/Fl_Light_Button.H>
|
||||
extern void setMixerInput(int);
|
||||
extern Fl_Light_Button *btnLineIn;
|
||||
extern Fl_Light_Button *btnMicIn;
|
||||
#include <FL/Fl_Value_Slider.H>
|
||||
extern void setPCMvolume(double);
|
||||
extern Fl_Value_Slider *valPCMvolume;
|
||||
#include <FL/Fl_Spinner.H>
|
||||
extern Fl_Spinner *cntRxRateCorr;
|
||||
extern Fl_Spinner *cntTxRateCorr;
|
||||
extern Fl_Spinner *cntTxOffset;
|
||||
extern Fl_Value_Input *valCWsweetspot;
|
||||
extern Fl_Value_Input *valRTTYsweetspot;
|
||||
extern Fl_Value_Input *valPSKsweetspot;
|
||||
extern Fl_Check_Button *btnStartAtSweetSpot;
|
||||
extern Fl_Check_Button *btnsendid;
|
||||
extern Fl_Group *tabModems;
|
||||
extern Fl_Tabs *tabsModems;
|
||||
extern Fl_Group *tabCW;
|
||||
extern Fl_Value_Slider *sldrCWbandwidth;
|
||||
#include <FL/Fl_Counter.H>
|
||||
extern Fl_Counter *cntCWrange;
|
||||
extern Fl_Check_Button *btnCWrcvTrack;
|
||||
#include <FL/Fl_Value_Output.H>
|
||||
extern Fl_Value_Output *valCWrcvWPM;
|
||||
#include <FL/Fl_Progress.H>
|
||||
extern Fl_Progress *prgsCWrcvWPM;
|
||||
extern Fl_Value_Slider *sldrCWxmtWPM;
|
||||
extern Fl_Counter *cntCWlowerlimit;
|
||||
extern Fl_Counter *cntCWupperlimit;
|
||||
extern Fl_Counter *cntCWweight;
|
||||
extern Fl_Counter *cntCWdash2dot;
|
||||
extern Fl_Counter *cntCWrisetime;
|
||||
extern Fl_Counter *cntCWdefWPM;
|
||||
extern Fl_Group *tabCWQSK;
|
||||
extern Fl_Check_Button *btnQSK;
|
||||
extern Fl_Counter *cntPreTiming;
|
||||
extern Fl_Counter *cntPostTiming;
|
||||
extern Fl_Group *tabDomEX;
|
||||
extern Fl_Input *txtSecondary;
|
||||
extern Fl_Button *btnRestartDomEX;
|
||||
extern Fl_Counter *valDominoEX_BW;
|
||||
extern Fl_Group *tabFeld;
|
||||
#include "fontdef.h"
|
||||
extern Fl_Choice *selHellFont;
|
||||
extern Fl_Value_Slider *sldrHellBW;
|
||||
extern Fl_Check_Button *btnHellXmtWidth;
|
||||
extern Fl_Check_Button *btnHellRcvWidth;
|
||||
extern Fl_Check_Button *btnBlackboard;
|
||||
extern Fl_Check_Button *btnHellFastAttack;
|
||||
extern Fl_Check_Button *btnHellSlowAttack;
|
||||
extern Fl_Check_Button *btnFeldHellIdle;
|
||||
extern Fl_Group *tabOlivia;
|
||||
extern Fl_Choice *mnuOlivia_Tones;
|
||||
extern Fl_Choice *mnuOlivia_Bandwidth;
|
||||
extern Fl_Button *btnRestartOlivia;
|
||||
extern Fl_Check_Button *btnPSKmailSweetSpot;
|
||||
extern Fl_Group *tabRTTY;
|
||||
extern Fl_Choice *selShift;
|
||||
extern Fl_Choice *selBaud;
|
||||
extern Fl_Choice *selBits;
|
||||
extern Fl_Choice *selParity;
|
||||
extern Fl_Choice *selStopBits;
|
||||
extern Fl_Check_Button *chkPseudoFSK;
|
||||
extern Fl_Button *btnRestartRtty;
|
||||
extern Fl_Check_Button *btnCRCRLF;
|
||||
extern Fl_Check_Button *btnAUTOCRLF;
|
||||
extern Fl_Counter *cntrAUTOCRLF;
|
||||
extern Fl_Check_Button *btnRTTY_USB;
|
||||
extern Fl_Round_Button *btnRTTYafc[3];
|
||||
extern Fl_Check_Button *btnPreferXhairScope;
|
||||
#include <FL/Fl_Return_Button.H>
|
||||
extern Fl_Return_Button *btnCloseConfig;
|
||||
extern Fl_Button *btnSaveConfig;
|
||||
Fl_Double_Window* ConfigureDialog();
|
||||
void openConfig();
|
||||
void closeDialog();
|
||||
void createConfig();
|
||||
#endif
|
|
@ -57,9 +57,6 @@ textview :: textview( int x, int y, int w, int h, const char *label )
|
|||
scrollbar->linesize( 1 );
|
||||
scrollbar->callback( _scrollbarCB, this );
|
||||
|
||||
mitems = 0;
|
||||
mpopup = (Fl_Menu_Button *)0;
|
||||
|
||||
box( FL_DOWN_BOX );
|
||||
color( FL_WHITE );
|
||||
|
||||
|
@ -473,29 +470,39 @@ void textview :: resize( int x, int y, int w, int h )
|
|||
// Viewer for received text
|
||||
// derived from Class textview
|
||||
//
|
||||
// redfines the handle() and menu_cb() functions specified in the
|
||||
// redefines the handle() and menu_cb() functions specified in the
|
||||
// base class. All other functions are in the base class
|
||||
//=====================================================================
|
||||
|
||||
void TextView::saveFile()
|
||||
{
|
||||
char * fn = File_Select(
|
||||
"Select ASCII text file",
|
||||
"*.txt",
|
||||
"", 0);
|
||||
if (fn) {
|
||||
ofstream out(fn);
|
||||
out << buff;
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
Fl_Menu_Item viewmenu[] = {
|
||||
{"divider", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"clear", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"Call", 0, 0 },
|
||||
{"Name", 0, 0 },
|
||||
{"Qth", 0, 0 },
|
||||
{"Loc", 0, 0 },
|
||||
{"RstIn", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"Save to", 0, 0 },
|
||||
{0}
|
||||
};
|
||||
int viewmenuNbr = 8;
|
||||
|
||||
TextView::TextView( int x, int y, int w, int h, const char *label )
|
||||
: textview ( x, y, w, h, label )
|
||||
{
|
||||
static Fl_Menu_Item menupopup[] = {
|
||||
{"Dismiss", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"divider", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"clear", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"Call", 0, _menu_cb, this},
|
||||
{"Name", 0, _menu_cb, this},
|
||||
{"Qth", 0, _menu_cb, this},
|
||||
{"Loc", 0, _menu_cb, this},
|
||||
{"RstIn", 0, _menu_cb, this},
|
||||
{0}
|
||||
};
|
||||
mitems = menupopup;
|
||||
|
||||
mpopup = new Fl_Menu_Button(-1, -1, -1, -1);
|
||||
mpopup->menu(mitems);
|
||||
mpopup->type(Fl_Menu_Button::POPUP1);
|
||||
cursorStyle = BLOCK_CURSOR;
|
||||
cursorON = true;
|
||||
wordwrap = true;
|
||||
|
@ -503,20 +510,32 @@ TextView::TextView( int x, int y, int w, int h, const char *label )
|
|||
|
||||
void TextView::menu_cb(int val)
|
||||
{
|
||||
if (val == 1)
|
||||
add("\n <<================>>\n", RCV);
|
||||
else if (val == 2)
|
||||
clear();
|
||||
else if (val == 3)
|
||||
inpCall->value(findtext().c_str());
|
||||
else if (val == 4)
|
||||
inpName->value(findtext().c_str());
|
||||
else if (val == 5)
|
||||
inpQth->value(findtext().c_str());
|
||||
else if (val == 6)
|
||||
inpLoc->value(findtext().c_str());
|
||||
else if (val == 7)
|
||||
inpRstIn->value(findtext().c_str());
|
||||
switch (val) {
|
||||
case 0:
|
||||
add("\n <<================>>\n", RCV);
|
||||
break;
|
||||
case 1:
|
||||
clear();
|
||||
break;
|
||||
case 2:
|
||||
inpCall->value(findtext().c_str());
|
||||
break;
|
||||
case 3:
|
||||
inpName->value(findtext().c_str());
|
||||
break;
|
||||
case 4:
|
||||
inpQth->value(findtext().c_str());
|
||||
break;
|
||||
case 5:
|
||||
inpLoc->value(findtext().c_str());
|
||||
break;
|
||||
case 6:
|
||||
inpRstIn->value(findtext().c_str());
|
||||
break;
|
||||
case 7:
|
||||
saveFile();
|
||||
break;
|
||||
}
|
||||
restoreFocus();
|
||||
}
|
||||
|
||||
|
@ -524,16 +543,24 @@ int TextView::handle(int event)
|
|||
{
|
||||
// handle events inside the textview and invoked by Right Mouse button or scrollbar
|
||||
if (Fl::event_inside( this )) {
|
||||
const Fl_Menu_Item * m;
|
||||
int xpos = Fl::event_x();
|
||||
int ypos = Fl::event_y();
|
||||
if (xpos > x() + w() - 20) {
|
||||
scrollbar->handle(event);
|
||||
return 1;
|
||||
} else if (event == FL_RELEASE && Fl::event_button() == 3) {
|
||||
}
|
||||
if (event == FL_PUSH && Fl::event_button() == 3) {
|
||||
popx = xpos - x();
|
||||
popy = ypos - y();
|
||||
mpopup->resize (xpos, ypos, -1, -1);
|
||||
mpopup->popup();
|
||||
m = viewmenu->popup(xpos, ypos, 0, 0, 0);
|
||||
if (m) {
|
||||
for (int i = 0; i < viewmenuNbr; i++)
|
||||
if (m == &viewmenu[i]) {
|
||||
menu_cb(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -547,23 +574,19 @@ int TextView::handle(int event)
|
|||
// base class. All other functions are in the base class
|
||||
//=====================================================================
|
||||
|
||||
Fl_Menu_Item editmenu[] = {
|
||||
{"clear", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"File", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"^t", 0, 0 },
|
||||
{"^r", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{"Picture", 0, 0 },
|
||||
{0}
|
||||
};
|
||||
int editmenuNbr = 5;
|
||||
|
||||
TextEdit::TextEdit( int x, int y, int w, int h, const char *label )
|
||||
: textview ( x, y, w, h, label )
|
||||
{
|
||||
static Fl_Menu_Item menupopup[] = {
|
||||
{"Dismiss", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"clear", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"File", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"^t", 0, _menu_cb, this},
|
||||
{"^r", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"Picture", 0, _menu_cb, this },
|
||||
{0}
|
||||
};
|
||||
mitems = menupopup;
|
||||
|
||||
mpopup = new Fl_Menu_Button(-1, -1, -1, -1);
|
||||
mpopup->menu(mitems);
|
||||
mpopup->type(Fl_Menu_Button::POPUP1);
|
||||
chrptr = 0;
|
||||
bkspaces = 0;
|
||||
textview::cursorStyle = HEAVY_CURSOR;
|
||||
|
@ -595,22 +618,22 @@ void TextEdit::readFile()
|
|||
|
||||
void TextEdit::menu_cb(int val)
|
||||
{
|
||||
if (val == 1) {
|
||||
if (val == 0) {
|
||||
clear();
|
||||
chrptr = 0;
|
||||
bkspaces = 0;
|
||||
}
|
||||
if (val == 2)
|
||||
if (val == 1)
|
||||
readFile();
|
||||
if (val == 3 && buff.empty()) {
|
||||
if (val == 2 && buff.empty()) {
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
}
|
||||
if (val == 4)
|
||||
if (val == 3)
|
||||
add("^r");
|
||||
if (val == 5)
|
||||
if (val == 4)
|
||||
if (active_modem->get_mode() == MODE_MFSK16)
|
||||
active_modem->makeTxViewer(0,0);
|
||||
}
|
||||
|
@ -678,18 +701,6 @@ int TextEdit::handle_key() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// substitute the FN # you want to map for each
|
||||
// ie: F1 ==> 1 + Fl_F
|
||||
// then remove the two slashes from each of the following lines
|
||||
// if (key == FL_Left)
|
||||
// return handle_fnckey(n + FL_F);
|
||||
// if (key == FL_Up)
|
||||
// return handle_fnckey(n + FL_F);
|
||||
// if (key == FL_Right)
|
||||
// return handle_fnckey(n + FL_F);
|
||||
// if (key == FL_Down)
|
||||
// return handle_fnckey(n + FL_F);
|
||||
|
||||
if (key == FL_Left) {
|
||||
active_modem->searchDown();
|
||||
return 1;
|
||||
|
@ -732,27 +743,36 @@ int TextEdit::handle(int event)
|
|||
return 1;
|
||||
}
|
||||
if (event == FL_KEYBOARD) {
|
||||
// textview::cursorON = true;
|
||||
return handle_key();
|
||||
}
|
||||
if (Fl::event_inside( this )) {
|
||||
const Fl_Menu_Item * m;
|
||||
int xpos = Fl::event_x();
|
||||
int ypos = Fl::event_y();
|
||||
if (xpos > x() + w() - 20) {
|
||||
scrollbar->handle(event);
|
||||
return 1;
|
||||
} else if (event == FL_RELEASE && Fl::event_button() == 3) {
|
||||
mpopup->resize (xpos, ypos, -1, -1);
|
||||
mpopup->popup();
|
||||
textview::cursorON = true;
|
||||
Fl::focus(this);
|
||||
redraw();
|
||||
}
|
||||
if (event == FL_PUSH && Fl::event_button() == 3) {
|
||||
popx = xpos - x();
|
||||
popy = ypos - y();
|
||||
m = editmenu->popup(xpos, ypos, 0, 0, 0);
|
||||
if (m) {
|
||||
for (int i = 0; i < editmenuNbr; i++)
|
||||
if (m == &editmenu[i]) {
|
||||
menu_cb(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case FL_RELEASE:
|
||||
case FL_PUSH:
|
||||
textview::cursorON = true;
|
||||
redraw();
|
||||
Fl::focus(this);
|
||||
return 1;
|
||||
case FL_FOCUS:
|
||||
textview::cursorON = true;
|
||||
redraw();
|
||||
|
@ -797,76 +817,3 @@ void TextEdit::cursorON()
|
|||
redraw();
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// Class MacroEdit
|
||||
// derived from base class textview
|
||||
// redfines the handle() and menu_cb() functions specified in the
|
||||
// base class. All other functions are in the base class
|
||||
//=====================================================================
|
||||
|
||||
MacroEdit::MacroEdit( int x, int y, int w, int h, const char *label )
|
||||
: textview ( x, y, w, h, label )
|
||||
{
|
||||
static Fl_Menu_Item menupopup[] = {
|
||||
{"Dismiss", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{"clear", 0, _menu_cb, this, FL_MENU_DIVIDER },
|
||||
{0}
|
||||
};
|
||||
mitems = menupopup;
|
||||
|
||||
mpopup = new Fl_Menu_Button(-1, -1, -1, -1);
|
||||
mpopup->menu(mitems);
|
||||
mpopup->type(Fl_Menu_Button::POPUP1);
|
||||
}
|
||||
|
||||
void MacroEdit::menu_cb(int val)
|
||||
{
|
||||
if (val == 1) {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
int MacroEdit::handle_key() {
|
||||
int key = Fl::event_key();
|
||||
if (key == FL_Enter) {
|
||||
add('\n');
|
||||
return 1;
|
||||
}
|
||||
if (key == FL_BackSpace) {
|
||||
add (0x08);
|
||||
return 1;
|
||||
}
|
||||
const char *ch = Fl::event_text();
|
||||
add(ch);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MacroEdit::handle(int event)
|
||||
{
|
||||
// handle events inside the MacroEdit widget
|
||||
if (Fl::event_inside( this )) {
|
||||
int xpos = Fl::event_x();
|
||||
int ypos = Fl::event_y();
|
||||
if (xpos > x() + w() - 20) {
|
||||
scrollbar->handle(event);
|
||||
return 1;
|
||||
} else if (event == FL_RELEASE && Fl::event_button() == 3) {
|
||||
mpopup->resize (xpos, ypos, -1, -1);
|
||||
mpopup->popup();
|
||||
Fl::focus(this);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
switch (event) {
|
||||
case FL_RELEASE:
|
||||
case FL_FOCUS:
|
||||
Fl::focus(this);
|
||||
return 1;
|
||||
case FL_UNFOCUS:
|
||||
return 1;
|
||||
case FL_KEYBOARD :
|
||||
return handle_key();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <FL/fl_ask.H>
|
||||
#include <FL/Fl_Pixmap.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
#include <FL/Fl_Tile.H>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
|
@ -78,6 +79,8 @@ Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0;
|
|||
cMixer mixer;
|
||||
|
||||
Fl_Button *btnTune = (Fl_Button *)0;
|
||||
Fl_Tile *TiledGroup = (Fl_Tile *)0;
|
||||
//Fl_Group *TiledGroup = (Fl_Group *)0;
|
||||
TextView *ReceiveText=(TextView *)0;
|
||||
TextEdit *TransmitText=(TextEdit *)0;
|
||||
Fl_Text_Buffer *rcvBuffer = (Fl_Text_Buffer *)0;
|
||||
|
@ -123,32 +126,6 @@ Fl_Progress *pgrsSquelch = (Fl_Progress *)0;
|
|||
|
||||
Fl_RGB_Image *feld_image = 0;
|
||||
|
||||
|
||||
#define Hmenu 24
|
||||
#define Hqsoframe 48
|
||||
#define Hnotes 24
|
||||
#define Hrcvtxt 200
|
||||
#define Hxmttxt 100
|
||||
//#define Hrcvtxt 160
|
||||
//#define Hxmttxt 100
|
||||
#define Hwfall 140
|
||||
//#define Hwfall 118
|
||||
#define Hstatus 22
|
||||
#define Hmacros 24
|
||||
#define Wmode 80
|
||||
#define Ws2n 100
|
||||
#define Wimd 100
|
||||
#define Wwarn 16
|
||||
#define bwAfcOnOff (Hwfall -22)/2
|
||||
#define bwSqlOnOff (Hwfall -22)/2
|
||||
|
||||
#define Wwfall 754
|
||||
//#define Wwfall 654
|
||||
#define HNOM (Hwfall + Hxmttxt + Hrcvtxt + Hmenu + (Hstatus + 4) + Hmacros + Hqsoframe + Hnotes)
|
||||
#define WNOM (Wwfall + Hwfall - 22)
|
||||
#define Wstatus (WNOM - Wmode - Ws2n - Wimd - Wwarn - bwAfcOnOff - bwSqlOnOff)
|
||||
|
||||
|
||||
void clearStatus()
|
||||
{
|
||||
clear_StatusMessages();
|
||||
|
@ -207,6 +184,8 @@ void clean_exit() {
|
|||
|
||||
if (bSaveFreqList)
|
||||
saveFreqList();
|
||||
|
||||
progStatus.saveLastState();
|
||||
|
||||
mixer.closeMixer();
|
||||
active_modem->set_stopflag(true);
|
||||
|
@ -1115,18 +1094,24 @@ void create_fl_digi_main() {
|
|||
valXmtMixer->deactivate();
|
||||
MixerFrame->end();
|
||||
|
||||
Fl_Group *TextFrame = new Fl_Group(sw,Y, WNOM-sw, Hrcvtxt + Hxmttxt);
|
||||
Fl_Tile *TiledGroup = new Fl_Tile(sw, Y, WNOM-sw, Hrcvtxt + Hxmttxt);
|
||||
// Fl_Group *TiledGroup = new Fl_Group(sw, Y, WNOM-sw, Hrcvtxt + Hxmttxt);
|
||||
Fl_Box *minbox = new Fl_Box(sw,Y + 66, WNOM-sw, Hxmttxt + Hrcvtxt - 66 - 32);
|
||||
minbox->hide();
|
||||
|
||||
ReceiveText = new TextView(sw, Y, WNOM-sw, Hrcvtxt, "");
|
||||
Fl_Group::current()->resizable(ReceiveText);
|
||||
|
||||
|
||||
FHdisp = new Raster(sw, Y, WNOM-sw, Hrcvtxt);
|
||||
FHdisp->hide();
|
||||
Y += Hrcvtxt;
|
||||
|
||||
TransmitText = new TextEdit(sw, Y, WNOM-sw, Hxmttxt);
|
||||
Y += Hxmttxt;
|
||||
TextFrame->end();
|
||||
Fl_Group::current()->resizable(TextFrame);
|
||||
|
||||
TiledGroup->resizable(minbox);
|
||||
TiledGroup->end();
|
||||
Fl_Group::current()->resizable(TiledGroup);
|
||||
|
||||
|
||||
Fl_Box *macroFrame = new Fl_Box(0, Y, WNOM, Hmacros);
|
||||
macroFrame->box(FL_ENGRAVED_FRAME);
|
||||
|
@ -1156,20 +1141,20 @@ void create_fl_digi_main() {
|
|||
wfpack->type(1);
|
||||
wf = new waterfall(0, Y, Wwfall, Hwfall);
|
||||
wf->end();
|
||||
Fl_Pack *ypack = new Fl_Pack(WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall);
|
||||
ypack->type(0);
|
||||
Fl_Pack *ypack = new Fl_Pack(WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall);
|
||||
ypack->type(0);
|
||||
|
||||
digiscope = new Digiscope (WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall-22);
|
||||
|
||||
pgrsSquelch = new Fl_Progress(
|
||||
WNOM-(Hwfall-22), Y + Hwfall - 22,
|
||||
Hwfall - 22, 10, "");
|
||||
pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
sldrSquelch = new Fl_Slider(
|
||||
FL_HOR_NICE_SLIDER,
|
||||
WNOM-(Hwfall-22), Y + Hwfall - 12,
|
||||
Hwfall - 22, 12, "");
|
||||
|
||||
digiscope = new Digiscope (WNOM-(Hwfall-22), Y, Hwfall-22, Hwfall-22);
|
||||
|
||||
pgrsSquelch = new Fl_Progress(
|
||||
WNOM-(Hwfall-22), Y + Hwfall - 22,
|
||||
Hwfall - 22, 10, "");
|
||||
pgrsSquelch->color(FL_BACKGROUND2_COLOR, FL_DARK_GREEN);
|
||||
sldrSquelch = new Fl_Slider(
|
||||
FL_HOR_NICE_SLIDER,
|
||||
WNOM-(Hwfall-22), Y + Hwfall - 12,
|
||||
Hwfall - 22, 12, "");
|
||||
|
||||
sldrSquelch->minimum(0);
|
||||
sldrSquelch->maximum(100);
|
||||
sldrSquelch->step(1);
|
||||
|
@ -1178,8 +1163,8 @@ void create_fl_digi_main() {
|
|||
sldrSquelch->callback((Fl_Callback*)cb_sldrSquelch);
|
||||
sldrSquelch->color(FL_INACTIVE_COLOR);
|
||||
|
||||
ypack->end();
|
||||
Fl_Group::current()->resizable(wf);
|
||||
ypack->end();
|
||||
Fl_Group::current()->resizable(wf);
|
||||
wfpack->end();
|
||||
Y += (Hwfall + 2);
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ void Font_Browser::FontNameSelect()
|
|||
if (!fn)
|
||||
return;
|
||||
|
||||
fontnbr = (Fl_Font)reinterpret_cast<int>(lst_Font->data(fn));
|
||||
fontnbr = (Fl_Font)reinterpret_cast<long>(lst_Font->data(fn));
|
||||
|
||||
// show the font name in the input
|
||||
txt_OutputFont->value(Fl::get_font_name(fontnbr));
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
// Copyright (C) 2001, 2002, 2003
|
||||
// Tomi Manninen (oh2bns@sral.fi)
|
||||
// Copyright (C) 2006
|
||||
// Hamish Moffatt (hamish@debian.org)
|
||||
// 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
|
||||
|
@ -47,7 +47,7 @@ void dominoex::tx_init(cSound *sc)
|
|||
scard = sc;
|
||||
txstate = TX_STATE_PREAMBLE;
|
||||
txprevtone = 0;
|
||||
counter = 0;
|
||||
counter = 0;
|
||||
phaseacc = 0.0;
|
||||
if (trx_state != STATE_TUNE && progdefaults.sendid == true)
|
||||
wfid->transmit(mode);
|
||||
|
@ -102,11 +102,11 @@ void dominoex::init()
|
|||
}
|
||||
|
||||
dominoex::~dominoex()
|
||||
{
|
||||
if (binsfft) delete binsfft;
|
||||
if (hilbert) delete hilbert;
|
||||
if (pipe) delete [] pipe;
|
||||
if (scopedata) delete [] scopedata;
|
||||
{
|
||||
if (binsfft) delete binsfft;
|
||||
if (hilbert) delete hilbert;
|
||||
if (pipe) delete [] pipe;
|
||||
if (scopedata) delete [] scopedata;
|
||||
if (filt) delete filt;
|
||||
if (wfid) delete wfid;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ dominoex::dominoex(trx_mode md)
|
|||
doublespaced = 0;
|
||||
samplerate = 11025;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
// case MODE_DOMINOEX8:
|
||||
symlen = 1024;
|
||||
basetone = 128; // 1000 Hz
|
||||
|
@ -171,17 +171,17 @@ dominoex::dominoex(trx_mode md)
|
|||
}
|
||||
|
||||
tonespacing = (double) (samplerate * ((doublespaced) ? 2 : 1)) / symlen;
|
||||
|
||||
|
||||
binsfft = new sfft( symlen,
|
||||
basetone - numtones*(doublespaced?2:1),
|
||||
basetone + 2*numtones*(doublespaced ? 2 : 1) );
|
||||
basetone + 2*numtones*(doublespaced ? 2 : 1) );
|
||||
|
||||
|
||||
hilbert = new C_FIR_filter();
|
||||
hilbert->init_hilbert(37, 1);
|
||||
afcfilt = new Cmovavg(AFC_COUNT);
|
||||
|
||||
pipe = new domrxpipe[2 * symlen];
|
||||
pipe = new domrxpipe[2 * symlen];
|
||||
scopedata = new double[2 * symlen];
|
||||
pipeptr = 0;
|
||||
symcounter = 0;
|
||||
|
@ -197,7 +197,7 @@ dominoex::dominoex(trx_mode md)
|
|||
|
||||
filt = new C_FIR_filter();
|
||||
filt->init_bandpass (127, 1, flo, fhi);
|
||||
|
||||
|
||||
fragmentsize = symlen;
|
||||
|
||||
s2n = 0.0;
|
||||
|
@ -207,11 +207,11 @@ dominoex::dominoex(trx_mode md)
|
|||
prev1vector = prev2vector = complex(0.0, 0.0);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// rx modules
|
||||
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// rx modules
|
||||
|
||||
complex dominoex::mixer(complex in, double f)
|
||||
{
|
||||
complex z;
|
||||
|
@ -229,13 +229,13 @@ complex dominoex::mixer(complex in, double f)
|
|||
}
|
||||
|
||||
void dominoex::recvchar(int c)
|
||||
{
|
||||
{
|
||||
if (c == -1)
|
||||
return;
|
||||
if (c & 0x100)
|
||||
put_sec_char(c & 0xFF);
|
||||
else
|
||||
put_rx_char(c & 0xFF);
|
||||
put_rx_char(c & 0xFF);
|
||||
}
|
||||
|
||||
void dominoex::decodesymbol(unsigned char curtone, unsigned char prevtone)
|
||||
|
@ -407,7 +407,7 @@ int dominoex::rx_process(double *buf, int len)
|
|||
complex z, *bins, noise;
|
||||
|
||||
while (len-- > 0) {
|
||||
// create analytic signal...shift in frequency to base band & bandpass filter
|
||||
// create analytic signal...shift in frequency to base band & bandpass filter
|
||||
z.re = z.im = *buf++;
|
||||
hilbert->run(z, z);
|
||||
z = mixer(z, frequency);
|
||||
|
@ -442,20 +442,20 @@ int dominoex::rx_process(double *buf, int len)
|
|||
pipeptr = (pipeptr + 1) % (2 * symlen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
// dominoex tx modules
|
||||
|
||||
int dominoex::get_secondary_char()
|
||||
{
|
||||
int dominoex::get_secondary_char()
|
||||
{
|
||||
static unsigned int cptr = 0;
|
||||
char chr;
|
||||
char chr;
|
||||
if (cptr > strSecXmtText.length()) cptr = 0;
|
||||
chr = strSecXmtText[cptr++];
|
||||
put_sec_char( chr );
|
||||
return chr;
|
||||
}
|
||||
put_sec_char( chr );
|
||||
return chr;
|
||||
}
|
||||
|
||||
void dominoex::sendsymbol(int sym)
|
||||
{
|
||||
|
@ -469,7 +469,7 @@ void dominoex::sendsymbol(int sym)
|
|||
if (reverse)
|
||||
tone = (numtones - 1) - tone;
|
||||
|
||||
f = tone * tonespacing + tx_frequency - bandwidth / 2;
|
||||
f = tone * tonespacing + get_txfreq_woffset() - bandwidth / 2;
|
||||
|
||||
phaseincr = twopi * f / samplerate;
|
||||
|
||||
|
@ -506,12 +506,12 @@ void dominoex::sendidle()
|
|||
{
|
||||
sendchar(0, 1); // <NUL>
|
||||
}
|
||||
|
||||
void dominoex::sendsecondary()
|
||||
{
|
||||
int c = get_secondary_char();
|
||||
sendchar(c & 0xFF, 1);
|
||||
}
|
||||
|
||||
void dominoex::sendsecondary()
|
||||
{
|
||||
int c = get_secondary_char();
|
||||
sendchar(c & 0xFF, 1);
|
||||
}
|
||||
|
||||
void dominoex::flushtx()
|
||||
{
|
||||
|
@ -539,8 +539,8 @@ int dominoex::tx_process()
|
|||
i = get_tx_char();
|
||||
if (i == 0)
|
||||
sendsecondary();
|
||||
else if (i == 3)
|
||||
txstate = TX_STATE_END;
|
||||
else if (i == 3)
|
||||
txstate = TX_STATE_END;
|
||||
else
|
||||
sendchar(i, 0);
|
||||
if (stopflag)
|
||||
|
|
|
@ -294,7 +294,7 @@ int feld::rx_process(double *buf, int len)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < n; i++)
|
||||
rx(zp[i]);
|
||||
break;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ double feld::nco(double freq)
|
|||
|
||||
void feld::send_symbol(int currsymb, int nextsymb)
|
||||
{
|
||||
double tone = tx_frequency;
|
||||
double tone = get_txfreq_woffset();
|
||||
double Amp;
|
||||
int outlen = 0;
|
||||
|
||||
|
@ -377,7 +377,7 @@ void feld::send_symbol(int currsymb, int nextsymb)
|
|||
switch (mode) {
|
||||
case MODE_FSKHELL :
|
||||
case MODE_FSKH105 :
|
||||
tone = tx_frequency + (reverse ? -1 : 1) * (currsymb ? -1 : 1) * bandwidth / 2.0;
|
||||
tone = get_txfreq_woffset() + (reverse ? -1 : 1) * (currsymb ? -1 : 1) * bandwidth / 2.0;
|
||||
break;
|
||||
case MODE_FELDHELL :
|
||||
default :
|
||||
|
|
|
@ -59,7 +59,7 @@ void id::make_pulse()
|
|||
void id::make_tones()
|
||||
{
|
||||
double f;
|
||||
double frequency = mode->get_txfreq();
|
||||
double frequency = mode->get_txfreq_woffset();
|
||||
double sr = mode->get_samplerate();
|
||||
for (int j = 0; j < NUMCHARS; j++)
|
||||
for (int i = 0; i < NUMTONES; i++) {
|
||||
|
|
|
@ -69,6 +69,7 @@ extern Fl_Value_Slider *valPCMvolume;
|
|||
#include <FL/Fl_Spinner.H>
|
||||
extern Fl_Spinner *cntRxRateCorr;
|
||||
extern Fl_Spinner *cntTxRateCorr;
|
||||
extern Fl_Spinner *cntTxOffset;
|
||||
extern Fl_Value_Input *valCWsweetspot;
|
||||
extern Fl_Value_Input *valRTTYsweetspot;
|
||||
extern Fl_Value_Input *valPSKsweetspot;
|
||||
|
@ -92,6 +93,10 @@ extern Fl_Counter *cntCWweight;
|
|||
extern Fl_Counter *cntCWdash2dot;
|
||||
extern Fl_Counter *cntCWrisetime;
|
||||
extern Fl_Counter *cntCWdefWPM;
|
||||
extern Fl_Group *tabCWQSK;
|
||||
extern Fl_Check_Button *btnQSK;
|
||||
extern Fl_Counter *cntPreTiming;
|
||||
extern Fl_Counter *cntPostTiming;
|
||||
extern Fl_Group *tabDomEX;
|
||||
extern Fl_Input *txtSecondary;
|
||||
extern Fl_Button *btnRestartDomEX;
|
||||
|
@ -110,13 +115,14 @@ extern Fl_Group *tabOlivia;
|
|||
extern Fl_Choice *mnuOlivia_Tones;
|
||||
extern Fl_Choice *mnuOlivia_Bandwidth;
|
||||
extern Fl_Button *btnRestartOlivia;
|
||||
extern Fl_Check_Button *btnPSKmailSweetSpot;
|
||||
extern Fl_Group *tabRTTY;
|
||||
extern Fl_Choice *selShift;
|
||||
extern Fl_Choice *selBaud;
|
||||
extern Fl_Choice *selBits;
|
||||
extern Fl_Choice *selParity;
|
||||
extern Fl_Choice *selStopBits;
|
||||
extern Fl_Check_Button *chkMsbFirst;
|
||||
extern Fl_Check_Button *chkPseudoFSK;
|
||||
extern Fl_Button *btnRestartRtty;
|
||||
extern Fl_Check_Button *btnCRCRLF;
|
||||
extern Fl_Check_Button *btnAUTOCRLF;
|
||||
|
|
|
@ -94,7 +94,6 @@ public:
|
|||
protected:
|
||||
Fl_Scrollbar *scrollbar;
|
||||
Fl_Menu_Button *mpopup;
|
||||
Fl_Menu_Item *mitems;
|
||||
|
||||
void scrollbarCB();
|
||||
inline static void _scrollbarCB( Fl_Widget* w, void* arg )
|
||||
|
@ -102,12 +101,6 @@ protected:
|
|||
((textview*)arg)->scrollbarCB();
|
||||
}
|
||||
|
||||
virtual void menu_cb(int){};
|
||||
inline static void _menu_cb(Fl_Widget *m, void *arg)
|
||||
{
|
||||
((textview*)arg)->menu_cb(((Fl_Menu_*)m)->value());
|
||||
}
|
||||
|
||||
int lineCount();
|
||||
void _backspace();
|
||||
void _add(char c, int attribute);
|
||||
|
@ -127,6 +120,7 @@ public:
|
|||
protected:
|
||||
int handle (int event);
|
||||
void menu_cb(int val);
|
||||
void saveFile();
|
||||
};
|
||||
|
||||
|
||||
|
@ -154,21 +148,4 @@ private:
|
|||
bool PauseBreak;
|
||||
};
|
||||
|
||||
class MacroEdit : public textview {
|
||||
public:
|
||||
MacroEdit( int x, int y, int w, int h, const char *label = 0 );
|
||||
virtual void add( char *text, int attr = 1 ) {textview::add(text);};
|
||||
virtual void add( const char *text, int attr = 1) {textview::add((char*)text);};
|
||||
virtual void add( char c, int attr = 1) {textview::add(c);};
|
||||
virtual void clear() {textview::clear();};
|
||||
protected:
|
||||
int handle_key();
|
||||
int handle (int event);
|
||||
void menu_cb(int val);
|
||||
virtual void setFont(Fl_Font fnt) { textview::setFont(fnt); }
|
||||
virtual void setFontSize(int siz) { textview::setFontSize(siz); }
|
||||
virtual void setFontColor(Fl_Color clr) { textview::setFontColor(clr); }
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,47 +8,52 @@
|
|||
#include <math.h>
|
||||
|
||||
class complex {
|
||||
public:
|
||||
double re;
|
||||
double im;
|
||||
public:
|
||||
double re;
|
||||
double im;
|
||||
complex(double r = 0.0, double i = 0.0) {
|
||||
re = r;
|
||||
im = i;
|
||||
}
|
||||
}
|
||||
~complex() {};
|
||||
double real() { return re; };
|
||||
void real(double R) {re = R;};
|
||||
double imag() { return im; };
|
||||
void imag(double I) {im = I;};
|
||||
complex conj () {
|
||||
complex z;
|
||||
z.re = re; z.im = -im;
|
||||
return z;
|
||||
}
|
||||
|
||||
// Z = X * Y
|
||||
complex operator* (complex y) {
|
||||
complex z;
|
||||
z.re = re * y.re - im * y.im;
|
||||
z.im = re * y.im + im * y.re;
|
||||
z.im = re * y.im + im * y.re;
|
||||
return z;
|
||||
}
|
||||
|
||||
// Z = X * y
|
||||
complex operator* (double y) {
|
||||
complex z;
|
||||
z.re = y * z.re;
|
||||
z.im = y * z.im;
|
||||
return z;
|
||||
}
|
||||
complex operator+ (complex y) {
|
||||
complex z;
|
||||
z.re = re + y.re;
|
||||
z.im = im + y.im;
|
||||
return z;
|
||||
}
|
||||
complex operator- (complex y) {
|
||||
complex z;
|
||||
z.re = re - y.re;
|
||||
z.im = im - y.im;
|
||||
return z;
|
||||
|
||||
// Z = X + Y
|
||||
complex operator+ (complex y) {
|
||||
complex z;
|
||||
z.re = re + y.re;
|
||||
z.im = im + y.im;
|
||||
return z;
|
||||
}
|
||||
|
||||
// Z = X - Y
|
||||
complex operator- (complex y) {
|
||||
complex z;
|
||||
z.re = re - y.re;
|
||||
z.im = im - y.im;
|
||||
return z;
|
||||
}
|
||||
|
||||
// Z = X / Y
|
||||
complex operator/ (complex y) {
|
||||
double denom = y.re*y.re + y.im*y.im;
|
||||
if (denom == 0.0) denom = 1e-10;
|
||||
|
@ -58,52 +63,45 @@ public:
|
|||
return z;
|
||||
}
|
||||
|
||||
complex ccor(complex x, complex y) {
|
||||
complex z;
|
||||
z.re = x.re * y.re + x.im * y.im;
|
||||
z.im = x.re * y.im - x.im * y.re;
|
||||
return z;
|
||||
}
|
||||
|
||||
// (complex conjugate of X) * Y
|
||||
complex operator% (complex y) { // operator type for ccor in gmfsk code
|
||||
// Z = (complex conjugate of X) * Y
|
||||
// Z1 = x1 + jy1, or Z1 = |Z1|exp(jP1)
|
||||
// Z2 = x2 + jy2, or Z2 = |Z2|exp(jP2)
|
||||
// Z = (x1 - jy1) * (x2 + jy2)
|
||||
// or Z = |Z1|*|Z2| exp (j (P2 - P1))
|
||||
complex operator% (complex y) {
|
||||
complex z;
|
||||
z.re = re * y.re + im * y.im;
|
||||
z.im = re * y.im - im * y.re;
|
||||
return z;
|
||||
}
|
||||
|
||||
double ccorI(complex y) {
|
||||
return (re * y.re + im * y.im);
|
||||
}
|
||||
double ccorQ(complex y) {
|
||||
return (re * y.im - im * y.re);
|
||||
}
|
||||
double norm() {
|
||||
return (re * re + im * im);
|
||||
|
||||
// n = |Z| * |Z|
|
||||
double norm() {
|
||||
return (re * re + im * im);
|
||||
}
|
||||
|
||||
// n = |Z|
|
||||
double mag() {
|
||||
return sqrt(norm());
|
||||
}
|
||||
double arg() {
|
||||
return atan2(im, re);
|
||||
}
|
||||
complex csqrt() {
|
||||
complex z;
|
||||
z.re = sqrt(mag() + re) / M_SQRT2;
|
||||
z.im = im / re / 2;
|
||||
return z;
|
||||
}
|
||||
};
|
||||
|
||||
inline complex cmac (complex *a, complex *b, int ptr, int len) {
|
||||
complex z;
|
||||
ptr = ptr % len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
z = z + a[i] * b[ptr];
|
||||
ptr = (ptr + 1) % len;
|
||||
}
|
||||
return z;
|
||||
// Z = x + jy
|
||||
// Z = |Z|exp(jP)
|
||||
// arg returns P
|
||||
double arg() {
|
||||
return atan2(im, re);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline complex cmac (complex *a, complex *b, int ptr, int len) {
|
||||
complex z;
|
||||
ptr = ptr % len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
z = z + a[i] * b[ptr];
|
||||
ptr = (ptr + 1) % len;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ struct configuration {
|
|||
double RTTYsweetspot;
|
||||
double PSKsweetspot;
|
||||
bool StartAtSweetSpot;
|
||||
bool PSKmailSweetSpot;
|
||||
// RTTY
|
||||
double rtty_squelch;
|
||||
int rtty_shift;
|
||||
|
@ -39,6 +40,7 @@ struct configuration {
|
|||
bool RTTY_USB;
|
||||
bool useUART;
|
||||
bool PreferXhairScope;
|
||||
bool PseudoFSK;
|
||||
// CW
|
||||
bool useCWkeylineRTS; // use RTS for CW
|
||||
bool useCWkeylineDTR; // use DTR for CW
|
||||
|
@ -52,6 +54,9 @@ struct configuration {
|
|||
int CWupperlimit;
|
||||
double CWrisetime;
|
||||
double CWdash2dot;
|
||||
bool QSK;
|
||||
double CWpre;
|
||||
double CWpost;
|
||||
|
||||
// FELD-HELL
|
||||
bool FELD_IDLE;
|
||||
|
@ -105,6 +110,7 @@ struct configuration {
|
|||
string SCdevice;
|
||||
int RX_corr;
|
||||
int TX_corr;
|
||||
int TxOffset;
|
||||
// Contest stuff
|
||||
bool UseLeadingZeros;
|
||||
int ContestStart;
|
||||
|
|
|
@ -123,6 +123,10 @@ protected:
|
|||
int lastsym; // last symbol sent
|
||||
double risetime; // leading/trailing edge rise time (msec)
|
||||
int knum; // number of samples on edges
|
||||
double qrqbuf[OUTBUFSIZE]; // signal array for qrq drive
|
||||
double qrqphase; //
|
||||
bool firstelement;
|
||||
|
||||
// double *keyshape; // array defining leading edge
|
||||
|
||||
// Receiving parameters:
|
||||
|
@ -143,6 +147,7 @@ protected:
|
|||
double dash_tracking;
|
||||
|
||||
inline double nco(double freq);
|
||||
inline double qrqnco();
|
||||
void update_syncscope();
|
||||
void update_Status();
|
||||
void sync_parameters();
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
fontnbr = n;
|
||||
lst_Font->value(1);
|
||||
for ( int i = 1; i <= lst_Font->size() - 1; i++ ) {
|
||||
if ((Fl_Font)reinterpret_cast<int>(lst_Font->data(i)) == n) {
|
||||
if ((Fl_Font)reinterpret_cast<long>(lst_Font->data(i)) == n) {
|
||||
lst_Font->value(i);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,31 @@
|
|||
#include "rigclass.h"
|
||||
#endif
|
||||
|
||||
#define Hmenu 24
|
||||
#define Hqsoframe 48
|
||||
#define Hnotes 24
|
||||
#define Hrcvtxt 200
|
||||
#define Hxmttxt 100
|
||||
//#define Hrcvtxt 160
|
||||
//#define Hxmttxt 100
|
||||
#define Hwfall 140
|
||||
//#define Hwfall 118
|
||||
#define Hstatus 22
|
||||
#define Hmacros 24
|
||||
#define Wmode 80
|
||||
#define Ws2n 100
|
||||
#define Wimd 100
|
||||
#define Wwarn 16
|
||||
#define bwAfcOnOff (Hwfall -22)/2
|
||||
#define bwSqlOnOff (Hwfall -22)/2
|
||||
|
||||
#define Wwfall 754
|
||||
//#define Wwfall 654
|
||||
#define HNOM (Hwfall + Hxmttxt + Hrcvtxt + Hmenu + (Hstatus + 4) + Hmacros + Hqsoframe + Hnotes)
|
||||
#define WNOM (Wwfall + Hwfall - 22)
|
||||
#define Wstatus (WNOM - Wmode - Ws2n - Wimd - Wwarn - bwAfcOnOff - bwSqlOnOff)
|
||||
|
||||
|
||||
extern Fl_Mutex trx_mutex;
|
||||
extern Fl_Cond trx_cond;
|
||||
extern Fl_Thread trx_thread;
|
||||
|
|
|
@ -102,10 +102,9 @@ public:
|
|||
void set_sigsearch(int n) { sigsearch = n; freqerr = 0.0;};
|
||||
bool freqlocked();
|
||||
double get_txfreq();
|
||||
double get_txfreq_woffset();
|
||||
void set_metric(double);
|
||||
double get_metric();
|
||||
void set_txoffset(double);
|
||||
double get_txoffset();
|
||||
void set_reverse(bool on);
|
||||
double get_bandwidth();
|
||||
void set_bandwidth(double);
|
||||
|
@ -115,6 +114,7 @@ public:
|
|||
int get_echo_char();
|
||||
|
||||
void ModulateXmtr(double *, int);
|
||||
void ModulateStereo(double *, double *, int);
|
||||
|
||||
void set_stopflag(bool b) { stopflag = b;};
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ private:
|
|||
int nbits;
|
||||
// RTTY_PARITY parity;
|
||||
int stoplen;
|
||||
int msb;
|
||||
int msb;
|
||||
bool useFSK;
|
||||
|
||||
double phaseacc;
|
||||
|
@ -114,6 +114,10 @@ private:
|
|||
double prevsymbol;
|
||||
complex prevsmpl;
|
||||
|
||||
double FSKbuf[OUTBUFSIZE]; // signal array for qrq drive
|
||||
double FSKphaseacc;
|
||||
double FSKnco();
|
||||
|
||||
int rxmode;
|
||||
int txmode;
|
||||
int preamble;
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
void Close();
|
||||
int Write(unsigned char *, int);
|
||||
int write_samples(double *, int);
|
||||
int write_stereo(double *, double *, int);
|
||||
int Read(unsigned char *, int);
|
||||
int Read(double *, int);
|
||||
int Fd() { return device_fd; }
|
||||
|
|
|
@ -12,11 +12,18 @@
|
|||
using namespace std;
|
||||
|
||||
struct status {
|
||||
trx_mode lastmode;
|
||||
int lastmode;
|
||||
int mainX;
|
||||
int mainY;
|
||||
int mainW;
|
||||
int mainH;
|
||||
bool rigShown;
|
||||
int rigX;
|
||||
int rigY;
|
||||
public:
|
||||
void readLastState();
|
||||
void saveModeState(trx_mode m);
|
||||
void initLastState();
|
||||
void saveLastState();
|
||||
friend std::istream &operator>>(std::istream &stream, status &c);
|
||||
friend std::ostream &operator<<(std::ostream &ostream, status c);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef _VERSION_H
|
||||
#define _VERSION_H
|
||||
|
||||
#define FLDIGI_VERSION "1.34"
|
||||
#define FLDIGI_VERSION "1.35J"
|
||||
|
||||
#endif
|
||||
|
|
11
src/main.cxx
11
src/main.cxx
|
@ -126,6 +126,7 @@ int main(int argc, char ** argv) {
|
|||
Fl::lock(); // start the gui thread!!
|
||||
Fl::visual(FL_RGB); // insure 24 bit color operation
|
||||
fl_register_images();
|
||||
Fl::set_fonts(0);
|
||||
|
||||
rigcontrol = createRigDialog();
|
||||
create_fl_digi_main();
|
||||
|
@ -150,15 +151,11 @@ int main(int argc, char ** argv) {
|
|||
|
||||
trx_start(scDevice.c_str());
|
||||
|
||||
progStatus.readLastState();
|
||||
progStatus.initLastState();
|
||||
|
||||
wf->opmode();
|
||||
|
||||
progdefaults.initInterface();
|
||||
|
||||
Fl::set_fonts(0);
|
||||
|
||||
progStatus.initLastState();
|
||||
wf->opmode();
|
||||
|
||||
if (mailserver || mailclient) {
|
||||
std::cout << "Starting pskmail transport layer" << std::endl; fflush(stdout);
|
||||
string PskMailLogName = PskMailDir;
|
||||
|
|
|
@ -588,7 +588,7 @@ void mfsk::sendsymbol(int sym)
|
|||
{
|
||||
double f, phaseincr;
|
||||
|
||||
f = tx_frequency - bandwidth / 2;
|
||||
f = get_txfreq_woffset() - bandwidth / 2;
|
||||
|
||||
sym = grayencode(sym & (numtones - 1));
|
||||
//printf("%5d", sym);
|
||||
|
@ -668,9 +668,9 @@ void mfsk::sendpic(unsigned char *data, int len)
|
|||
if (txstate == TX_STATE_PICTURE)
|
||||
updateTxPic(data[i]);
|
||||
if (reverse)
|
||||
f = tx_frequency - bandwidth * (data[i] - 128) / 256.0;
|
||||
f = get_txfreq_woffset() - bandwidth * (data[i] - 128) / 256.0;
|
||||
else
|
||||
f = tx_frequency + bandwidth * (data[i] - 128) / 256.0;
|
||||
f = get_txfreq_woffset() + bandwidth * (data[i] - 128) / 256.0;
|
||||
|
||||
for (j = 0; j < SAMPLES_PER_PIXEL; j++) {
|
||||
*ptr++ = cos(phaseacc);
|
||||
|
|
|
@ -23,6 +23,7 @@ configuration progdefaults = {
|
|||
1000, // int RTTYsweetspot;
|
||||
1000, // int PSKsweetspot;
|
||||
true, // bool StartAtSweetSpot;
|
||||
true, // bool PSKmailSweetSpot;
|
||||
// RTTY
|
||||
25.0, // double rtty_squelch;
|
||||
3, // int rtty_shift; = 170
|
||||
|
@ -42,6 +43,7 @@ configuration progdefaults = {
|
|||
false, // bool RTTY_USB;
|
||||
false, // bool useUART;
|
||||
false, // bool PreferXhairScope;
|
||||
false, // bool PseudoFSK;
|
||||
// CW
|
||||
false, // bool useCWkeylineRTS;
|
||||
false, // bool useCWkeylineDTR;
|
||||
|
@ -55,6 +57,9 @@ configuration progdefaults = {
|
|||
50, // int CWupperlimit;
|
||||
4.0, // double CWrisetime;
|
||||
3.0, // double CWdash2dot;
|
||||
false, // bool QSK;
|
||||
4.0, // double CWpre;
|
||||
4.0, // double CWpost;
|
||||
|
||||
// FELD-HELL
|
||||
false, // bool FELD_IDLE;
|
||||
|
@ -106,8 +111,9 @@ configuration progdefaults = {
|
|||
"fldigi ", // secondary text
|
||||
// Sound card
|
||||
"/dev/dsp", // string SCdevice;
|
||||
0, // double RX_corr;
|
||||
0, // double TX_corr;
|
||||
0, // int RX_corr;
|
||||
0, // int TX_corr;
|
||||
0, // int TxOffset;
|
||||
// Contest controls
|
||||
true, // bool UseLeadingZeros;
|
||||
0, // int ContestStart;
|
||||
|
@ -198,6 +204,7 @@ void configuration::writeDefaultsXML()
|
|||
writeXMLint(f, "FONTCOLOR", FontColor);
|
||||
|
||||
writeXMLbool(f, "STARTATSWEETSPOT", StartAtSweetSpot);
|
||||
writeXMLbool(f, "PSKMAILSWEETSPOT", PSKmailSweetSpot);
|
||||
writeXMLdbl(f, "CWSWEETSPOT", CWsweetspot);
|
||||
writeXMLdbl(f, "PSKSWEETSPOT", PSKsweetspot);
|
||||
writeXMLdbl(f, "RTTYSWEETSPOT", RTTYsweetspot);
|
||||
|
@ -215,6 +222,7 @@ void configuration::writeDefaultsXML()
|
|||
writeXMLint(f, "RTTYAUTOCOUNT", rtty_autocount);
|
||||
writeXMLint(f, "RTTYAFCSPEED", rtty_afcspeed);
|
||||
writeXMLbool(f, "PREFERXHAIRSCOPE", PreferXhairScope);
|
||||
writeXMLbool(f, "PseudoFSK", PseudoFSK);
|
||||
|
||||
writeXMLint(f, "CWWEIGHT", CWweight);
|
||||
writeXMLint(f, "CWSPEED", CWspeed);
|
||||
|
@ -226,6 +234,10 @@ void configuration::writeDefaultsXML()
|
|||
writeXMLbool(f, "CWTRACK", CWtrack);
|
||||
writeXMLdbl(f, "CWRISETIME", CWrisetime);
|
||||
writeXMLdbl(f, "CWDASH2DOT", CWdash2dot);
|
||||
writeXMLbool(f, "QSK", QSK);
|
||||
writeXMLdbl(f, "CWpre", CWpre);
|
||||
writeXMLdbl(f, "CWpost", CWpost);
|
||||
|
||||
writeXMLint(f, "OLIVIATONES", oliviatones);
|
||||
writeXMLint(f, "OLIVIABW", oliviabw);
|
||||
writeXMLdbl(f, "DOMINOEXBW", DOMINOEX_BW);
|
||||
|
@ -259,8 +271,9 @@ void configuration::writeDefaultsXML()
|
|||
writeXMLstr(f, "PTTDEV", PTTdev);
|
||||
writeXMLstr(f, "SECONDARYTEXT", secText);
|
||||
writeXMLstr(f, "SCDEVICE", SCdevice);
|
||||
writeXMLdbl(f, "RXCORR", RX_corr);
|
||||
writeXMLdbl(f, "TXCORR", TX_corr);
|
||||
writeXMLint(f, "RXCORR", RX_corr);
|
||||
writeXMLint(f, "TXCORR", TX_corr);
|
||||
writeXMLint(f, "TXOFFSET", TxOffset);
|
||||
writeXMLbool(f, "USELEADINGZEROS", UseLeadingZeros);
|
||||
writeXMLint(f, "CONTESTSTART", ContestStart);
|
||||
writeXMLint(f, "CONTESTDIGITS", ContestDigits);
|
||||
|
@ -390,6 +403,12 @@ void configuration::writeDefaults(ofstream &f)
|
|||
f << CWrisetime << endl;
|
||||
f << CWdash2dot << endl;
|
||||
f << defCWspeed << endl;
|
||||
f << QSK << endl;
|
||||
f << CWpre << endl;
|
||||
f << CWpost << endl;
|
||||
f << PseudoFSK << endl;
|
||||
f << PSKmailSweetSpot << endl;
|
||||
f << TxOffset << endl;
|
||||
}
|
||||
|
||||
void configuration::readDefaults(ifstream &f)
|
||||
|
@ -497,6 +516,12 @@ void configuration::readDefaults(ifstream &f)
|
|||
f >> CWrisetime;
|
||||
f >> CWdash2dot;
|
||||
f >> defCWspeed;
|
||||
f >> QSK;
|
||||
f >> CWpre;
|
||||
f >> CWpost;
|
||||
f >> PseudoFSK;
|
||||
f >> PSKmailSweetSpot;
|
||||
f >> TxOffset;
|
||||
}
|
||||
|
||||
void configuration::loadDefaults() {
|
||||
|
@ -514,11 +539,13 @@ void configuration::loadDefaults() {
|
|||
case PARITY_ONE : selParity->value(4); break;
|
||||
default : selParity->value(0); break;
|
||||
}
|
||||
chkMsbFirst->value(rtty_msbfirst);
|
||||
// chkMsbFirst->value(rtty_msbfirst);
|
||||
selStopBits->value(rtty_stop);
|
||||
btnCRCRLF->value(rtty_crcrlf);
|
||||
btnAUTOCRLF->value(rtty_autocrlf);
|
||||
cntrAUTOCRLF->value(rtty_autocount);
|
||||
chkPseudoFSK->value(PseudoFSK);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (rtty_afcspeed == i)
|
||||
btnRTTYafc[i]->value(1);
|
||||
|
@ -550,7 +577,7 @@ void configuration::storeDefaults() {
|
|||
case 4 : rtty_parity = PARITY_ONE; break;
|
||||
default : rtty_parity = PARITY_NONE; break;
|
||||
}
|
||||
rtty_msbfirst = chkMsbFirst->value();
|
||||
// rtty_msbfirst = chkMsbFirst->value();
|
||||
rtty_stop = selStopBits->value();
|
||||
rtty_crcrlf = btnCRCRLF->value();
|
||||
rtty_autocrlf = btnAUTOCRLF->value();
|
||||
|
@ -666,6 +693,7 @@ int configuration::openDefaults() {
|
|||
valRTTYsweetspot->value(RTTYsweetspot);
|
||||
valPSKsweetspot->value(PSKsweetspot);
|
||||
btnStartAtSweetSpot->value(StartAtSweetSpot);
|
||||
btnPSKmailSweetSpot->value(PSKmailSweetSpot);
|
||||
|
||||
// txtCWFSKport->value(CWFSKport.c_str());
|
||||
|
||||
|
@ -691,6 +719,11 @@ int configuration::openDefaults() {
|
|||
cntCWdash2dot->value(CWdash2dot);
|
||||
sldrCWxmtWPM->minimum(CWlowerlimit);
|
||||
sldrCWxmtWPM->maximum(CWupperlimit);
|
||||
btnQSK->value(QSK);
|
||||
cntPreTiming->maximum((int)(2400/CWspeed)/2.0);
|
||||
cntPreTiming->value(CWpre);
|
||||
cntPostTiming->maximum((int)(2400/CWspeed)/2.0);
|
||||
cntPostTiming->value(CWpost);
|
||||
|
||||
selHellFont->value(feldfontnbr);
|
||||
btnFeldHellIdle->value(FELD_IDLE);
|
||||
|
@ -750,6 +783,7 @@ int configuration::openDefaults() {
|
|||
}
|
||||
cntRxRateCorr->value(RX_corr);
|
||||
cntTxRateCorr->value(TX_corr);
|
||||
cntTxOffset->value(TxOffset);
|
||||
|
||||
Fl::unlock();
|
||||
|
||||
|
@ -853,9 +887,10 @@ void configuration::initInterface() {
|
|||
btnPTT[2]->activate();
|
||||
rigMEM_init();
|
||||
wf->setQSY(1);
|
||||
activate_rig_menu_item(false);
|
||||
} else if (chkUSERIGCATis) { // start the rigCAT thread
|
||||
btnPTT[3]->activate();
|
||||
if (rigCAT_init() == false) { //btnPTTis == 1 ? true : false) == false) {
|
||||
if (rigCAT_init() == false) {
|
||||
wf->USB(true);
|
||||
cboBand->show();
|
||||
btnSideband->show();
|
||||
|
|
|
@ -135,7 +135,7 @@ void check_formail() {
|
|||
|
||||
parse_mailtext();
|
||||
if (mailtext.length() > 0) {
|
||||
if (mailserver)
|
||||
if (mailserver && progdefaults.PSKmailSweetSpot)
|
||||
active_modem->set_freq(progdefaults.PSKsweetspot);
|
||||
|
||||
pText = mailtext.begin();
|
||||
|
|
|
@ -16,39 +16,71 @@
|
|||
#include "wwv.h"
|
||||
#include "analysis.h"
|
||||
|
||||
#include "rigsupport.h"
|
||||
|
||||
extern void startup_modem(modem *m);
|
||||
|
||||
status progStatus = {
|
||||
MODE_BPSK31 // trx_mode lastmode;
|
||||
(int)MODE_BPSK31, // trx_mode lastmode;
|
||||
0, // int mainX;
|
||||
0, // int mainY;
|
||||
WNOM, // int mainW;
|
||||
HNOM, // int mainH;
|
||||
false, // bool rigShown;
|
||||
0, // int rigX;
|
||||
0, // int rigY;
|
||||
};
|
||||
|
||||
|
||||
void status::saveModeState(trx_mode m)
|
||||
{
|
||||
progStatus.lastmode = m;
|
||||
lastmode = (int)m;
|
||||
}
|
||||
|
||||
void status::saveLastState()
|
||||
{
|
||||
mainX = fl_digi_main->x();
|
||||
mainY = fl_digi_main->y();
|
||||
mainW = fl_digi_main->w();
|
||||
mainH = fl_digi_main->h();
|
||||
if (rigcontrol)
|
||||
if (rigcontrol->visible()) {
|
||||
rigShown = rigcontrol->visible();
|
||||
rigX = rigcontrol->x();
|
||||
rigY = rigcontrol->y();
|
||||
}
|
||||
string deffname = HomeDir;
|
||||
deffname.append("fldigi.status");
|
||||
ofstream deffile(deffname.c_str(), ios::out);
|
||||
deffile << (int)lastmode << endl;
|
||||
deffile << lastmode << endl;
|
||||
deffile << mainX << endl;
|
||||
deffile << mainY << endl;
|
||||
deffile << mainW << endl;
|
||||
deffile << mainH << endl;
|
||||
deffile << rigShown << endl;
|
||||
deffile << rigX << endl;
|
||||
deffile << rigY << endl;
|
||||
deffile.close();
|
||||
}
|
||||
|
||||
void status::readLastState()
|
||||
{
|
||||
int iMode;
|
||||
string deffname = HomeDir;
|
||||
deffname.append("fldigi.status");
|
||||
ifstream deffile(deffname.c_str(), ios::in);
|
||||
if (deffile) {
|
||||
deffile >> iMode;
|
||||
deffile.close();
|
||||
lastmode = (trx_mode)iMode;
|
||||
}
|
||||
}
|
||||
|
||||
void status::initLastState()
|
||||
{
|
||||
switch (lastmode) {
|
||||
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.close();
|
||||
}
|
||||
trx_mode m = (trx_mode) lastmode;
|
||||
switch (m) {
|
||||
case MODE_CW : initCW(); break;
|
||||
case MODE_MFSK8 : initMFSK8(); break;
|
||||
case MODE_MFSK16 : initMFSK16(); break;
|
||||
|
@ -86,4 +118,14 @@ void status::initLastState()
|
|||
active_modem->set_freq(progdefaults.RTTYsweetspot);
|
||||
else
|
||||
active_modem->set_freq(progdefaults.PSKsweetspot);
|
||||
|
||||
fl_digi_main->resize(mainX, mainY, mainW, mainH);
|
||||
if (rigShown == true) {
|
||||
if (!rigcontrol)
|
||||
createRigDialog();
|
||||
int rdW = rigcontrol->w();
|
||||
int rdH = rigcontrol->h();
|
||||
rigcontrol->resize(rigX, rigY, rdW, rdH);
|
||||
rigcontrol->show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ void olivia::tx_init(cSound *sc)
|
|||
|
||||
preamblesent = 0;
|
||||
postamblesent = 0;
|
||||
txbasefreq = tx_frequency;
|
||||
txbasefreq = get_txfreq_woffset();
|
||||
|
||||
Rx->Flush();
|
||||
|
||||
|
@ -279,7 +279,7 @@ void olivia::restart()
|
|||
Tx->Bandwidth = 125 * (1 << bw);
|
||||
Tx->SampleRate = 8000.0;//samplerate;
|
||||
Tx->OutputSampleRate = samplerate;
|
||||
txbasefreq = tx_frequency;
|
||||
txbasefreq = get_txfreq_woffset();
|
||||
|
||||
if (reverse) {
|
||||
Tx->FirstCarrierMultiplier = (txbasefreq + (Tx->Bandwidth / 2)) / 500;
|
||||
|
|
|
@ -76,7 +76,7 @@ void psk::rx_init()
|
|||
dcd = 0;
|
||||
bitclk = 0;
|
||||
freqerr = 0.0;
|
||||
if (mailserver) sigsearch = 3;
|
||||
if (mailserver && progdefaults.PSKmailSweetSpot) sigsearch = 3;
|
||||
digiscope->mode(Digiscope::PHASE);
|
||||
put_MODEstatus(mode);
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ psk::psk(trx_mode pskmode) : modem()
|
|||
wfid = new id(this);
|
||||
|
||||
pipeptr = 0;
|
||||
if (mailserver)
|
||||
if (mailserver && progdefaults.PSKmailSweetSpot)
|
||||
sigsearch = 3;
|
||||
else
|
||||
sigsearch = 0;
|
||||
|
@ -283,7 +283,7 @@ void psk::searchUp()
|
|||
void psk::afc()
|
||||
{
|
||||
double error, ftest, sigpwr, noise;
|
||||
if (mailserver)
|
||||
if (mailserver && progdefaults.PSKmailSweetSpot)
|
||||
ftest = wf->peakFreq((int)progdefaults.PSKsweetspot, (int) bandwidth);
|
||||
else
|
||||
ftest = wf->peakFreq((int)frequency, (int)(bandwidth) );
|
||||
|
@ -293,7 +293,8 @@ void psk::afc()
|
|||
if (sigsearch) {
|
||||
freqerr = 0.0;
|
||||
if (sigpwr/noise > 2.0) {//afcthreshold) {
|
||||
if (!mailserver || (mailserver && (fabs(progdefaults.PSKsweetspot - ftest) < 15))) {
|
||||
if (!mailserver || (mailserver && !progdefaults.PSKmailSweetSpot) ||
|
||||
(mailserver && (fabs(progdefaults.PSKsweetspot - ftest) < 15))) {
|
||||
frequency = ftest;
|
||||
set_freq(frequency);
|
||||
sigsearch--;
|
||||
|
@ -316,7 +317,7 @@ void psk::afc()
|
|||
set_freq (frequency);
|
||||
//sprintf(phasemsg,"%5.4f %8.2f", freqerr, frequency);
|
||||
//put_status(phasemsg);
|
||||
} else if (mailserver)
|
||||
} else if (mailserver && progdefaults.PSKmailSweetSpot)
|
||||
sigsearch = 3;
|
||||
}
|
||||
|
||||
|
@ -495,7 +496,7 @@ void psk::tx_symbol(int sym)
|
|||
}
|
||||
symbol = prevsymbol * symbol; // complex multiplication
|
||||
|
||||
delta = 2.0 * M_PI * tx_frequency / samplerate;
|
||||
delta = 2.0 * M_PI * get_txfreq_woffset() / samplerate;
|
||||
|
||||
for (int i = 0; i < symbollen; i++) {
|
||||
|
||||
|
|
|
@ -27,33 +27,37 @@ cSound::cSound(const char *dev ) {
|
|||
|
||||
try {
|
||||
int err;
|
||||
snd_buffer = new float[SND_BUF_LEN];
|
||||
src_buffer = new float[SND_BUF_LEN];
|
||||
cbuff = new unsigned char [2 * SND_BUF_LEN];
|
||||
snd_buffer = new float [2*SND_BUF_LEN]; //new float[SND_BUF_LEN];
|
||||
src_buffer = new float [2*SND_BUF_LEN]; //new float[SND_BUF_LEN];
|
||||
cbuff = new unsigned char [4 * SND_BUF_LEN]; //new unsigned char [2 * SND_BUF_LEN];
|
||||
if (!snd_buffer || !src_buffer || !cbuff)
|
||||
throw("Cannot create src buffers");
|
||||
for (int i = 0; i < SND_BUF_LEN; i++)
|
||||
// for (int i = 0; i < SND_BUF_LEN; i++)
|
||||
for (int i = 0; i < 2*SND_BUF_LEN; i++)
|
||||
snd_buffer[i] = src_buffer[i] = 0.0;
|
||||
for (int i = 0; i < 2 * SND_BUF_LEN; i++)
|
||||
// for (int i = 0; i < 2 * SND_BUF_LEN; i++)
|
||||
for (int i = 0; i < 4 * SND_BUF_LEN; i++)
|
||||
cbuff[i] = 0;
|
||||
|
||||
tx_src_data = new SRC_DATA;
|
||||
rx_src_data = new SRC_DATA;
|
||||
if (!tx_src_data || !rx_src_data)
|
||||
throw("Cannot create source data structures");
|
||||
rx_src_state = src_new(SRC_SINC_FASTEST, 1, &err);
|
||||
|
||||
// rx_src_state = src_new(SRC_SINC_FASTEST, 1, &err);
|
||||
rx_src_state = src_new(SRC_SINC_FASTEST, 2, &err);
|
||||
if (rx_src_state == 0)
|
||||
throw(src_strerror(err));
|
||||
tx_src_data->src_ratio = 1.0;
|
||||
tx_src_state = src_new(SRC_SINC_FASTEST, 1, &err);
|
||||
if (rx_src_state == 0)
|
||||
|
||||
// tx_src_state = src_new(SRC_SINC_FASTEST, 1, &err);
|
||||
tx_src_state = src_new(SRC_SINC_FASTEST, 2, &err);
|
||||
if (tx_src_state == 0)
|
||||
throw(src_strerror(err));
|
||||
|
||||
rx_src_data->src_ratio = 1.0/(1.0 + rxppm/1e6);
|
||||
src_set_ratio ( rx_src_state, 1.0/(1.0 + rxppm/1e6));
|
||||
|
||||
// tx_src_data->src_ratio = 1.0/(1.0 + txppm/1e6);
|
||||
tx_src_data->src_ratio = 1.0 + txppm/1e6; // for gmfsk compatibility
|
||||
// src_set_ratio ( tx_src_state, 1.0/(1.0 + txppm/1e6));
|
||||
tx_src_data->src_ratio = 1.0 + txppm/1e6;
|
||||
src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
|
||||
}
|
||||
catch (SndException){
|
||||
|
@ -99,7 +103,8 @@ int cSound::Open(int md, int freq)
|
|||
if (device_fd == -1)
|
||||
throw SndException(errno);
|
||||
Format(AFMT_S16_LE); // default: 16 bit little endian
|
||||
Channels(1); // 1 channel
|
||||
// Channels(1); // 1 channel
|
||||
Channels(2); // 2 channels
|
||||
Frequency(freq);
|
||||
setfragsize();
|
||||
}
|
||||
|
@ -239,10 +244,12 @@ int cSound::Read(double *buffer, int buffersize)
|
|||
if (device_fd == -1)
|
||||
return -1;
|
||||
|
||||
numread = Read(cbuff, buffersize * 2);
|
||||
numread = Read(cbuff, buffersize * 4);
|
||||
for (int i = 0; i < buffersize * 2; i++)
|
||||
src_buffer[i] = ibuff[i] / MAXSC;
|
||||
|
||||
for (int i = 0; i < buffersize; i++)
|
||||
src_buffer[i] =
|
||||
buffer[i] = ibuff[i] / MAXSC;
|
||||
buffer[i] = src_buffer[2*i];
|
||||
|
||||
if (rxppm != progdefaults.RX_corr) {
|
||||
rxppm = progdefaults.RX_corr;
|
||||
|
@ -253,6 +260,7 @@ int cSound::Read(double *buffer, int buffersize)
|
|||
return buffersize;
|
||||
|
||||
// process using samplerate library
|
||||
|
||||
rx_src_data->data_in = src_buffer;
|
||||
rx_src_data->input_frames = buffersize;
|
||||
rx_src_data->data_out = snd_buffer;
|
||||
|
@ -265,9 +273,10 @@ int cSound::Read(double *buffer, int buffersize)
|
|||
numread = rx_src_data->output_frames_gen;
|
||||
|
||||
for (int i = 0; i < numread; i++)
|
||||
buffer[i] = snd_buffer[i];
|
||||
buffer[i] = snd_buffer[2*i];
|
||||
|
||||
return numread;
|
||||
|
||||
}
|
||||
|
||||
int cSound::write_samples(double *buf, int count)
|
||||
|
@ -281,28 +290,26 @@ int cSound::write_samples(double *buf, int count)
|
|||
|
||||
if (txppm != progdefaults.TX_corr) {
|
||||
txppm = progdefaults.TX_corr;
|
||||
// tx_src_data->src_ratio = 1.0/(1.0 + txppm/1e6);
|
||||
// src_set_ratio ( tx_src_state, 1.0/(1.0 + txppm/1e6));
|
||||
tx_src_data->src_ratio = 1.0 + txppm/1e6;
|
||||
src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
|
||||
}
|
||||
|
||||
if (txppm == 0) {
|
||||
wbuff = new short int[count];
|
||||
wbuff = new short int[2*count];
|
||||
p = (unsigned char *)wbuff;
|
||||
for (int i = 0; i < count; i++) {
|
||||
wbuff[i] = (short int)(buf[i] * maxsc);
|
||||
wbuff[2*i] = wbuff[2*i+1] = (short int)(buf[i] * maxsc);
|
||||
}
|
||||
count *= sizeof(short int);
|
||||
retval = Write(p, count);
|
||||
retval = Write(p, 2*count);
|
||||
delete [] wbuff;
|
||||
}
|
||||
else {
|
||||
float *inbuf;
|
||||
inbuf = new float[count];
|
||||
inbuf = new float[2*count];
|
||||
int bufsize;
|
||||
for (int i = 0; i < count; i++)
|
||||
inbuf[i] = buf[i];
|
||||
inbuf[2*i] = inbuf[2*i+1] = buf[i];
|
||||
tx_src_data->data_in = inbuf;
|
||||
tx_src_data->input_frames = count;
|
||||
tx_src_data->data_out = src_buffer;
|
||||
|
@ -315,15 +322,80 @@ int cSound::write_samples(double *buf, int count)
|
|||
}
|
||||
delete [] inbuf;
|
||||
bufsize = tx_src_data->output_frames_gen;
|
||||
wbuff = new short int[bufsize];
|
||||
wbuff = new short int[2*bufsize];
|
||||
p = (unsigned char *)wbuff;
|
||||
|
||||
for (int i = 0; i < bufsize; i++)
|
||||
for (int i = 0; i < 2*bufsize; i++)
|
||||
wbuff[i] = (short int)(src_buffer[i] * maxsc);
|
||||
int num2write = bufsize * 2 * sizeof(short int);
|
||||
|
||||
retval = Write(p, bufsize * 2);
|
||||
retval = Write(p, num2write);
|
||||
delete [] wbuff;
|
||||
if (retval != bufsize * 2)
|
||||
if (retval != num2write)
|
||||
return -1;
|
||||
retval = count;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int cSound::write_stereo(double *bufleft, double *bufright, int count)
|
||||
{
|
||||
int retval;
|
||||
short int *wbuff;
|
||||
unsigned char *p;
|
||||
|
||||
if (device_fd == -1 || count <= 0)
|
||||
return -1;
|
||||
|
||||
if (txppm != progdefaults.TX_corr) {
|
||||
txppm = progdefaults.TX_corr;
|
||||
tx_src_data->src_ratio = 1.0 + txppm/1e6;
|
||||
src_set_ratio ( tx_src_state, 1.0 + txppm/1e6);
|
||||
}
|
||||
|
||||
if (txppm == 0) {
|
||||
wbuff = new short int[count];
|
||||
wbuff = new short int[2*count];
|
||||
p = (unsigned char *)wbuff;
|
||||
for (int i = 0; i < count; i++) {
|
||||
wbuff[2*i] = (short int)(bufleft[i] * maxsc);
|
||||
wbuff[2*i + 1] = (short int)(bufright[i] * maxsc);
|
||||
}
|
||||
count *= sizeof(short int);
|
||||
retval = Write(p, 2*count);
|
||||
delete [] wbuff;
|
||||
}
|
||||
else {
|
||||
float *inbuf;
|
||||
inbuf = new float[2*count];
|
||||
int bufsize;
|
||||
for (int i = 0; i < count; i++) {
|
||||
inbuf[2*i] = bufleft[i];
|
||||
inbuf[2*i+1] = bufright[i];
|
||||
}
|
||||
tx_src_data->data_in = inbuf;
|
||||
tx_src_data->input_frames = count;
|
||||
tx_src_data->data_out = src_buffer;
|
||||
tx_src_data->output_frames = SND_BUF_LEN;
|
||||
tx_src_data->end_of_input = 0;
|
||||
|
||||
if (src_process(tx_src_state, tx_src_data) != 0) {
|
||||
delete [] inbuf;
|
||||
return -1;
|
||||
}
|
||||
delete [] inbuf;
|
||||
bufsize = tx_src_data->output_frames_gen;
|
||||
wbuff = new short int[2*bufsize];
|
||||
p = (unsigned char *)wbuff;
|
||||
|
||||
for (int i = 0; i < 2*bufsize; i++)
|
||||
wbuff[i] = (short int)(src_buffer[i] * maxsc);
|
||||
|
||||
int num2write = bufsize * 2 * sizeof(short int);
|
||||
retval = Write(p, num2write);
|
||||
delete [] wbuff;
|
||||
if (retval != num2write)
|
||||
return -1;
|
||||
retval = count;
|
||||
}
|
||||
|
|
|
@ -592,8 +592,8 @@ void throb::send(int symbol)
|
|||
tone2 = (num_tones - 1) - tone2;
|
||||
}
|
||||
|
||||
w1 = 2.0 * M_PI * (tx_frequency + freqs[tone1]) / THROB_SAMPLE_RATE;
|
||||
w2 = 2.0 * M_PI * (tx_frequency + freqs[tone2]) / THROB_SAMPLE_RATE;
|
||||
w1 = 2.0 * M_PI * (get_txfreq_woffset() + freqs[tone1]) / THROB_SAMPLE_RATE;
|
||||
w2 = 2.0 * M_PI * (get_txfreq_woffset() + freqs[tone2]) / THROB_SAMPLE_RATE;
|
||||
|
||||
for (i = 0; i < symlen; i++)
|
||||
outbuf[i] = txpulse[i] *
|
||||
|
|
|
@ -110,6 +110,10 @@ double modem::get_txfreq(void)
|
|||
return tx_frequency;
|
||||
}
|
||||
|
||||
double modem::get_txfreq_woffset(void)
|
||||
{
|
||||
return (tx_frequency - progdefaults.TxOffset);
|
||||
}
|
||||
|
||||
int modem::get_freq()
|
||||
{
|
||||
|
@ -202,3 +206,18 @@ void modem::ModulateXmtr(double *buffer, int len)
|
|||
}
|
||||
}
|
||||
|
||||
void modem::ModulateStereo(double *left, double *right, int len)
|
||||
{
|
||||
scard->write_stereo(left, right, len);
|
||||
if (progdefaults.viewXmtSignal)
|
||||
for (int i = 0; i < len; i++) {
|
||||
scdata[scptr] = left[i] * 0.1;
|
||||
scptr++;
|
||||
if (scptr == 512) {
|
||||
wf->sig_data(scdata, 512);
|
||||
scptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -158,13 +158,13 @@ void trx_tune_loop()
|
|||
while (trx_state == STATE_TUNE) {
|
||||
if (_trx_tune == 0) {
|
||||
wf->set_XmtRcvBtn(true);
|
||||
xmttune::keydown(active_modem->get_txfreq(), scard);
|
||||
xmttune::keydown(active_modem->get_txfreq_woffset(), scard);
|
||||
_trx_tune = 1;
|
||||
} else
|
||||
xmttune::tune(active_modem->get_txfreq(), scard);
|
||||
xmttune::tune(active_modem->get_txfreq_woffset(), scard);
|
||||
}
|
||||
scard->Close();
|
||||
xmttune::keyup(active_modem->get_txfreq(), scard);
|
||||
xmttune::keyup(active_modem->get_txfreq_woffset(), scard);
|
||||
_trx_tune = 0;
|
||||
} else
|
||||
MilliSleep(10);
|
||||
|
|
Ładowanie…
Reference in New Issue