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 35) Bug fixes for the FM Hell modes
36) Changed the way that the video text / id is generated. 36) Changed the way that the video text / id is generated.
37) Added XML-RPC support. 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) 2.10.3)
1) Corrected memory leak bug. 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 dnl contain other characters or be empty
m4_define(FLDIGI_MAJOR, [2]) m4_define(FLDIGI_MAJOR, [2])
m4_define(FLDIGI_MINOR, [11]) 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]) 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]) m4_if([$4], [no], [ac_cv_want_[]$1=yes])
if test "x$ac_cv_want_[]$1" = "xno"; then case "x$ac_cv_want_[]$1" in
AC_DEFINE([USE_]PKG_NAME_UC, 0) "xno")
ac_cv_[]$1=no 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 else
PKG_CHECK_EXISTS([$2], ac_cv_[]$1=yes, ac_cv_[]$1=no) AC_DEFINE([USE_]PKG_NAME_UC, 0, [Define to 1 if we are using $1])
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
fi fi
AC_SUBST(PKG_NAME_UC[_CFLAGS]) AC_SUBST(PKG_NAME_UC[_CFLAGS])
AC_SUBST(PKG_NAME_UC[_LIBS]) AC_SUBST(PKG_NAME_UC[_LIBS])

Wyświetl plik

@ -1,6 +1,6 @@
AC_DEFUN([AC_FLDIGI_STATIC], [ AC_DEFUN([AC_FLDIGI_STATIC], [
AC_ARG_ENABLE([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 [case "${enableval}" in
yes|no) ac_cv_static="${enableval}" ;; yes|no) ac_cv_static="${enableval}" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-static]) ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-static]) ;;

Wyświetl plik

@ -1,10 +1,19 @@
AC_DEFUN([AC_FLDIGI_XMLRPC_CONFIG], [ AC_DEFUN([AC_FLDIGI_XMLRPC_CONFIG], [
ac_cv_xmlrpc=no 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 if test "x$XMLRPC_CFLAGS" != "x" && test "x$XMLRPC_LIBS" != "x"; then
XMLRPC_CFLAGS=`$XMLRPC_C_CONFIG c++2 abyss-server --cflags`
XMLRPC_LIBS=`$XMLRPC_C_CONFIG c++2 abyss-server --ldadd`
ac_cv_xmlrpc=yes 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 fi
]) ])
@ -24,19 +33,14 @@ AC_DEFUN([AC_FLDIGI_XMLRPC], [
AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc]) AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc])
ac_cv_xmlrpc=no ac_cv_xmlrpc=no
else else
AC_FLDIGI_XMLRPC_CONFIG
if test "x$ac_cv_want_xmlrpc" = "xcheck"; then if test "x$ac_cv_want_xmlrpc" = "xcheck"; then
AC_FLDIGI_XMLRPC_CONFIG
if test "x$ac_cv_xmlrpc" = "xyes"; then if test "x$ac_cv_xmlrpc" = "xyes"; then
AC_DEFINE(USE_XMLRPC, 1, [Define to 1 if we are using xmlrpc]) AC_DEFINE(USE_XMLRPC, 1, [Define to 1 if we are using xmlrpc])
else else
AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc]) AC_DEFINE(USE_XMLRPC, 0, [Define to 1 if we are using xmlrpc])
fi fi
else # $ac_cv_want_xmlrpc is yes 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 if test "x$ac_cv_xmlrpc" = "xno"; then
AC_MSG_FAILURE([--with-xmlrpc was given, but check for libxmlrpc-c failed]) AC_MSG_FAILURE([--with-xmlrpc was given, but check for libxmlrpc-c failed])
else else

Wyświetl plik

@ -215,6 +215,7 @@ fldigi_SOURCES += \
include/rigsupport.h \ include/rigsupport.h \
include/rigxml.h \ include/rigxml.h \
include/ringbuffer.h \ include/ringbuffer.h \
include/rsid.h \
include/rtty.h \ include/rtty.h \
include/serial.h \ include/serial.h \
include/sound.h \ include/sound.h \
@ -282,6 +283,7 @@ fldigi_SOURCES += \
rigcontrol/rigsupport.cxx \ rigcontrol/rigsupport.cxx \
rigcontrol/rigxml.cxx \ rigcontrol/rigxml.cxx \
rigcontrol/serial.cxx \ rigcontrol/serial.cxx \
rsid/rsid.cxx \
soundcard/mixer.cxx \ soundcard/mixer.cxx \
soundcard/sound.cxx \ soundcard/sound.cxx \
soundcard/soundconf.cxx \ soundcard/soundconf.cxx \
@ -332,7 +334,9 @@ EXTRA_fldigi_SOURCES += \
mt63/symbol.dat \ mt63/symbol.dat \
mt63/alias_k5.dat \ mt63/alias_k5.dat \
mt63/mt63intl.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 # Additional non-source files that we distribute
EXTRA_DIST = \ EXTRA_DIST = \

Wyświetl plik

@ -778,6 +778,13 @@ static void cb_btnStartAtSweetSpot(Fl_Check_Button* o, void*) {
progdefaults.changed = true; 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_Group *tabModems=(Fl_Group *)0;
Fl_Tabs *tabsModems=(Fl_Tabs *)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 = new Fl_Group(0, 25, 400, 195, "Video");
tabVideo->color((Fl_Color)51); tabVideo->color((Fl_Color)51);
tabVideo->selection_color((Fl_Color)51); tabVideo->selection_color((Fl_Color)51);
tabVideo->hide();
{ Fl_Group* o = new Fl_Group(5, 40, 390, 77, "Video Preamble"); { Fl_Group* o = new Fl_Group(5, 40, 390, 77, "Video Preamble");
o->box(FL_ENGRAVED_FRAME); o->box(FL_ENGRAVED_FRAME);
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE); 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 = new Fl_Group(0, 25, 400, 195, "SndCrd");
tabSoundCard->color((Fl_Color)51); tabSoundCard->color((Fl_Color)51);
tabSoundCard->selection_color((Fl_Color)51); tabSoundCard->selection_color((Fl_Color)51);
tabSoundCard->hide();
{ tabsSoundCard = new Fl_Tabs(0, 25, 400, 195); { tabsSoundCard = new Fl_Tabs(0, 25, 400, 195);
tabsSoundCard->selection_color((Fl_Color)10); tabsSoundCard->selection_color((Fl_Color)10);
{ tabAudio = new Fl_Group(0, 50, 400, 170, "Audio devices"); { tabAudio = new Fl_Group(0, 50, 400, 170, "Audio devices");
tabAudio->color((Fl_Color)51); tabAudio->color((Fl_Color)51);
tabAudio->selection_color((Fl_Color)51); tabAudio->selection_color((Fl_Color)51);
tabAudio->hide();
{ AudioOSS = new Fl_Group(5, 58, 391, 35); { AudioOSS = new Fl_Group(5, 58, 391, 35);
AudioOSS->box(FL_ENGRAVED_FRAME); AudioOSS->box(FL_ENGRAVED_FRAME);
{ btnAudioIO[0] = new Fl_Round_Button(5, 63, 100, 25, "OSS"); { btnAudioIO[1] = new Fl_Round_Button(5, 63, 100, 25, "OSS");
btnAudioIO[0]->down_box(FL_DIAMOND_DOWN_BOX); btnAudioIO[1]->down_box(FL_DIAMOND_DOWN_BOX);
btnAudioIO[0]->selection_color((Fl_Color)1); btnAudioIO[1]->selection_color((Fl_Color)1);
btnAudioIO[0]->callback((Fl_Callback*)cb_btnAudioIO); btnAudioIO[1]->callback((Fl_Callback*)cb_btnAudioIO);
} // Fl_Round_Button* btnAudioIO[0] } // Fl_Round_Button* btnAudioIO[1]
{ Fl_Input_Choice* o = menuOSSDev = new Fl_Input_Choice(280, 63, 110, 25, "Device"); { Fl_Input_Choice* o = menuOSSDev = new Fl_Input_Choice(280, 63, 110, 25, "Device");
menuOSSDev->callback((Fl_Callback*)cb_menuOSSDev); menuOSSDev->callback((Fl_Callback*)cb_menuOSSDev);
o->value(progdefaults.OSSdevice.c_str()); 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 } // Fl_Group* AudioOSS
{ AudioPort = new Fl_Group(5, 95, 390, 61); { AudioPort = new Fl_Group(5, 95, 390, 61);
AudioPort->box(FL_ENGRAVED_FRAME); AudioPort->box(FL_ENGRAVED_FRAME);
{ btnAudioIO[1] = new Fl_Round_Button(5, 115, 95, 25, "PortAudio"); { btnAudioIO[0] = new Fl_Round_Button(5, 115, 95, 25, "PortAudio");
btnAudioIO[1]->down_box(FL_DIAMOND_DOWN_BOX); btnAudioIO[0]->down_box(FL_DIAMOND_DOWN_BOX);
btnAudioIO[1]->selection_color((Fl_Color)1); btnAudioIO[0]->selection_color((Fl_Color)1);
btnAudioIO[1]->callback((Fl_Callback*)cb_btnAudioIO1); btnAudioIO[0]->callback((Fl_Callback*)cb_btnAudioIO1);
} // Fl_Round_Button* btnAudioIO[1] } // Fl_Round_Button* btnAudioIO[0]
{ menuPortInDev = new Fl_Choice(165, 99, 225, 25, "Capture"); { menuPortInDev = new Fl_Choice(165, 99, 225, 25, "Capture");
menuPortInDev->down_box(FL_BORDER_BOX); menuPortInDev->down_box(FL_BORDER_BOX);
menuPortInDev->callback((Fl_Callback*)cb_menuPortInDev); 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 = new Fl_Group(0, 50, 400, 170, "Audio settings");
tabAudioOpt->color((Fl_Color)51); tabAudioOpt->color((Fl_Color)51);
tabAudioOpt->selection_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"); { Fl_Spinner* o = cntRxRateCorr = new Fl_Spinner(5, 160, 85, 25, "RX ppm");
cntRxRateCorr->value(1); cntRxRateCorr->value(1);
cntRxRateCorr->callback((Fl_Callback*)cb_cntRxRateCorr); cntRxRateCorr->callback((Fl_Callback*)cb_cntRxRateCorr);
@ -1968,6 +1975,17 @@ l with your sound hardware.");
} // Fl_Check_Button* btnStartAtSweetSpot } // Fl_Check_Button* btnStartAtSweetSpot
o->end(); o->end();
} // Fl_Group* o } // 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(); tabMisc->end();
} // Fl_Group* tabMisc } // Fl_Group* tabMisc
{ tabModems = new Fl_Group(0, 25, 401, 195, "Modem"); { 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 {} {} code {} {}
Fl_Window {} { Fl_Window {} {
label {fldigi - config} open 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 Fl_Tabs tabsConfigure {open
xywh {0 0 405 220} color 47 selection_color 9 xywh {0 0 405 220} color 47 selection_color 9
@ -326,7 +326,7 @@ progdefaults.changed = true;
} }
Fl_Group tabVideo { Fl_Group tabVideo {
label Video open 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 {} { Fl_Group {} {
label {Video Preamble} open label {Video Preamble} open
@ -367,7 +367,7 @@ if (o->value() == 1)
sldrVideowidth->deactivate(); sldrVideowidth->deactivate();
else else
sldrVideowidth->activate(); sldrVideowidth->activate();
progdefaults.changed = true;} selected progdefaults.changed = true;}
xywh {290 49 100 20} down_box DOWN_BOX value 1 xywh {290 49 100 20} down_box DOWN_BOX value 1
code0 {o->value(progdefaults.ID_SMALL);} code0 {o->value(progdefaults.ID_SMALL);}
} }
@ -683,19 +683,19 @@ o->label((inpQRZuserpassword->type() & FL_SECRET_INPUT) ? "Show" : "Hide");}
} }
Fl_Group tabSoundCard { Fl_Group tabSoundCard {
label SndCrd open 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 Fl_Tabs tabsSoundCard {open
xywh {0 25 400 195} selection_color 10 xywh {0 25 400 195} selection_color 10
} { } {
Fl_Group tabAudio { Fl_Group tabAudio {
label {Audio devices} open 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 Fl_Group AudioOSS {open
xywh {5 58 391 35} box ENGRAVED_FRAME xywh {5 58 391 35} box ENGRAVED_FRAME
} { } {
Fl_Round_Button {btnAudioIO[0]} { Fl_Round_Button {btnAudioIO[1]} {
label OSS label OSS
callback {sound_update(SND_IDX_OSS); callback {sound_update(SND_IDX_OSS);
progdefaults.changed = true; progdefaults.changed = true;
@ -714,7 +714,7 @@ progdefaults.changed = true;} open
Fl_Group AudioPort {open Fl_Group AudioPort {open
xywh {5 95 390 61} box ENGRAVED_FRAME xywh {5 95 390 61} box ENGRAVED_FRAME
} { } {
Fl_Round_Button {btnAudioIO[1]} { Fl_Round_Button {btnAudioIO[0]} {
label PortAudio label PortAudio
callback {sound_update(SND_IDX_PORT); callback {sound_update(SND_IDX_PORT);
progdefaults.changed = true; progdefaults.changed = true;
@ -765,14 +765,14 @@ http://www.pulseaudio.org/wiki/ServerStrings} xywh {165 161 225 25}
label {File I/O only} label {File I/O only}
callback {sound_update(SND_IDX_NULL); callback {sound_update(SND_IDX_NULL);
progdefaults.changed = true; progdefaults.changed = true;
resetSoundCard();} resetSoundCard();} selected
xywh {5 192 100 25} down_box DIAMOND_DOWN_BOX selection_color 1 xywh {5 192 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
} }
} }
} }
Fl_Group tabAudioOpt { Fl_Group tabAudioOpt {
label {Audio settings} open 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 { Fl_Spinner cntRxRateCorr {
label {RX ppm} label {RX ppm}
@ -933,6 +933,18 @@ progdefaults.changed = true;}
code0 {o->value(progdefaults.StartAtSweetSpot);} 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 { Fl_Group tabModems {
label Modem open label Modem open

Wyświetl plik

@ -98,6 +98,7 @@
#include "qrunner.h" #include "qrunner.h"
#include "Viewer.h" #include "Viewer.h"
#include "soundconf.h"
Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0; Fl_Double_Window *fl_digi_main=(Fl_Double_Window *)0;
Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)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_THOR5].name, 0, cb_init_mode, (void *)MODE_THOR5 },
{ mode_info[MODE_THOR8].name, 0, cb_init_mode, (void *)MODE_THOR8 }, { 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_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_THOR16].name, 0, cb_init_mode, (void *)MODE_THOR16 },
{ mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22 }, { mode_info[MODE_THOR22].name, 0, cb_init_mode, (void *)MODE_THOR22 },
{ 0 } { 0 }
@ -404,7 +405,7 @@ void init_modem(trx_mode mode)
break; break;
case MODE_THOR4: case MODE_THOR5: case MODE_THOR8: 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 : startup_modem(*mode_info[mode].modem ? *mode_info[mode].modem :
*mode_info[mode].modem = new thor(mode)); *mode_info[mode].modem = new thor(mode));
quick_change = quick_change_thor; quick_change = quick_change_thor;
@ -807,6 +808,55 @@ void cb_mnuFun(Fl_Widget*, void*)
} }
#endif #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 *) { void cbTune(Fl_Widget *w, void *) {
Fl_Button *b = (Fl_Button *)w; Fl_Button *b = (Fl_Button *)w;
if (active_modem == wwv_modem || active_modem == anal_modem) { 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_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_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_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_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}, { 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}, {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}, {"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}, {"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}, {"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}, {"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}, {"About", 0, cb_mnuAbout, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
{0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0},
@ -1964,7 +2015,7 @@ void resetTHOR() {
md == MODE_THOR5 || md == MODE_THOR5 ||
md == MODE_THOR8 || md == MODE_THOR8 ||
md == MODE_THOR11 || md == MODE_THOR11 ||
md == MODE_TSOR11 || // md == MODE_TSOR11 ||
md == MODE_THOR16 || md == MODE_THOR16 ||
md == MODE_THOR22 ) { md == MODE_THOR22 ) {
active_modem->restart(); active_modem->restart();
@ -2098,36 +2149,6 @@ void setReverse(int rev) {
active_modem->set_reverse(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) void change_modem_param(int state)
{ {
int d; int d;
@ -2182,3 +2203,13 @@ void change_modem_param(int state)
snprintf(msg, sizeof(msg), "Squelch = %2.0f %%", val->value()); snprintf(msg, sizeof(msg), "Squelch = %2.0f %%", val->value());
put_status(msg, 2); 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 // if TX buffer empty
// send idle character // send idle character
if (c == -1) { if (c == -1) {
if (progdefaults.FELD_IDLE == true) if (progdefaults.HellXmtIdle == true)
c = '.'; c = '.';
else { else {
send_null_column(); send_null_column();

Wyświetl plik

@ -117,6 +117,7 @@ extern Fl_Value_Input *valCWsweetspot;
extern Fl_Value_Input *valRTTYsweetspot; extern Fl_Value_Input *valRTTYsweetspot;
extern Fl_Value_Input *valPSKsweetspot; extern Fl_Value_Input *valPSKsweetspot;
extern Fl_Check_Button *btnStartAtSweetSpot; extern Fl_Check_Button *btnStartAtSweetSpot;
extern Fl_Check_Button *chkTransmitRSid;
extern Fl_Group *tabModems; extern Fl_Group *tabModems;
extern Fl_Tabs *tabsModems; extern Fl_Tabs *tabsModems;
extern Fl_Group *tabCW; extern Fl_Group *tabCW;

Wyświetl plik

@ -12,6 +12,8 @@
using namespace std; using namespace std;
struct configuration { struct configuration {
bool rsid;
bool TransmitRSid;
bool changed; bool changed;
double wfRefLevel; double wfRefLevel;
double wfAmpSpan; 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 change_modem_param(int state);
extern void start_tx();
extern void colorize_macro(int i); extern void colorize_macro(int i);
extern void colorize_macros(); extern void colorize_macros();

Wyświetl plik

@ -105,6 +105,7 @@ public:
void set_metric(double); void set_metric(double);
double get_metric(); double get_metric();
void set_reverse(bool on); void set_reverse(bool on);
bool get_reverse() { return reverse; }
double get_bandwidth(); double get_bandwidth();
void set_bandwidth(double); void set_bandwidth(double);
int get_samplerate(); 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 initialize(void);
static void terminate(void); static void terminate(void);
static const std::vector<const PaDeviceInfo*>& devices(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: public:
SoundPort(const char *in_dev, const char *out_dev); SoundPort(const char *in_dev, const char *out_dev);
@ -247,6 +249,7 @@ private:
enum { STREAM_IN, STREAM_OUT }; enum { STREAM_IN, STREAM_OUT };
static bool pa_init; static bool pa_init;
static std::vector<const PaDeviceInfo*> devs; static std::vector<const PaDeviceInfo*> devs;
static std::vector<double> supported_rates[2];
double req_sample_rate; double req_sample_rate;
float* fbuf; float* fbuf;

Wyświetl plik

@ -1,7 +1,7 @@
#ifndef SOUNDCONF_H #ifndef SOUNDCONF_H
#define 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 SND_IDX_PULSE, SND_IDX_NULL, SND_IDX_END
}; };

Wyświetl plik

@ -44,7 +44,7 @@
using namespace std; using namespace std;
#define THORNUMMTONES 18 #define THORNUMTONES 18
#define THORMAXFFTS 8 #define THORMAXFFTS 8
#define THORBASEFREQ 500.0 #define THORBASEFREQ 500.0
#define THORFIRSTIF 1000.0 #define THORFIRSTIF 1000.0
@ -52,7 +52,7 @@ using namespace std;
#define THORSCOPESIZE 64 #define THORSCOPESIZE 64
struct THORrxpipe { struct THORrxpipe {
complex vector[THORMAXFFTS * THORNUMMTONES * 6]; complex vector[THORMAXFFTS * THORNUMTONES * 6];
}; };
class thor : public modem { class thor : public modem {
@ -141,7 +141,7 @@ private:
int get_secondary_char(); int get_secondary_char();
void reset_filters(); void reset_filters();
void decodePairs(unsigned char symbol); void decodePairs(unsigned char symbol);
void decodeEX(int c); // void decodeEX(int c);
// Tx // Tx
void sendtone(int tone, int duration); void sendtone(int tone, int duration);

Wyświetl plik

@ -33,6 +33,7 @@
#include "waterfall.h" #include "waterfall.h"
#include "globals.h" #include "globals.h"
#include "fl_digi.h" #include "fl_digi.h"
#include "rsid.h"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -50,6 +51,7 @@ extern Fl_Mutex trx_mutex;
extern Fl_Thread trx_thread; extern Fl_Thread trx_thread;
extern state_t trx_state; extern state_t trx_state;
extern modem *active_modem; extern modem *active_modem;
extern cRsId *ReedSolomon;
extern SoundBase *scard; extern SoundBase *scard;

Wyświetl plik

@ -288,7 +288,8 @@ public:
class waterfall: public Fl_Group { class waterfall: public Fl_Group {
friend void x1_cb(Fl_Widget *w, void* v); 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_cb(Fl_Widget *w, void * v);
friend void slew_left(Fl_Widget *w, void * v); friend void slew_left(Fl_Widget *w, void * v);
friend void slew_right(Fl_Widget *w, void * v); friend void slew_right(Fl_Widget *w, void * v);
@ -374,7 +375,7 @@ public:
private: private:
Fl_Box *bezel; Fl_Box *bezel;
WFdisp *wfdisp; WFdisp *wfdisp;
Fl_Button *bwclr; Fl_Button *bw_rsid;
Fl_Button *mode; Fl_Button *mode;
Fl_Button *x1; Fl_Button *x1;
Fl_Button *left; Fl_Button *left;

Wyświetl plik

@ -14,7 +14,7 @@ private:
XML_RPC_Server operator=(const XML_RPC_Server&); XML_RPC_Server operator=(const XML_RPC_Server&);
void add_methods(void); void add_methods(void);
static int get_socket(const char* node, const char* service, int& fd); static int get_socket(const char* node, const char* service, int& fd);
static void* thread_func(void* arg); static void* thread_func(void*);
private: private:
static XML_RPC_Server* inst; static XML_RPC_Server* inst;

Wyświetl plik

@ -933,6 +933,7 @@ void cb_picRxSave( Fl_Widget *w, void *who)
#if USE_LIBJPEG #if USE_LIBJPEG
picRx->save_jpeg(fn); picRx->save_jpeg(fn);
#endif #endif
break;
} }
} }
@ -1102,11 +1103,7 @@ void cb_picTxSendColor( Fl_Widget *w, void *who)
picTx->clear(); picTx->clear();
FL_UNLOCK_D(); FL_UNLOCK_D();
// start the transmission // start the transmission
fl_lock(&trx_mutex); start_tx();
if (trx_state != STATE_TX)
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
me->startpic = true; me->startpic = true;
} }
@ -1137,11 +1134,7 @@ void cb_picTxSendGrey( Fl_Widget *w, void *who)
picTx->clear(); picTx->clear();
FL_UNLOCK_D(); FL_UNLOCK_D();
// start the transmission // start the transmission
fl_lock(&trx_mutex); start_tx();
if (trx_state != STATE_TX)
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
me->startpic = true; me->startpic = true;
} }

Wyświetl plik

@ -16,6 +16,8 @@
#include <fstream> #include <fstream>
configuration progdefaults = { configuration progdefaults = {
false, // bool rsid;
false, // bool TransmitRSid;
false, // bool changed; false, // bool changed;
0.0, // double wfRefLevel; 0.0, // double wfRefLevel;
70.0, // double wfAmpSpan; 70.0, // double wfAmpSpan;
@ -170,7 +172,7 @@ configuration progdefaults = {
SAMPLE_RATE_UNSET, // int sample_rate; SAMPLE_RATE_UNSET, // int sample_rate;
SAMPLE_RATE_UNSET, // int in_sample_rate; SAMPLE_RATE_UNSET, // int in_sample_rate;
SAMPLE_RATE_UNSET, // int out_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 RX_corr;
0, // int TX_corr; 0, // int TX_corr;
0, // int TxOffset; 0, // int TxOffset;
@ -293,7 +295,8 @@ enum TAG { \
USEGROUPCOLORS, FKEYGROUP1, FKEYGROUP2, FKEYGROUP3, USEGROUPCOLORS, FKEYGROUP1, FKEYGROUP2, FKEYGROUP3,
FKEYTEXTCOLOR, FKEYTEXTCOLOR,
RXFONTNBR, RXFONTSIZE, TXFONTNBR, TXFONTSIZE, RXFONTNBR, RXFONTSIZE, TXFONTNBR, TXFONTSIZE,
RXFONTCOLOR, TXFONTCOLOR RXFONTCOLOR, TXFONTCOLOR,
TRANSMITRSID
}; };
void writeXMLint(ofstream &f, const char * tag, int val) 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, "RXFONTCOLOR", RxColor.R, RxColor.G, RxColor.B);
writeXMLrgb(f, "TXFONTCOLOR", TxColor.R, TxColor.G, TxColor.B); writeXMLrgb(f, "TXFONTCOLOR", TxColor.R, TxColor.G, TxColor.B);
writeXMLbool(f, "TRANSMITRSID", TransmitRSid);
f << "</FLDIGI_DEFS>\n"; f << "</FLDIGI_DEFS>\n";
f.close(); f.close();
} }
@ -1038,6 +1043,8 @@ bool configuration::readDefaultsXML()
sscanf( xml->getNodeData(), "%d %d %d", sscanf( xml->getNodeData(), "%d %d %d",
&TxColor.R, &TxColor.G, &TxColor.B); &TxColor.R, &TxColor.G, &TxColor.B);
break; break;
case TRANSMITRSID :
TransmitRSid = atoi(xml->getNodeData());
} }
break; break;
@ -1203,6 +1210,7 @@ bool configuration::readDefaultsXML()
else if (!strcmp("TXFONTSIZE", nodeName)) tag = TXFONTSIZE; else if (!strcmp("TXFONTSIZE", nodeName)) tag = TXFONTSIZE;
else if (!strcmp("RXFONTCOLOR", nodeName)) tag = RXFONTCOLOR; else if (!strcmp("RXFONTCOLOR", nodeName)) tag = RXFONTCOLOR;
else if (!strcmp("TXFONTCOLOR", nodeName)) tag = TXFONTCOLOR; else if (!strcmp("TXFONTCOLOR", nodeName)) tag = TXFONTCOLOR;
else if (!strcmp("TRANSMITRSID", nodeName)) tag = TRANSMITRSID;
else tag = IGNORE; else tag = IGNORE;
} }
break; break;
@ -1429,6 +1437,8 @@ int configuration::setDefaults() {
selHellFont->value(feldfontnbr); selHellFont->value(feldfontnbr);
btnFeldHellIdle->value(FELD_IDLE); btnFeldHellIdle->value(FELD_IDLE);
chkTransmitRSid->value(TransmitRSid);
string bandsfname = HomeDir; string bandsfname = HomeDir;
bandsfname.append("frequencies.def"); bandsfname.append("frequencies.def");
ifstream bandsfile(bandsfname.c_str(), ios::in); 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() ); TransmitText->add( (expandMacro(n)).c_str() );
if ( TransmitON ) { if ( TransmitON ) {
active_modem->set_stopflag(false); active_modem->set_stopflag(false);
fl_lock(&trx_mutex); start_tx();
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
TransmitON = false; TransmitON = false;
} }
} }

Wyświetl plik

@ -131,10 +131,7 @@ void process_msgque()
active_modem->set_stopflag(false); active_modem->set_stopflag(false);
fl_lock(&trx_mutex); start_tx();
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
} }
} }
} }
@ -212,11 +209,7 @@ void check_formail() {
pskmail_text_available = true; pskmail_text_available = true;
active_modem->set_stopflag(false); active_modem->set_stopflag(false);
start_tx();
fl_lock(&trx_mutex);
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
} }
} }
#else #else
@ -240,10 +233,7 @@ void check_formail() {
pText = mailtext.begin(); pText = mailtext.begin();
pskmail_text_available = true; pskmail_text_available = true;
active_modem->set_stopflag(false); active_modem->set_stopflag(false);
fl_lock(&trx_mutex); start_tx();
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
arqmode = true; arqmode = true;
} }
} }

Wyświetl plik

@ -86,7 +86,6 @@ XML_RPC_Server::XML_RPC_Server(int sfd_)
server_thread = new Fl_Thread; server_thread = new Fl_Thread;
run = true; run = true;
fl_create_thread(*server_thread, thread_func, this);
} }
XML_RPC_Server::~XML_RPC_Server() XML_RPC_Server::~XML_RPC_Server()
{ {
@ -103,7 +102,7 @@ void XML_RPC_Server::start(const char* node, const char* service)
return; return;
int sfd = -1, err; int sfd = -1, err;
if ((err = get_socket(node, service, sfd)) == -1) { if ((err = get_socket(node, service, sfd)) != 0) {
#if HAVE_GETADDRINFO #if HAVE_GETADDRINFO
if (err < 0) if (err < 0)
cerr << gai_strerror(err) << '\n'; 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); inst = new XML_RPC_Server(sfd);
fl_create_thread(*server_thread, thread_func, NULL);
} }
void XML_RPC_Server::stop(void) 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; res = 0;
#endif // HAVE_GETADDRINFO #endif // HAVE_GETADDRINFO
int v = 1; if (res == 0) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1) int v = 1;
perror("setsockopt TCP_NODELAY"); if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)) == -1)
perror("setsockopt TCP_NODELAY");
}
return res; return res;
} }
void* XML_RPC_Server::thread_func(void* arg) void* XML_RPC_Server::thread_func(void*)
{ {
SET_THREAD_ID(XMLRPC_TID); SET_THREAD_ID(XMLRPC_TID);
@ -267,20 +269,15 @@ ret:
// ============================================================================= // =============================================================================
// helper functions // 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) static void set_button(Fl_Button* button, bool value)
{ {
REQ(static_cast<int (Fl_Button::*)(int)>(&Fl_Button::value), button, value); button->value(value);
frob(button); button->do_callback();
} }
static void set_valuator(Fl_Valuator* valuator, double value) static void set_valuator(Fl_Valuator* valuator, double value)
{ {
REQ(static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value), valuator, value); valuator->value(value);
frob(valuator); valuator->do_callback();
} }
// ============================================================================= // =============================================================================
@ -380,7 +377,7 @@ public:
Modem_get_name() Modem_get_name()
{ {
_signature = "s:n"; _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) 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 class Modem_get_id : public xmlrpc_c::method
{ {
public: public:
Modem_get_id() Modem_get_id()
{ {
_signature = "i:n"; _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) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
@ -408,7 +423,7 @@ public:
Modem_get_max_id() Modem_get_max_id()
{ {
_signature = "i:n"; _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) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
@ -431,7 +446,7 @@ public:
bool found = false; bool found = false;
string s = params.getString(0); string s = params.getString(0);
for (size_t i = 0; i < NUM_MODES; i++) { 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); init_modem_sync(i);
found = true; found = true;
break; break;
@ -541,7 +556,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
int v = cntSearchRange->value(); 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); *retval = xmlrpc_c::value_int(v);
} }
}; };
@ -557,7 +572,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
int v = cntSearchRange->value() + params.getInt(0); int v = cntSearchRange->value() + params.getInt(0);
set_valuator(cntSearchRange, v); REQ(set_valuator, cntSearchRange, v);
*retval = xmlrpc_c::value_int(v); *retval = xmlrpc_c::value_int(v);
} }
}; };
@ -616,7 +631,7 @@ public:
} }
int v = val->value(); 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); *retval = xmlrpc_c::value_int(v);
} }
}; };
@ -644,7 +659,7 @@ public:
} }
int v = val->value() + params.getInt(0); int v = val->value() + params.getInt(0);
set_valuator(val, v); REQ(set_valuator, val, v);
*retval = xmlrpc_c::value_int(v); *retval = xmlrpc_c::value_int(v);
} }
}; };
@ -759,7 +774,7 @@ public:
Main_set_freq() Main_set_freq()
{ {
_signature = "d:d"; _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) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
@ -825,7 +840,7 @@ public:
{ {
Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff; Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff;
bool v = b->value(); bool v = b->value();
set_button(b, params.getBoolean(0)); REQ(set_button, b, params.getBoolean(0));
*retval = xmlrpc_c::value_boolean(v); *retval = xmlrpc_c::value_boolean(v);
} }
}; };
@ -842,7 +857,7 @@ public:
{ {
Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff; Fl_Button* b = useCheckButtons ? chk_afconoff : btn_afconoff;
bool v = b->value(); bool v = b->value();
set_button(b, !v); REQ(set_button, b, !v);
*retval = xmlrpc_c::value_boolean(!v); *retval = xmlrpc_c::value_boolean(!v);
} }
}; };
@ -875,7 +890,7 @@ public:
{ {
Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff; Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff;
bool v = b->value(); bool v = b->value();
set_button(b, params.getBoolean(0)); REQ(set_button, b, params.getBoolean(0));
*retval = xmlrpc_c::value_boolean(v); *retval = xmlrpc_c::value_boolean(v);
} }
}; };
@ -892,7 +907,7 @@ public:
{ {
Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff; Fl_Button* b = useCheckButtons ? chk_sqlonoff : btn_sqlonoff;
bool v = b->value(); bool v = b->value();
set_button(b, !v); REQ(set_button, b, !v);
*retval = xmlrpc_c::value_boolean(!v); *retval = xmlrpc_c::value_boolean(!v);
} }
}; };
@ -905,7 +920,7 @@ public:
Main_get_sql_level() Main_get_sql_level()
{ {
_signature = "d:n"; _signature = "d:n";
_help = "Returns the squelch level"; _help = "Returns the squelch level.";
} }
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
@ -926,9 +941,9 @@ public:
double v = sldrSquelch->value(); double v = sldrSquelch->value();
// Squelch slider min/max are reversed when !twoscopes. Argh. // Squelch slider min/max are reversed when !twoscopes. Argh.
if (twoscopes) if (twoscopes)
set_valuator(sldrSquelch, params.getDouble(0, sldrSquelch->minimum(), sldrSquelch->maximum())); REQ(set_valuator, sldrSquelch, params.getDouble(0, sldrSquelch->minimum(), sldrSquelch->maximum()));
else 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); *retval = xmlrpc_c::value_double(v);
} }
}; };
@ -944,7 +959,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
double v = sldrSquelch->value(); 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()); *retval = xmlrpc_c::value_double(sldrSquelch->value());
} }
}; };
@ -976,7 +991,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
bool v = wf->btnRev->value(); 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); *retval = xmlrpc_c::value_boolean(v);
} }
}; };
@ -992,7 +1007,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
bool v = wf->btnRev->value(); bool v = wf->btnRev->value();
set_button(wf->btnRev, !v); REQ(set_button, wf->btnRev, !v);
*retval = xmlrpc_c::value_boolean(!v); *retval = xmlrpc_c::value_boolean(!v);
} }
}; };
@ -1024,7 +1039,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
bool v = wf->xmtlock->value(); 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); *retval = xmlrpc_c::value_boolean(v);
} }
}; };
@ -1040,7 +1055,7 @@ public:
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{ {
bool v = wf->xmtlock->value(); bool v = wf->xmtlock->value();
set_button(wf->xmtlock, !v); REQ(set_button, wf->xmtlock, !v);
*retval = xmlrpc_c::value_boolean(!v); *retval = xmlrpc_c::value_boolean(!v);
} }
}; };
@ -1055,7 +1070,7 @@ public:
Main_get_tx_status() Main_get_tx_status()
{ {
_signature = "s:n"; _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) 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) 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(); *retval = xmlrpc_c::value_nil();
} }
}; };
@ -1093,7 +1108,7 @@ public:
} }
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) 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(); *retval = xmlrpc_c::value_nil();
} }
}; };
@ -1108,7 +1123,7 @@ public:
} }
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval) 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(); *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 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_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_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_get_max_id, "modem.get_max_id"));
methods->push_back(rpc_method(new Modem_set_by_name, "modem.set_by_name")); 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 <iostream>
#include <string> #include <string>
#include <vector>
#include <sstream>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@ -42,6 +44,8 @@
#include <semaphore.h> #include <semaphore.h>
#include <limits.h> #include <limits.h>
#include <bits/stream_iterator.h>
#if USE_OSS #if USE_OSS
# include <sys/soundcard.h> # include <sys/soundcard.h>
#endif #endif
@ -671,6 +675,8 @@ size_t SoundOSS::Write_stereo(double *bufleft, double *bufright, size_t count)
bool SoundPort::pa_init = false; bool SoundPort::pa_init = false;
std::vector<const PaDeviceInfo*> SoundPort::devs; std::vector<const PaDeviceInfo*> SoundPort::devs;
static ostringstream device_text[2];
vector<double> SoundPort::supported_rates[2];
void SoundPort::initialize(void) void SoundPort::initialize(void)
{ {
if (pa_init) if (pa_init)
@ -693,7 +699,6 @@ void SoundPort::initialize(void)
devs.reserve(ndev); devs.reserve(ndev);
for (PaDeviceIndex i = 0; i < ndev; i++) for (PaDeviceIndex i = 0; i < ndev; i++)
devs.push_back(Pa_GetDeviceInfo(i)); devs.push_back(Pa_GetDeviceInfo(i));
} }
void SoundPort::terminate(void) void SoundPort::terminate(void)
{ {
@ -707,6 +712,16 @@ const std::vector<const PaDeviceInfo*>& SoundPort::devices(void)
{ {
return devs; 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) SoundPort::SoundPort(const char *in_dev, const char *out_dev)
: req_sample_rate(0), fbuf(0) : 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 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; 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) || if ((dir == 0 && (*sd[dir].idev)->maxInputChannels == 0) ||
(dir == 1 && (*sd[dir].idev)->maxOutputChannels == 0)) (dir == 1 && (*sd[dir].idev)->maxOutputChannels == 0))
@ -1213,6 +1206,47 @@ void SoundPort::init_stream(unsigned dir)
sd[1].params.hostApiSpecificStreamInfo = NULL; 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); sd[dir].dev_sample_rate = find_srate(dir);
#ifndef NDEBUG #ifndef NDEBUG
if (sd[dir].dev_sample_rate != req_sample_rate) if (sd[dir].dev_sample_rate != req_sample_rate)
@ -1359,23 +1393,11 @@ double SoundPort::find_srate(unsigned dir)
return sr; return sr;
} }
double srates[] = { req_sample_rate, (*sd[dir].idev)->defaultSampleRate }; for (vector<double>::const_iterator i = supported_rates[dir].begin(); i != supported_rates[dir].end(); i++)
int err; if (req_sample_rate == *i || (*sd[dir].idev)->defaultSampleRate == *i)
for (size_t i = 0; i < sizeof(srates)/sizeof(srates[0]); i++) { return *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
}
throw SndPortException(err); throw SndException("No supported sample rate found");
} }
void SoundPort::pa_perror(int err, const char* str) void SoundPort::pa_perror(int err, const char* str)

Wyświetl plik

@ -5,6 +5,9 @@
# include <list> # include <list>
#endif #endif
#include <cstdlib>
#include <cstring>
#include "soundconf.h" #include "soundconf.h"
#include "sound.h" #include "sound.h"
#include "main.h" #include "main.h"
@ -13,6 +16,8 @@
using namespace std; 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) static void init_oss(void)
{ {
@ -181,16 +186,28 @@ static void init_portaudio(void)
#endif #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 void sound_init_options(void)
{ {
static const Fl_Menu_Item sample_rate_menu[] = { build_srate_menu(menuInSampleRate, std_sample_rates,
{ "Auto" }, { "Native", 0, 0, 0, FL_MENU_DIVIDER }, sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1);
{ "8000" }, { "9600" }, { "11025" }, { "12000" }, { "16000" }, build_srate_menu(menuOutSampleRate, std_sample_rates,
{ "22050" }, { "24000" }, { "32000" }, { "44100" }, { "48000" }, sizeof(std_sample_rates)/sizeof(*std_sample_rates) - 1);
{ "88200" }, { "96000" }, { "192000" }, { 0 }
};
menuInSampleRate->menu(sample_rate_menu);
menuOutSampleRate->menu(sample_rate_menu);
const char* cname; const char* cname;
for (int i = 0; (cname = src_get_name(i)); i++) { for (int i = 0; (cname = src_get_name(i)); i++) {
@ -301,24 +318,64 @@ void sound_update(unsigned idx)
progdefaults.btnAudioIOis = idx; progdefaults.btnAudioIOis = idx;
switch (idx) { switch (idx) {
#if USE_OSS
case SND_IDX_OSS: case SND_IDX_OSS:
menuOSSDev->activate(); menuOSSDev->activate();
scDevice[0] = scDevice[1] = menuOSSDev->value(); scDevice[0] = scDevice[1] = menuOSSDev->value();
break; break;
#endif
#if USE_PORTAUDIO
case SND_IDX_PORT: case SND_IDX_PORT:
menuPortInDev->activate(); menuPortInDev->activate();
menuPortOutDev->activate(); menuPortOutDev->activate();
menuInSampleRate->activate();
menuOutSampleRate->activate();
if (menuPortInDev->text()) if (menuPortInDev->text())
scDevice[0] = menuPortInDev->text(); scDevice[0] = menuPortInDev->text();
if (menuPortOutDev->text()) if (menuPortOutDev->text())
scDevice[1] = 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; break;
#endif
#if USE_PULSEAUDIO
case SND_IDX_PULSE: case SND_IDX_PULSE:
inpPulseServer->activate(); inpPulseServer->activate();
scDevice[0] = scDevice[1] = inpPulseServer->value(); scDevice[0] = scDevice[1] = inpPulseServer->value();
break; break;
#endif
case SND_IDX_NULL: case SND_IDX_NULL:
scDevice[0] = scDevice[1] = ""; scDevice[0] = scDevice[1] = "";
break; break;

Wyświetl plik

@ -142,11 +142,11 @@ thor::thor(trx_mode md)
samplerate = 11025; samplerate = 11025;
break; break;
case MODE_TSOR11: // case MODE_TSOR11:
symlen = 1024; // symlen = 1024;
doublespaced = 1; // doublespaced = 1;
samplerate = 11025; // samplerate = 11025;
break; // break;
case MODE_THOR22: case MODE_THOR22:
symlen = 512; symlen = 512;
@ -174,12 +174,12 @@ thor::thor(trx_mode md)
basetone = (int)floor(THORBASEFREQ * symlen / samplerate + 0.5); basetone = (int)floor(THORBASEFREQ * symlen / samplerate + 0.5);
lotone = basetone - (THORNUMMTONES/2) * (doublespaced ? 2 : 1); lotone = basetone - (THORNUMTONES/2) * (doublespaced ? 2 : 1);
hitone = basetone + 3 * (THORNUMMTONES/2) * (doublespaced ? 2 : 1); hitone = basetone + 3 * (THORNUMTONES/2) * (doublespaced ? 2 : 1);
tonespacing = (double) (samplerate * ((doublespaced) ? 2 : 1)) / symlen; tonespacing = (double) (samplerate * ((doublespaced) ? 2 : 1)) / symlen;
bandwidth = THORNUMMTONES * tonespacing; bandwidth = THORNUMTONES * tonespacing;
hilbert = new C_FIR_filter(); hilbert = new C_FIR_filter();
hilbert->init_hilbert(37, 1); hilbert->init_hilbert(37, 1);
@ -203,7 +203,7 @@ thor::thor(trx_mode md)
pipe = new THORrxpipe[twosym]; pipe = new THORrxpipe[twosym];
scopedata.alloc(THORSCOPESIZE); scopedata.alloc(THORSCOPESIZE);
videodata.alloc((THORMAXFFTS * THORNUMMTONES * 2 * (doublespaced?2:1) )); videodata.alloc((THORMAXFFTS * THORNUMTONES * 2 * (doublespaced?2:1) ));
pipeptr = 0; 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() void thor::decodesymbol()
{ {
int c; int c;
double fdiff; double fdiff, avg, softmag;
unsigned char symbols[4];
// Decode the IFK+ sequence, which results in a single nibble // Decode the IFK+ sequence, which results in a single nibble
fdiff = currsymbol - prev1symbol; fdiff = currsymbol - prev1symbol;
if (reverse) fdiff = -fdiff; if (reverse) fdiff = -fdiff;
if (doublespaced) fdiff /= 2 * paths; fdiff /= paths;
else fdiff /= paths; if (doublespaced) fdiff /= 2.0;
c = (int)floor(fdiff + .5) - 2; c = (int)floor(fdiff + .5) - 2;
if (c < 0) c += THORNUMMTONES; if (c < 0) c += THORNUMTONES;
// decodeEX(c); avg = (currmag + prev1mag + prev2mag) / 3.0;
unsigned char symbols[4];
double avg = (currmag + prev1mag + prev2mag) / 3.0;
if (avg == 0.0) avg = 1e-20; if (avg == 0.0) avg = 1e-20;
double softmag = currmag / avg; softmag = currmag / avg;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
// hard symbol decode // hard symbol decode
@ -355,7 +336,7 @@ int thor::harddecode()
{ {
double x, max = 0.0; double x, max = 0.0;
int symbol = 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(); x = pipe[pipeptr].vector[i].mag();
if (x > max) { if (x > max) {
max = x; max = x;
@ -371,16 +352,16 @@ void thor::update_syncscope()
double max = 0, min = 1e6, range, mag; double max = 0, min = 1e6, range, mag;
// dom waterfall // 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) { 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(); mag = pipe[pipeptr].vector[i].mag();
if (max < mag) max = mag; if (max < mag) max = mag;
if (min > mag) min = mag; if (min > mag) min = mag;
} }
range = max - min; 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) { if (range > 2) {
mag = (pipe[pipeptr].vector[i].mag() - min) / range + 0.0001; mag = (pipe[pipeptr].vector[i].mag() - min) / range + 0.0001;
mag = 1 + 2 * log10(mag); mag = 1 + 2 * log10(mag);
@ -390,7 +371,7 @@ void thor::update_syncscope()
videodata[i] = 255*mag; 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(); videodata.next();
// set_scope(scopedata, twosym); // set_scope(scopedata, twosym);
@ -428,7 +409,7 @@ void thor::synchronize()
} }
syn = syncfilter->run(syn); 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) { if (currsymbol != prev1symbol && prev1symbol != prev2symbol) {
sig = pipe[pipeptr].vector[currsymbol].mag(); sig = pipe[pipeptr].vector[currsymbol].mag();
noise = 0.0; 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) if (i != currsymbol)
noise += pipe[pipeptr].vector[i].mag(); noise += pipe[pipeptr].vector[i].mag();
} }
noise /= (paths * THORNUMMTONES * 2 * (doublespaced?2:1) - 1); noise /= (paths * THORNUMTONES * 2 * (doublespaced?2:1) - 1);
if (noise) if (noise)
s2n = decayavg( s2n, sig / noise, 8); 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]); z = mixer(n + 1, zp[i]);
bins = binsfft[n]->run(z); bins = binsfft[n]->run(z);
// copy current vector to the pipe interleaving the FFT vectors // 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]; pipe[pipeptr].vector[n + paths * i] = bins[i];
} }
} }
@ -548,10 +529,10 @@ void thor::sendsymbol(int sym)
complex z; complex z;
int tone; int tone;
tone = (txprevtone + 2 + sym) % THORNUMMTONES; tone = (txprevtone + 2 + sym) % THORNUMTONES;
txprevtone = tone; txprevtone = tone;
if (reverse) if (reverse)
tone = (THORNUMMTONES - 1) - tone; tone = (THORNUMTONES - 1) - tone;
sendtone(tone, 1); sendtone(tone, 1);
} }
@ -624,12 +605,12 @@ int thor::tx_process()
case TX_STATE_PREAMBLE: case TX_STATE_PREAMBLE:
Clearbits(); Clearbits();
for (int j = 0; j < 16; j++) sendsymbol(0); for (int j = 0; j < 16; j++) sendsymbol(0);
// sendtone(THORNUMMTONES/2, 4); // sendtone(THORNUMTONES/2, 4);
// for (int k = 0; k < 3; k++) { // for (int k = 0; k < 3; k++) {
// sendtone(THORNUMMTONES, 3); // sendtone(THORNUMTONES, 3);
// sendtone(0, 3); // sendtone(0, 3);
// } // }
// sendtone(THORNUMMTONES/2, 4); // sendtone(THORNUMTONES/2, 4);
sendidle(); sendidle();
txstate = TX_STATE_START; txstate = TX_STATE_START;

Wyświetl plik

@ -493,8 +493,8 @@ void modem::wfid_send(long int symbol)
sym = symbol; sym = symbol;
msk = mask[symbol]; msk = mask[symbol];
for (j = 0; j < NUMTONES * NUMCHARS; j++) { for (j = 0; j < NUMTONES * NUMCHARS; j++) {
if (sym & 1 == 1) if (sym & 1)
wfid_outbuf[i] += ((msk & 1 == 1 ? -1 : 1 ) * sin(wfid_w[j] * i) * wfid_txpulse[i]); wfid_outbuf[i] += (msk & 1 ? -1 : 1 ) * sin(wfid_w[j] * i) * wfid_txpulse[i];
sym = sym >> 1; sym = sym >> 1;
msk = msk >> 1; msk = msk >> 1;
} }

Wyświetl plik

@ -66,8 +66,10 @@ bool restartOK = false;
bool trx_wait = false; bool trx_wait = false;
modem *active_modem = 0; modem *active_modem = 0;
cRsId *ReedSolomon = 0;
SoundBase *scard; SoundBase *scard;
int _trx_tune; int _trx_tune;
// Ringbuffer for the audio "history". A pointer into this buffer // Ringbuffer for the audio "history". A pointer into this buffer
@ -80,6 +82,9 @@ bool bHistory = false;
static int dummy = 0; static int dummy = 0;
static bool trxrunning = false; static bool trxrunning = false;
static bool rsid_detecting = false;
#include "tune.cxx" #include "tune.cxx"
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
@ -96,6 +101,7 @@ void trx_trx_receive_loop()
if (active_modem) { if (active_modem) {
try { try {
scard->Open(O_RDONLY, active_modem->get_samplerate()); scard->Open(O_RDONLY, active_modem->get_samplerate());
REQ(sound_update, progdefaults.btnAudioIOis);
} }
catch (const SndException& e) { catch (const SndException& e) {
put_status(e.what(), 5); put_status(e.what(), 5);
@ -110,6 +116,40 @@ void trx_trx_receive_loop()
active_modem->rx_init(); active_modem->rx_init();
while (1) { 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 { try {
if (trxrb.write_space() == 0) // discard some old data if (trxrb.write_space() == 0) // discard some old data
trxrb.read_advance(SCBLOCKSIZE); trxrb.read_advance(SCBLOCKSIZE);
@ -130,8 +170,12 @@ void trx_trx_receive_loop()
trxrb.write_advance(numread); trxrb.write_advance(numread);
REQ(&waterfall::sig_data, wf, rbvec[0].buf, numread); REQ(&waterfall::sig_data, wf, rbvec[0].buf, numread);
if (!bHistory) if (!bHistory) {
active_modem->rx_process(rbvec[0].buf, numread); if (rsid_detecting == true)
ReedSolomon->search(rbvec[0].buf, numread);
else
active_modem->rx_process(rbvec[0].buf, numread);
}
else { else {
bool afc = progStatus.afconoff; bool afc = progStatus.afconoff;
progStatus.afconoff = false; progStatus.afconoff = false;
@ -162,6 +206,7 @@ void trx_trx_transmit_loop()
if (active_modem) { if (active_modem) {
try { try {
scard->Open(O_WRONLY, active_modem->get_samplerate()); scard->Open(O_WRONLY, active_modem->get_samplerate());
REQ(sound_update, progdefaults.btnAudioIOis);
} }
catch (const SndException& e) { catch (const SndException& e) {
put_status(e.what(), 1); put_status(e.what(), 1);
@ -172,6 +217,9 @@ void trx_trx_transmit_loop()
push2talk->set(true); push2talk->set(true);
active_modem->tx_init(scard); active_modem->tx_init(scard);
if (progdefaults.TransmitRSid == true)
ReedSolomon->send();
while (trx_state == STATE_TX) { while (trx_state == STATE_TX) {
try { try {
if (active_modem->tx_process() < 0) if (active_modem->tx_process() < 0)
@ -207,6 +255,7 @@ void trx_tune_loop()
if (active_modem) { if (active_modem) {
try { try {
scard->Open(O_WRONLY, active_modem->get_samplerate()); scard->Open(O_WRONLY, active_modem->get_samplerate());
REQ(sound_update, progdefaults.btnAudioIOis);
} }
catch (const SndException& e) { catch (const SndException& e) {
put_status(e.what(), 1); put_status(e.what(), 1);
@ -375,6 +424,8 @@ void trx_start(void)
} }
if (scard) delete scard; if (scard) delete scard;
if (ReedSolomon) delete ReedSolomon;
switch (progdefaults.btnAudioIOis) { switch (progdefaults.btnAudioIOis) {
#if USE_OSS #if USE_OSS
@ -399,6 +450,8 @@ void trx_start(void)
abort(); abort();
} }
ReedSolomon = new cRsId;
trx_state = STATE_RX; trx_state = STATE_RX;
_trx_tune = 0; _trx_tune = 0;
active_modem = 0; active_modem = 0;

Wyświetl plik

@ -339,8 +339,10 @@ void WFdisp::update_fft_db()
void WFdisp::processFFT() { void WFdisp::processFFT() {
int n; int n;
double scale; double scale;
if (progdefaults.rsid == true)
scale = (double)SC_SMPLRATE / active_modem->get_samplerate(); scale = (double)SC_SMPLRATE / ReedSolomon->samplerate();
else
scale = (double)SC_SMPLRATE / active_modem->get_samplerate();
scale *= FFT_LEN / 2000.0; scale *= FFT_LEN / 2000.0;
if (dispcnt == 0) { if (dispcnt == 0) {
@ -509,6 +511,7 @@ void WFdisp::carrier(int cf) {
if (cf > bandwidth / 2 && cf < (IMAGE_WIDTH - bandwidth / 2)) { if (cf > bandwidth / 2 && cf < (IMAGE_WIDTH - bandwidth / 2)) {
carrierfreq = cf; carrierfreq = cf;
makeMarker(); makeMarker();
redrawCursor();
} }
} }
@ -843,16 +846,36 @@ void x1_cb(Fl_Widget *w, void* v) {
restoreFocus(); restoreFocus();
} }
void bwclr_cb(Fl_Widget *w, void * v) { void bw_rsid_toggle(waterfall *wf)
waterfall *wf = (waterfall *)w->parent(); {
wf->wfdisp->DispColor(!wf->wfdisp->DispColor()); if (trx_state == STATE_TX)
if (wf->wfdisp->DispColor() == 0) return;
w->label("gry"); if (progdefaults.rsid == true) {
else progdefaults.rsid = false;
w->label("clr"); 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(); 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) { void slew_left(Fl_Widget *w, void * v) {
waterfall *wf = (waterfall *)w->parent(); waterfall *wf = (waterfall *)w->parent();
wf->wfdisp->slew(-100); wf->wfdisp->slew(-100);
@ -989,7 +1012,7 @@ void mode_cb(Fl_Widget *w, void *v) {
wf->wfdisp->Mode(SCOPE); wf->wfdisp->Mode(SCOPE);
w->label("sig"); w->label("sig");
wf->x1->deactivate(); wf->x1->deactivate();
wf->bwclr->deactivate(); wf->bw_rsid->deactivate();
wf->wfcarrier->deactivate(); wf->wfcarrier->deactivate();
wf->wfRefLevel->deactivate(); wf->wfRefLevel->deactivate();
wf->wfAmpSpan->deactivate(); wf->wfAmpSpan->deactivate();
@ -1003,7 +1026,7 @@ void mode_cb(Fl_Widget *w, void *v) {
wf->wfdisp->Mode(WATERFALL); wf->wfdisp->Mode(WATERFALL);
w->label("Wtr"); w->label("Wtr");
wf->x1->activate(); wf->x1->activate();
wf->bwclr->activate(); wf->bw_rsid->activate();
wf->wfcarrier->activate(); wf->wfcarrier->activate();
wf->wfRefLevel->activate(); wf->wfRefLevel->activate();
wf->wfAmpSpan->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"); // wfdisp->tooltip("Click to set tracking point");
xpos = x() + wSpace; xpos = x() + wSpace;
bwclr = new Fl_Button(xpos, buttonrow, bwColor*(w0<600?w0/6:100)/100, BTN_HEIGHT, "clr"); bw_rsid = new Fl_Button(xpos, buttonrow, bwColor*(w0<600?w0/6:100)/100, BTN_HEIGHT, "Id?");
bwclr->callback(bwclr_cb, 0); bw_rsid->callback(bw_rsid_cb, 0);
bwclr->tooltip("Color / BW waterfall"); bw_rsid->tooltip("Auto detect RSID");
xpos = xpos + bwColor*(w0<600?w0/6:100)/100 + wSpace; 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"); 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 // fall through to (un)pause for M-r or A-r
case FL_Pause: case FL_Pause:
if (trx_state != STATE_TX) { if (trx_state != STATE_TX) {
fl_lock(&trx_mutex); start_tx();
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
} }
else else
PauseBreak = true; PauseBreak = true;
@ -983,10 +980,7 @@ void FTextEdit::menu_cb(int val)
switch (val) { switch (val) {
case TX_MENU_TX: case TX_MENU_TX:
active_modem->set_stopflag(false); active_modem->set_stopflag(false);
fl_lock(&trx_mutex); start_tx();
trx_state = STATE_TX;
fl_unlock(&trx_mutex);
wf->set_XmtRcvBtn(true);
break; break;
case TX_MENU_RX: case TX_MENU_RX:
insert_position(tbuf->length()); insert_position(tbuf->length());