Upstream version 2.11AJ

pull/2/head
Stelios Bounanos 2008-05-24 22:33:19 +01:00
rodzic 713f7e18ed
commit eb5bd6f512
36 zmienionych plików z 1476 dodań i 290 usunięć

Wyświetl plik

@ -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.

Wyświetl plik

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

Wyświetl plik

@ -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])

Wyświetl plik

@ -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]) ;;

Wyświetl plik

@ -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

Wyświetl plik

@ -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 = \

Wyświetl plik

@ -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");

Wyświetl plik

@ -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

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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();

Wyświetl plik

@ -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;

Wyświetl plik

@ -12,6 +12,8 @@
using namespace std;
struct configuration {
bool rsid;
bool TransmitRSid;
bool changed;
double wfRefLevel;
double wfAmpSpan;

Wyświetl plik

@ -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();

Wyświetl plik

@ -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();

135
src/include/rsid.h 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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"));

595
src/rsid/rsid.cxx 100644
Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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");

Wyświetl plik

@ -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());