kopia lustrzana https://github.com/jamescoxon/dl-fldigi
Upstream version 2.11AJ
rodzic
713f7e18ed
commit
eb5bd6f512
|
@ -81,6 +81,10 @@ Change Log:
|
|||
35) Bug fixes for the FM Hell modes
|
||||
36) Changed the way that the video text / id is generated.
|
||||
37) Added XML-RPC support.
|
||||
38) Added Audio Device identification display (on Help menu)
|
||||
39) Added transmit & receive Reed Solomon mode identifier. Automatic
|
||||
detection, mode change and frequency centering during receive.
|
||||
ID sent at beginning of each transmission (toggled on Misc tab).
|
||||
|
||||
2.10.3)
|
||||
1) Corrected memory leak bug.
|
||||
|
|
|
@ -9,7 +9,7 @@ dnl major and minor must be integers; patch may
|
|||
dnl contain other characters or be empty
|
||||
m4_define(FLDIGI_MAJOR, [2])
|
||||
m4_define(FLDIGI_MINOR, [11])
|
||||
m4_define(FLDIGI_PATCH, [AI])
|
||||
m4_define(FLDIGI_PATCH, [AJ])
|
||||
|
||||
AC_INIT([fldigi], FLDIGI_MAJOR.FLDIGI_MINOR[FLDIGI_PATCH], [w1hkj AT w1hkj DOT com])
|
||||
|
||||
|
|
|
@ -13,29 +13,26 @@ m4_if([$3], [yes],
|
|||
])
|
||||
m4_if([$4], [no], [ac_cv_want_[]$1=yes])
|
||||
|
||||
if test "x$ac_cv_want_[]$1" = "xno"; then
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 0)
|
||||
ac_cv_[]$1=no
|
||||
case "x$ac_cv_want_[]$1" in
|
||||
"xno")
|
||||
ac_cv_[]$1=no
|
||||
;;
|
||||
"xcheck")
|
||||
PKG_CHECK_MODULES(PKG_NAME_UC, [$2], [ac_cv_[]$1=yes], [ac_cv_[]$1=no])
|
||||
;;
|
||||
"xyes")
|
||||
PKG_CHECK_MODULES(PKG_NAME_UC, [$2])
|
||||
# if we get here the test has succeeded
|
||||
ac_cv_[]$1=yes
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "x$ac_cv_[]$1" = "xyes"; then
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 1, [Define to 1 if we are using $1])
|
||||
else
|
||||
PKG_CHECK_EXISTS([$2], ac_cv_[]$1=yes, ac_cv_[]$1=no)
|
||||
if test "x$ac_cv_want_[]$1" = "xcheck"; then
|
||||
PKG_CHECK_MODULES(PKG_NAME_UC, [$2], [:], [:])
|
||||
if test "x$ac_cv_[]$1" = "xyes"; then
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 1, [Define to 1 if we are using $1])
|
||||
else
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 0, [Define to 1 if we are using $1])
|
||||
fi
|
||||
else # $ac_cv_want_[]$1 is yes
|
||||
if test "x$ac_cv_[]$1" = "xno"; then
|
||||
if test "x$3" = "xyes"; then
|
||||
AC_MSG_NOTICE([--with-[]$1 was given, but test for $1 failed])
|
||||
fi
|
||||
else
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 1, [Define to 1 if we are using $1])
|
||||
fi
|
||||
PKG_CHECK_MODULES(PKG_NAME_UC, $2) # for the error message
|
||||
fi
|
||||
AC_DEFINE([USE_]PKG_NAME_UC, 0, [Define to 1 if we are using $1])
|
||||
fi
|
||||
|
||||
AC_SUBST(PKG_NAME_UC[_CFLAGS])
|
||||
AC_SUBST(PKG_NAME_UC[_LIBS])
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
AC_DEFUN([AC_FLDIGI_STATIC], [
|
||||
AC_ARG_ENABLE([static],
|
||||
AC_HELP_STRING([--enable-static], [enable static linking]),
|
||||
AC_HELP_STRING([--enable-static], [enable static linking for some libraries]),
|
||||
[case "${enableval}" in
|
||||
yes|no) ac_cv_static="${enableval}" ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-static]) ;;
|
||||
|
|
24
m4/xmlrpc.m4
24
m4/xmlrpc.m4
|
@ -1,10 +1,19 @@
|
|||
AC_DEFUN([AC_FLDIGI_XMLRPC_CONFIG], [
|
||||
ac_cv_xmlrpc=no
|
||||
AC_PATH_PROG([XMLRPC_C_CONFIG], [xmlrpc-c-config], [no])
|
||||
if test "x$XMLRPC_C_CONFIG" != "xno" && $XMLRPC_C_CONFIG c++2 abyss-server; then
|
||||
XMLRPC_CFLAGS=`$XMLRPC_C_CONFIG c++2 abyss-server --cflags`
|
||||
XMLRPC_LIBS=`$XMLRPC_C_CONFIG c++2 abyss-server --ldadd`
|
||||
|
||||
if test "x$XMLRPC_CFLAGS" != "x" && test "x$XMLRPC_LIBS" != "x"; then
|
||||
ac_cv_xmlrpc=yes
|
||||
else
|
||||
AC_PATH_PROG([XMLRPC_C_CONFIG], [xmlrpc-c-config], [no])
|
||||
if test "x$XMLRPC_C_CONFIG" != "xno" && $XMLRPC_C_CONFIG c++2 abyss-server; then
|
||||
ac_cv_xmlrpc=yes
|
||||
|
||||
test "x$XMLRPC_CFLAGS" = "x" && XMLRPC_CFLAGS=`$XMLRPC_C_CONFIG c++2 abyss-server --cflags`
|
||||
if test "x$XMLRPC_LIBS" = "x"; then
|
||||
XMLRPC_LIBS=`$XMLRPC_C_CONFIG c++2 abyss-server --ldadd`
|
||||
test "$ac_cv_static" = "yes" && XMLRPC_LIBS="-Wl,-Bstatic $XMLRPC_LIBS -Wl,-Bdynamic"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
|
@ -24,19 +33,14 @@ AC_DEFUN([AC_FLDIGI_XMLRPC], [
|
|||
AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc])
|
||||
ac_cv_xmlrpc=no
|
||||
else
|
||||
AC_FLDIGI_XMLRPC_CONFIG
|
||||
if test "x$ac_cv_want_xmlrpc" = "xcheck"; then
|
||||
AC_FLDIGI_XMLRPC_CONFIG
|
||||
if test "x$ac_cv_xmlrpc" = "xyes"; then
|
||||
AC_DEFINE(USE_XMLRPC, 1, [Define to 1 if we are using xmlrpc])
|
||||
else
|
||||
AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc])
|
||||
fi
|
||||
else # $ac_cv_want_xmlrpc is yes
|
||||
if test "x$XMLRPC_CFLAGS" != "x" || test "x$XMLRPC_LIBS" != "x"; then
|
||||
ac_cv_xmlrpc=yes
|
||||
else
|
||||
AC_FLDIGI_XMLRPC_CONFIG
|
||||
fi
|
||||
if test "x$ac_cv_xmlrpc" = "xno"; then
|
||||
AC_MSG_FAILURE([--with-xmlrpc was given, but check for libxmlrpc-c failed])
|
||||
else
|
||||
|
|
|
@ -215,6 +215,7 @@ fldigi_SOURCES += \
|
|||
include/rigsupport.h \
|
||||
include/rigxml.h \
|
||||
include/ringbuffer.h \
|
||||
include/rsid.h \
|
||||
include/rtty.h \
|
||||
include/serial.h \
|
||||
include/sound.h \
|
||||
|
@ -282,6 +283,7 @@ fldigi_SOURCES += \
|
|||
rigcontrol/rigsupport.cxx \
|
||||
rigcontrol/rigxml.cxx \
|
||||
rigcontrol/serial.cxx \
|
||||
rsid/rsid.cxx \
|
||||
soundcard/mixer.cxx \
|
||||
soundcard/sound.cxx \
|
||||
soundcard/soundconf.cxx \
|
||||
|
@ -332,7 +334,9 @@ EXTRA_fldigi_SOURCES += \
|
|||
mt63/symbol.dat \
|
||||
mt63/alias_k5.dat \
|
||||
mt63/mt63intl.dat \
|
||||
trx/tune.cxx
|
||||
trx/tune.cxx \
|
||||
rsid/rsid_fft.cxx \
|
||||
rsid/rsid_fft.h
|
||||
|
||||
# Additional non-source files that we distribute
|
||||
EXTRA_DIST = \
|
||||
|
|
|
@ -778,6 +778,13 @@ static void cb_btnStartAtSweetSpot(Fl_Check_Button* o, void*) {
|
|||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Check_Button *chkTransmitRSid=(Fl_Check_Button *)0;
|
||||
|
||||
static void cb_chkTransmitRSid(Fl_Check_Button* o, void*) {
|
||||
progdefaults.TransmitRSid = o->value();
|
||||
progdefaults.changed = true;
|
||||
}
|
||||
|
||||
Fl_Group *tabModems=(Fl_Group *)0;
|
||||
|
||||
Fl_Tabs *tabsModems=(Fl_Tabs *)0;
|
||||
|
@ -1534,6 +1541,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
{ tabVideo = new Fl_Group(0, 25, 400, 195, "Video");
|
||||
tabVideo->color((Fl_Color)51);
|
||||
tabVideo->selection_color((Fl_Color)51);
|
||||
tabVideo->hide();
|
||||
{ Fl_Group* o = new Fl_Group(5, 40, 390, 77, "Video Preamble");
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
|
@ -1771,20 +1779,18 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
{ tabSoundCard = new Fl_Group(0, 25, 400, 195, "SndCrd");
|
||||
tabSoundCard->color((Fl_Color)51);
|
||||
tabSoundCard->selection_color((Fl_Color)51);
|
||||
tabSoundCard->hide();
|
||||
{ tabsSoundCard = new Fl_Tabs(0, 25, 400, 195);
|
||||
tabsSoundCard->selection_color((Fl_Color)10);
|
||||
{ tabAudio = new Fl_Group(0, 50, 400, 170, "Audio devices");
|
||||
tabAudio->color((Fl_Color)51);
|
||||
tabAudio->selection_color((Fl_Color)51);
|
||||
tabAudio->hide();
|
||||
{ AudioOSS = new Fl_Group(5, 58, 391, 35);
|
||||
AudioOSS->box(FL_ENGRAVED_FRAME);
|
||||
{ btnAudioIO[0] = new Fl_Round_Button(5, 63, 100, 25, "OSS");
|
||||
btnAudioIO[0]->down_box(FL_DIAMOND_DOWN_BOX);
|
||||
btnAudioIO[0]->selection_color((Fl_Color)1);
|
||||
btnAudioIO[0]->callback((Fl_Callback*)cb_btnAudioIO);
|
||||
} // Fl_Round_Button* btnAudioIO[0]
|
||||
{ btnAudioIO[1] = new Fl_Round_Button(5, 63, 100, 25, "OSS");
|
||||
btnAudioIO[1]->down_box(FL_DIAMOND_DOWN_BOX);
|
||||
btnAudioIO[1]->selection_color((Fl_Color)1);
|
||||
btnAudioIO[1]->callback((Fl_Callback*)cb_btnAudioIO);
|
||||
} // Fl_Round_Button* btnAudioIO[1]
|
||||
{ Fl_Input_Choice* o = menuOSSDev = new Fl_Input_Choice(280, 63, 110, 25, "Device");
|
||||
menuOSSDev->callback((Fl_Callback*)cb_menuOSSDev);
|
||||
o->value(progdefaults.OSSdevice.c_str());
|
||||
|
@ -1793,11 +1799,11 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
} // Fl_Group* AudioOSS
|
||||
{ AudioPort = new Fl_Group(5, 95, 390, 61);
|
||||
AudioPort->box(FL_ENGRAVED_FRAME);
|
||||
{ btnAudioIO[1] = new Fl_Round_Button(5, 115, 95, 25, "PortAudio");
|
||||
btnAudioIO[1]->down_box(FL_DIAMOND_DOWN_BOX);
|
||||
btnAudioIO[1]->selection_color((Fl_Color)1);
|
||||
btnAudioIO[1]->callback((Fl_Callback*)cb_btnAudioIO1);
|
||||
} // Fl_Round_Button* btnAudioIO[1]
|
||||
{ btnAudioIO[0] = new Fl_Round_Button(5, 115, 95, 25, "PortAudio");
|
||||
btnAudioIO[0]->down_box(FL_DIAMOND_DOWN_BOX);
|
||||
btnAudioIO[0]->selection_color((Fl_Color)1);
|
||||
btnAudioIO[0]->callback((Fl_Callback*)cb_btnAudioIO1);
|
||||
} // Fl_Round_Button* btnAudioIO[0]
|
||||
{ menuPortInDev = new Fl_Choice(165, 99, 225, 25, "Capture");
|
||||
menuPortInDev->down_box(FL_BORDER_BOX);
|
||||
menuPortInDev->callback((Fl_Callback*)cb_menuPortInDev);
|
||||
|
@ -1836,6 +1842,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
{ tabAudioOpt = new Fl_Group(0, 50, 400, 170, "Audio settings");
|
||||
tabAudioOpt->color((Fl_Color)51);
|
||||
tabAudioOpt->selection_color((Fl_Color)51);
|
||||
tabAudioOpt->hide();
|
||||
{ Fl_Spinner* o = cntRxRateCorr = new Fl_Spinner(5, 160, 85, 25, "RX ppm");
|
||||
cntRxRateCorr->value(1);
|
||||
cntRxRateCorr->callback((Fl_Callback*)cb_cntRxRateCorr);
|
||||
|
@ -1968,6 +1975,17 @@ l with your sound hardware.");
|
|||
} // Fl_Check_Button* btnStartAtSweetSpot
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ Fl_Group* o = new Fl_Group(5, 125, 390, 50, "RSid");
|
||||
o->box(FL_ENGRAVED_FRAME);
|
||||
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
|
||||
{ Fl_Check_Button* o = chkTransmitRSid = new Fl_Check_Button(50, 143, 70, 15, "Transmit RSid");
|
||||
chkTransmitRSid->tooltip("Transmit Reed Solomon ID");
|
||||
chkTransmitRSid->down_box(FL_DOWN_BOX);
|
||||
chkTransmitRSid->callback((Fl_Callback*)cb_chkTransmitRSid);
|
||||
o->value(progdefaults.TransmitRSid);
|
||||
} // Fl_Check_Button* chkTransmitRSid
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
tabMisc->end();
|
||||
} // Fl_Group* tabMisc
|
||||
{ tabModems = new Fl_Group(0, 25, 401, 195, "Modem");
|
||||
|
|
|
@ -37,7 +37,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
|
|||
code {} {}
|
||||
Fl_Window {} {
|
||||
label {fldigi - config} open
|
||||
xywh {523 186 400 250} type Double color 45 selection_color 51 align 80 visible
|
||||
xywh {809 461 400 250} type Double color 45 selection_color 51 align 80 visible
|
||||
} {
|
||||
Fl_Tabs tabsConfigure {open
|
||||
xywh {0 0 405 220} color 47 selection_color 9
|
||||
|
@ -326,7 +326,7 @@ progdefaults.changed = true;
|
|||
}
|
||||
Fl_Group tabVideo {
|
||||
label Video open
|
||||
xywh {0 25 400 195} color 51 selection_color 51
|
||||
xywh {0 25 400 195} color 51 selection_color 51 hide
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Video Preamble} open
|
||||
|
@ -367,7 +367,7 @@ if (o->value() == 1)
|
|||
sldrVideowidth->deactivate();
|
||||
else
|
||||
sldrVideowidth->activate();
|
||||
progdefaults.changed = true;} selected
|
||||
progdefaults.changed = true;}
|
||||
xywh {290 49 100 20} down_box DOWN_BOX value 1
|
||||
code0 {o->value(progdefaults.ID_SMALL);}
|
||||
}
|
||||
|
@ -683,19 +683,19 @@ o->label((inpQRZuserpassword->type() & FL_SECRET_INPUT) ? "Show" : "Hide");}
|
|||
}
|
||||
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_Tabs tabsSoundCard {open
|
||||
xywh {0 25 400 195} selection_color 10
|
||||
} {
|
||||
Fl_Group tabAudio {
|
||||
label {Audio devices} open
|
||||
xywh {0 50 400 170} color 51 selection_color 51 hide
|
||||
xywh {0 50 400 170} color 51 selection_color 51
|
||||
} {
|
||||
Fl_Group AudioOSS {open
|
||||
xywh {5 58 391 35} box ENGRAVED_FRAME
|
||||
} {
|
||||
Fl_Round_Button {btnAudioIO[0]} {
|
||||
Fl_Round_Button {btnAudioIO[1]} {
|
||||
label OSS
|
||||
callback {sound_update(SND_IDX_OSS);
|
||||
progdefaults.changed = true;
|
||||
|
@ -714,7 +714,7 @@ progdefaults.changed = true;} open
|
|||
Fl_Group AudioPort {open
|
||||
xywh {5 95 390 61} box ENGRAVED_FRAME
|
||||
} {
|
||||
Fl_Round_Button {btnAudioIO[1]} {
|
||||
Fl_Round_Button {btnAudioIO[0]} {
|
||||
label PortAudio
|
||||
callback {sound_update(SND_IDX_PORT);
|
||||
progdefaults.changed = true;
|
||||
|
@ -765,14 +765,14 @@ http://www.pulseaudio.org/wiki/ServerStrings} xywh {165 161 225 25}
|
|||
label {File I/O only}
|
||||
callback {sound_update(SND_IDX_NULL);
|
||||
progdefaults.changed = true;
|
||||
resetSoundCard();}
|
||||
resetSoundCard();} selected
|
||||
xywh {5 192 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabAudioOpt {
|
||||
label {Audio settings} open
|
||||
xywh {0 50 400 170} color 51 selection_color 51
|
||||
xywh {0 50 400 170} color 51 selection_color 51 hide
|
||||
} {
|
||||
Fl_Spinner cntRxRateCorr {
|
||||
label {RX ppm}
|
||||
|
@ -933,6 +933,18 @@ progdefaults.changed = true;}
|
|||
code0 {o->value(progdefaults.StartAtSweetSpot);}
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label RSid open
|
||||
xywh {5 125 390 50} box ENGRAVED_FRAME align 21
|
||||
} {
|
||||
Fl_Check_Button chkTransmitRSid {
|
||||
label {Transmit RSid}
|
||||
callback {progdefaults.TransmitRSid = o->value();
|
||||
progdefaults.changed = true;}
|
||||
tooltip {Transmit Reed Solomon ID} xywh {50 143 70 15} down_box DOWN_BOX
|
||||
code0 {o->value(progdefaults.TransmitRSid);}
|
||||
}
|
||||
}
|
||||
}
|
||||
Fl_Group tabModems {
|
||||
label Modem open
|
||||
|
|
|
@ -98,6 +98,7 @@
|
|||
#include "qrunner.h"
|
||||
|
||||
#include "Viewer.h"
|
||||
#include "soundconf.h"
|
||||
|
||||
Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0;
|
||||
Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0;
|
||||
|
@ -207,7 +208,7 @@ Fl_Menu_Item quick_change_thor[] = {
|
|||
{ mode_info[MODE_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5 },
|
||||
{ mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8 },
|
||||
{ mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11 },
|
||||
{ mode_info[MODE_TSOR11].name, 0, cb_init_mode, (void *)MODE_TSOR11 },
|
||||
// { mode_info[MODE_TSOR11].name, 0, cb_init_mode, (void *)MODE_TSOR11 },
|
||||
{ mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16 },
|
||||
{ mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22 },
|
||||
{ 0 }
|
||||
|
@ -404,7 +405,7 @@ void init_modem(trx_mode mode)
|
|||
break;
|
||||
|
||||
case MODE_THOR4: case MODE_THOR5: case MODE_THOR8:
|
||||
case MODE_THOR11: case MODE_TSOR11: case MODE_THOR16: case MODE_THOR22:
|
||||
case MODE_THOR11:case MODE_THOR16: case MODE_THOR22: //case MODE_TSOR11:
|
||||
startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem :
|
||||
*mode_info[mode].modem = new thor(mode));
|
||||
quick_change = quick_change_thor;
|
||||
|
@ -807,6 +808,55 @@ void cb_mnuFun(Fl_Widget*, void*)
|
|||
}
|
||||
#endif
|
||||
|
||||
void cb_mnuAudioInfo(Fl_Widget*, void*)
|
||||
{
|
||||
if (progdefaults.btnAudioIOis != SND_IDX_PORT) {
|
||||
fl_alert("Audio device information is only available for the PortAudio backend");
|
||||
return;
|
||||
}
|
||||
|
||||
#if USE_PORTAUDIO
|
||||
size_t ndev;
|
||||
string devtext[2], headers[2];
|
||||
SoundPort::devices_info(devtext[0], devtext[1]);
|
||||
if (devtext[0] != devtext[1]) {
|
||||
headers[0] = "Capture device";
|
||||
headers[1] = "Playback device";
|
||||
ndev = 2;
|
||||
}
|
||||
else {
|
||||
headers[0] = "Capture and playback devices";
|
||||
ndev = 1;
|
||||
}
|
||||
|
||||
string audio_info;
|
||||
for (size_t i = 0; i < ndev; i++) {
|
||||
audio_info.append("<center><h4>").append(headers[i]).append("</h4>\n<table border=\"1\">\n");
|
||||
|
||||
string::size_type j, n = -1;
|
||||
while ((j = devtext[i].find(": ", n+1)) != string::npos) {
|
||||
audio_info.append("<tr>")
|
||||
.append("<td align=\"center\">")
|
||||
.append(devtext[i].substr(n+1, j-n-1))
|
||||
.append("</td>");
|
||||
|
||||
if ((n = devtext[i].find('\n', j)) == string::npos) {
|
||||
devtext[i] += '\n';
|
||||
n = devtext[i].length() - 1;
|
||||
}
|
||||
|
||||
audio_info.append("<td align=\"center\">")
|
||||
.append(devtext[i].substr(j+2, n-j-2))
|
||||
.append("</td>")
|
||||
.append("</tr>\n");
|
||||
}
|
||||
audio_info.append("</table></center><br>\n");
|
||||
}
|
||||
|
||||
fldigi_help(audio_info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cbTune(Fl_Widget *w, void *) {
|
||||
Fl_Button *b = (Fl_Button *)w;
|
||||
if (active_modem == wwv_modem || active_modem == anal_modem) {
|
||||
|
@ -1091,7 +1141,7 @@ Fl_Menu_Item menu_[] = {
|
|||
{ mode_info[MODE_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{ mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{ mode_info[MODE_THOR11].name, 0, cb_init_mode, (void *)MODE_THOR11, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{ mode_info[MODE_TSOR11].name, 0, cb_init_mode, (void *)MODE_TSOR11, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
//{ mode_info[MODE_TSOR11].name, 0, cb_init_mode, (void *)MODE_TSOR11, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{ mode_info[MODE_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{ mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{0,0,0,0,0,0,0,0,0},
|
||||
|
@ -1142,6 +1192,7 @@ Fl_Menu_Item menu_[] = {
|
|||
{"Online documentation", 0, cb_mnuVisitURL, (void *)PACKAGE_DOCS, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{"Home page", 0, cb_mnuVisitURL, (void *)PACKAGE_HOME, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{"Command line options", 0, cb_mnuCmdLineHelp, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{"Audio device info", 0, cb_mnuAudioInfo, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{"Build info", 0, cb_mnuBuildInfo, 0, FL_MENU_DIVIDER, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{"About", 0, cb_mnuAbout, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
|
||||
{0,0,0,0,0,0,0,0,0},
|
||||
|
@ -1964,7 +2015,7 @@ void resetTHOR() {
|
|||
md == MODE_THOR5 ||
|
||||
md == MODE_THOR8 ||
|
||||
md == MODE_THOR11 ||
|
||||
md == MODE_TSOR11 ||
|
||||
// md == MODE_TSOR11 ||
|
||||
md == MODE_THOR16 ||
|
||||
md == MODE_THOR22 ) {
|
||||
active_modem->restart();
|
||||
|
@ -2098,36 +2149,6 @@ void setReverse(int rev) {
|
|||
active_modem->set_reverse(rev);
|
||||
}
|
||||
|
||||
/*
|
||||
void setAfcOnOff(bool b) {
|
||||
FL_LOCK();
|
||||
afconoff->value(b);
|
||||
FL_UNLOCK();
|
||||
FL_AWAKE();
|
||||
}
|
||||
|
||||
void setSqlOnOff(bool b) {
|
||||
FL_LOCK();
|
||||
sqlonoff->value(b);
|
||||
FL_UNLOCK();
|
||||
FL_AWAKE();
|
||||
}
|
||||
|
||||
bool QueryAfcOnOff() {
|
||||
FL_LOCK_E();
|
||||
int v = afconoff->value();
|
||||
FL_UNLOCK_E();
|
||||
return v;
|
||||
}
|
||||
|
||||
bool QuerySqlOnOff() {
|
||||
FL_LOCK_E();
|
||||
int v = sqlonoff->value();
|
||||
FL_UNLOCK_E();
|
||||
return v;
|
||||
}
|
||||
*/
|
||||
|
||||
void change_modem_param(int state)
|
||||
{
|
||||
int d;
|
||||
|
@ -2182,3 +2203,13 @@ void change_modem_param(int state)
|
|||
snprintf(msg, sizeof(msg), "Squelch = %2.0f %%", val->value());
|
||||
put_status(msg, 2);
|
||||
}
|
||||
|
||||
void start_tx()
|
||||
{
|
||||
if (progdefaults.rsid == true) return;
|
||||
fl_lock(&trx_mutex);
|
||||
if (trx_state != STATE_TX)
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
}
|
||||
|
|
|
@ -505,7 +505,7 @@ int feld::tx_process()
|
|||
// if TX buffer empty
|
||||
// send idle character
|
||||
if (c == -1) {
|
||||
if (progdefaults.FELD_IDLE == true)
|
||||
if (progdefaults.HellXmtIdle == true)
|
||||
c = '.';
|
||||
else {
|
||||
send_null_column();
|
||||
|
|
|
@ -117,6 +117,7 @@ extern Fl_Value_Input *valCWsweetspot;
|
|||
extern Fl_Value_Input *valRTTYsweetspot;
|
||||
extern Fl_Value_Input *valPSKsweetspot;
|
||||
extern Fl_Check_Button *btnStartAtSweetSpot;
|
||||
extern Fl_Check_Button *chkTransmitRSid;
|
||||
extern Fl_Group *tabModems;
|
||||
extern Fl_Tabs *tabsModems;
|
||||
extern Fl_Group *tabCW;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
using namespace std;
|
||||
|
||||
struct configuration {
|
||||
bool rsid;
|
||||
bool TransmitRSid;
|
||||
bool changed;
|
||||
double wfRefLevel;
|
||||
double wfAmpSpan;
|
||||
|
|
|
@ -151,6 +151,8 @@ extern void init_modem_sync(trx_mode mode);
|
|||
|
||||
extern void change_modem_param(int state);
|
||||
|
||||
extern void start_tx();
|
||||
|
||||
extern void colorize_macro(int i);
|
||||
extern void colorize_macros();
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
void set_metric(double);
|
||||
double get_metric();
|
||||
void set_reverse(bool on);
|
||||
bool get_reverse() { return reverse; }
|
||||
double get_bandwidth();
|
||||
void set_bandwidth(double);
|
||||
int get_samplerate();
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// rsid.h
|
||||
//
|
||||
// Copyright (C) 2006
|
||||
// Dave Freese, W1HKJ
|
||||
//
|
||||
// This file is part of fldigi.
|
||||
//
|
||||
// fldigi is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// fldigi is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with fldigi; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tone separation: 10.766Hz
|
||||
// Integer tone separator (x 16): 172
|
||||
// Error on 16 tones: 0.25Hz
|
||||
|
||||
// Tone duration: 0.093 sec
|
||||
// Tone duration, #samples at 8ksps: 743
|
||||
// Error on 15 tones: negligible
|
||||
|
||||
// 1024 samples -> 512 tones
|
||||
// 2048 samples, second half zeros
|
||||
|
||||
// each 512 samples new FFT
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef RSID_H
|
||||
#define RSID_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <cstring>
|
||||
#include <FL/Fl.H>
|
||||
|
||||
#include "globals.h"
|
||||
#include "modem.h"
|
||||
#include "fft.h"
|
||||
#include "misc.h"
|
||||
|
||||
#define RSID_FFT_SIZE 1024
|
||||
//#define RSID_FFT_SIZE 512
|
||||
#define RSID_NSYMBOLS 15
|
||||
//#define RSID_ARRAY_SIZE 1024
|
||||
#define RSID_ARRAY_SIZE (RSID_FFT_SIZE * 2)
|
||||
#define RSID_NTIMES (RSID_NSYMBOLS * 2)
|
||||
|
||||
// each rsid symbol has a duration equal to 1024 samples at 11025 Hz smpl rate
|
||||
#define RSID_SYMLEN 0.09288 // duration of each rsid symbol
|
||||
|
||||
enum {
|
||||
RSID_BANDWIDTH_500 = 0,
|
||||
RSID_BANDWIDTH_1K,
|
||||
RSID_BANDWIDTH_WIDE,
|
||||
};
|
||||
|
||||
struct RSIDs { uchar rs; trx_mode mode; };
|
||||
|
||||
class cRsId {
|
||||
private:
|
||||
int _samplerate;
|
||||
// Table of precalculated Reed Solomon symbols
|
||||
uchar *pCodes;
|
||||
|
||||
static RSIDs rsid_ids[];
|
||||
int rsid_ids_size;
|
||||
|
||||
static const int Squares[];
|
||||
static const int indices[];
|
||||
|
||||
// receive
|
||||
Cfft *rsid_fft;
|
||||
// Span of FFT bins, in which the RSID will be searched for
|
||||
int nBinLow;
|
||||
int nBinHigh;
|
||||
double aInputSamples[RSID_ARRAY_SIZE];
|
||||
double fftwindow[RSID_ARRAY_SIZE];
|
||||
double aFFTReal[RSID_ARRAY_SIZE];
|
||||
double aFFTAmpl[RSID_FFT_SIZE];
|
||||
|
||||
// Hashing tables
|
||||
uchar aHashTable1[256];
|
||||
uchar aHashTable2[256];
|
||||
|
||||
bool bPrevTimeSliceValid;
|
||||
int iPrevDistance;
|
||||
int iPrevBin;
|
||||
int iPrevSymbol;
|
||||
int iTime; // modulo RSID_NTIMES
|
||||
int aBuckets[RSID_NTIMES][RSID_FFT_SIZE];
|
||||
|
||||
int DistanceOut;
|
||||
int MetricsOut;
|
||||
|
||||
// transmit
|
||||
double phase;
|
||||
double *outbuf;
|
||||
|
||||
|
||||
private:
|
||||
void Encode(int code, uchar *rsid);
|
||||
int HammingDistance(int iBucket, uchar *p2);
|
||||
void CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd);
|
||||
bool search_amp( int &pSymbolOut, int &pBinOut);
|
||||
public:
|
||||
cRsId();
|
||||
~cRsId();
|
||||
bool encode(trx_mode mode, int submode, uchar *rsid);
|
||||
bool search( const double *pSamples, int nSamples );
|
||||
// , bool bReverse,
|
||||
// int *pSymbolOut, int *pBinOut, int *pDistanceOut,
|
||||
// int *pMetricsOut);
|
||||
void apply (int iSymbol, int iBin);
|
||||
void send();
|
||||
|
||||
int samplerate() { return _samplerate;}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -216,6 +216,8 @@ public:
|
|||
static void initialize(void);
|
||||
static void terminate(void);
|
||||
static const std::vector<const PaDeviceInfo*>& devices(void);
|
||||
static void devices_info(std::string& in, std::string& out);
|
||||
static const std::vector<double>& get_supported_rates(unsigned dir);
|
||||
|
||||
public:
|
||||
SoundPort(const char *in_dev, const char *out_dev);
|
||||
|
@ -247,6 +249,7 @@ private:
|
|||
enum { STREAM_IN, STREAM_OUT };
|
||||
static bool pa_init;
|
||||
static std::vector<const PaDeviceInfo*> devs;
|
||||
static std::vector<double> supported_rates[2];
|
||||
double req_sample_rate;
|
||||
float* fbuf;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SOUNDCONF_H
|
||||
#define SOUNDCONF_H
|
||||
|
||||
enum { SND_IDX_UNKNOWN = -1, SND_IDX_OSS, SND_IDX_PORT,
|
||||
enum { SND_IDX_UNKNOWN = -1, SND_IDX_PORT, SND_IDX_OSS,
|
||||
SND_IDX_PULSE, SND_IDX_NULL, SND_IDX_END
|
||||
};
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define THORNUMMTONES 18
|
||||
#define THORNUMTONES 18
|
||||
#define THORMAXFFTS 8
|
||||
#define THORBASEFREQ 500.0
|
||||
#define THORFIRSTIF 1000.0
|
||||
|
@ -52,7 +52,7 @@ using namespace std;
|
|||
#define THORSCOPESIZE 64
|
||||
|
||||
struct THORrxpipe {
|
||||
complex vector[THORMAXFFTS * THORNUMMTONES * 6];
|
||||
complex vector[THORMAXFFTS * THORNUMTONES * 6];
|
||||
};
|
||||
|
||||
class thor : public modem {
|
||||
|
@ -141,7 +141,7 @@ private:
|
|||
int get_secondary_char();
|
||||
void reset_filters();
|
||||
void decodePairs(unsigned char symbol);
|
||||
void decodeEX(int c);
|
||||
// void decodeEX(int c);
|
||||
|
||||
// Tx
|
||||
void sendtone(int tone, int duration);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "waterfall.h"
|
||||
#include "globals.h"
|
||||
#include "fl_digi.h"
|
||||
#include "rsid.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -50,6 +51,7 @@ extern Fl_Mutex trx_mutex;
|
|||
extern Fl_Thread trx_thread;
|
||||
extern state_t trx_state;
|
||||
extern modem *active_modem;
|
||||
extern cRsId *ReedSolomon;
|
||||
|
||||
extern SoundBase *scard;
|
||||
|
||||
|
|
|
@ -288,7 +288,8 @@ public:
|
|||
|
||||
class waterfall: public Fl_Group {
|
||||
friend void x1_cb(Fl_Widget *w, void* v);
|
||||
friend void bwclr_cb(Fl_Widget *w, void * v);
|
||||
friend void bw_rsid_cb(Fl_Widget *w, void * v);
|
||||
friend void bw_rsid_toggle(waterfall *);
|
||||
// friend void slew_cb(Fl_Widget *w, void * v);
|
||||
friend void slew_left(Fl_Widget *w, void * v);
|
||||
friend void slew_right(Fl_Widget *w, void * v);
|
||||
|
@ -374,7 +375,7 @@ public:
|
|||
private:
|
||||
Fl_Box *bezel;
|
||||
WFdisp *wfdisp;
|
||||
Fl_Button *bwclr;
|
||||
Fl_Button *bw_rsid;
|
||||
Fl_Button *mode;
|
||||
Fl_Button *x1;
|
||||
Fl_Button *left;
|
||||
|
|
|
@ -14,7 +14,7 @@ private:
|
|||
XML_RPC_Server operator=(const XML_RPC_Server&);
|
||||
void add_methods(void);
|
||||
static int get_socket(const char* node, const char* service, int& fd);
|
||||
static void* thread_func(void* arg);
|
||||
static void* thread_func(void*);
|
||||
|
||||
private:
|
||||
static XML_RPC_Server* inst;
|
||||
|
|
|
@ -933,6 +933,7 @@ void cb_picRxSave( Fl_Widget *w, void *who)
|
|||
#if USE_LIBJPEG
|
||||
picRx->save_jpeg(fn);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1102,11 +1103,7 @@ void cb_picTxSendColor( Fl_Widget *w, void *who)
|
|||
picTx->clear();
|
||||
FL_UNLOCK_D();
|
||||
// start the transmission
|
||||
fl_lock(&trx_mutex);
|
||||
if (trx_state != STATE_TX)
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
me->startpic = true;
|
||||
}
|
||||
|
||||
|
@ -1137,11 +1134,7 @@ void cb_picTxSendGrey( Fl_Widget *w, void *who)
|
|||
picTx->clear();
|
||||
FL_UNLOCK_D();
|
||||
// start the transmission
|
||||
fl_lock(&trx_mutex);
|
||||
if (trx_state != STATE_TX)
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
me->startpic = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <fstream>
|
||||
|
||||
configuration progdefaults = {
|
||||
false, // bool rsid;
|
||||
false, // bool TransmitRSid;
|
||||
false, // bool changed;
|
||||
0.0, // double wfRefLevel;
|
||||
70.0, // double wfAmpSpan;
|
||||
|
@ -170,7 +172,7 @@ configuration progdefaults = {
|
|||
SAMPLE_RATE_UNSET, // int sample_rate;
|
||||
SAMPLE_RATE_UNSET, // int in_sample_rate;
|
||||
SAMPLE_RATE_UNSET, // int out_sample_rate;
|
||||
SRC_SINC_FASTEST, // string sample_converter;
|
||||
SRC_SINC_MEDIUM_QUALITY, // int sample_converter;
|
||||
0, // int RX_corr;
|
||||
0, // int TX_corr;
|
||||
0, // int TxOffset;
|
||||
|
@ -293,7 +295,8 @@ enum TAG { \
|
|||
USEGROUPCOLORS, FKEYGROUP1, FKEYGROUP2, FKEYGROUP3,
|
||||
FKEYTEXTCOLOR,
|
||||
RXFONTNBR, RXFONTSIZE, TXFONTNBR, TXFONTSIZE,
|
||||
RXFONTCOLOR, TXFONTCOLOR
|
||||
RXFONTCOLOR, TXFONTCOLOR,
|
||||
TRANSMITRSID
|
||||
};
|
||||
|
||||
void writeXMLint(ofstream &f, const char * tag, int val)
|
||||
|
@ -517,6 +520,8 @@ void configuration::writeDefaultsXML()
|
|||
writeXMLrgb(f, "RXFONTCOLOR", RxColor.R, RxColor.G, RxColor.B);
|
||||
writeXMLrgb(f, "TXFONTCOLOR", TxColor.R, TxColor.G, TxColor.B);
|
||||
|
||||
writeXMLbool(f, "TRANSMITRSID", TransmitRSid);
|
||||
|
||||
f << "</FLDIGI_DEFS>\n";
|
||||
f.close();
|
||||
}
|
||||
|
@ -1038,6 +1043,8 @@ bool configuration::readDefaultsXML()
|
|||
sscanf( xml->getNodeData(), "%d %d %d",
|
||||
&TxColor.R, &TxColor.G, &TxColor.B);
|
||||
break;
|
||||
case TRANSMITRSID :
|
||||
TransmitRSid = atoi(xml->getNodeData());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1203,6 +1210,7 @@ bool configuration::readDefaultsXML()
|
|||
else if (!strcmp("TXFONTSIZE", nodeName)) tag = TXFONTSIZE;
|
||||
else if (!strcmp("RXFONTCOLOR", nodeName)) tag = RXFONTCOLOR;
|
||||
else if (!strcmp("TXFONTCOLOR", nodeName)) tag = TXFONTCOLOR;
|
||||
else if (!strcmp("TRANSMITRSID", nodeName)) tag = TRANSMITRSID;
|
||||
else tag = IGNORE;
|
||||
}
|
||||
break;
|
||||
|
@ -1429,6 +1437,8 @@ int configuration::setDefaults() {
|
|||
selHellFont->value(feldfontnbr);
|
||||
btnFeldHellIdle->value(FELD_IDLE);
|
||||
|
||||
chkTransmitRSid->value(TransmitRSid);
|
||||
|
||||
string bandsfname = HomeDir;
|
||||
bandsfname.append("frequencies.def");
|
||||
ifstream bandsfile(bandsfname.c_str(), ios::in);
|
||||
|
|
|
@ -643,10 +643,7 @@ void MACROTEXT::execute(int n)
|
|||
TransmitText->add( (expandMacro(n)).c_str() );
|
||||
if ( TransmitON ) {
|
||||
active_modem->set_stopflag(false);
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
TransmitON = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,10 +131,7 @@ void process_msgque()
|
|||
|
||||
active_modem->set_stopflag(false);
|
||||
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,11 +209,7 @@ void check_formail() {
|
|||
pskmail_text_available = true;
|
||||
|
||||
active_modem->set_stopflag(false);
|
||||
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -240,10 +233,7 @@ void check_formail() {
|
|||
pText = mailtext.begin();
|
||||
pskmail_text_available = true;
|
||||
active_modem->set_stopflag(false);
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
arqmode = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,6 @@ XML_RPC_Server::XML_RPC_Server(int sfd_)
|
|||
|
||||
server_thread = new Fl_Thread;
|
||||
run = true;
|
||||
fl_create_thread(*server_thread, thread_func, this);
|
||||
}
|
||||
XML_RPC_Server::~XML_RPC_Server()
|
||||
{
|
||||
|
@ -103,7 +102,7 @@ void XML_RPC_Server::start(const char* node, const char* service)
|
|||
return;
|
||||
|
||||
int sfd = -1, err;
|
||||
if ((err = get_socket(node, service, sfd)) == -1) {
|
||||
if ((err = get_socket(node, service, sfd)) != 0) {
|
||||
#if HAVE_GETADDRINFO
|
||||
if (err < 0)
|
||||
cerr << gai_strerror(err) << '\n';
|
||||
|
@ -115,6 +114,7 @@ void XML_RPC_Server::start(const char* node, const char* service)
|
|||
}
|
||||
|
||||
inst = new XML_RPC_Server(sfd);
|
||||
fl_create_thread(*server_thread, thread_func, NULL);
|
||||
}
|
||||
void XML_RPC_Server::stop(void)
|
||||
{
|
||||
|
@ -198,15 +198,17 @@ int XML_RPC_Server::get_socket(const char* node, const char* service, int& fd)
|
|||
res = 0;
|
||||
#endif // HAVE_GETADDRINFO
|
||||
|
||||
int v = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1)
|
||||
perror("setsockopt TCP_NODELAY");
|
||||
if (res == 0) {
|
||||
int v = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1)
|
||||
perror("setsockopt TCP_NODELAY");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void* XML_RPC_Server::thread_func(void* arg)
|
||||
void* XML_RPC_Server::thread_func(void*)
|
||||
{
|
||||
SET_THREAD_ID(XMLRPC_TID);
|
||||
|
||||
|
@ -267,20 +269,15 @@ ret:
|
|||
// =============================================================================
|
||||
// helper functions
|
||||
|
||||
static void frob(Fl_Widget* widget)
|
||||
{
|
||||
REQ(static_cast<void (Fl_Widget::*)(void)>(&Fl_Widget::do_callback), widget);
|
||||
}
|
||||
|
||||
static void set_button(Fl_Button* button, bool value)
|
||||
{
|
||||
REQ(static_cast<int (Fl_Button::*)(int)>(&Fl_Button::value), button, value);
|
||||
frob(button);
|
||||
button->value(value);
|
||||
button->do_callback();
|
||||
}
|
||||
static void set_valuator(Fl_Valuator* valuator, double value)
|
||||
{
|
||||
REQ(static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value), valuator, value);
|
||||
frob(valuator);
|
||||
valuator->value(value);
|
||||
valuator->do_callback();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
@ -380,7 +377,7 @@ public:
|
|||
Modem_get_name()
|
||||
{
|
||||
_signature = "s:n";
|
||||
_help = "Returns the name of the current modem";
|
||||
_help = "Returns the name of the current modem.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -388,13 +385,31 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class Modem_get_names : public xmlrpc_c::method
|
||||
{
|
||||
public:
|
||||
Modem_get_names()
|
||||
{
|
||||
_signature = "A:n";
|
||||
_help = "Returns all modem names.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
vector<xmlrpc_c::value> names;
|
||||
names.reserve(NUM_MODES);
|
||||
for (size_t i = 0; i < NUM_MODES; i++)
|
||||
names.push_back(xmlrpc_c::value_string(mode_info[i].sname));
|
||||
*retval = xmlrpc_c::value_array(names);
|
||||
}
|
||||
};
|
||||
|
||||
class Modem_get_id : public xmlrpc_c::method
|
||||
{
|
||||
public:
|
||||
Modem_get_id()
|
||||
{
|
||||
_signature = "i:n";
|
||||
_help = "Returns the ID of the current modem";
|
||||
_help = "Returns the ID of the current modem.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -408,7 +423,7 @@ public:
|
|||
Modem_get_max_id()
|
||||
{
|
||||
_signature = "i:n";
|
||||
_help = "Returns the maximum modem ID number";
|
||||
_help = "Returns the maximum modem ID number.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -431,7 +446,7 @@ public:
|
|||
bool found = false;
|
||||
string s = params.getString(0);
|
||||
for (size_t i = 0; i < NUM_MODES; i++) {
|
||||
if (!strcmp(mode_info[i].sname, s.c_str())) {
|
||||
if (s == mode_info[i].sname) {
|
||||
init_modem_sync(i);
|
||||
found = true;
|
||||
break;
|
||||
|
@ -541,7 +556,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
int v = cntSearchRange->value();
|
||||
set_valuator(cntSearchRange, params.getInt(0, cntSearchRange->minimum(), cntSearchRange->maximum()));
|
||||
REQ(set_valuator, cntSearchRange, params.getInt(0, cntSearchRange->minimum(), cntSearchRange->maximum()));
|
||||
*retval = xmlrpc_c::value_int(v);
|
||||
}
|
||||
};
|
||||
|
@ -557,7 +572,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
int v = cntSearchRange->value() + params.getInt(0);
|
||||
set_valuator(cntSearchRange, v);
|
||||
REQ(set_valuator, cntSearchRange, v);
|
||||
*retval = xmlrpc_c::value_int(v);
|
||||
}
|
||||
};
|
||||
|
@ -616,7 +631,7 @@ public:
|
|||
}
|
||||
|
||||
int v = val->value();
|
||||
set_valuator(val, params.getInt(0, val->minimum(), val->maximum()));
|
||||
REQ(set_valuator, val, params.getInt(0, val->minimum(), val->maximum()));
|
||||
*retval = xmlrpc_c::value_int(v);
|
||||
}
|
||||
};
|
||||
|
@ -644,7 +659,7 @@ public:
|
|||
}
|
||||
|
||||
int v = val->value() + params.getInt(0);
|
||||
set_valuator(val, v);
|
||||
REQ(set_valuator, val, v);
|
||||
*retval = xmlrpc_c::value_int(v);
|
||||
}
|
||||
};
|
||||
|
@ -759,7 +774,7 @@ public:
|
|||
Main_set_freq()
|
||||
{
|
||||
_signature = "d:d";
|
||||
_help = "Sets the RF carrier frequency. Returns the old value";
|
||||
_help = "Sets the RF carrier frequency. Returns the old value.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -825,7 +840,7 @@ public:
|
|||
{
|
||||
Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff;
|
||||
bool v = b->value();
|
||||
set_button(b, params.getBoolean(0));
|
||||
REQ(set_button, b, params.getBoolean(0));
|
||||
*retval = xmlrpc_c::value_boolean(v);
|
||||
}
|
||||
};
|
||||
|
@ -842,7 +857,7 @@ public:
|
|||
{
|
||||
Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff;
|
||||
bool v = b->value();
|
||||
set_button(b, !v);
|
||||
REQ(set_button, b, !v);
|
||||
*retval = xmlrpc_c::value_boolean(!v);
|
||||
}
|
||||
};
|
||||
|
@ -875,7 +890,7 @@ public:
|
|||
{
|
||||
Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff;
|
||||
bool v = b->value();
|
||||
set_button(b, params.getBoolean(0));
|
||||
REQ(set_button, b, params.getBoolean(0));
|
||||
*retval = xmlrpc_c::value_boolean(v);
|
||||
}
|
||||
};
|
||||
|
@ -892,7 +907,7 @@ public:
|
|||
{
|
||||
Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff;
|
||||
bool v = b->value();
|
||||
set_button(b, !v);
|
||||
REQ(set_button, b, !v);
|
||||
*retval = xmlrpc_c::value_boolean(!v);
|
||||
}
|
||||
};
|
||||
|
@ -905,7 +920,7 @@ public:
|
|||
Main_get_sql_level()
|
||||
{
|
||||
_signature = "d:n";
|
||||
_help = "Returns the squelch level";
|
||||
_help = "Returns the squelch level.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -926,9 +941,9 @@ public:
|
|||
double v = sldrSquelch->value();
|
||||
// Squelch slider min/max are reversed when !twoscopes. Argh.
|
||||
if (twoscopes)
|
||||
set_valuator(sldrSquelch, params.getDouble(0, sldrSquelch->minimum(), sldrSquelch->maximum()));
|
||||
REQ(set_valuator, sldrSquelch, params.getDouble(0, sldrSquelch->minimum(), sldrSquelch->maximum()));
|
||||
else
|
||||
set_valuator(sldrSquelch, params.getDouble(0, sldrSquelch->maximum(), sldrSquelch->minimum()));
|
||||
REQ(set_valuator, sldrSquelch, params.getDouble(0, sldrSquelch->maximum(), sldrSquelch->minimum()));
|
||||
*retval = xmlrpc_c::value_double(v);
|
||||
}
|
||||
};
|
||||
|
@ -944,7 +959,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
double v = sldrSquelch->value();
|
||||
set_valuator(sldrSquelch, v + params.getDouble(0)); // FIXME: check range
|
||||
REQ(set_valuator, sldrSquelch, v + params.getDouble(0)); // FIXME: check range
|
||||
*retval = xmlrpc_c::value_double(sldrSquelch->value());
|
||||
}
|
||||
};
|
||||
|
@ -976,7 +991,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
bool v = wf->btnRev->value();
|
||||
set_button(wf->btnRev, params.getBoolean(0));
|
||||
REQ(set_button, wf->btnRev, params.getBoolean(0));
|
||||
*retval = xmlrpc_c::value_boolean(v);
|
||||
}
|
||||
};
|
||||
|
@ -992,7 +1007,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
bool v = wf->btnRev->value();
|
||||
set_button(wf->btnRev, !v);
|
||||
REQ(set_button, wf->btnRev, !v);
|
||||
*retval = xmlrpc_c::value_boolean(!v);
|
||||
}
|
||||
};
|
||||
|
@ -1024,7 +1039,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
bool v = wf->xmtlock->value();
|
||||
set_button(wf->xmtlock, params.getBoolean(0));
|
||||
REQ(set_button, wf->xmtlock, params.getBoolean(0));
|
||||
*retval = xmlrpc_c::value_boolean(v);
|
||||
}
|
||||
};
|
||||
|
@ -1040,7 +1055,7 @@ public:
|
|||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
bool v = wf->xmtlock->value();
|
||||
set_button(wf->xmtlock, !v);
|
||||
REQ(set_button, wf->xmtlock, !v);
|
||||
*retval = xmlrpc_c::value_boolean(!v);
|
||||
}
|
||||
};
|
||||
|
@ -1055,7 +1070,7 @@ public:
|
|||
Main_get_tx_status()
|
||||
{
|
||||
_signature = "s:n";
|
||||
_help = "Returns transmit/tune/receive status";
|
||||
_help = "Returns transmit/tune/receive status.";
|
||||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
|
@ -1078,7 +1093,7 @@ public:
|
|||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
set_button(wf->xmtrcv, true);
|
||||
REQ(set_button, wf->xmtrcv, true);
|
||||
*retval = xmlrpc_c::value_nil();
|
||||
}
|
||||
};
|
||||
|
@ -1093,7 +1108,7 @@ public:
|
|||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
set_button(btnTune, !btnTune->value());
|
||||
REQ(set_button, btnTune, !btnTune->value());
|
||||
*retval = xmlrpc_c::value_nil();
|
||||
}
|
||||
};
|
||||
|
@ -1108,7 +1123,7 @@ public:
|
|||
}
|
||||
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
|
||||
{
|
||||
set_button(wf->xmtrcv, false);
|
||||
REQ(set_button, wf->xmtrcv, false);
|
||||
*retval = xmlrpc_c::value_nil();
|
||||
}
|
||||
};
|
||||
|
@ -1409,6 +1424,7 @@ void XML_RPC_Server::add_methods(void)
|
|||
methods->push_back(rpc_method(new Fldigi_name_version, "fldigi.name_version"));
|
||||
|
||||
methods->push_back(rpc_method(new Modem_get_name, "modem.get_name"));
|
||||
methods->push_back(rpc_method(new Modem_get_names, "modem.get_names"));
|
||||
methods->push_back(rpc_method(new Modem_get_id, "modem.get_id"));
|
||||
methods->push_back(rpc_method(new Modem_get_max_id, "modem.get_max_id"));
|
||||
methods->push_back(rpc_method(new Modem_set_by_name, "modem.set_by_name"));
|
||||
|
|
|
@ -0,0 +1,595 @@
|
|||
#include <math.h>
|
||||
|
||||
#include "rsid.h"
|
||||
#include "filters.h"
|
||||
#include "main.h"
|
||||
#include "trx.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include "rsid_fft.cxx"
|
||||
|
||||
RSIDs cRsId::rsid_ids[] = {
|
||||
{ 1, MODE_BPSK31 },
|
||||
{ 2, MODE_PSK63 },
|
||||
{ 3, MODE_QPSK63 },
|
||||
{ 4, MODE_PSK125 },
|
||||
{ 5, MODE_QPSK125 },
|
||||
{ 7, NUM_MODES },
|
||||
{ 8, NUM_MODES },
|
||||
{ 9, MODE_MT63_500 }, // MT63-500-LG
|
||||
{ 10, MODE_MT63_500 }, // MT63-500-ST
|
||||
{ 11, MODE_MT63_500 }, // MT63-500-VST
|
||||
{ 12, MODE_MT63_1000 }, // MT63-1000-LG
|
||||
{ 13, MODE_MT63_1000 }, // MT63-1000-ST
|
||||
{ 14, MODE_MT63_1000 }, // MT63-1000-VST
|
||||
{ 15, MODE_MT63_2000 }, // MT63-2000-LG
|
||||
{ 17, MODE_MT63_2000 }, // MT63-2000-ST
|
||||
{ 18, MODE_MT63_2000 }, // MT63-2000-VST
|
||||
{ 19, NUM_MODES }, // PSKAM10
|
||||
{ 20, NUM_MODES }, // PSKAM31
|
||||
{ 21, NUM_MODES }, // PSKAM50
|
||||
{ 22, NUM_MODES }, // PSK63F
|
||||
{ 23, NUM_MODES }, // PSK220F
|
||||
{ 24, NUM_MODES }, // CHIP-64
|
||||
{ 25, NUM_MODES }, // CHIP-128
|
||||
{ 26, MODE_CW }, // CW
|
||||
{ 27, NUM_MODES }, // CCW-OOK-12
|
||||
{ 28, NUM_MODES }, // CCW-OOK-24
|
||||
{ 29, NUM_MODES }, // CCW-OOK-48
|
||||
{ 30, NUM_MODES }, // CCW-FSK-12
|
||||
{ 31, NUM_MODES }, // CCW-FSK-24
|
||||
{ 33, NUM_MODES }, // CCW-FSK-48
|
||||
{ 34, NUM_MODES }, // PACTOR1-FEC
|
||||
{ 35, NUM_MODES }, // PACKET-300
|
||||
{ 36, NUM_MODES }, // PACKET-1200
|
||||
{ 37, MODE_RTTY }, // ASCII-7
|
||||
{ 38, MODE_RTTY }, // ASCII-8
|
||||
{ 39, MODE_RTTY }, // RTTY-45
|
||||
{ 40, MODE_RTTY }, // RTTY-50
|
||||
{ 41, MODE_RTTY }, // RTTY-75
|
||||
{ 42, NUM_MODES }, // AMTOR FEC
|
||||
{ 43, MODE_THROB1 }, // THROB-1
|
||||
{ 44, MODE_THROB2 }, // THROB-2
|
||||
{ 45, MODE_THROB4 }, // THROB-4
|
||||
{ 46, MODE_THROBX1 }, // THROBX-1
|
||||
{ 47, MODE_THROBX2 }, // THROBX-2
|
||||
{ 49, NUM_MODES }, // CONTESTIA-8-250
|
||||
{ 50, NUM_MODES }, // CONTESTIA-16-500
|
||||
{ 51, NUM_MODES }, // CONTESTIA-32-1000
|
||||
{ 52, NUM_MODES }, // CONTESTIA-8-500
|
||||
{ 53, NUM_MODES }, // CONTESTIA-16-1000
|
||||
{ 54, NUM_MODES }, // CONTESTIA-4-500
|
||||
{ 55, NUM_MODES }, // CONTESTIA-4-250
|
||||
{ 56, NUM_MODES }, // VOICE
|
||||
|
||||
{ 57, MODE_MFSK16 }, // MFSK16
|
||||
{ 60, MODE_MFSK8 }, // MFSK8
|
||||
|
||||
{ 61, NUM_MODES }, // RTTYM-8-250
|
||||
{ 62, NUM_MODES }, // RTTYM-16-500
|
||||
{ 63, NUM_MODES }, // RTTYM-32-1000
|
||||
{ 65, NUM_MODES }, // RTTYM-8-500
|
||||
{ 66, NUM_MODES }, // RTTYM-16-1000
|
||||
{ 67, NUM_MODES }, // RTTYM-4-500
|
||||
{ 68, NUM_MODES }, // RTTYM-4-250
|
||||
|
||||
{ 69, MODE_OLIVIA }, // OLIVIA-8-250
|
||||
{ 70, MODE_OLIVIA }, // OLIVIA-16-500
|
||||
{ 71, MODE_OLIVIA }, // OLIVIA-32-1000
|
||||
{ 72, MODE_OLIVIA }, // OLIVIA-8-500
|
||||
{ 73, MODE_OLIVIA }, // OLIVIA-16-1000
|
||||
{ 74, MODE_OLIVIA }, // OLIVIA-4-500
|
||||
{ 75, MODE_OLIVIA }, // OLIVIA-4-250
|
||||
|
||||
{ 76, NUM_MODES }, // PAX
|
||||
{ 77, NUM_MODES }, // PAX2
|
||||
{ 78, NUM_MODES }, // DOMINOF
|
||||
{ 79, NUM_MODES }, // FAX
|
||||
{ 81, NUM_MODES }, // SSTV
|
||||
|
||||
{ 84, MODE_DOMINOEX4 }, // DOMINOEX-4
|
||||
{ 85, MODE_DOMINOEX5 }, // DOMINOEX-5
|
||||
{ 86, MODE_DOMINOEX8 }, // DOMINOEX-8
|
||||
{ 87, MODE_DOMINOEX11 }, // DOMINOEX-11
|
||||
{ 88, MODE_DOMINOEX16 }, // DOMINOEX-16
|
||||
{ 90, MODE_DOMINOEX22 }, // DOMINOEX-22
|
||||
{ 92, MODE_THOR4 }, // DOMINOEX-4-FEC
|
||||
{ 93, MODE_THOR5 }, // DOMINOEX-5-FEC
|
||||
{ 97, MODE_THOR8 }, // DOMINOEX-8-FEC
|
||||
{ 98, MODE_THOR11 }, // DOMINOEX-11-FEC
|
||||
{ 99, MODE_THOR16 }, // DOMINOEX-16-FEC
|
||||
{ 101, MODE_THOR22 }, // DOMINOEX-22-FEC
|
||||
|
||||
{ 104, MODE_FELDHELL }, // FELD HELL
|
||||
{ 105, NUM_MODES }, // PSK HELL
|
||||
{ 106, MODE_HELL80 }, // HELL 80
|
||||
{ 107, MODE_FSKH105 }, // FM HELL-105
|
||||
{ 108, NUM_MODES }, // FM HELL-245
|
||||
|
||||
{ 110, MODE_QPSK31 },
|
||||
{ 0, NUM_MODES }
|
||||
};
|
||||
|
||||
const int cRsId::Squares[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,
|
||||
0, 2, 4, 6, 8,10,12,14, 9,11,13,15, 1, 3, 5, 7,
|
||||
0, 3, 6, 5,12,15,10, 9, 1, 2, 7, 4,13,14,11, 8,
|
||||
0, 4, 8,12, 9,13, 1, 5,11,15, 3, 7, 2, 6,10,14,
|
||||
0, 5,10,15,13, 8, 7, 2, 3, 6, 9,12,14,11, 4, 1,
|
||||
0, 6,12,10, 1, 7,13,11, 2, 4,14, 8, 3, 5,15, 9,
|
||||
0, 7,14, 9, 5, 2,11,12,10,13, 4, 3,15, 8, 1, 6,
|
||||
0, 8, 9, 1,11, 3, 2,10,15, 7, 6,14, 4,12,13, 5,
|
||||
0, 9,11, 2,15, 6, 4,13, 7,14,12, 5, 8, 1, 3,10,
|
||||
0,10,13, 7, 3, 9,14, 4, 6,12,11, 1, 5,15, 8, 2,
|
||||
0,11,15, 4, 7,12, 8, 3,14, 5, 1,10, 9, 2, 6,13,
|
||||
0,12, 1,13, 2,14, 3,15, 4, 8, 5, 9, 6,10, 7,11,
|
||||
0,13, 3,14, 6,11, 5, 8,12, 1,15, 2,10, 7, 9, 4,
|
||||
0,14, 5,11,10, 4,15, 1,13, 3, 8, 6, 7, 9, 2,12,
|
||||
0,15, 7, 8,14, 1, 9, 6, 5,10, 2,13,11, 4,12, 3
|
||||
};
|
||||
|
||||
const int cRsId::indices[] = {
|
||||
2, 4, 8, 9, 11, 15, 7, 14, 5, 10, 13, 3
|
||||
};
|
||||
|
||||
cRsId :: cRsId()
|
||||
{
|
||||
rsid_ids_size = 0;
|
||||
|
||||
// compute current size of rsid_ids
|
||||
while (rsid_ids[rsid_ids_size].rs) rsid_ids_size++;
|
||||
|
||||
// Initialization of assigned mode/submode IDs.
|
||||
// HashTable is used for finding a code with lowest Hamming distance.
|
||||
memset (aHashTable1, 255, 256);
|
||||
memset (aHashTable2, 255, 256);
|
||||
|
||||
pCodes = new uchar[rsid_ids_size * RSID_NSYMBOLS];
|
||||
|
||||
for (int i = 0; i < rsid_ids_size; i++) {
|
||||
uchar *c = pCodes + i * RSID_NSYMBOLS;
|
||||
int hash1;
|
||||
int hash2;
|
||||
Encode(rsid_ids[i].rs, c);
|
||||
hash1 = c[11] | (c[12] << 4);
|
||||
hash2 = c[13] | (c[14] << 4);
|
||||
|
||||
aHashTable1[hash1] = i;
|
||||
aHashTable2[hash2] = i;
|
||||
}
|
||||
// for (int is = 0; is < rsid_ids_size; is++) {
|
||||
// std::cout << is << ", , ";
|
||||
// for (int ic = 0; ic < RSID_NSYMBOLS; ic++)SHIFT
|
||||
// std::cout << (int)(*(pCodes + ic + is * RSID_NSYMBOLS)) << ", ";
|
||||
// std::cout << std::endl;
|
||||
// }
|
||||
|
||||
iPrevDistance = 99;
|
||||
|
||||
memset(aInputSamples, 0, RSID_ARRAY_SIZE * sizeof(double));
|
||||
memset(aFFTReal, 0, RSID_ARRAY_SIZE * sizeof(double));
|
||||
|
||||
// rsid_fft = new Cfft(RSID_FFT_SIZE);
|
||||
// rsid_fft->setWindow(FFT_BLACKMAN);
|
||||
|
||||
BlackmanWindow(fftwindow, RSID_ARRAY_SIZE);
|
||||
|
||||
nBinLow = 10;
|
||||
nBinHigh = RSID_FFT_SIZE - 32;
|
||||
iTime = 0;
|
||||
bPrevTimeSliceValid = false;
|
||||
|
||||
_samplerate = 11025;
|
||||
}
|
||||
|
||||
cRsId::~cRsId()
|
||||
{
|
||||
delete rsid_fft;
|
||||
delete [] pCodes;
|
||||
}
|
||||
|
||||
void cRsId::Encode(int code, uchar *rsid)
|
||||
{
|
||||
rsid[0] = code >> 8;
|
||||
rsid[1] = (code >> 4) & 0x0f;
|
||||
rsid[2] = code & 0x0f;
|
||||
for (int i = 3; i < RSID_NSYMBOLS; i++)
|
||||
rsid[i] = 0;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
for (int j = RSID_NSYMBOLS - 1; j > 0; j--)
|
||||
rsid[j] = rsid[j - 1] ^ Squares[(rsid[j] << 4) + indices[i]];
|
||||
rsid[0] = Squares[(rsid[0] << 4) + indices[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void cRsId::CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd)
|
||||
{
|
||||
double Amp = 0.0, AmpMax = 0.0;
|
||||
int iBucketMax = iBegin - 2;
|
||||
int i, j, jEnd;
|
||||
|
||||
for (i = iBegin; i < iEnd; i += 2) {
|
||||
if (iBucketMax == i - 2) {
|
||||
// The maximum amplitude is out of span. Sweep over all the 16 coefficients
|
||||
AmpMax = pSpectrum[i];
|
||||
iBucketMax = i;
|
||||
jEnd = i + 32;
|
||||
for (j = i + 2; j < jEnd; j += 2) {
|
||||
Amp = pSpectrum[j];
|
||||
if (Amp > AmpMax) {
|
||||
AmpMax = Amp;
|
||||
iBucketMax = j;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
j = i + 30;
|
||||
Amp = pSpectrum[j];
|
||||
if (Amp > AmpMax) {
|
||||
AmpMax = Amp;
|
||||
iBucketMax = j;
|
||||
}
|
||||
}
|
||||
aBuckets[iTime][i] = (iBucketMax - i) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool cRsId::search( const double *pSamples, int nSamples )
|
||||
{
|
||||
int i, ns;
|
||||
bool bReverse = false;
|
||||
double Real, Imag;
|
||||
|
||||
if (wf->Reverse() == true && wf->USB() == true) bReverse = true;
|
||||
if (wf->Reverse() == false && wf->USB() == false) bReverse = true;
|
||||
|
||||
ns = nSamples;
|
||||
if (ns > RSID_ARRAY_SIZE / 4) {
|
||||
std::cout << "ns = " << ns << std::endl;
|
||||
ns = RSID_ARRAY_SIZE / 4;
|
||||
}
|
||||
|
||||
// make backup of search boundaries
|
||||
int nnBinLow = nBinLow;
|
||||
int nnBinHigh = nBinHigh;
|
||||
|
||||
if (bReverse) {
|
||||
nBinLow = RSID_FFT_SIZE - nBinHigh;
|
||||
nBinHigh = RSID_FFT_SIZE - nBinLow;
|
||||
}
|
||||
|
||||
memset (aFFTReal, 0, RSID_ARRAY_SIZE * sizeof(double));
|
||||
memmove (aInputSamples, aInputSamples + ns, ns * sizeof(double));
|
||||
memcpy (aInputSamples + ns, pSamples, ns * sizeof(double));
|
||||
memcpy (aFFTReal, aInputSamples, RSID_ARRAY_SIZE * sizeof(double));
|
||||
|
||||
// for (int i = 0; i < RSID_ARRAY_SIZE; i++)
|
||||
// aFFTReal[i] = aInputSamples[i] * fftwindow[i];
|
||||
|
||||
rsrfft( aFFTReal, 11);
|
||||
|
||||
memset(aFFTAmpl, 0, RSID_FFT_SIZE * sizeof(double));
|
||||
for (i = 1; i < RSID_FFT_SIZE; i++) {
|
||||
if (bReverse) {
|
||||
Real = aFFTReal[RSID_FFT_SIZE - i];
|
||||
Imag = aFFTReal[RSID_FFT_SIZE + i];
|
||||
} else {
|
||||
Real = aFFTReal[i];
|
||||
Imag = aFFTReal[2 * RSID_FFT_SIZE - i];
|
||||
}
|
||||
aFFTAmpl[i] = Real * Real + Imag * Imag;
|
||||
}
|
||||
|
||||
int SymbolOut = -1,
|
||||
BinOut = -1;
|
||||
|
||||
if (search_amp ( SymbolOut, BinOut ) ){
|
||||
|
||||
if (bReverse) {
|
||||
BinOut = 1024 - BinOut - 31;
|
||||
nBinLow = nnBinLow;
|
||||
nBinHigh = nnBinHigh;
|
||||
}
|
||||
apply(SymbolOut, BinOut);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (bReverse) {
|
||||
nBinLow = nnBinLow;
|
||||
nBinHigh = nnBinHigh;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// change the current mode and frequency to the rsid detected values
|
||||
double newfreq;
|
||||
trx_mode newmode;
|
||||
|
||||
void changemodefrequency(void*) {
|
||||
active_modem->set_freq(newfreq);
|
||||
init_modem(newmode);
|
||||
}
|
||||
|
||||
void cRsId::apply(int iSymbol, int iBin)
|
||||
{
|
||||
|
||||
double freq = (iBin + 14) * 11025.0 / 2048.0;
|
||||
|
||||
int mbin = 0;
|
||||
for (int n = 0; n < rsid_ids_size; n++)
|
||||
if (rsid_ids[n].rs == iSymbol) {
|
||||
mbin = rsid_ids[n].mode;
|
||||
break;
|
||||
}
|
||||
|
||||
// std::cout << iBin
|
||||
// << ", Mode: " << mode_info[mbin].sname
|
||||
// << ", Frequency " << (int)(freq + 0.5)
|
||||
// << std::endl;
|
||||
|
||||
bw_rsid_toggle(wf);
|
||||
|
||||
newfreq = freq;
|
||||
newmode = mbin;
|
||||
|
||||
if (iSymbol == 37) {
|
||||
progdefaults.rtty_baud = 5;
|
||||
progdefaults.rtty_bits = 1;
|
||||
progdefaults.rtty_shift = 9;
|
||||
}
|
||||
if (iSymbol == 38) {
|
||||
progdefaults.rtty_baud = 5;
|
||||
progdefaults.rtty_bits = 2;
|
||||
progdefaults.rtty_shift = 9;
|
||||
}
|
||||
if (iSymbol == 39) {
|
||||
progdefaults.rtty_baud = 1;
|
||||
progdefaults.rtty_bits = 0;
|
||||
progdefaults.rtty_shift = 3;
|
||||
}
|
||||
if (iSymbol == 40) {
|
||||
progdefaults.rtty_baud = 2;
|
||||
progdefaults.rtty_bits = 0;
|
||||
progdefaults.rtty_shift = 3;
|
||||
}
|
||||
if (iSymbol == 41) {
|
||||
progdefaults.rtty_baud = 4;
|
||||
progdefaults.rtty_bits = 0;
|
||||
progdefaults.rtty_shift = 9;
|
||||
}
|
||||
|
||||
Fl::add_timeout(0.10, changemodefrequency);
|
||||
|
||||
|
||||
/*
|
||||
int submode = 0;
|
||||
|
||||
switch (iSymbol) {
|
||||
// 37, // ASCII-7
|
||||
// 38, // ASCII-8
|
||||
|
||||
case 39: mode = MODE_RTTY; submode = ID_SUBMODE_RTTY_HAM_45_170; break;
|
||||
|
||||
case 43: mode = MODE_THROB; submode = ID_SUBMODE_TPS1; break;
|
||||
case 44: mode = MODE_THROB; submode = ID_SUBMODE_TPS2; break;
|
||||
case 45: mode = MODE_THROB; submode = ID_SUBMODE_TPS4; break;
|
||||
|
||||
case 46: mode = MODE_THROBX; submode = ID_SUBMODE_TPS1; break;
|
||||
case 47: mode = MODE_THROBX; submode = ID_SUBMODE_TPS2; break;
|
||||
|
||||
case 49: mode = MODE_CONTESTIA; submode = ID_SUBMODE_8_250; break;
|
||||
case 50: mode = MODE_CONTESTIA; submode = ID_SUBMODE_16_500; break;
|
||||
case 51: mode = MODE_CONTESTIA; submode = ID_SUBMODE_32_1K; break;
|
||||
case 52: mode = MODE_CONTESTIA; submode = ID_SUBMODE_8_500; break;
|
||||
case 53: mode = MODE_CONTESTIA; submode = ID_SUBMODE_16_1K; break;
|
||||
case 54: mode = MODE_CONTESTIA; submode = ID_SUBMODE_4_500; break;
|
||||
case 55: mode = MODE_CONTESTIA; submode = ID_SUBMODE_4_250; break;
|
||||
case 57: mode = MODE_MFSK16; break;
|
||||
|
||||
case 61: mode = MODE_RTTYM; submode = ID_SUBMODE_8_250; break;
|
||||
case 62: mode = MODE_RTTYM; submode = ID_SUBMODE_16_500; break;
|
||||
case 63: mode = MODE_RTTYM; submode = ID_SUBMODE_32_1K; break;
|
||||
case 65: mode = MODE_RTTYM; submode = ID_SUBMODE_8_500; break;
|
||||
case 66: mode = MODE_RTTYM; submode = ID_SUBMODE_16_1K; break;
|
||||
case 67: mode = MODE_RTTYM; submode = ID_SUBMODE_4_500; break;
|
||||
case 68: mode = MODE_RTTYM; submode = ID_SUBMODE_4_250; break;
|
||||
|
||||
case 69: mode = MODE_OLIVIA; submode = ID_SUBMODE_8_250; break;
|
||||
case 70: mode = MODE_OLIVIA; submode = ID_SUBMODE_16_500; break;
|
||||
case 71: mode = MODE_OLIVIA; submode = ID_SUBMODE_32_1K; break;
|
||||
case 72: mode = MODE_OLIVIA; submode = ID_SUBMODE_8_500; break;
|
||||
case 73: mode = MODE_OLIVIA; submode = ID_SUBMODE_16_1K; break;
|
||||
case 74: mode = MODE_OLIVIA; submode = ID_SUBMODE_4_500; break;
|
||||
case 75: mode = MODE_OLIVIA; submode = ID_SUBMODE_4_250; break;
|
||||
|
||||
case 110: mode = MODE_PSK; submode = ID_SUBMODE_PSK_QPSK31; break;
|
||||
|
||||
default: _ASSERT(false);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool cRsId::encode(trx_mode mode, int submode, uchar *rsid)
|
||||
{
|
||||
int ptr = 0, code;
|
||||
while ( (rsid_ids[ptr].mode != mode) && (rsid_ids[ptr].rs != 0) )
|
||||
ptr++;
|
||||
code = rsid_ids[ptr].rs;
|
||||
|
||||
if (code == 0)
|
||||
return false;
|
||||
|
||||
Encode(code + submode, rsid);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// search_amp routine #1
|
||||
//=============================================================================
|
||||
|
||||
int cRsId::HammingDistance(int iBucket, uchar *p2)
|
||||
{
|
||||
int dist = 0;
|
||||
int j = iTime - RSID_NTIMES + 1; // first value
|
||||
if (j < 0)
|
||||
j += RSID_NTIMES;
|
||||
for (int i = 0; i < RSID_NSYMBOLS; i++) {
|
||||
if (aBuckets[j][iBucket] != p2[i])//*p2++)
|
||||
if (++dist == 2)
|
||||
return dist;
|
||||
j += 2;
|
||||
if (j >= RSID_NTIMES)
|
||||
j -= RSID_NTIMES;
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
bool cRsId::search_amp( int &SymbolOut, int &BinOut)
|
||||
{
|
||||
int i, j;
|
||||
int iDistanceMin = 99; // infinity
|
||||
int iDistance;
|
||||
int iBin = -1;
|
||||
int iSymbol = -1;
|
||||
int iEnd = nBinHigh - 30;
|
||||
int i1, i2, i3;
|
||||
|
||||
if (++iTime == RSID_NTIMES)
|
||||
iTime = 0;
|
||||
|
||||
i1 = iTime - 6;
|
||||
i2 = i1 + 2;
|
||||
i3 = i2 + 2;
|
||||
|
||||
if (i1 < 0) {
|
||||
i1 += RSID_NTIMES;
|
||||
if (i2 < 0) {
|
||||
i2 += RSID_NTIMES;
|
||||
if (i3 < 0)
|
||||
i3 += RSID_NTIMES;
|
||||
}
|
||||
}
|
||||
|
||||
CalculateBuckets ( aFFTAmpl, nBinLow, nBinHigh - 30);
|
||||
CalculateBuckets ( aFFTAmpl, nBinLow + 1, nBinHigh - 30);
|
||||
|
||||
for (i = nBinLow; i < iEnd; ++ i) {
|
||||
j = aHashTable1[aBuckets[i1][i] | (aBuckets[i2][i] << 4)];
|
||||
if (j != 255) {
|
||||
iDistance = HammingDistance(i, pCodes + j * RSID_NSYMBOLS);
|
||||
if (iDistance < 2 && iDistance < iDistanceMin) {
|
||||
iDistanceMin = iDistance;
|
||||
iSymbol = rsid_ids[j].rs;
|
||||
iBin = i;
|
||||
}
|
||||
}
|
||||
j = aHashTable2[aBuckets[i3][i] | (aBuckets[iTime][i] << 4)];
|
||||
if (j != 255) {
|
||||
iDistance = HammingDistance (i, pCodes + j * RSID_NSYMBOLS);
|
||||
if (iDistance < 2 && iDistance < iDistanceMin) {
|
||||
iDistanceMin = iDistance;
|
||||
iSymbol = rsid_ids[j].rs;
|
||||
iBin = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iSymbol == -1) {
|
||||
// No RSID found in this time slice.
|
||||
// If there is a code stored from the previous time slice, return it.
|
||||
if (bPrevTimeSliceValid) {
|
||||
SymbolOut = iPrevSymbol;
|
||||
BinOut = iPrevBin;
|
||||
DistanceOut = iPrevDistance;
|
||||
MetricsOut = 0;
|
||||
bPrevTimeSliceValid = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! bPrevTimeSliceValid ||
|
||||
iDistanceMin <= iPrevDistance) {
|
||||
iPrevSymbol = iSymbol;
|
||||
iPrevBin = iBin;
|
||||
iPrevDistance = iDistanceMin;
|
||||
}
|
||||
bPrevTimeSliceValid = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// transmit rsid code for current mode
|
||||
//=============================================================================
|
||||
|
||||
void cRsId::send()
|
||||
{
|
||||
int iTone;
|
||||
uchar rsid[RSID_NSYMBOLS];
|
||||
double phaseincr;
|
||||
double freq, fr;
|
||||
double sr;
|
||||
int symlen;
|
||||
|
||||
sr = active_modem->get_samplerate();
|
||||
symlen = (int)floor(RSID_SYMLEN * sr + 0.5);
|
||||
fr = 1.0 * active_modem->get_txfreq() - (11025.0 * 7 / 1024);
|
||||
|
||||
trx_mode m = active_modem->get_mode();
|
||||
int submode = 0;
|
||||
switch (m) {
|
||||
case MODE_RTTY :
|
||||
if (progdefaults.rtty_baud == 5 &&
|
||||
progdefaults.rtty_bits == 1 &&
|
||||
progdefaults.rtty_shift == 9) submode = 0;
|
||||
else if (progdefaults.rtty_baud == 5 &&
|
||||
progdefaults.rtty_bits == 1 &&
|
||||
progdefaults.rtty_shift == 9) submode = 1;
|
||||
else if (progdefaults.rtty_baud == 1 &&
|
||||
progdefaults.rtty_bits == 0 &&
|
||||
progdefaults.rtty_shift == 3) submode = 2;
|
||||
else if (progdefaults.rtty_baud == 2 &&
|
||||
progdefaults.rtty_bits == 0 &&
|
||||
progdefaults.rtty_shift == 3) submode = 3;
|
||||
else if (progdefaults.rtty_baud == 4 &&
|
||||
progdefaults.rtty_bits == 0 &&
|
||||
progdefaults.rtty_shift == 9) submode = 4;
|
||||
else submode = 2; // 45 baud Baudot, shift 170
|
||||
break;
|
||||
default:
|
||||
submode = 0;
|
||||
}
|
||||
|
||||
if (!encode (active_modem->get_mode(), submode, rsid))
|
||||
return;
|
||||
|
||||
outbuf = new double[symlen];
|
||||
|
||||
// transmit sequence of 15 symbols (tones)
|
||||
phase = 0.0;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
iTone = rsid[i];
|
||||
if (active_modem->get_reverse())
|
||||
iTone = 15 - iTone;
|
||||
freq = fr + iTone * 11025.0 / 1024;
|
||||
phaseincr = 2.0 * M_PI * freq / sr;
|
||||
|
||||
for (int j = 0; j < symlen; j++) {
|
||||
phase += phaseincr;
|
||||
if (phase > 2.0 * M_PI) phase -= 2.0 * M_PI;
|
||||
outbuf[j] = sin(phase);
|
||||
}
|
||||
active_modem->ModulateXmtr(outbuf, symlen);
|
||||
|
||||
}
|
||||
// transmit 3 symbol periods of silence
|
||||
for (int j = 0; j < symlen; j++) outbuf[j] = 0.0;
|
||||
active_modem->ModulateXmtr(outbuf, symlen);
|
||||
active_modem->ModulateXmtr(outbuf, symlen);
|
||||
active_modem->ModulateXmtr(outbuf, symlen);
|
||||
// clean up
|
||||
|
||||
delete [] outbuf;
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
CC=================================================================CC
|
||||
CC CC
|
||||
CC Subroutine RSRFFT(X,M): CC
|
||||
CC A real-valued, in-place, split-radix FFT program CC
|
||||
CC Decimation-in-time, cos/sin in second loop CC
|
||||
CC and computed recursively CC
|
||||
CC Output in order: CC
|
||||
CC [ Re(0),Re(1),....,Re(N/2),Im(N/2-1),...Im(1)] CC
|
||||
CC CC
|
||||
CC Input/output CC
|
||||
CC X Array of input/output (length >= N) CC
|
||||
CC M Transform length is N=2**M CC
|
||||
CC CC
|
||||
CC Calls: CC
|
||||
CC RSTAGE,RBITREV CC
|
||||
CC CC
|
||||
CC Author: CC
|
||||
CC H.V. Sorensen, University of Pennsylvania, Oct. 1985 CC
|
||||
CC Arpa address: hvs@ee.upenn.edu CC
|
||||
CC Modified: CC
|
||||
CC F. Bonzanigo, ETH-Zurich, Sep. 1986 CC
|
||||
CC H.V. Sorensen, University of Pennsylvania, Mar. 1987 CC
|
||||
CC H.V. Sorensen, University of Pennsylvania, Oct. 1987 CC
|
||||
CC CC
|
||||
CC Reference: CC
|
||||
CC Sorensen, Jones, Heideman, Burrus :"Real-valued fast CC
|
||||
CC Fourier transform algorithms", IEEE Tran. ASSP, CC
|
||||
CC Vol. ASSP-35, No. 6, pp. 849-864, June 1987 CC
|
||||
CC CC
|
||||
CC This program may be used and distributed freely as CC
|
||||
CC as long as this header is included CC
|
||||
CC CC
|
||||
CC=================================================================CC
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "rsid_fft.h"
|
||||
|
||||
void rsrfft( double *x, int m )
|
||||
{
|
||||
int n, is, id, i0, n2, n4, k;
|
||||
double t1;
|
||||
|
||||
x--;
|
||||
n = 1 << m;
|
||||
/*C-------Digit reverse counter---------------------------------------C*/
|
||||
rbitrev( x, m);
|
||||
/*C-----Length two butterflies----------------------------------------C*/
|
||||
is = 1;
|
||||
id = 4;
|
||||
do {
|
||||
for (i0 = is; i0 <= n; i0 += id) {
|
||||
t1 = x[i0];
|
||||
x[i0] = t1 + x[i0+1];
|
||||
x[i0+1] = t1 - x[i0+1];
|
||||
}
|
||||
is = 2*id-1;
|
||||
id = 4*id;
|
||||
} while (is < n);
|
||||
/*C-------L shaped butterflies----------------------------------------C*/
|
||||
n2 = 2;
|
||||
for (k = 2; k <= m; k++) {
|
||||
n2 = n2 * 2;
|
||||
n4 = n2 / 4;
|
||||
rstage(n, n2, n4, &x[0], &x[n4], &x[2 * n4], &x[3 * n4]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
C===================================================================C
|
||||
C Subroutine RSTAGE - the work-horse of the RFFT C
|
||||
C Computes a stage of a real-valued split-radix length N C
|
||||
C transform. C
|
||||
C Author C
|
||||
C H.V. Sorensen, University of Pennsylvania, Mar. 1987 C
|
||||
C===================================================================C
|
||||
*/
|
||||
void rstage(
|
||||
int n, int n2, int n4,
|
||||
double *x1, double *x2, double *x3, double *x4)
|
||||
{
|
||||
int n8, is, id, i1, i2, j, jn;
|
||||
double t1, t2, e, t3, t4, t5;
|
||||
double ss1, sd1, ss3, sd3;
|
||||
double cc1, cd1, cc3, cd3;
|
||||
|
||||
n8 = n2 / 8;
|
||||
is = 0;
|
||||
id = n2*2;
|
||||
|
||||
do {
|
||||
for (i1 = is + 1; i1 <= n; i1 += id) {
|
||||
t1 = x4[i1]+x3[i1];
|
||||
x4[i1] = x4[i1]-x3[i1];
|
||||
x3[i1] = x1[i1]-t1;
|
||||
x1[i1] = x1[i1]+t1;
|
||||
}
|
||||
is = 2*id - n2;
|
||||
id = 4*id;
|
||||
} while (is < n);
|
||||
|
||||
if (n4-1 <= 0) return;
|
||||
|
||||
is = 0;
|
||||
id = n2 * 2;
|
||||
do {
|
||||
for (i2 = is + 1 + n8; i2 <= n; i2 += id) {
|
||||
t1 = (x3[i2] + x4[i2]) * .7071067811865475;
|
||||
t2 = (x3[i2] - x4[i2]) * .7071067811865475;
|
||||
x4[i2] = x2[i2] - t1;
|
||||
x3[i2] = -x2[i2] - t1;
|
||||
x2[i2] = x1[i2] - t2;
|
||||
x1[i2] = x1[i2] + t2;
|
||||
}
|
||||
is = 2 * id - n2;
|
||||
id = 4 * id;
|
||||
} while (is < n);
|
||||
|
||||
if (n8-1 <= 0) return;
|
||||
|
||||
e = 2 * 3.14159265358979323 / n2;
|
||||
ss1 = sin(e);
|
||||
sd1 = ss1;
|
||||
sd3 = 3 * sd1 - 4 * (sd1 * sd1 * sd1);
|
||||
ss3 = sd3;
|
||||
cc1 = cos(e);
|
||||
cd1 = cc1;
|
||||
cd3 = 4 * (cd1 * cd1 * cd1) - 3.0 * cd1;
|
||||
cc3 = cd3;
|
||||
|
||||
for (j = 2; j <= n8; j++) {
|
||||
is = 0;
|
||||
id = 2 * n2;
|
||||
jn = n4 - 2*j + 2;
|
||||
do {
|
||||
for (i1 = is + j; i1 <= n; i1 += id) {
|
||||
i2 = i1 + jn;
|
||||
t1 = x3[i1]*cc1 + x3[i2]*ss1;
|
||||
t2 = x3[i2]*cc1 - x3[i1]*ss1;
|
||||
t3 = x4[i1]*cc3 + x4[i2]*ss3;
|
||||
t4 = x4[i2]*cc3 - x4[i1]*ss3;
|
||||
t5 = t1 + t3;
|
||||
t3 = t1 - t3;
|
||||
t1 = t2 + t4;
|
||||
t4 = t2 - t4;
|
||||
x3[i1] = t1 - x2[i2];
|
||||
x4[i2] = t1 + x2[i2];
|
||||
x3[i2] = -x2[i1] - t3;
|
||||
x4[i1] = x2[i1] - t3;
|
||||
x2[i2] = x1[i1] - t5;
|
||||
x1[i1] = x1[i1] + t5;
|
||||
x2[i1] = x1[i2] + t4;
|
||||
x1[i2] = x1[i2] - t4;
|
||||
}
|
||||
is = 2*id - n2;
|
||||
id = 4*id;
|
||||
} while (is < n);
|
||||
|
||||
t1 = cc1*cd1 - ss1*sd1;
|
||||
ss1 = cc1*sd1 + ss1*cd1;
|
||||
cc1 = t1;
|
||||
t3 = cc3*cd3 - ss3*sd3;
|
||||
ss3 = cc3*sd3 + ss3*cd3;
|
||||
cc3 = t3;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CC=================================================================CC
|
||||
CC CC
|
||||
CC Subroutine RBITREV(X,M): CC
|
||||
CC Bitreverses the array X of length 2**M. It generates a CC
|
||||
CC table ITAB (minimum length is SQRT(2**M) if M is even CC
|
||||
CC or SQRT(2*2**M) if M is odd). ITAB need only be generated CC
|
||||
CC once for a given transform length. CC
|
||||
CC CC
|
||||
CC Author: CC
|
||||
CC H.V. Sorensen, University of Pennsylvania, Aug. 1987 CC
|
||||
CC Arpa address: hvs@ee.upenn.edu CC
|
||||
CC CC
|
||||
CC This program may be used and distributed freely as long CC
|
||||
CC as this header is included. CC
|
||||
CC CC
|
||||
CC=================================================================CC
|
||||
*/
|
||||
void rbitrev(double *x, int m)
|
||||
{
|
||||
int itab[257];
|
||||
int m2, nbit, imax, lbss, i, j, k, l, j0;
|
||||
double t1;
|
||||
/*C-------Initialization of ITAB array--------------------------------C*/
|
||||
m2 = m / 2;
|
||||
nbit = 1 << m2;
|
||||
if (2 * m2 != m) m2 = m2 + 1;
|
||||
itab[1] = 0;
|
||||
itab[2] = 1;
|
||||
imax = 1;
|
||||
|
||||
for (lbss = 2; lbss <= m2; lbss++) {
|
||||
imax = 2 * imax;
|
||||
for (i=1;i<=imax;i++) {
|
||||
itab[i] = 2 * itab[i];
|
||||
itab[i+imax] = 1 + itab[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*C-------The actual bitreversal--------------------------------------C*/
|
||||
for ( k =2; k <= nbit; k++) {
|
||||
j0 = nbit * itab[k] + 1;
|
||||
i = k;
|
||||
j = j0;
|
||||
for (l=2;l<=itab[k]+1;l++) {
|
||||
t1 = x[i];
|
||||
x[i] = x[j];
|
||||
x[j] = t1;
|
||||
i = i + nbit;
|
||||
j = j0 + itab[l];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef RSID_FFT_H
|
||||
#define RSID_FFT_H
|
||||
|
||||
extern void rsrfft( double *x, int m );
|
||||
|
||||
extern void rstage(
|
||||
int n, int n2, int n4,
|
||||
double *x1, double *x2, double *x3, double *x4);
|
||||
|
||||
extern void rbitrev(double *x, int m);
|
||||
|
||||
#endif
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -42,6 +44,8 @@
|
|||
#include <semaphore.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <bits/stream_iterator.h>
|
||||
|
||||
#if USE_OSS
|
||||
# include <sys/soundcard.h>
|
||||
#endif
|
||||
|
@ -671,6 +675,8 @@ size_t SoundOSS::Write_stereo(double *bufleft, double *bufright, size_t count)
|
|||
|
||||
bool SoundPort::pa_init = false;
|
||||
std::vector<const PaDeviceInfo*> SoundPort::devs;
|
||||
static ostringstream device_text[2];
|
||||
vector<double> SoundPort::supported_rates[2];
|
||||
void SoundPort::initialize(void)
|
||||
{
|
||||
if (pa_init)
|
||||
|
@ -693,7 +699,6 @@ void SoundPort::initialize(void)
|
|||
devs.reserve(ndev);
|
||||
for (PaDeviceIndex i = 0; i < ndev; i++)
|
||||
devs.push_back(Pa_GetDeviceInfo(i));
|
||||
|
||||
}
|
||||
void SoundPort::terminate(void)
|
||||
{
|
||||
|
@ -707,6 +712,16 @@ const std::vector<const PaDeviceInfo*>& SoundPort::devices(void)
|
|||
{
|
||||
return devs;
|
||||
}
|
||||
void SoundPort::devices_info(string& in, string& out)
|
||||
{
|
||||
in = device_text[0].str();
|
||||
out = device_text[1].str();
|
||||
}
|
||||
const vector<double>& SoundPort::get_supported_rates(unsigned dir)
|
||||
{
|
||||
return supported_rates[dir];
|
||||
}
|
||||
|
||||
|
||||
SoundPort::SoundPort(const char *in_dev, const char *out_dev)
|
||||
: req_sample_rate(0), fbuf(0)
|
||||
|
@ -1168,28 +1183,6 @@ void SoundPort::init_stream(unsigned dir)
|
|||
else if (sd[dir].idev == devs.end()) // if we only found a near-match point the idev iterator to it
|
||||
sd[dir].idev = devs.begin() + idx;
|
||||
|
||||
#ifndef NDEBUG
|
||||
cerr << "PA_debug: using " << dir_str[dir] << " device:"
|
||||
<< "\n index: " << idx
|
||||
<< "\n name: " << (*sd[dir].idev)->name
|
||||
<< "\n hostAPI: " << Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->name
|
||||
<< "\n maxInputChannels: " << (*sd[dir].idev)->maxInputChannels
|
||||
<< "\n maxOutputChannels: " << (*sd[dir].idev)->maxOutputChannels
|
||||
<< "\n defaultLowInputLatency: " << (*sd[dir].idev)->defaultLowInputLatency
|
||||
<< "\n defaultHighInputLatency: " << (*sd[dir].idev)->defaultHighInputLatency
|
||||
<< "\n defaultLowOutputLatency: " << (*sd[dir].idev)->defaultLowOutputLatency
|
||||
<< "\n defaultHighOutputLatency: " << (*sd[dir].idev)->defaultHighOutputLatency
|
||||
<< "\n defaultSampleRate: " << (*sd[dir].idev)->defaultSampleRate
|
||||
<< boolalpha
|
||||
<< "\n isInputOnlyDevice: " << ((*sd[dir].idev)->maxOutputChannels == 0)
|
||||
<< "\n isOutputOnlyDevice: " << ((*sd[dir].idev)->maxInputChannels == 0)
|
||||
<< "\n isFullDuplexDevice: " << full_duplex_device(*sd[dir].idev)
|
||||
<< "\n isSystemDefaultInputDevice: " << (idx == Pa_GetDefaultInputDevice())
|
||||
<< "\n isSystemDefaultOutputDevice: " << (idx == Pa_GetDefaultOutputDevice())
|
||||
<< "\n isHostApiDefaultInputDevice: " << (idx == Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->defaultInputDevice)
|
||||
<< "\n isHostApiDefaultOutputDevice: " << (idx == Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->defaultOutputDevice)
|
||||
<< "\n";
|
||||
#endif
|
||||
|
||||
if ((dir == 0 && (*sd[dir].idev)->maxInputChannels == 0) ||
|
||||
(dir == 1 && (*sd[dir].idev)->maxOutputChannels == 0))
|
||||
|
@ -1213,6 +1206,47 @@ void SoundPort::init_stream(unsigned dir)
|
|||
sd[1].params.hostApiSpecificStreamInfo = NULL;
|
||||
}
|
||||
|
||||
|
||||
extern double std_sample_rates[];
|
||||
supported_rates[dir].clear();
|
||||
supported_rates[dir].push_back((*sd[dir].idev)->defaultSampleRate);
|
||||
for (const double* i = std_sample_rates; *i > 0.0; i++)
|
||||
if (Pa_IsFormatSupported((dir == 0 ? &sd[0].params : NULL),
|
||||
(dir == 1 ? &sd[1].params : NULL), *i) == paFormatIsSupported)
|
||||
supported_rates[dir].push_back(*i);
|
||||
ostringstream ss;
|
||||
if (supported_rates[dir].size() > 1)
|
||||
copy(supported_rates[dir].begin(), supported_rates[dir].end(), ostream_iterator<unsigned>(ss, " "));
|
||||
else
|
||||
ss << "Unknown";
|
||||
|
||||
device_text[dir].str("");
|
||||
device_text[dir]
|
||||
<< "index: " << idx
|
||||
<< "\nname: " << (*sd[dir].idev)->name
|
||||
<< "\nhost API: " << Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->name
|
||||
<< "\nmax input channels: " << (*sd[dir].idev)->maxInputChannels
|
||||
<< "\nmax output channels: " << (*sd[dir].idev)->maxOutputChannels
|
||||
<< "\ndefault sample rate: " << (*sd[dir].idev)->defaultSampleRate
|
||||
<< "\nsupported sample rates: " << ss.str()
|
||||
<< boolalpha
|
||||
<< "\ninput only: " << ((*sd[dir].idev)->maxOutputChannels == 0)
|
||||
<< "\noutput only: " << ((*sd[dir].idev)->maxInputChannels == 0)
|
||||
<< "\nfull duplex: " << full_duplex_device(*sd[dir].idev)
|
||||
<< "\nsystem default input: " << (idx == Pa_GetDefaultInputDevice())
|
||||
<< "\nsystem default output: " << (idx == Pa_GetDefaultOutputDevice())
|
||||
<< "\nhost API default input: " << (idx == Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->defaultInputDevice)
|
||||
<< "\nhost API default output: " << (idx == Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->defaultOutputDevice)
|
||||
<< "\ndefault low input latency: " << (*sd[dir].idev)->defaultLowInputLatency
|
||||
<< "\ndefault high input latency: " << (*sd[dir].idev)->defaultHighInputLatency
|
||||
<< "\ndefault low output latency: " << (*sd[dir].idev)->defaultLowOutputLatency
|
||||
<< "\ndefault high output latency: " << (*sd[dir].idev)->defaultHighOutputLatency
|
||||
<< "\n";
|
||||
#ifndef NDEBUG
|
||||
cerr << "PA_debug: using " << dir_str[dir] << " device:\n" << device_text[dir].str();
|
||||
#endif
|
||||
|
||||
|
||||
sd[dir].dev_sample_rate = find_srate(dir);
|
||||
#ifndef NDEBUG
|
||||
if (sd[dir].dev_sample_rate != req_sample_rate)
|
||||
|
@ -1359,23 +1393,11 @@ double SoundPort::find_srate(unsigned dir)
|
|||
return sr;
|
||||
}
|
||||
|
||||
double srates[] = { req_sample_rate, (*sd[dir].idev)->defaultSampleRate };
|
||||
int err;
|
||||
for (size_t i = 0; i < sizeof(srates)/sizeof(srates[0]); i++) {
|
||||
#ifndef NDEBUG
|
||||
cerr << "PA_debug: trying " << srates[i] << " Hz" << endl;
|
||||
#endif
|
||||
if ((err = Pa_IsFormatSupported((dir == 0 ? &sd[0].params : NULL),
|
||||
(dir == 1 ? &sd[1].params : NULL),
|
||||
srates[i])) == paFormatIsSupported)
|
||||
return srates[i];
|
||||
#ifndef NDEBUG
|
||||
else
|
||||
pa_perror(err, "Pa_IsFormatSupported");
|
||||
#endif
|
||||
}
|
||||
for (vector<double>::const_iterator i = supported_rates[dir].begin(); i != supported_rates[dir].end(); i++)
|
||||
if (req_sample_rate == *i || (*sd[dir].idev)->defaultSampleRate == *i)
|
||||
return *i;
|
||||
|
||||
throw SndPortException(err);
|
||||
throw SndException("No supported sample rate found");
|
||||
}
|
||||
|
||||
void SoundPort::pa_perror(int err, const char* str)
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
# include <list>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "soundconf.h"
|
||||
#include "sound.h"
|
||||
#include "main.h"
|
||||
|
@ -13,6 +16,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
double std_sample_rates[] = { 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0,
|
||||
32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1.0 };
|
||||
|
||||
static void init_oss(void)
|
||||
{
|
||||
|
@ -181,16 +186,28 @@ static void init_portaudio(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void build_srate_menu(Fl_Menu_* menu, const double* rates, size_t length, double defrate = -1.0)
|
||||
{
|
||||
menu->clear();
|
||||
menu->add("Auto");
|
||||
menu->add("Native", 0, 0, 0, FL_MENU_DIVIDER);
|
||||
|
||||
char s[16];
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (defrate != rates[i])
|
||||
snprintf(s, sizeof(s), "%.0f", rates[i]);
|
||||
else
|
||||
snprintf(s, sizeof(s), "%.0f (native)", rates[i]);
|
||||
menu->add(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void sound_init_options(void)
|
||||
{
|
||||
static const Fl_Menu_Item sample_rate_menu[] = {
|
||||
{ "Auto" }, { "Native", 0, 0, 0, FL_MENU_DIVIDER },
|
||||
{ "8000" }, { "9600" }, { "11025" }, { "12000" }, { "16000" },
|
||||
{ "22050" }, { "24000" }, { "32000" }, { "44100" }, { "48000" },
|
||||
{ "88200" }, { "96000" }, { "192000" }, { 0 }
|
||||
};
|
||||
menuInSampleRate->menu(sample_rate_menu);
|
||||
menuOutSampleRate->menu(sample_rate_menu);
|
||||
build_srate_menu(menuInSampleRate, std_sample_rates,
|
||||
sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1);
|
||||
build_srate_menu(menuOutSampleRate, std_sample_rates,
|
||||
sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1);
|
||||
|
||||
const char* cname;
|
||||
for (int i = 0; (cname = src_get_name(i)); i++) {
|
||||
|
@ -301,24 +318,64 @@ void sound_update(unsigned idx)
|
|||
|
||||
progdefaults.btnAudioIOis = idx;
|
||||
switch (idx) {
|
||||
#if USE_OSS
|
||||
case SND_IDX_OSS:
|
||||
menuOSSDev->activate();
|
||||
scDevice[0] = scDevice[1] = menuOSSDev->value();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if USE_PORTAUDIO
|
||||
case SND_IDX_PORT:
|
||||
menuPortInDev->activate();
|
||||
menuPortOutDev->activate();
|
||||
menuInSampleRate->activate();
|
||||
menuOutSampleRate->activate();
|
||||
if (menuPortInDev->text())
|
||||
scDevice[0] = menuPortInDev->text();
|
||||
if (menuPortOutDev->text())
|
||||
scDevice[1] = menuPortOutDev->text();
|
||||
|
||||
{
|
||||
Fl_Menu_* menus[2] = { menuInSampleRate, menuOutSampleRate };
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
char* label = strdup(menus[i]->text());
|
||||
const vector<double>& srates = SoundPort::get_supported_rates(i);
|
||||
|
||||
switch (srates.size()) {
|
||||
case 0: // startup; no devices initialised yet
|
||||
build_srate_menu(menus[i], std_sample_rates,
|
||||
sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1);
|
||||
break;
|
||||
case 1: // default sample rate only, build menu with all std rates
|
||||
build_srate_menu(menus[i], std_sample_rates,
|
||||
sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1, srates[0]);
|
||||
|
||||
break;
|
||||
default: // first element is default sample rate, build menu with rest
|
||||
build_srate_menu(menus[i], &srates[0] + 1, srates.size() - 1, srates[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const Fl_Menu_Item* item = menus[i]->menu(); item->text; item++) {
|
||||
if (strstr(item->text, label)) {
|
||||
menus[i]->value(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(label);
|
||||
|
||||
menus[i]->activate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if USE_PULSEAUDIO
|
||||
case SND_IDX_PULSE:
|
||||
inpPulseServer->activate();
|
||||
scDevice[0] = scDevice[1] = inpPulseServer->value();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SND_IDX_NULL:
|
||||
scDevice[0] = scDevice[1] = "";
|
||||
break;
|
||||
|
|
|
@ -142,11 +142,11 @@ thor::thor(trx_mode md)
|
|||
samplerate = 11025;
|
||||
break;
|
||||
|
||||
case MODE_TSOR11:
|
||||
symlen = 1024;
|
||||
doublespaced = 1;
|
||||
samplerate = 11025;
|
||||
break;
|
||||
// case MODE_TSOR11:
|
||||
// symlen = 1024;
|
||||
// doublespaced = 1;
|
||||
// samplerate = 11025;
|
||||
// break;
|
||||
|
||||
case MODE_THOR22:
|
||||
symlen = 512;
|
||||
|
@ -174,12 +174,12 @@ thor::thor(trx_mode md)
|
|||
|
||||
|
||||
basetone = (int)floor(THORBASEFREQ * symlen / samplerate + 0.5);
|
||||
lotone = basetone - (THORNUMMTONES/2) * (doublespaced ? 2 : 1);
|
||||
hitone = basetone + 3 * (THORNUMMTONES/2) * (doublespaced ? 2 : 1);
|
||||
lotone = basetone - (THORNUMTONES/2) * (doublespaced ? 2 : 1);
|
||||
hitone = basetone + 3 * (THORNUMTONES/2) * (doublespaced ? 2 : 1);
|
||||
|
||||
tonespacing = (double) (samplerate * ((doublespaced) ? 2 : 1)) / symlen;
|
||||
|
||||
bandwidth = THORNUMMTONES * tonespacing;
|
||||
bandwidth = THORNUMTONES * tonespacing;
|
||||
|
||||
hilbert = new C_FIR_filter();
|
||||
hilbert->init_hilbert(37, 1);
|
||||
|
@ -203,7 +203,7 @@ thor::thor(trx_mode md)
|
|||
pipe = new THORrxpipe[twosym];
|
||||
|
||||
scopedata.alloc(THORSCOPESIZE);
|
||||
videodata.alloc((THORMAXFFTS * THORNUMMTONES * 2 * (doublespaced?2:1) ));
|
||||
videodata.alloc((THORMAXFFTS * THORNUMTONES * 2 * (doublespaced?2:1) ));
|
||||
|
||||
pipeptr = 0;
|
||||
|
||||
|
@ -295,43 +295,24 @@ void thor::decodePairs(unsigned char symbol)
|
|||
}
|
||||
}
|
||||
|
||||
void thor::decodeEX(int ch)
|
||||
{
|
||||
unsigned char symbols[4];
|
||||
int c = ch;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((c & 1) == 1) symbols[3-i] = 255;
|
||||
else symbols[3-i] = 1;
|
||||
c = c / 2;
|
||||
}
|
||||
|
||||
Rxinlv->symbols(symbols);
|
||||
|
||||
for (int i = 0; i < 4; i++) decodePairs(symbols[i]);
|
||||
|
||||
}
|
||||
|
||||
void thor::decodesymbol()
|
||||
{
|
||||
int c;
|
||||
double fdiff;
|
||||
double fdiff, avg, softmag;
|
||||
unsigned char symbols[4];
|
||||
|
||||
// Decode the IFK+ sequence, which results in a single nibble
|
||||
|
||||
fdiff = currsymbol - prev1symbol;
|
||||
if (reverse) fdiff = -fdiff;
|
||||
if (doublespaced) fdiff /= 2 * paths;
|
||||
else fdiff /= paths;
|
||||
fdiff /= paths;
|
||||
if (doublespaced) fdiff /= 2.0;
|
||||
c = (int)floor(fdiff + .5) - 2;
|
||||
if (c < 0) c += THORNUMMTONES;
|
||||
if (c < 0) c += THORNUMTONES;
|
||||
|
||||
// decodeEX(c);
|
||||
|
||||
unsigned char symbols[4];
|
||||
double avg = (currmag + prev1mag + prev2mag) / 3.0;
|
||||
avg = (currmag + prev1mag + prev2mag) / 3.0;
|
||||
if (avg == 0.0) avg = 1e-20;
|
||||
double softmag = currmag / avg;
|
||||
softmag = currmag / avg;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// hard symbol decode
|
||||
|
@ -355,7 +336,7 @@ int thor::harddecode()
|
|||
{
|
||||
double x, max = 0.0;
|
||||
int symbol = 0;
|
||||
for (int i = 0; i < (paths * THORNUMMTONES * 2 * (doublespaced ? 2 : 1) ); i++) {
|
||||
for (int i = 0; i < (paths * THORNUMTONES * 2 * (doublespaced ? 2 : 1) ); i++) {
|
||||
x = pipe[pipeptr].vector[i].mag();
|
||||
if (x > max) {
|
||||
max = x;
|
||||
|
@ -371,16 +352,16 @@ void thor::update_syncscope()
|
|||
double max = 0, min = 1e6, range, mag;
|
||||
|
||||
// dom waterfall
|
||||
memset(videodata, 0, (paths * THORNUMMTONES * 2 * (doublespaced?2:1) ) * sizeof(double));
|
||||
memset(videodata, 0, (paths * THORNUMTONES * 2 * (doublespaced?2:1) ) * sizeof(double));
|
||||
|
||||
if (!progStatus.sqlonoff || metric >= progStatus.sldrSquelchValue) {
|
||||
for (int i = 0; i < (paths * THORNUMMTONES * 2 * (doublespaced?2:1) ); i++ ) {
|
||||
for (int i = 0; i < (paths * THORNUMTONES * 2 * (doublespaced?2:1) ); i++ ) {
|
||||
mag = pipe[pipeptr].vector[i].mag();
|
||||
if (max < mag) max = mag;
|
||||
if (min > mag) min = mag;
|
||||
}
|
||||
range = max - min;
|
||||
for (int i = 0; i < (paths * THORNUMMTONES * 2 * (doublespaced?2:1) ); i++ ) {
|
||||
for (int i = 0; i < (paths * THORNUMTONES * 2 * (doublespaced?2:1) ); i++ ) {
|
||||
if (range > 2) {
|
||||
mag = (pipe[pipeptr].vector[i].mag() - min) / range + 0.0001;
|
||||
mag = 1 + 2 * log10(mag);
|
||||
|
@ -390,7 +371,7 @@ void thor::update_syncscope()
|
|||
videodata[i] = 255*mag;
|
||||
}
|
||||
}
|
||||
set_video(videodata, (paths * THORNUMMTONES * 2 * (doublespaced?2:1) ), false);
|
||||
set_video(videodata, (paths * THORNUMTONES * 2 * (doublespaced?2:1) ), false);
|
||||
videodata.next();
|
||||
|
||||
// set_scope(scopedata, twosym);
|
||||
|
@ -428,7 +409,7 @@ void thor::synchronize()
|
|||
}
|
||||
syn = syncfilter->run(syn);
|
||||
|
||||
synccounter += (int) floor(1.0 * (syn - symlen) / THORNUMMTONES + 0.5);
|
||||
synccounter += (int) floor(1.0 * (syn - symlen) / THORNUMTONES + 0.5);
|
||||
}
|
||||
|
||||
|
||||
|
@ -437,11 +418,11 @@ void thor::eval_s2n()
|
|||
if (currsymbol != prev1symbol && prev1symbol != prev2symbol) {
|
||||
sig = pipe[pipeptr].vector[currsymbol].mag();
|
||||
noise = 0.0;
|
||||
for (int i = 0; i < paths * THORNUMMTONES * 2 * (doublespaced?2:1); i++) {
|
||||
for (int i = 0; i < paths * THORNUMTONES * 2 * (doublespaced?2:1); i++) {
|
||||
if (i != currsymbol)
|
||||
noise += pipe[pipeptr].vector[i].mag();
|
||||
}
|
||||
noise /= (paths * THORNUMMTONES * 2 * (doublespaced?2:1) - 1);
|
||||
noise /= (paths * THORNUMTONES * 2 * (doublespaced?2:1) - 1);
|
||||
|
||||
if (noise)
|
||||
s2n = decayavg( s2n, sig / noise, 8);
|
||||
|
@ -484,7 +465,7 @@ int thor::rx_process(const double *buf, int len)
|
|||
z = mixer(n + 1, zp[i]);
|
||||
bins = binsfft[n]->run(z);
|
||||
// copy current vector to the pipe interleaving the FFT vectors
|
||||
for (int i = 0; i < THORNUMMTONES * 2 * (doublespaced ? 2 : 1); i++) {
|
||||
for (int i = 0; i < THORNUMTONES * 2 * (doublespaced ? 2 : 1); i++) {
|
||||
pipe[pipeptr].vector[n + paths * i] = bins[i];
|
||||
}
|
||||
}
|
||||
|
@ -548,10 +529,10 @@ void thor::sendsymbol(int sym)
|
|||
complex z;
|
||||
int tone;
|
||||
|
||||
tone = (txprevtone + 2 + sym) % THORNUMMTONES;
|
||||
tone = (txprevtone + 2 + sym) % THORNUMTONES;
|
||||
txprevtone = tone;
|
||||
if (reverse)
|
||||
tone = (THORNUMMTONES - 1) - tone;
|
||||
tone = (THORNUMTONES - 1) - tone;
|
||||
sendtone(tone, 1);
|
||||
}
|
||||
|
||||
|
@ -624,12 +605,12 @@ int thor::tx_process()
|
|||
case TX_STATE_PREAMBLE:
|
||||
Clearbits();
|
||||
for (int j = 0; j < 16; j++) sendsymbol(0);
|
||||
// sendtone(THORNUMMTONES/2, 4);
|
||||
// sendtone(THORNUMTONES/2, 4);
|
||||
// for (int k = 0; k < 3; k++) {
|
||||
// sendtone(THORNUMMTONES, 3);
|
||||
// sendtone(THORNUMTONES, 3);
|
||||
// sendtone(0, 3);
|
||||
// }
|
||||
// sendtone(THORNUMMTONES/2, 4);
|
||||
// sendtone(THORNUMTONES/2, 4);
|
||||
|
||||
sendidle();
|
||||
txstate = TX_STATE_START;
|
||||
|
|
|
@ -493,8 +493,8 @@ void modem::wfid_send(long int symbol)
|
|||
sym = symbol;
|
||||
msk = mask[symbol];
|
||||
for (j = 0; j < NUMTONES * NUMCHARS; j++) {
|
||||
if (sym & 1 == 1)
|
||||
wfid_outbuf[i] += ((msk & 1 == 1 ? -1 : 1 ) * sin(wfid_w[j] * i) * wfid_txpulse[i]);
|
||||
if (sym & 1)
|
||||
wfid_outbuf[i] += (msk & 1 ? -1 : 1 ) * sin(wfid_w[j] * i) * wfid_txpulse[i];
|
||||
sym = sym >> 1;
|
||||
msk = msk >> 1;
|
||||
}
|
||||
|
|
|
@ -66,8 +66,10 @@ bool restartOK = false;
|
|||
bool trx_wait = false;
|
||||
|
||||
modem *active_modem = 0;
|
||||
cRsId *ReedSolomon = 0;
|
||||
SoundBase *scard;
|
||||
|
||||
|
||||
int _trx_tune;
|
||||
|
||||
// Ringbuffer for the audio "history". A pointer into this buffer
|
||||
|
@ -80,6 +82,9 @@ bool bHistory = false;
|
|||
|
||||
static int dummy = 0;
|
||||
static bool trxrunning = false;
|
||||
|
||||
static bool rsid_detecting = false;
|
||||
|
||||
#include "tune.cxx"
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -96,6 +101,7 @@ void trx_trx_receive_loop()
|
|||
if (active_modem) {
|
||||
try {
|
||||
scard->Open(O_RDONLY, active_modem->get_samplerate());
|
||||
REQ(sound_update, progdefaults.btnAudioIOis);
|
||||
}
|
||||
catch (const SndException& e) {
|
||||
put_status(e.what(), 5);
|
||||
|
@ -110,6 +116,40 @@ void trx_trx_receive_loop()
|
|||
active_modem->rx_init();
|
||||
|
||||
while (1) {
|
||||
if (progdefaults.rsid == true && rsid_detecting == false) {
|
||||
rsid_detecting = true;
|
||||
try {
|
||||
scard->Open(O_RDONLY, ReedSolomon->samplerate());
|
||||
}
|
||||
catch (const SndException& e) {
|
||||
put_status(e.what(), 5);
|
||||
scard->Close();
|
||||
if (e.error() == EBUSY && progdefaults.btnAudioIOis == SND_IDX_PORT) {
|
||||
sound_close();
|
||||
sound_init();
|
||||
}
|
||||
MilliSleep(1000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (progdefaults.rsid == false && rsid_detecting == true) {
|
||||
rsid_detecting = false;
|
||||
try {
|
||||
scard->Open(O_RDONLY, active_modem->get_samplerate());
|
||||
}
|
||||
catch (const SndException& e) {
|
||||
put_status(e.what(), 5);
|
||||
scard->Close();
|
||||
if (e.error() == EBUSY && progdefaults.btnAudioIOis == SND_IDX_PORT) {
|
||||
sound_close();
|
||||
sound_init();
|
||||
}
|
||||
MilliSleep(1000);
|
||||
return;
|
||||
}
|
||||
active_modem->rx_init();
|
||||
}
|
||||
|
||||
try {
|
||||
if (trxrb.write_space() == 0) // discard some old data
|
||||
trxrb.read_advance(SCBLOCKSIZE);
|
||||
|
@ -130,8 +170,12 @@ void trx_trx_receive_loop()
|
|||
trxrb.write_advance(numread);
|
||||
REQ(&waterfall::sig_data, wf, rbvec[0].buf, numread);
|
||||
|
||||
if (!bHistory)
|
||||
active_modem->rx_process(rbvec[0].buf, numread);
|
||||
if (!bHistory) {
|
||||
if (rsid_detecting == true)
|
||||
ReedSolomon->search(rbvec[0].buf, numread);
|
||||
else
|
||||
active_modem->rx_process(rbvec[0].buf, numread);
|
||||
}
|
||||
else {
|
||||
bool afc = progStatus.afconoff;
|
||||
progStatus.afconoff = false;
|
||||
|
@ -162,6 +206,7 @@ void trx_trx_transmit_loop()
|
|||
if (active_modem) {
|
||||
try {
|
||||
scard->Open(O_WRONLY, active_modem->get_samplerate());
|
||||
REQ(sound_update, progdefaults.btnAudioIOis);
|
||||
}
|
||||
catch (const SndException& e) {
|
||||
put_status(e.what(), 1);
|
||||
|
@ -172,6 +217,9 @@ void trx_trx_transmit_loop()
|
|||
push2talk->set(true);
|
||||
active_modem->tx_init(scard);
|
||||
|
||||
if (progdefaults.TransmitRSid == true)
|
||||
ReedSolomon->send();
|
||||
|
||||
while (trx_state == STATE_TX) {
|
||||
try {
|
||||
if (active_modem->tx_process() < 0)
|
||||
|
@ -207,6 +255,7 @@ void trx_tune_loop()
|
|||
if (active_modem) {
|
||||
try {
|
||||
scard->Open(O_WRONLY, active_modem->get_samplerate());
|
||||
REQ(sound_update, progdefaults.btnAudioIOis);
|
||||
}
|
||||
catch (const SndException& e) {
|
||||
put_status(e.what(), 1);
|
||||
|
@ -375,6 +424,8 @@ void trx_start(void)
|
|||
}
|
||||
|
||||
if (scard) delete scard;
|
||||
if (ReedSolomon) delete ReedSolomon;
|
||||
|
||||
|
||||
switch (progdefaults.btnAudioIOis) {
|
||||
#if USE_OSS
|
||||
|
@ -399,6 +450,8 @@ void trx_start(void)
|
|||
abort();
|
||||
}
|
||||
|
||||
ReedSolomon = new cRsId;
|
||||
|
||||
trx_state = STATE_RX;
|
||||
_trx_tune = 0;
|
||||
active_modem = 0;
|
||||
|
|
|
@ -339,8 +339,10 @@ void WFdisp::update_fft_db()
|
|||
void WFdisp::processFFT() {
|
||||
int n;
|
||||
double scale;
|
||||
|
||||
scale = (double)SC_SMPLRATE / active_modem->get_samplerate();
|
||||
if (progdefaults.rsid == true)
|
||||
scale = (double)SC_SMPLRATE / ReedSolomon->samplerate();
|
||||
else
|
||||
scale = (double)SC_SMPLRATE / active_modem->get_samplerate();
|
||||
scale *= FFT_LEN / 2000.0;
|
||||
|
||||
if (dispcnt == 0) {
|
||||
|
@ -509,6 +511,7 @@ void WFdisp::carrier(int cf) {
|
|||
if (cf > bandwidth / 2 && cf < (IMAGE_WIDTH - bandwidth / 2)) {
|
||||
carrierfreq = cf;
|
||||
makeMarker();
|
||||
redrawCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,16 +846,36 @@ void x1_cb(Fl_Widget *w, void* v) {
|
|||
restoreFocus();
|
||||
}
|
||||
|
||||
void bwclr_cb(Fl_Widget *w, void * v) {
|
||||
waterfall *wf = (waterfall *)w->parent();
|
||||
wf->wfdisp->DispColor(!wf->wfdisp->DispColor());
|
||||
if (wf->wfdisp->DispColor() == 0)
|
||||
w->label("gry");
|
||||
else
|
||||
w->label("clr");
|
||||
void bw_rsid_toggle(waterfall *wf)
|
||||
{
|
||||
if (trx_state == STATE_TX)
|
||||
return;
|
||||
if (progdefaults.rsid == true) {
|
||||
progdefaults.rsid = false;
|
||||
wf->bw_rsid->color(FL_BACKGROUND_COLOR);
|
||||
wf->bw_rsid->redraw();
|
||||
wf->xmtrcv->activate();
|
||||
} else {
|
||||
progdefaults.rsid = true;
|
||||
wf->bw_rsid->color(FL_YELLOW);
|
||||
wf->bw_rsid->redraw();
|
||||
wf->xmtrcv->deactivate();
|
||||
}
|
||||
restoreFocus();
|
||||
}
|
||||
|
||||
void bw_rsid_cb(Fl_Widget *w, void * v) {
|
||||
waterfall *wf = (waterfall *)w->parent();
|
||||
// wf->wfdisp->DispColor(!wf->wfdisp->DispColor());
|
||||
// if (wf->wfdisp->DispColor() == 0) {
|
||||
// w->label("gry");
|
||||
// } else {
|
||||
// w->label("clr");
|
||||
// }
|
||||
// restoreFocus();
|
||||
bw_rsid_toggle(wf);
|
||||
}
|
||||
|
||||
void slew_left(Fl_Widget *w, void * v) {
|
||||
waterfall *wf = (waterfall *)w->parent();
|
||||
wf->wfdisp->slew(-100);
|
||||
|
@ -989,7 +1012,7 @@ void mode_cb(Fl_Widget *w, void *v) {
|
|||
wf->wfdisp->Mode(SCOPE);
|
||||
w->label("sig");
|
||||
wf->x1->deactivate();
|
||||
wf->bwclr->deactivate();
|
||||
wf->bw_rsid->deactivate();
|
||||
wf->wfcarrier->deactivate();
|
||||
wf->wfRefLevel->deactivate();
|
||||
wf->wfAmpSpan->deactivate();
|
||||
|
@ -1003,7 +1026,7 @@ void mode_cb(Fl_Widget *w, void *v) {
|
|||
wf->wfdisp->Mode(WATERFALL);
|
||||
w->label("Wtr");
|
||||
wf->x1->activate();
|
||||
wf->bwclr->activate();
|
||||
wf->bw_rsid->activate();
|
||||
wf->wfcarrier->activate();
|
||||
wf->wfRefLevel->activate();
|
||||
wf->wfAmpSpan->activate();
|
||||
|
@ -1262,9 +1285,9 @@ waterfall::waterfall(int x0, int y0, int w0, int h0, char *lbl) :
|
|||
// wfdisp->tooltip("Click to set tracking point");
|
||||
|
||||
xpos = x() + wSpace;
|
||||
bwclr = new Fl_Button(xpos, buttonrow, bwColor*(w0<600?w0/6:100)/100, BTN_HEIGHT, "clr");
|
||||
bwclr->callback(bwclr_cb, 0);
|
||||
bwclr->tooltip("Color / BW waterfall");
|
||||
bw_rsid = new Fl_Button(xpos, buttonrow, bwColor*(w0<600?w0/6:100)/100, BTN_HEIGHT, "Id?");
|
||||
bw_rsid->callback(bw_rsid_cb, 0);
|
||||
bw_rsid->tooltip("Auto detect RSID");
|
||||
|
||||
xpos = xpos + bwColor*(w0<600?w0/6:100)/100 + wSpace;
|
||||
mode = new Fl_Button(xpos, buttonrow, bwFFT*(w0<600?w0/6:100)/100, BTN_HEIGHT,"Wtr");
|
||||
|
|
|
@ -819,10 +819,7 @@ int FTextEdit::handle_key(int key)
|
|||
// fall through to (un)pause for M-r or A-r
|
||||
case FL_Pause:
|
||||
if (trx_state != STATE_TX) {
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
}
|
||||
else
|
||||
PauseBreak = true;
|
||||
|
@ -983,10 +980,7 @@ void FTextEdit::menu_cb(int val)
|
|||
switch (val) {
|
||||
case TX_MENU_TX:
|
||||
active_modem->set_stopflag(false);
|
||||
fl_lock(&trx_mutex);
|
||||
trx_state = STATE_TX;
|
||||
fl_unlock(&trx_mutex);
|
||||
wf->set_XmtRcvBtn(true);
|
||||
start_tx();
|
||||
break;
|
||||
case TX_MENU_RX:
|
||||
insert_position(tbuf->length());
|
||||
|
|
Ładowanie…
Reference in New Issue