From 28348e0eac8c2f853ff8c7d577688d1766ee5bd6 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Tue, 10 Oct 2023 23:35:52 +0100 Subject: [PATCH 1/3] updates to make it install to the right place --- debian/install | 2 +- debian/qtsoundmodem.desktop | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/install b/debian/install index db69a5c..badbb26 100644 --- a/debian/install +++ b/debian/install @@ -1,3 +1,3 @@ -QtSoundModem /usr/bin/qtsoundmodem +QtSoundModem /usr/bin debian/qtsoundmodem.desktop /usr/share/applications debian/QtSoundModem.png /usr/share/pixmaps diff --git a/debian/qtsoundmodem.desktop b/debian/qtsoundmodem.desktop index ae3e609..7ad2f91 100644 --- a/debian/qtsoundmodem.desktop +++ b/debian/qtsoundmodem.desktop @@ -2,7 +2,7 @@ Name=QtSoundModem Comment=QtSoundModem Version=1.0 -Exec=/usr/bin/qtsoundmodem +Exec=/usr/bin/QtSoundModem GenericName=QtSoundModem Icon=QtSoundModem NoDisplay=false From c264c0c63857e0c36303687d2dfc533500b93cf1 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 17 Dec 2023 13:53:32 +0000 Subject: [PATCH 2/3] New upstream version 0.0.0.71 --- Config.cpp | 7 + ModemDialog.ui | 55 + QtSoundModem-DESKTOP-MHE5LO8.vcxproj | 292 -- QtSoundModem-HPLaptop.vcxproj | 288 -- QtSoundModem.cpp | 727 +-- QtSoundModem.cpp.bak | 2866 ----------- QtSoundModem.h | 9 +- QtSoundModem.ui | 159 +- QtSoundModem.vcxproj-DESKTOP-MHE5LO8.user | 34 - QtSoundModem.vcxproj-HPLaptop.user | 34 - QtSoundModem.vcxproj.user | 14 +- SMMain-DESKTOP-MHE5LO8.c | 1433 ------ SMMain-HPLaptop.c | 1381 ----- SMMain.c | 6 +- UZ7HOStuff-DESKTOP-MHE5LO8.h | 1110 ---- UZ7HOStuff-HPLaptop.h | 1023 ---- UZ7HOStuff.h | 23 +- UZ7HOStuff.h.bak | 1049 ---- agwlib.h | 45 - ais.h | 8 - aprs_tt.h | 191 - audio_stats.h | 7 - ax25_agw.c | 49 +- ax25_demod.c | 1 + ax25_link.h | 88 - ax25_mod-DESKTOP-MHE5LO8.c | 1810 ------- ax25_pad2.h | 55 - beacon.h | 6 - cdigipeater.h | 62 - cm108.h | 5 - config.h | 262 - debug/QtSoundModem.ini | 201 - debug/moc_predefs-DESKTOP-MHE5LO8.h | 12 - debug/moc_predefs.h | 2 +- decode_aprs.h | 150 - dedupe.h | 10 - demod.h | 17 - demod_afsk.h | 8 - demod_psk.h | 7 - devicesDialog.ui | 15 +- digipeater.h | 78 - dlq.h | 148 - dns_sd_common.h | 7 - dns_sd_dw.h | 10 - dtime_now.h | 18 - dtmf.h | 14 - dw9600.c | 1 + dwgps.h | 61 - dwgpsd.h | 22 - dwgpsnmea.h | 32 - dwsock.h | 21 - encode_aprs.h | 17 - fcs_calc.h | 11 - fsk_filters.h | 7 - fsk_gen_filter.h | 15 - gen_tone.h | 17 - grm_sym.h | 501 -- hdlc_send.h | 17 - igate.h | 128 - il2p.c | 182 +- il2p.c.bak | 4502 ----------------- kiss.h | 24 - kiss_frame.h | 126 - kiss_mode.c | 1 - kissnet.h | 29 - kissserial.h | 23 - latlong.h | 24 - log.h | 19 - main.cpp | 4 +- mgn_icon.h | 276 - mheard.h | 20 - morse.h | 8 - multi_modem.h | 24 - pfilter.h | 13 - ptt.h | 26 - recv.h | 6 - redecode.h | 15 - ...redefs-DESKTOP-MHE5LO8.h => moc_predefs.h} | 22 +- rpack.h | 94 - rrbb.h | 92 - serial_port.h | 32 - server.h | 32 - sm_main.c | 19 +- symbols.h | 19 - telemetry.h | 15 - tq.h | 41 - tt_text.h | 38 - tt_user.h | 15 - tune.h | 1 - version.h | 21 - waypoint.h | 24 - xid.h | 32 - xmit.h | 27 - 93 files changed, 766 insertions(+), 19726 deletions(-) delete mode 100644 QtSoundModem-DESKTOP-MHE5LO8.vcxproj delete mode 100644 QtSoundModem-HPLaptop.vcxproj delete mode 100644 QtSoundModem.cpp.bak delete mode 100644 QtSoundModem.vcxproj-DESKTOP-MHE5LO8.user delete mode 100644 QtSoundModem.vcxproj-HPLaptop.user delete mode 100644 SMMain-DESKTOP-MHE5LO8.c delete mode 100644 SMMain-HPLaptop.c delete mode 100644 UZ7HOStuff-DESKTOP-MHE5LO8.h delete mode 100644 UZ7HOStuff-HPLaptop.h delete mode 100644 UZ7HOStuff.h.bak delete mode 100644 agwlib.h delete mode 100644 ais.h delete mode 100644 aprs_tt.h delete mode 100644 audio_stats.h delete mode 100644 ax25_link.h delete mode 100644 ax25_mod-DESKTOP-MHE5LO8.c delete mode 100644 ax25_pad2.h delete mode 100644 beacon.h delete mode 100644 cdigipeater.h delete mode 100644 cm108.h delete mode 100644 config.h delete mode 100644 debug/QtSoundModem.ini delete mode 100644 debug/moc_predefs-DESKTOP-MHE5LO8.h delete mode 100644 decode_aprs.h delete mode 100644 dedupe.h delete mode 100644 demod.h delete mode 100644 demod_afsk.h delete mode 100644 demod_psk.h delete mode 100644 digipeater.h delete mode 100644 dlq.h delete mode 100644 dns_sd_common.h delete mode 100644 dns_sd_dw.h delete mode 100644 dtime_now.h delete mode 100644 dtmf.h delete mode 100644 dwgps.h delete mode 100644 dwgpsd.h delete mode 100644 dwgpsnmea.h delete mode 100644 dwsock.h delete mode 100644 encode_aprs.h delete mode 100644 fcs_calc.h delete mode 100644 fsk_filters.h delete mode 100644 fsk_gen_filter.h delete mode 100644 gen_tone.h delete mode 100644 grm_sym.h delete mode 100644 hdlc_send.h delete mode 100644 igate.h delete mode 100644 il2p.c.bak delete mode 100644 kiss.h delete mode 100644 kiss_frame.h delete mode 100644 kissnet.h delete mode 100644 kissserial.h delete mode 100644 latlong.h delete mode 100644 log.h delete mode 100644 mgn_icon.h delete mode 100644 mheard.h delete mode 100644 morse.h delete mode 100644 multi_modem.h delete mode 100644 pfilter.h delete mode 100644 ptt.h delete mode 100644 recv.h delete mode 100644 redecode.h rename release/{moc_predefs-DESKTOP-MHE5LO8.h => moc_predefs.h} (95%) delete mode 100644 rpack.h delete mode 100644 rrbb.h delete mode 100644 serial_port.h delete mode 100644 server.h delete mode 100644 symbols.h delete mode 100644 telemetry.h delete mode 100644 tq.h delete mode 100644 tt_text.h delete mode 100644 tt_user.h delete mode 100644 tune.h delete mode 100644 version.h delete mode 100644 waypoint.h delete mode 100644 xid.h delete mode 100644 xmit.h diff --git a/Config.cpp b/Config.cpp index ad03176..f660aaa 100644 --- a/Config.cpp +++ b/Config.cpp @@ -54,6 +54,7 @@ extern int CWIDLeft; extern int CWIDRight; extern int CWIDType; extern bool afterTraffic; +extern bool darkTheme; extern "C" int RSID_SABM[4]; extern "C" int RSID_UI[4]; @@ -115,6 +116,7 @@ void GetPortSettings(int Chan) fx25_mode[Chan] = getAX25Param("FX25", FX25_MODE_RX).toInt(); il2p_mode[Chan] = getAX25Param("IL2P", IL2P_MODE_NONE).toInt(); + il2p_crc[Chan] = getAX25Param("IL2PCRC", 0).toInt(); RSID_UI[Chan] = getAX25Param("RSID_UI", 0).toInt(); RSID_SABM[Chan] = getAX25Param("RSID_SABM", 0).toInt(); RSID_SetModem[Chan] = getAX25Param("RSID_SetModem", 0).toInt(); @@ -303,6 +305,8 @@ void getSettings() } + darkTheme = settings->value("Init/darkTheme", false).toBool(); + delete(settings); } @@ -347,6 +351,7 @@ void SavePortSettings(int Chan) saveAX25Param("MyDigiCall", MyDigiCall[Chan]); saveAX25Param("FX25", fx25_mode[Chan]); saveAX25Param("IL2P", il2p_mode[Chan]); + saveAX25Param("IL2PCRC", il2p_crc[Chan]); saveAX25Param("RSID_UI", RSID_UI[Chan]); saveAX25Param("RSID_SABM", RSID_SABM[Chan]); saveAX25Param("RSID_SetModem", RSID_SetModem[Chan]); @@ -463,6 +468,8 @@ void saveSettings() settings->setValue("Modem/CWIDType", CWIDType); settings->setValue("Modem/afterTraffic", afterTraffic); + settings->setValue("Init/darkTheme", darkTheme); + saveAX25Params(0); saveAX25Params(1); saveAX25Params(2); diff --git a/ModemDialog.ui b/ModemDialog.ui index e8f7903..9b5b856 100644 --- a/ModemDialog.ui +++ b/ModemDialog.ui @@ -737,6 +737,19 @@ Retries + + + + 200 + 280 + 53 + 21 + + + + CRC + + @@ -1445,6 +1458,19 @@ + + + + 200 + 280 + 53 + 21 + + + + CRC + + @@ -2202,6 +2228,19 @@ + + + + 200 + 280 + 53 + 21 + + + + CRC + + @@ -2956,6 +2995,19 @@ + + + + 200 + 280 + 53 + 21 + + + + CRC + + @@ -3041,6 +3093,9 @@ Save + + true + diff --git a/QtSoundModem-DESKTOP-MHE5LO8.vcxproj b/QtSoundModem-DESKTOP-MHE5LO8.vcxproj deleted file mode 100644 index adcd4b6..0000000 --- a/QtSoundModem-DESKTOP-MHE5LO8.vcxproj +++ /dev/null @@ -1,292 +0,0 @@ - - - - - Release - Win32 - - - Debug - Win32 - - - - {4EDE958E-D0AC-37B4-81F7-78313A262DCD} - QtSoundModem - QtVS_v304 - 10.0.17763.0 - 10.0.19041.0 - $(MSBuildProjectDirectory)\QtMsBuild - - - - v141 - release\ - false - NotSet - Application - release\ - QtSoundModem - - - v141 - debug\ - false - NotSet - Application - debug\ - QtSoundModem - - - - - - - - - - - - - - - - - - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)Intermed\$(Platform)\$(Configuration)\ - QtSoundModem - true - true - - - $(SolutionDir)$(Platform)\$(Configuration)\ - $(SolutionDir)Intermed\$(Platform)\$(Configuration)\\ - QtSoundModem - true - false - - - 5.14 - core;network;gui;widgets;serialport - - - 5.14.2 - core;network;gui;widgets;serialport - - - - - - - rsid;.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;release;/include;%(AdditionalIncludeDirectories) - -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) - $(IntDir) - false - None - 4577;4467;%(DisableSpecificWarnings) - Sync - $(IntDir) - MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) - false - $(OutDir) - MultiThreadedDLL - true - true - Level3 - true - - - libfftw3f-3.lib;shell32.lib;setupapi.lib;WS2_32.Lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) - "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) - true - false - true - false - true - $(OutDir)QtSoundModem.exe - true - Windows - true - - - Unsigned - None - 0 - - - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_SERIALPORT_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) - - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(IntDir) - moc_%(Filename).cpp - - - QtSoundModem - default - Rcc'ing %(Identity)... - $(IntDir) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(IntDir) - ui_%(Filename).h - - - - - .\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;debug;/include;rsid;%(AdditionalIncludeDirectories) - -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) - $(IntDir) - false - EditAndContinue - 4577;4467;%(DisableSpecificWarnings) - Sync - $(IntDir) - Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - true - true - Level3 - true - $(OutDir) - - - libfftw3f-3.lib;shell32.lib;setupapi.lib;WS2_32.Lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) - "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) - true - true - true - $(OutDir)\QtSoundModem.exe - true - Windows - true - false - - - Unsigned - None - 0 - - - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_SERIALPORT_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) - - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(IntDir) - moc_%(Filename).cpp - - - QtSoundModem - default - Rcc'ing %(Identity)... - $(IntDir) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(IntDir) - ui_%(Filename).h - - - - - - - - - - CompileAsC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Document - true - $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) - cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h - Generate moc_predefs.h - debug\moc_predefs.h;%(Outputs) - - - Document - $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) - cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h - Generate moc_predefs.h - release\moc_predefs.h;%(Outputs) - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/QtSoundModem-HPLaptop.vcxproj b/QtSoundModem-HPLaptop.vcxproj deleted file mode 100644 index 3b99dd0..0000000 --- a/QtSoundModem-HPLaptop.vcxproj +++ /dev/null @@ -1,288 +0,0 @@ - - - - - Release - Win32 - - - Debug - Win32 - - - - {4EDE958E-D0AC-37B4-81F7-78313A262DCD} - QtSoundModem - QtVS_v304 - 10.0.19041.0 - 10.0.19041.0 - $(MSBuildProjectDirectory)\QtMsBuild - - - - v141 - release\ - false - NotSet - Application - release\ - QtSoundModem - - - v141 - debug\ - false - NotSet - Application - debug\ - QtSoundModem - - - - - - - - - - - - - - - - - - C:\Dev\Msdev2005\projects\QT\QtSoundModem\Win32\Debug\ - C:\Dev\Msdev2005\projects\QT\QtSoundModem\Intermed\Win32\Debug\ - QtSoundModem - true - true - - - C:\Dev\Msdev2005\projects\QT\QtSoundModem\Win32\Release\ - C:\Dev\Msdev2005\projects\QT\QtSoundModem\Intermed\Win32\Release\ - QtSoundModem - true - false - - - 5.14.2_msvc2017 - core;network;gui;widgets;serialport - - - 5.14.2_msvc2017 - core;network;gui;widgets;serialport - - - - - - - rsid;.\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;release;/include;%(AdditionalIncludeDirectories) - -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) - $(IntDir) - false - None - 4577;4467;%(DisableSpecificWarnings) - Sync - $(IntDir) - MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) - false - $(OutDir) - MultiThreadedDLL - true - true - Level3 - true - - - libfftw3f-3.lib;shell32.lib;setupapi.lib;WS2_32.Lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) - "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) - true - false - true - false - true - $(OutDir)\QtSoundModem.exe - true - Windows - true - - - Unsigned - None - 0 - - - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;NDEBUG;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_SERIALPORT_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) - - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(IntDir) - moc_%(Filename).cpp - - - QtSoundModem - default - Rcc'ing %(Identity)... - $(IntDir) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(IntDir) - ui_%(Filename).h - - - - - .\GeneratedFiles\$(ConfigurationName);.\GeneratedFiles;.;debug;/include;rsid;%(AdditionalIncludeDirectories) - -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) - $(IntDir) - false - EditAndContinue - 4577;4467;%(DisableSpecificWarnings) - Sync - $(IntDir) - Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;%(PreprocessorDefinitions) - false - MultiThreadedDebugDLL - true - true - Level3 - true - $(OutDir) - - - libfftw3f-3.lib;shell32.lib;setupapi.lib;WS2_32.Lib;%(AdditionalDependencies) - C:\opensslx86\lib;C:\Utils\my_sql\mysql-5.7.25-win32\lib;C:\Utils\postgresqlx86\pgsql\lib;%(AdditionalLibraryDirectories) - "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) - true - true - true - $(OutDir)\QtSoundModem.exe - true - Windows - true - false - - - Unsigned - None - 0 - - - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;QT_WIDGETS_LIB;QT_GUI_LIB;QT_NETWORK_LIB;QT_SERIALPORT_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) - - - msvc - ./$(Configuration)/moc_predefs.h - Moc'ing %(Identity)... - output - $(IntDir) - moc_%(Filename).cpp - - - QtSoundModem - default - Rcc'ing %(Identity)... - $(IntDir) - qrc_%(Filename).cpp - - - Uic'ing %(Identity)... - $(IntDir) - ui_%(Filename).h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Document - true - $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) - cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h - Generate moc_predefs.h - debug\moc_predefs.h;%(Outputs) - - - Document - $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) - cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h - Generate moc_predefs.h - release\moc_predefs.h;%(Outputs) - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/QtSoundModem.cpp b/QtSoundModem.cpp index cadb3fb..976ca95 100644 --- a/QtSoundModem.cpp +++ b/QtSoundModem.cpp @@ -51,17 +51,18 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses QImage *Constellation[4]; -QImage *Waterfall[4] = { 0,0,0,0 }; -QImage *Header[4]; +QImage *Waterfall = 0; QLabel *DCDLabel[4]; QLineEdit *chanOffsetLabel[4]; QImage *DCDLed[4]; QImage *RXLevel; +QImage *RXLevel2; + +QLabel *WaterfallCopy; -QLabel *WaterfallCopy[2]; -QLabel *HeaderCopy[2]; QLabel * RXLevelCopy; +QLabel * RXLevel2Copy; QTextEdit * monWindowCopy; @@ -73,6 +74,8 @@ QList Ports = QSerialPortInfo::availablePorts(); void saveSettings(); void getSettings(); +void DrawModemFreqRange(); + extern "C" void CloseSound(); extern "C" void GetSoundDevices(); extern "C" char modes_name[modes_count][21]; @@ -120,11 +123,10 @@ extern "C" int Freq_Change(int Chan, int Freq); void set_speed(int snd_ch, int Modem); void init_speed(int snd_ch); - void wf_pointer(int snd_ch); void FourierTransform(int NumSamples, short * RealIn, float * RealOut, float * ImagOut, int InverseTransform); void dofft(short * in, float * outr, float * outi); void init_raduga(); - void wf_Scale(int Chan); + void DrawFreqTicks(); void AGW_Report_Modem_Change(int port); char * strlop(char * buf, char delim); void sendRSID(int Chan, int dropTX); @@ -157,7 +159,10 @@ int WaterfallMin = 00; int WaterfallMax = 6000; int Configuring = 0; +bool lockWaterfall = false; +bool inWaterfall = false; +extern "C" int NeedWaterfallHeaders; extern "C" float BinSize; extern "C" { int RSID_SABM[4]; } @@ -175,6 +180,12 @@ QRgb red = qRgb(255, 0, 0); QRgb yellow = qRgb(255, 255, 0); QRgb cyan = qRgb(0, 255, 255); +QRgb txText = qRgb(192, 0, 0); +QRgb rxText = qRgb(0, 0, 192); + +bool darkTheme = true; +bool minimizeonStart = true; + // Indexed colour list from ARDOPC #define WHITE 0 @@ -198,7 +209,7 @@ QRgb vbColours[16] = { qRgb(255, 255, 255), qRgb(255, 99, 71), qRgb(255, 215, 0) qRgb(218, 165, 32), qRgb(255, 0, 255) }; unsigned char WaterfallLines[2][80][4096] = { 0 }; -int NextWaterfallLine[2] = { 0 }; +int NextWaterfallLine[2] = {0, 0}; unsigned int LastLevel = 255; unsigned int LastBusy = 255; @@ -307,8 +318,20 @@ void QtSoundModem::resizeEvent(QResizeEvent* event) QRect r = geometry(); - int A, B, C, W; - int modemBoxHeight = 30; + QRect r1 = ui.monWindow->geometry(); + QRect r2 = ui.centralWidget->geometry(); + + int modemBoxHeight = 34; + + int Width = r.width(); + int Height = r.height() - 25; + + int monitorTop; + int monitorHeight; + int sessionTop; + int sessionHeight = 0; + int waterfallsTop; + int waterfallsHeight = WaterfallImageHeight; ui.modeB->setVisible(soundChannel[1]); ui.centerB->setVisible(soundChannel[1]); @@ -331,78 +354,46 @@ void QtSoundModem::resizeEvent(QResizeEvent* event) if (soundChannel[2] || soundChannel[3]) modemBoxHeight = 60; + ui.Waterfall->setVisible(0); - A = r.height() - 25; // No waterfalls + monitorTop = modemBoxHeight + 1; - if (UsingBothChannels && Secondwaterfall) + // Now have one waterfall label containing headers and waterfalls + + if (Firstwaterfall || Secondwaterfall) + ui.Waterfall->setVisible(1); + + if (AGWServ) { - // Two waterfalls - - ui.WaterfallA->setVisible(1); - ui.HeaderA->setVisible(1); - ui.WaterfallB->setVisible(1); - ui.HeaderB->setVisible(1); - - A = r.height() - 258; // Top of Waterfall A - B = A + 115; // Top of Waterfall B + sessionTable->setVisible(true); + sessionHeight = 150; } else { - // One waterfall - - // Could be Left or Right - - if (Firstwaterfall) - { - if (soundChannel[0] == RIGHT) - { - ui.WaterfallA->setVisible(0); - ui.HeaderA->setVisible(0); - ui.WaterfallB->setVisible(1); - ui.HeaderB->setVisible(1); - } - else - { - ui.WaterfallA->setVisible(1); - ui.HeaderA->setVisible(1); - ui.WaterfallB->setVisible(0); - ui.HeaderB->setVisible(0); - } - - A = r.height() - 145; // Top of Waterfall A - } - else - A = r.height() - 25; // Top of Waterfall A + sessionTable->setVisible(false); } - C = A - 150; // Bottom of Monitor, Top of connection list - W = r.width(); + // if only displaying one Waterfall, change height of waterfall area - // Calc Positions of Waterfalls - - ui.monWindow->setGeometry(QRect(0, modemBoxHeight, W, C - (modemBoxHeight + 26))); - sessionTable->setGeometry(QRect(0, C, W, 175)); - - if (UsingBothChannels) + if (UsingBothChannels == 0 || (Firstwaterfall == 0) || (Secondwaterfall == 0)) { - ui.HeaderA->setGeometry(QRect(0, A, W, 38)); - ui.WaterfallA->setGeometry(QRect(0, A + 38, W, 80)); - ui.HeaderB->setGeometry(QRect(0, B, W, 38)); - ui.WaterfallB->setGeometry(QRect(0, B + 38, W, 80)); - } - else - { - if (soundChannel[0] == RIGHT) - { - ui.HeaderB->setGeometry(QRect(0, A, W, 38)); - ui.WaterfallB->setGeometry(QRect(0, A + 38, W, 80)); - } - else - { - ui.HeaderA->setGeometry(QRect(0, A, W, 38)); - ui.WaterfallA->setGeometry(QRect(0, A + 38, W, 80)); - } + waterfallsHeight /= 2; } + + if ((Firstwaterfall == 0) && (Secondwaterfall == 0)) + waterfallsHeight = 0; + + monitorHeight = Height - sessionHeight - waterfallsHeight - modemBoxHeight; + waterfallsTop = Height - waterfallsHeight; + sessionTop = Height - (sessionHeight + waterfallsHeight); + + ui.monWindow->setGeometry(QRect(0, monitorTop, Width, monitorHeight)); + + if (AGWServ) + sessionTable->setGeometry(QRect(0, sessionTop, Width, sessionHeight)); + + if (waterfallsHeight) + ui.Waterfall->setGeometry(QRect(0, waterfallsTop, Width, waterfallsHeight + 2)); } QAction * setupMenuLine(QMenu * Menu, char * Label, QObject * parent, int State) @@ -426,50 +417,40 @@ void QtSoundModem::menuChecked() int state = Act->isChecked(); if (Act == actWaterfall1) - { - int oldstate = Firstwaterfall; Firstwaterfall = state; - if (state != oldstate) - initWaterfall(0, state); - - } else if (Act == actWaterfall2) - { - int oldstate = Secondwaterfall; Secondwaterfall = state; - if (state != oldstate) - initWaterfall(1, state); + initWaterfall(Firstwaterfall | Secondwaterfall); - } saveSettings(); } -void QtSoundModem::initWaterfall(int chan, int state) +void QtSoundModem::initWaterfall(int state) { if (state == 1) { - if (chan == 0) - { - ui.WaterfallA = new QLabel(ui.centralWidget); - WaterfallCopy[0] = ui.WaterfallA; - } - else - { - ui.WaterfallB = new QLabel(ui.centralWidget); - WaterfallCopy[1] = ui.WaterfallB; - } - Waterfall[chan] = new QImage(1024, 80, QImage::Format_RGB32); - Waterfall[chan]->fill(black); + // if (ui.Waterfall) + // { + // delete ui.Waterfall; + // ui.Waterfall = new QLabel(ui.centralWidget); + // } + WaterfallCopy = ui.Waterfall; + + Waterfall = new QImage(1024, WaterfallImageHeight + 2, QImage::Format_RGB32); + + NeedWaterfallHeaders = 1; + } else { - delete(Waterfall[chan]); - Waterfall[chan] = 0; + delete(Waterfall); + Waterfall = 0; } QSize Size(800, 602); // Not actually used, but Event constructor needs it + QResizeEvent *event = new QResizeEvent(Size, Size); QApplication::sendEvent(this, event); } @@ -518,7 +499,7 @@ void DoPSKWindows() constellationDialog->resize(NextX, 140); } - +QTimer *wftimer; QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) { @@ -530,6 +511,8 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) mythis = this; + getSettings(); + QSettings mysettings("QtSoundModem.ini", QSettings::IniFormat); family = mysettings.value("FontFamily", "Courier New").toString(); @@ -606,7 +589,7 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) restoreGeometry(mysettings.value("geometry").toByteArray()); restoreState(mysettings.value("windowState").toByteArray()); - sessionTable = new QTableWidget(this); + sessionTable = new QTableWidget(ui.centralWidget); sessionTable->verticalHeader()->setVisible(FALSE); sessionTable->verticalHeader()->setDefaultSectionSize(20); @@ -615,7 +598,7 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) sessionTable->setColumnCount(12); m_TableHeader << "MyCall" << "DestCall" << "Status" << "Sent pkts" << "Sent Bytes" << "Rcvd pkts" << "Rcvd bytes" << "Rcvd FC" << "FEC corr" << "CPS TX" << "CPS RX" << "Direction"; - sessionTable->setStyleSheet("QHeaderView::section { background-color:rgb(224, 224, 224) }"); + mysetstyle(); sessionTable->setHorizontalHeaderLabels(m_TableHeader); sessionTable->setColumnWidth(0, 80); @@ -672,14 +655,11 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) actAbout = ui.menuBar->addAction("&About"); connect(actAbout, SIGNAL(triggered()), this, SLOT(doAbout())); - Header[0] = new QImage(1024, 38, QImage::Format_RGB32); - Header[1] = new QImage(1024, 38, QImage::Format_RGB32); RXLevel = new QImage(150, 10, QImage::Format_RGB32); RXLevel->fill(white); ui.RXLevel->setPixmap(QPixmap::fromImage(*RXLevel)); RXLevelCopy = ui.RXLevel; - DCDLabel[0] = new QLabel(this); DCDLabel[0]->setObjectName(QString::fromUtf8("DCDLedA")); DCDLabel[0]->setGeometry(QRect(280, 31, 12, 12)); @@ -720,42 +700,16 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) chanOffsetLabel[2] = ui.RXOffsetC; chanOffsetLabel[3] = ui.RXOffsetD; + WaterfallCopy = ui.Waterfall; - // Waterfall[0]->setColorCount(16); - // Waterfall[1]->setColorCount(16); + initWaterfall(Firstwaterfall | Secondwaterfall); - - // for (i = 0; i < 16; i++) - // { - // Waterfall[0]->setColor(i, vbColours[i]); - // Waterfall[1]->setColor(i, vbColours[i]); - // } - - WaterfallCopy[0] = ui.WaterfallA; - WaterfallCopy[1] = ui.WaterfallB; - - initWaterfall(0, 1); - initWaterfall(1, 1); - - Header[0]->fill(black); - Header[1]->fill(black); - - HeaderCopy[0] = ui.HeaderA; - HeaderCopy[1] = ui.HeaderB; monWindowCopy = ui.monWindow; ui.monWindow->document()->setMaximumBlockCount(10000); // connect(ui.monWindow, SIGNAL(selectionChanged()), this, SLOT(onTEselectionChanged())); - ui.HeaderA->setPixmap(QPixmap::fromImage(*Header[0])); - ui.HeaderB->setPixmap(QPixmap::fromImage(*Header[1])); - - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); - wf_Scale(0); - wf_Scale(1); - connect(ui.modeA, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); connect(ui.modeB, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); connect(ui.modeC, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); @@ -785,7 +739,6 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) ui.DCDSlider->setValue(dcd_threshold); - char valChar[32]; sprintf(valChar, "RX Offset %d", rxOffset); ui.RXOffsetLabel->setText(valChar); @@ -811,7 +764,7 @@ QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) connect(timer, SIGNAL(timeout()), this, SLOT(MyTimerSlot())); timer->start(100); - QTimer *wftimer = new QTimer(this); + wftimer = new QTimer(this); connect(wftimer, SIGNAL(timeout()), this, SLOT(doRestartWF())); wftimer->start(1000 * 300); @@ -885,7 +838,7 @@ void extSetOffset(int chan) sprintf(valChar, "%d", chanOffset[chan]); chanOffsetLabel[chan]->setText(valChar); - wf_pointer(soundChannel[chan]); + NeedWaterfallHeaders = true; pnt_change[0] = 1; pnt_change[1] = 1; @@ -928,6 +881,18 @@ void QtSoundModem::MyTimerSlot() DoPSKWindows(); } + if (NeedWaterfallHeaders) + { + NeedWaterfallHeaders = 0; + + if (Waterfall) + { + Waterfall->fill(black); + DrawModemFreqRange(); + DrawFreqTicks(); + } + } + show_grid(); } @@ -1101,8 +1066,7 @@ void QtSoundModem::clickedSlotI(int i) sprintf(valChar, "RX Offset %d",rxOffset); ui.RXOffsetLabel->setText(valChar); - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); + NeedWaterfallHeaders = true; pnt_change[0] = 1; pnt_change[1] = 1; @@ -1276,10 +1240,13 @@ void QtSoundModem::clickedSlot() { bool ok; Font = QFontDialog::getFont(&ok, QFont(Font, this)); + if (ok) { // the user clicked OK and font is set to the font the user selected QApplication::setFont(Font); + sessionTable->horizontalHeader()->setFont(Font); + saveSettings(); } else @@ -1287,7 +1254,7 @@ void QtSoundModem::clickedSlot() // the user canceled the dialog; font is set to the initial // value, in this case Helvetica [Cronyx], 10 - QApplication::setFont(Font); +// QApplication::setFont(Font); } return; @@ -1480,6 +1447,11 @@ void QtSoundModem::doModems() Dlg->IL2PModeC->setCurrentIndex(il2p_mode[2]); Dlg->IL2PModeD->setCurrentIndex(il2p_mode[3]); + Dlg->CRC_A->setChecked(il2p_crc[0]); + Dlg->CRC_B->setChecked(il2p_crc[1]); + Dlg->CRC_C->setChecked(il2p_crc[2]); + Dlg->CRC_D->setChecked(il2p_crc[3]); + Dlg->CWIDCall->setText(CWIDCall); Dlg->CWIDInterval->setText(QString::number(CWIDInterval)); Dlg->CWIDMark->setText(CWIDMark); @@ -1569,6 +1541,12 @@ extern "C" void get_exclude_list(char * line, TStringList * list); void QtSoundModem::modemaccept() { modemSave(); + + AGW_Report_Modem_Change(0); + AGW_Report_Modem_Change(1); + AGW_Report_Modem_Change(2); + AGW_Report_Modem_Change(3); + delete(Dlg); saveSettings(); @@ -1698,6 +1676,11 @@ void QtSoundModem::modemSave() il2p_mode[2] = Dlg->IL2PModeC->currentIndex(); il2p_mode[3] = Dlg->IL2PModeD->currentIndex(); + il2p_crc[0] = Dlg->CRC_A->isChecked(); + il2p_crc[1] = Dlg->CRC_B->isChecked(); + il2p_crc[2] = Dlg->CRC_C->isChecked(); + il2p_crc[3] = Dlg->CRC_D->isChecked(); + recovery[0] = Dlg->recoverBitA->currentIndex(); recovery[1] = Dlg->recoverBitB->currentIndex(); recovery[2] = Dlg->recoverBitC->currentIndex(); @@ -1749,7 +1732,6 @@ void QtSoundModem::modemSave() for (i = 0; i < 4; i++) { initTStringList(&list_digi_callsigns[i]); - get_exclude_list(MyDigiCall[i], &list_digi_callsigns[i]); } @@ -1766,6 +1748,7 @@ void QtSoundModem::modemSave() Q = Dlg->LPFWidthD->text(); lpf[3] = Q.toInt(); */ + } void QtSoundModem::modemreject() @@ -2139,6 +2122,7 @@ void QtSoundModem::doDevices() Dev->DualPTT->setChecked(DualPTT); Dev->multiCore->setChecked(multiCore); + Dev->darkTheme->setChecked(darkTheme); Dev->WaterfallMin->setCurrentIndex(Dev->WaterfallMin->findText(QString::number(WaterfallMin), Qt::MatchFixedString)); Dev->WaterfallMax->setCurrentIndex(Dev->WaterfallMax->findText(QString::number(WaterfallMax), Qt::MatchFixedString)); @@ -2150,6 +2134,33 @@ void QtSoundModem::doDevices() } +void QtSoundModem::mysetstyle() +{ + if (darkTheme) + { + qApp->setStyleSheet( + "QWidget {color: white; background-color: black}" + "QTabBar::tab {color: rgb(127, 127, 127); background-color: black}" + "QTabBar::tab::selected {color: white}" + "QPushButton {border-style: outset; border-width: 2px; border-color: rgb(127, 127, 127)}" + "QPushButton::default {border-style: outset; border-width: 2px; border-color: white}"); + + sessionTable->setStyleSheet("QHeaderView::section { background-color:rgb(40, 40, 40) }"); + + txText = qRgb(255, 127, 127); + rxText = qRgb(173, 216, 230); + } + else + { + qApp->setStyleSheet(""); + + sessionTable->setStyleSheet("QHeaderView::section { background-color:rgb(224, 224, 224) }"); + + txText = qRgb(192, 0, 0); + rxText = qRgb(0, 0, 192); + } +} + void QtSoundModem::deviceaccept() { QVariant Q = Dev->inputDevice->currentText(); @@ -2251,7 +2262,6 @@ void QtSoundModem::deviceaccept() if (UsingLeft && UsingRight) UsingBothChannels = 1; - SCO = Dev->singleChannelOutput->isChecked(); raduga = Dev->colourWaterfall->isChecked(); AGWServ = Dev->AGWEnabled->isChecked(); @@ -2275,6 +2285,8 @@ void QtSoundModem::deviceaccept() DualPTT = Dev->DualPTT->isChecked(); TX_rotate = Dev->txRotation->isChecked(); multiCore = Dev->multiCore->isChecked(); + darkTheme = Dev->darkTheme->isChecked(); + mysetstyle(); if (Dev->CAT->isChecked()) PTTMode = PTTCAT; @@ -2360,8 +2372,7 @@ void QtSoundModem::deviceaccept() ClosePTTPort(); OpenPTTPort(); - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); + NeedWaterfallHeaders = true; delete(Dev); saveSettings(); @@ -2406,33 +2417,55 @@ void QtSoundModem::handleButton(int Port, int Type) doCalib(Port, Type); } + + void QtSoundModem::doRestartWF() { - if (Firstwaterfall) + if (inWaterfall) { - initWaterfall(0, 0); - initWaterfall(0, 1); - } + // in waterfall update thread - if (Secondwaterfall) + wftimer->start(5000); + return; + } + + lockWaterfall = true; + + if (Firstwaterfall | Secondwaterfall) { - initWaterfall(1, 0); - initWaterfall(1, 1); + initWaterfall(0); + initWaterfall(1); } delete(RXLevel); delete(ui.RXLevel); ui.RXLevel = new QLabel(ui.centralWidget); RXLevelCopy = ui.RXLevel; - ui.RXLevel->setGeometry(QRect(780, 17, 150, 12)); -// ui.RXLevel->setFrameShape(QFrame::Box); -// ui.RXLevel->setFrameShadow(QFrame::Sunken); + ui.RXLevel->setGeometry(QRect(780, 14, 150, 11)); + ui.RXLevel->setFrameShape(QFrame::Box); + ui.RXLevel->setFrameShadow(QFrame::Sunken); + + delete(RXLevel2); + delete(ui.RXLevel2); + + ui.RXLevel2 = new QLabel(ui.centralWidget); + RXLevel2Copy = ui.RXLevel2; + + ui.RXLevel2->setGeometry(QRect(780, 23, 150, 11)); + ui.RXLevel2->setFrameShape(QFrame::Box); + ui.RXLevel2->setFrameShadow(QFrame::Sunken); RXLevel = new QImage(150, 10, QImage::Format_RGB32); RXLevel->fill(cyan); -// ui.RXLevel->setPixmap(QPixmap::fromImage(*RXLevel)); + + RXLevel2 = new QImage(150, 10, QImage::Format_RGB32); + RXLevel2->fill(white); ui.RXLevel->setVisible(1); + if (UsingBothChannels) + ui.RXLevel2->setVisible(1); + + lockWaterfall = false; } @@ -2489,7 +2522,7 @@ void QtSoundModem::RefreshSpectrum(unsigned char * Data) // Last 4 bytes are level busy and Tuning lines - Waterfall[0]->fill(Black); + Waterfall->fill(Black); if (Data[206] != LastLevel) { @@ -2510,13 +2543,13 @@ void QtSoundModem::RefreshSpectrum(unsigned char * Data) if (val > 63) val = 63; - Waterfall[0]->setPixel(i, val, Yellow); + Waterfall->setPixel(i, val, Yellow); if (val < 62) - Waterfall[0]->setPixel(i, val + 1, Gold); + Waterfall->setPixel(i, val + 1, Gold); Data++; } - ui.WaterfallA->setPixmap(QPixmap::fromImage(*Waterfall[0])); + ui.Waterfall->setPixmap(QPixmap::fromImage(*Waterfall)); } @@ -2552,7 +2585,7 @@ void QtSoundModem::RefreshWaterfall(int snd_ch, unsigned char * Data) { int j; unsigned char * Line; - int len = Waterfall[0]->bytesPerLine(); + int len = Waterfall->bytesPerLine(); int TopLine = NextWaterfallLine[snd_ch]; // Write line to cyclic buffer then draw starting with the line just written @@ -2565,16 +2598,15 @@ void QtSoundModem::RefreshWaterfall(int snd_ch, unsigned char * Data) for (j = 63; j > 0; j--) { - Line = Waterfall[0]->scanLine(j); + Line = Waterfall->scanLine(j); memcpy(Line, &WaterfallLines[snd_ch][TopLine++][0], len); if (TopLine > 63) TopLine = 0; } - ui.WaterfallA->setPixmap(QPixmap::fromImage(*Waterfall[0])); + ui.Waterfall->setPixmap(QPixmap::fromImage(*Waterfall)); } - void QtSoundModem::sendtoTrace(char * Msg, int tx) { const QTextCursor old_cursor = monWindowCopy->textCursor(); @@ -2587,9 +2619,9 @@ void QtSoundModem::sendtoTrace(char * Msg, int tx) // Insert the text at the position of the cursor (which is the end of the document). if (tx) - monWindowCopy->setTextColor(qRgb(192, 0, 0)); + monWindowCopy->setTextColor(txText); else - monWindowCopy->setTextColor(qRgb(0, 0, 192)); + monWindowCopy->setTextColor(rxText); monWindowCopy->textCursor().insertText(Msg); @@ -2651,180 +2683,157 @@ extern "C" int nonGUIMode; // This draws the Frequency Scale on Waterfall -extern "C" void wf_Scale(int Chan) +extern "C" void DrawFreqTicks() { if (nonGUIMode) return; + // Draw Frequency Markers on waterfall header(s); + int x, i; char Textxx[20]; - QImage * bm = Header[Chan]; + QImage * bm = Waterfall; QPainter qPainter(bm); qPainter.setBrush(Qt::black); qPainter.setPen(Qt::white); - if (Chan == 0) - sprintf(Textxx, "Left"); - else - sprintf(Textxx, "Right"); + int Chan; #ifdef WIN32 - int Top = 3; + int Top = 3; #else - int Top = 4; + int Top = 4; #endif + int Base = 0; - qPainter.drawText(2, Top, 100, 20, 0, Textxx); - - // We drew markers every 100 Hz or 100 / binsize pixels - - - int Markers = ((WaterfallMax - WaterfallMin) / 100) + 5; // Number of Markers to draw - int Freq = WaterfallMin; - float PixelsPerMarker = 100.0 / BinSize; - - - - for (i = 0; i < Markers; i++) - { - x = round(PixelsPerMarker * i); - if (x < 1025) + for (Chan = 0; Chan < 2; Chan++) { - if ((Freq % 500) == 0) - qPainter.drawLine(x, 22, x, 15); + if (Chan == 1 || ((UsingBothChannels == 0) && (UsingRight == 1))) + sprintf(Textxx, "Right"); else - qPainter.drawLine(x, 22, x, 18); + sprintf(Textxx, "Left"); - if ((Freq % 500) == 0) + qPainter.drawText(2, Top, 100, 20, 0, Textxx); + + // We drew markers every 100 Hz or 100 / binsize pixels + + int Markers = ((WaterfallMax - WaterfallMin) / 100) + 5; // Number of Markers to draw + int Freq = WaterfallMin; + float PixelsPerMarker = 100.0 / BinSize; + + for (i = 0; i < Markers; i++) { - sprintf(Textxx, "%d", Freq); + x = round(PixelsPerMarker * i); + if (x < 1025) + { + if ((Freq % 500) == 0) + qPainter.drawLine(x, Base + 22, x, Base + 15); + else + qPainter.drawLine(x, Base + 22, x, Base + 18); - if (x < 924) - qPainter.drawText(x - 12, Top, 100, 20, 0, Textxx); + if ((Freq % 500) == 0) + { + sprintf(Textxx, "%d", Freq); + + if (x < 924) + qPainter.drawText(x - 12, Top, 100, 20, 0, Textxx); + } + } + Freq += 100; } + + if (UsingBothChannels == 0) + break; + + Top += WaterfallTotalPixels; + Base = WaterfallTotalPixels; } - Freq += 100; - } - HeaderCopy[Chan]->setPixmap(QPixmap::fromImage(*bm)); } -// This draws the frequency Markers on the Waterfall +// These draws the frequency Markers on the Waterfall - -void do_pointer(int waterfall) +void DrawModemFreqRange() { if (nonGUIMode) return; + // Draws the modem freq bars on waterfall header(s) + int x1, x2, k, pos1, pos2, pos3; - QImage * bm = Header[waterfall]; + QImage * bm = Waterfall; QPainter qPainter(bm); qPainter.setBrush(Qt::NoBrush); qPainter.setPen(Qt::white); - // bm->fill(black); + int Chan; + int LRtoDisplay = LEFT; + int top = 0; - qPainter.fillRect(0, 23, 1024, 10, Qt::black); - - // We drew markers every 100 Hz or 100 / binsize pixels - - float PixelsPerHz = 1.0 / BinSize; - k = 26; - - // draw all enabled ports on the ports on this soundcard - - // First Modem is always on the first waterfall - // If second is enabled it is on the first unless different - // channel from first - - for (int i = 0; i < 4; i++) + for (Chan = 0; Chan < 2; Chan++) { + if (Chan == 1 || ((UsingBothChannels == 0) && (UsingRight == 1))) + LRtoDisplay = RIGHT; + + // bm->fill(black); + + // qPainter.fillRect(top, 23, 1024, 10, Qt::black); + + // We drew markers every 100 Hz or 100 / binsize pixels + + float PixelsPerHz = 1.0 / BinSize; + k = 26 + top; + + // draw all enabled ports on the ports on this soundcard + + // First Modem is always on the first waterfall + // If second is enabled it is on the first unless different + // channel from first + + for (int i = 0; i < 4; i++) + { + if (soundChannel[i] != LRtoDisplay) + continue; + + pos1 = roundf((((rxOffset + chanOffset[i] + rx_freq[i]) - 0.5*rx_shift[i]) - WaterfallMin) * PixelsPerHz) - 5; + pos2 = roundf((((rxOffset + chanOffset[i] + rx_freq[i]) + 0.5*rx_shift[i]) - WaterfallMin) * PixelsPerHz) - 5; + pos3 = roundf(((rxOffset + chanOffset[i] + rx_freq[i])) - WaterfallMin * PixelsPerHz); + x1 = pos1 + 5; + x2 = pos2 + 5; + + qPainter.setPen(Qt::white); + qPainter.drawLine(x1, k, x2, k); + qPainter.drawLine(x1, k - 3, x1, k + 3); + qPainter.drawLine(x2, k - 3, x2, k + 3); + // qPainter.drawLine(pos3, k - 3, pos3, k + 3); + + if (rxOffset || chanOffset[i]) + { + // Draw TX posn if rxOffset used + + pos3 = roundf((rx_freq[i] - WaterfallMin) * PixelsPerHz); + qPainter.setPen(Qt::magenta); + qPainter.drawLine(pos3, k - 3, pos3, k + 3); + qPainter.drawLine(pos3, k - 3, pos3, k + 3); + qPainter.drawLine(pos3 - 2, k - 3, pos3 + 2, k - 3); + } + + k += 3; + } if (UsingBothChannels == 0) - { - // Only One Waterfall. If first chan is + break; - if ((waterfall == 0 && soundChannel[i] == RIGHT) || (waterfall == 1 && soundChannel[i] == LEFT)) - return; - } - - if (soundChannel[i] == 0) - continue; - - - if (UsingBothChannels == 1) - if ((waterfall == 0 && soundChannel[i] == RIGHT) || (waterfall == 1 && soundChannel[i] == LEFT)) - continue; - - pos1 = roundf((((rxOffset + chanOffset[i] + rx_freq[i]) - 0.5*rx_shift[i]) - WaterfallMin) * PixelsPerHz) - 5; - pos2 = roundf((((rxOffset + chanOffset[i] + rx_freq[i]) + 0.5*rx_shift[i]) - WaterfallMin) * PixelsPerHz) - 5; - pos3 = roundf(((rxOffset + chanOffset[i] + rx_freq[i])) - WaterfallMin * PixelsPerHz); - x1 = pos1 + 5; - x2 = pos2 + 5; - - qPainter.setPen(Qt::white); - qPainter.drawLine(x1, k, x2, k); - qPainter.drawLine(x1, k - 3, x1, k + 3); - qPainter.drawLine(x2, k - 3, x2, k + 3); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - - if (rxOffset || chanOffset[i]) - { - // Draw TX posn if rxOffset used - - pos3 = roundf((rx_freq[i] - WaterfallMin) * PixelsPerHz); - qPainter.setPen(Qt::magenta); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - qPainter.drawLine(pos3 - 2, k - 3, pos3 + 2, k - 3); - } - - k += 3; + LRtoDisplay = RIGHT; + top = WaterfallTotalPixels; } - HeaderCopy[waterfall]->setPixmap(QPixmap::fromImage(*bm)); -} - -void wf_pointer(int snd_ch) -{ - UNUSED(snd_ch); - - do_pointer(0); - do_pointer(1); -// do_pointer(2); -// do_pointer(3); } void doWaterfallThread(void * param); -/* -#ifdef WIN32 - -#define pthread_t uintptr_t - -extern "C" uintptr_t _beginthread(void(__cdecl *start_address)(void *), unsigned stack_size, void *arglist); - -#else - -#include - -extern "C" pthread_t _beginthread(void(*start_address)(void *), unsigned stack_size, void * arglist) -{ - pthread_t thread; - - if (pthread_create(&thread, NULL, (void * (*)(void *))start_address, (void*)arglist) != 0) - perror("New Thread"); - else - pthread_detach(thread); - - return thread; -} - -#endif -*/ extern "C" void doWaterfall(int snd_ch) { if (nonGUIMode) @@ -2833,6 +2842,9 @@ extern "C" void doWaterfall(int snd_ch) if (Closing) return; + if (lockWaterfall) + return; + // if (multiCore) // Run modems in separate threads // _beginthread(doWaterfallThread, 0, xx); // else @@ -2840,6 +2852,20 @@ extern "C" void doWaterfall(int snd_ch) } +extern "C" void displayWaterfall() +{ + // if we are using both channels but only want right need to extract correct half of Image + + if (Waterfall == nullptr) + return; + + if (UsingBothChannels && (Firstwaterfall == 0)) + WaterfallCopy->setAlignment(Qt::AlignBottom | Qt::AlignLeft); + else + WaterfallCopy->setAlignment(Qt::AlignTop | Qt::AlignLeft); + + WaterfallCopy->setPixmap(QPixmap::fromImage(*Waterfall)); +} extern "C" float aFFTAmpl[1024]; extern "C" void SMUpdateBusyDetector(int LR, float * Real, float *Imag); @@ -2847,13 +2873,20 @@ extern "C" void SMUpdateBusyDetector(int LR, float * Real, float *Imag); void doWaterfallThread(void * param) { int snd_ch = (int)(size_t)param; - int WaterfallNumber = snd_ch; + + if (lockWaterfall) + return; + + if (Configuring) + return; + + inWaterfall = true; // don't allow restart waterfall if (snd_ch == 1 && UsingLeft == 0) // Only using right snd_ch = 0; // Samples are in first buffer - QImage * bm = Waterfall[snd_ch]; - + QImage * bm = Waterfall; + int i; single mag; UCHAR * p; @@ -2865,9 +2898,8 @@ void doWaterfallThread(void * param) float RealOut[8192] = { 0 }; float ImagOut[8192]; - if (Configuring) - return; + RefreshLevel(CurrentLevel); // Signal Level hFFTSize = FFTSize / 2; @@ -2909,7 +2941,7 @@ void doWaterfallThread(void * param) } } else - { + { dofft(&fft_buf[snd_ch][0], RealOut, ImagOut); // FourierTransform(1024, &fft_buf[snd_ch][0], RealOut, ImagOut, 0); @@ -2950,71 +2982,70 @@ void doWaterfallThread(void * param) SMUpdateBusyDetector(snd_ch, RealOut, ImagOut); - RefreshLevel(CurrentLevel); // Signal Level + // we always do fft so we can get centre freq and do busy detect. But only upodate waterfall if on display if (bm == 0) + { + inWaterfall = false; return; - - try - { - - p = Line; - lineLen = bm->bytesPerLine(); - - if (raduga == DISP_MONO) - { - for (i = Start; i < End; i++) - { - n = fft_disp[snd_ch][i]; - *(p++) = n; // all colours the same - *(p++) = n; - *(p++) = n; - p++; - } - } - else - { - for (i = Start; i < End; i++) - { - n = fft_disp[snd_ch][i]; - memcpy(p, &RGBWF[n], 4); - p += 4; - } - } - - // Scroll - - int TopLine = NextWaterfallLine[snd_ch]; - - // Write line to cyclic buffer then draw starting with the line just written - - memcpy(&WaterfallLines[snd_ch][NextWaterfallLine[snd_ch]++][0], Line, 4096); - if (NextWaterfallLine[snd_ch] > 79) - NextWaterfallLine[snd_ch] = 0; - - for (int j = 79; j > 0; j--) - { - p = bm->scanLine(j); - memcpy(p, &WaterfallLines[snd_ch][TopLine][0], lineLen); - TopLine++; - if (TopLine > 79) - TopLine = 0; - } - - WaterfallCopy[WaterfallNumber]->setPixmap(QPixmap::fromImage(*bm)); - // WaterfallCopy[snd_ch - 1]->setPixmap(*pm); - // WaterfallCopy[1]->setPixmap(QPixmap::fromImage(*bm)); } - catch (const std::exception& e) // caught by reference to base + if ((Firstwaterfall == 0 && snd_ch == 0) || (Secondwaterfall == 0 && snd_ch == 1)) { - qDebug() << " a standard exception was caught, with message '" - << e.what() << "'\n"; + inWaterfall = false; + return; } + p = Line; + lineLen = 4096; + + if (raduga == DISP_MONO) + { + for (i = Start; i < End; i++) + { + n = fft_disp[snd_ch][i]; + *(p++) = n; // all colours the same + *(p++) = n; + *(p++) = n; + p++; + } + } + else + { + for (i = Start; i < End; i++) + { + n = fft_disp[snd_ch][i]; + memcpy(p, &RGBWF[n], 4); + p += 4; + } + } + + // Scroll + + int TopLine = NextWaterfallLine[snd_ch]; + int TopScanLine = WaterfallHeaderPixels; + + if (snd_ch) + TopScanLine += WaterfallTotalPixels; + + // Write line to cyclic buffer then draw starting with the line just written + + memcpy(&WaterfallLines[snd_ch][NextWaterfallLine[snd_ch]++][0], Line, 4096); + if (NextWaterfallLine[snd_ch] > 79) + NextWaterfallLine[snd_ch] = 0; + + for (int j = 79; j > 0; j--) + { + p = bm->scanLine(j + TopScanLine); + memcpy(p, &WaterfallLines[snd_ch][TopLine][0], lineLen); + TopLine++; + if (TopLine > 79) + TopLine = 0; + } + + inWaterfall = false; } - void QtSoundModem::changeEvent(QEvent* e) { if (e->type() == QEvent::WindowStateChange) diff --git a/QtSoundModem.cpp.bak b/QtSoundModem.cpp.bak deleted file mode 100644 index 3efef28..0000000 --- a/QtSoundModem.cpp.bak +++ /dev/null @@ -1,2866 +0,0 @@ -/* -Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO - -This file is part of QtSoundModem - -QtSoundModem 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 3 of the License, or -(at your option) any later version. - -QtSoundModem 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 QtSoundModem. If not, see http://www.gnu.org/licenses - -*/ - -// UZ7HO Soundmodem Port by John Wiseman G8BPQ - -// UZ7HO Soundmodem Port - -// Not Working 4psk100 FEC - -// Thoughts on Waterfall Display. - -// Original used a 2048 sample FFT giving 5.859375 Hz bins. We plotted 1024 points, giving a 0 to 6000 specrum - -// If we want say 300 to 3300 we need about half the bin size so twice the fft size. But should we also fit required range to window size? - -// Unless we resize the most displayed bit of the screen in around 900 pixels. So each bin should be 3300 / 900 = 3.66667 Hz or a FFT size of around 3273 - -#include "QtSoundModem.h" -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "UZ7HOStuff.h" - - -QImage *Constellation; -QImage *Waterfall[4] = { 0,0,0,0 }; -QImage *Header[4]; -QLabel *DCDLabel[4]; -QLineEdit *chanOffsetLabel[4]; -QImage *DCDLed[4]; - -QImage *RXLevel; - -QLabel *WaterfallCopy[2]; -QLabel *HeaderCopy[2]; - -QTextEdit * monWindowCopy; - -extern workerThread *t; -extern QtSoundModem * w; - -QList Ports = QSerialPortInfo::availablePorts(); - -void saveSettings(); -void getSettings(); -extern "C" void CloseSound(); -extern "C" void GetSoundDevices(); -extern "C" char modes_name[modes_count][20]; -extern "C" int speed[5]; -extern "C" int KISSPort; -extern "C" short rx_freq[5]; - -extern "C" int CaptureCount; -extern "C" int PlaybackCount; - -extern "C" int CaptureIndex; // Card number -extern "C" int PlayBackIndex; - -extern "C" char CaptureNames[16][256]; -extern "C" char PlaybackNames[16][256]; - -extern "C" int SoundMode; -extern "C" int multiCore; - -extern "C" int refreshModems; - -extern "C" int pnt_change[5]; -extern "C" int needRSID[4]; - -extern "C" int needSetOffset[4]; - -extern "C" float MagOut[4096]; -extern "C" float MaxMagOut; -extern "C" int MaxMagIndex; - -extern "C" -{ - int InitSound(BOOL Report); - void soundMain(); - void MainLoop(); - void modulator(UCHAR snd_ch, int buf_size); - void SampleSink(int LR, short Sample); - void doCalib(int Port, int Act); - int Freq_Change(int Chan, int Freq); - void set_speed(int snd_ch, int Modem); - void init_speed(int snd_ch); - void wf_pointer(int snd_ch); - void FourierTransform(int NumSamples, short * RealIn, float * RealOut, float * ImagOut, int InverseTransform); - void dofft(short * in, float * outr, float * outi); - void init_raduga(); - void wf_Scale(int Chan); - void AGW_Report_Modem_Change(int port); - char * strlop(char * buf, char delim); - void sendRSID(int Chan, int dropTX); - void RSIDinitfft(); - void il2p_init(int il2p_debug); -} - -void make_graph_buf(float * buf, short tap, QPainter * bitmap); - -int ModemA = 2; -int ModemB = 2; -int ModemC = 2; -int ModemD = 2; -int FreqA = 1500; -int FreqB = 1500; -int FreqC = 1500; -int FreqD = 1500; -int DCD = 50; - -char CWIDCall[128] = ""; -int CWIDInterval = 0; -int CWIDLeft = 0; -int CWIDRight = 0; -int CWIDType = 1; // on/off - -extern "C" { int RSID_SABM[4]; } -extern "C" { int RSID_UI[4]; } -extern "C" { int RSID_SetModem[4]; } - -int Closing = FALSE; // Set to stop background thread - -QRgb white = qRgb(255, 255, 255); -QRgb black = qRgb(0, 0, 0); - -QRgb green = qRgb(0, 255, 0); -QRgb red = qRgb(255, 0, 0); -QRgb yellow = qRgb(255, 255, 0); -QRgb cyan = qRgb(0, 255, 255); - -// Indexed colour list from ARDOPC - -#define WHITE 0 -#define Tomato 1 -#define Gold 2 -#define Lime 3 -#define Yellow 4 -#define Orange 5 -#define Khaki 6 -#define Cyan 7 -#define DeepSkyBlue 8 -#define RoyalBlue 9 -#define Navy 10 -#define Black 11 -#define Goldenrod 12 -#define Fuchsia 13 - -QRgb vbColours[16] = { qRgb(255, 255, 255), qRgb(255, 99, 71), qRgb(255, 215, 0), qRgb(0, 255, 0), - qRgb(255, 255, 0), qRgb(255, 165, 0), qRgb(240, 240, 140), qRgb(0, 255, 255), - qRgb(0, 191, 255), qRgb(65, 105, 225), qRgb(0, 0, 128), qRgb(0, 0, 0), - qRgb(218, 165, 32), qRgb(255, 0, 255) }; - -unsigned char WaterfallLines[2][80][4096] = { 0 }; -int NextWaterfallLine[2] = { 0 }; - -unsigned int LastLevel = 255; -unsigned int LastBusy = 255; - -extern "C" int UDPClientPort; -extern "C" int UDPServerPort; -extern "C" int TXPort; -extern char UDPHost[64]; - -QTimer *cwidtimer; - -QSystemTrayIcon * trayIcon = nullptr; - -int MintoTray = 1; - -int RSID_WF = 0; // Set to use RSID FFT for Waterfall. - -extern "C" void WriteDebugLog(char * Mess) -{ - qDebug() << Mess; -} - -void QtSoundModem::doupdateDCD(int Chan, int State) -{ - DCDLabel[Chan]->setVisible(State); -} - -extern "C" char * frame_monitor(string * frame, char * code, bool tx_stat); -extern "C" char * ShortDateTime(); - -extern "C" void mon_rsid(int snd_ch, char * RSID) -{ - int Len; - char * Msg = (char *)malloc(1024); // Cant pass local variable via signal/slot - - sprintf(Msg, "%d:%s [%s%c]", snd_ch + 1, RSID, ShortDateTime(), 'R'); - - Len = strlen(Msg); - - if (Msg[Len - 1] != '\r') - { - Msg[Len++] = '\r'; - Msg[Len] = 0; - } - - emit t->sendtoTrace(Msg, 0); -} - -extern "C" void put_frame(int snd_ch, string * frame, char * code, int tx, int excluded) -{ - UNUSED(excluded); - - int Len; - char * Msg = (char *)malloc(1024); // Cant pass local variable via signal/slot - - if (strcmp(code, "NON-AX25") == 0) - sprintf(Msg, "%d: Length, ShortDateTime(), 'R'); - else - sprintf(Msg, "%d:%s", snd_ch + 1, frame_monitor(frame, code, tx)); - - Len = strlen(Msg); - - if (Msg[Len - 1] != '\r') - { - Msg[Len++] = '\r'; - Msg[Len] = 0; - } - - emit t->sendtoTrace(Msg, tx); -} - -extern "C" void updateDCD(int Chan, bool State) -{ - emit t->updateDCD(Chan, State); -} - -bool QtSoundModem::eventFilter(QObject* obj, QEvent *evt) -{ - UNUSED(obj); - - if (evt->type() == QEvent::Resize) - { - return QWidget::event(evt); - } - - if (evt->type() == QEvent::WindowStateChange) - { - if (windowState().testFlag(Qt::WindowMinimized) == true) - w_state = WIN_MINIMIZED; - else - w_state = WIN_MAXIMIZED; - } -// if (evt->type() == QGuiApplication::applicationStateChanged) - this is a sigma; -// { -// qDebug() << "App State changed =" << evt->type() << endl; -// } - - return QWidget::event(evt); -} - -void QtSoundModem::resizeEvent(QResizeEvent* event) -{ - QMainWindow::resizeEvent(event); - - QRect r = geometry(); - - int A, B, C, W; - int modemBoxHeight = 30; - - ui.modeB->setVisible(soundChannel[1]); - ui.centerB->setVisible(soundChannel[1]); - ui.labelB->setVisible(soundChannel[1]); - DCDLabel[1]->setVisible(soundChannel[1]); - ui.RXOffsetB->setVisible(soundChannel[1]); - - ui.modeC->setVisible(soundChannel[2]); - ui.centerC->setVisible(soundChannel[2]); - ui.labelC->setVisible(soundChannel[2]); - DCDLabel[2]->setVisible(soundChannel[2]); - ui.RXOffsetC->setVisible(soundChannel[2]); - - ui.modeD->setVisible(soundChannel[3]); - ui.centerD->setVisible(soundChannel[3]); - ui.labelD->setVisible(soundChannel[3]); - DCDLabel[3]->setVisible(soundChannel[3]); - ui.RXOffsetD->setVisible(soundChannel[3]); - - if (soundChannel[2] || soundChannel[3]) - modemBoxHeight = 60; - - - A = r.height() - 25; // No waterfalls - - if (UsingBothChannels && Secondwaterfall) - { - // Two waterfalls - - ui.WaterfallA->setVisible(1); - ui.HeaderA->setVisible(1); - ui.WaterfallB->setVisible(1); - ui.HeaderB->setVisible(1); - - A = r.height() - 258; // Top of Waterfall A - B = A + 115; // Top of Waterfall B - } - else - { - // One waterfall - - // Could be Left or Right - - if (Firstwaterfall) - { - if (soundChannel[0] == RIGHT) - { - ui.WaterfallA->setVisible(0); - ui.HeaderA->setVisible(0); - ui.WaterfallB->setVisible(1); - ui.HeaderB->setVisible(1); - } - else - { - ui.WaterfallA->setVisible(1); - ui.HeaderA->setVisible(1); - ui.WaterfallB->setVisible(0); - ui.HeaderB->setVisible(0); - } - - A = r.height() - 145; // Top of Waterfall A - } - else - A = r.height() - 25; // Top of Waterfall A - } - - C = A - 150; // Bottom of Monitor, Top of connection list - W = r.width(); - - // Calc Positions of Waterfalls - - ui.monWindow->setGeometry(QRect(0, modemBoxHeight, W, C - (modemBoxHeight + 26))); - sessionTable->setGeometry(QRect(0, C, W, 175)); - - if (UsingBothChannels) - { - ui.HeaderA->setGeometry(QRect(0, A, W, 35)); - ui.WaterfallA->setGeometry(QRect(0, A + 35, W, 80)); - ui.HeaderB->setGeometry(QRect(0, B, W, 35)); - ui.WaterfallB->setGeometry(QRect(0, B + 35, W, 80)); - } - else - { - if (soundChannel[0] == RIGHT) - { - ui.HeaderB->setGeometry(QRect(0, A, W, 35)); - ui.WaterfallB->setGeometry(QRect(0, A + 35, W, 80)); - } - else - { - ui.HeaderA->setGeometry(QRect(0, A, W, 35)); - ui.WaterfallA->setGeometry(QRect(0, A + 35, W, 80)); - } - } -} - -QAction * setupMenuLine(QMenu * Menu, char * Label, QObject * parent, int State) -{ - QAction * Act = new QAction(Label, parent); - Menu->addAction(Act); - - Act->setCheckable(true); - if (State) - Act->setChecked(true); - - parent->connect(Act, SIGNAL(triggered()), parent, SLOT(menuChecked())); - - return Act; -} - -void QtSoundModem::menuChecked() -{ - QAction * Act = static_cast(QObject::sender()); - - int state = Act->isChecked(); - - if (Act == actWaterfall1) - { - int oldstate = Firstwaterfall; - Firstwaterfall = state; - - if (state != oldstate) - initWaterfall(0, state); - - } - else if (Act == actWaterfall2) - { - int oldstate = Secondwaterfall; - Secondwaterfall = state; - - if (state != oldstate) - initWaterfall(1, state); - - } - saveSettings(); -} - -void QtSoundModem::initWaterfall(int chan, int state) -{ - if (state == 1) - { - if (chan == 0) - { - ui.WaterfallA = new QLabel(ui.centralWidget); - WaterfallCopy[0] = ui.WaterfallA; - } - else - { - ui.WaterfallB = new QLabel(ui.centralWidget); - WaterfallCopy[1] = ui.WaterfallB; - } - Waterfall[chan] = new QImage(1024, 80, QImage::Format_RGB32); - Waterfall[chan]->fill(black); - - } - else - { - delete(Waterfall[chan]); - Waterfall[chan] = 0; - } - - QSize Size(800, 602); // Not actually used, but Event constructor needs it - QResizeEvent *event = new QResizeEvent(Size, Size); - QApplication::sendEvent(this, event); -} - -// Local copies - -QLabel *RXOffsetLabel; -QSlider *RXOffset; - -QtSoundModem::QtSoundModem(QWidget *parent) : QMainWindow(parent) -{ - ui.setupUi(this); - - QSettings mysettings("QtSoundModem.ini", QSettings::IniFormat); - - if (MintoTray) - { - char popUp[256]; - sprintf(popUp, "QtSoundModem %d %d", AGWPort, KISSPort); - trayIcon = new QSystemTrayIcon(QIcon(":/QtSoundModem/soundmodem.ico"), this); - trayIcon->setToolTip(popUp); - trayIcon->show(); - - connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(TrayActivated(QSystemTrayIcon::ActivationReason))); - } - - - restoreGeometry(mysettings.value("geometry").toByteArray()); - restoreState(mysettings.value("windowState").toByteArray()); - - sessionTable = new QTableWidget(this); - - sessionTable->verticalHeader()->setVisible(FALSE); - sessionTable->verticalHeader()->setDefaultSectionSize(20); - sessionTable->horizontalHeader()->setDefaultSectionSize(68); - sessionTable->setRowCount(1); - sessionTable->setColumnCount(12); - m_TableHeader << "MyCall" << "DestCall" << "Status" << "Sent pkts" << "Sent Bytes" << "Rcvd pkts" << "Rcvd bytes" << "Rcvd FC" << "FEC corr" << "CPS TX" << "CPS RX" << "Direction"; - - sessionTable->setStyleSheet("QHeaderView::section { background-color:rgb(224, 224, 224) }"); - - sessionTable->setHorizontalHeaderLabels(m_TableHeader); - sessionTable->setColumnWidth(0, 80); - sessionTable->setColumnWidth(1, 80); - sessionTable->setColumnWidth(4, 76); - sessionTable->setColumnWidth(5, 76); - sessionTable->setColumnWidth(6, 80); - sessionTable->setColumnWidth(11, 72); - - for (int i = 0; i < modes_count; i++) - { - ui.modeA->addItem(modes_name[i]); - ui.modeB->addItem(modes_name[i]); - ui.modeC->addItem(modes_name[i]); - ui.modeD->addItem(modes_name[i]); - } - - // Set up Menus - - setupMenu = ui.menuBar->addMenu(tr("Settings")); - - actDevices = new QAction("Setup Devices", this); - setupMenu->addAction(actDevices); - - connect(actDevices, SIGNAL(triggered()), this, SLOT(clickedSlot())); - actDevices->setObjectName("actDevices"); - actModems = new QAction("Setup Modems", this); - actModems->setObjectName("actModems"); - setupMenu->addAction(actModems); - - connect(actModems, SIGNAL(triggered()), this, SLOT(clickedSlot())); - - actMintoTray = setupMenu->addAction("Minimize to Tray", this, SLOT(MinimizetoTray())); - actMintoTray->setCheckable(1); - actMintoTray->setChecked(MintoTray); - - viewMenu = ui.menuBar->addMenu(tr("&View")); - - actWaterfall1 = setupMenuLine(viewMenu, (char *)"First waterfall", this, Firstwaterfall); - actWaterfall2 = setupMenuLine(viewMenu, (char *)"Second Waterfall", this, Secondwaterfall); - - actCalib = ui.menuBar->addAction("&Calibration"); - connect(actCalib, SIGNAL(triggered()), this, SLOT(doCalibrate())); - - actRestartWF = ui.menuBar->addAction("Restart Waterfall"); - connect(actRestartWF, SIGNAL(triggered()), this, SLOT(doRestartWF())); - - actAbout = ui.menuBar->addAction("&About"); - connect(actAbout, SIGNAL(triggered()), this, SLOT(doAbout())); - - // Constellation = new QImage(91, 91, QImage::Format_RGB32); - - Header[0] = new QImage(1024, 35, QImage::Format_RGB32); - Header[1] = new QImage(1024, 35, QImage::Format_RGB32); - RXLevel = new QImage(150, 10, QImage::Format_RGB32); - - DCDLabel[0] = new QLabel(this); - DCDLabel[0]->setObjectName(QString::fromUtf8("DCDLedA")); - DCDLabel[0]->setGeometry(QRect(280, 31, 12, 12)); - DCDLabel[0]->setVisible(TRUE); - - DCDLabel[1] = new QLabel(this); - DCDLabel[1]->setObjectName(QString::fromUtf8("DCDLedB")); - DCDLabel[1]->setGeometry(QRect(575, 31, 12, 12)); - DCDLabel[1]->setVisible(TRUE); - - DCDLabel[2] = new QLabel(this); - DCDLabel[2]->setObjectName(QString::fromUtf8("DCDLedC")); - DCDLabel[2]->setGeometry(QRect(280, 61, 12, 12)); - DCDLabel[2]->setVisible(FALSE); - - DCDLabel[3] = new QLabel(this); - DCDLabel[3]->setObjectName(QString::fromUtf8("DCDLedD")); - DCDLabel[3]->setGeometry(QRect(575, 61, 12, 12)); - DCDLabel[3]->setVisible(FALSE); - - DCDLed[0] = new QImage(12, 12, QImage::Format_RGB32); - DCDLed[1] = new QImage(12, 12, QImage::Format_RGB32); - DCDLed[2] = new QImage(12, 12, QImage::Format_RGB32); - DCDLed[3] = new QImage(12, 12, QImage::Format_RGB32); - - DCDLed[0]->fill(red); - DCDLed[1]->fill(red); - DCDLed[2]->fill(red); - DCDLed[3]->fill(red); - - DCDLabel[0]->setPixmap(QPixmap::fromImage(*DCDLed[0])); - DCDLabel[1]->setPixmap(QPixmap::fromImage(*DCDLed[1])); - DCDLabel[2]->setPixmap(QPixmap::fromImage(*DCDLed[2])); - DCDLabel[3]->setPixmap(QPixmap::fromImage(*DCDLed[3])); - - chanOffsetLabel[0] = ui.RXOffsetA; - chanOffsetLabel[1] = ui.RXOffsetB; - chanOffsetLabel[2] = ui.RXOffsetC; - chanOffsetLabel[3] = ui.RXOffsetD; - - - // Waterfall[0]->setColorCount(16); - // Waterfall[1]->setColorCount(16); - - - // for (i = 0; i < 16; i++) - // { - // Waterfall[0]->setColor(i, vbColours[i]); - // Waterfall[1]->setColor(i, vbColours[i]); - // } - - WaterfallCopy[0] = ui.WaterfallA; - WaterfallCopy[1] = ui.WaterfallB; - - initWaterfall(0, 1); - initWaterfall(1, 1); - - Header[0]->fill(black); - Header[1]->fill(black); - - HeaderCopy[0] = ui.HeaderA; - HeaderCopy[1] = ui.HeaderB; - monWindowCopy = ui.monWindow; - - ui.monWindow->document()->setMaximumBlockCount(10000); - -// connect(ui.monWindow, SIGNAL(selectionChanged()), this, SLOT(onTEselectionChanged())); - - ui.HeaderA->setPixmap(QPixmap::fromImage(*Header[0])); - ui.HeaderB->setPixmap(QPixmap::fromImage(*Header[1])); - - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); - wf_Scale(0); - wf_Scale(1); - - // RefreshLevel(0); - // RXLevel->setPixmap(QPixmap::fromImage(*RXLevel)); - - connect(ui.modeA, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.modeB, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.modeC, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.modeD, SIGNAL(currentIndexChanged(int)), this, SLOT(clickedSlotI(int))); - - ui.modeA->setCurrentIndex(speed[0]); - ui.modeB->setCurrentIndex(speed[1]); - ui.modeC->setCurrentIndex(speed[2]); - ui.modeD->setCurrentIndex(speed[3]); - - ModemA = ui.modeA->currentIndex(); - - ui.centerA->setValue(rx_freq[0]); - ui.centerB->setValue(rx_freq[1]); - ui.centerC->setValue(rx_freq[2]); - ui.centerD->setValue(rx_freq[3]); - - connect(ui.centerA, SIGNAL(valueChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.centerB, SIGNAL(valueChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.centerC, SIGNAL(valueChanged(int)), this, SLOT(clickedSlotI(int))); - connect(ui.centerD, SIGNAL(valueChanged(int)), this, SLOT(clickedSlotI(int))); - - ui.DCDSlider->setValue(dcd_threshold); - - - char valChar[32]; - sprintf(valChar, "RX Offset %d", rxOffset); - ui.RXOffsetLabel->setText(valChar); - ui.RXOffset->setValue(rxOffset); - - RXOffsetLabel = ui.RXOffsetLabel; - RXOffset = ui.RXOffset; - - connect(ui.DCDSlider, SIGNAL(sliderMoved(int)), this, SLOT(clickedSlotI(int))); - connect(ui.RXOffset, SIGNAL(valueChanged(int)), this, SLOT(clickedSlotI(int))); - - - QObject::connect(t, SIGNAL(sendtoTrace(char *, int)), this, SLOT(sendtoTrace(char *, int)), Qt::QueuedConnection); - QObject::connect(t, SIGNAL(updateDCD(int, int)), this, SLOT(doupdateDCD(int, int)), Qt::QueuedConnection); - - connect(ui.RXOffsetA, SIGNAL(returnPressed()), this, SLOT(returnPressed())); - connect(ui.RXOffsetB, SIGNAL(returnPressed()), this, SLOT(returnPressed())); - connect(ui.RXOffsetC, SIGNAL(returnPressed()), this, SLOT(returnPressed())); - connect(ui.RXOffsetD, SIGNAL(returnPressed()), this, SLOT(returnPressed())); - - QTimer *timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(MyTimerSlot())); - timer->start(100); - - - cwidtimer = new QTimer(this); - connect(cwidtimer, SIGNAL(timeout()), this, SLOT(CWIDTimer())); - - if (CWIDInterval) - cwidtimer->start(CWIDInterval * 60000); - - if (RSID_SetModem[0]) - { - RSID_WF = 1; - RSIDinitfft(); - } - il2p_init(1); -} - -void QtSoundModem::MinimizetoTray() -{ - MintoTray = actMintoTray->isChecked(); - saveSettings(); - QMessageBox::about(this, tr("QtSoundModem"), - tr("Program must be restarted to change Minimize mode")); -} - - -void QtSoundModem::TrayActivated(QSystemTrayIcon::ActivationReason reason) -{ - if (reason == 3) - { - showNormal(); - w->setWindowState((w->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - } -} - -extern "C" void sendCWID(char * strID, BOOL blnPlay, int Chan); - -void QtSoundModem::CWIDTimer() -{ - sendCWID(CWIDCall, CWIDType, 0); - calib_mode[0] = 4; -} - -void extSetOffset(int chan) -{ - char valChar[32]; - sprintf(valChar, "%d", chanOffset[chan]); - chanOffsetLabel[chan]->setText(valChar); - - wf_pointer(soundChannel[chan]); - - pnt_change[0] = 1; - pnt_change[1] = 1; - pnt_change[2] = 1; - pnt_change[3] = 1; - - return; -} - -void QtSoundModem::MyTimerSlot() -{ - // 100 mS Timer Event - - for (int i = 0; i < 4; i++) - { - - if (needSetOffset[i]) - { - needSetOffset[i] = 0; - extSetOffset(i); // Update GUI - } - } - - if (refreshModems) - { - refreshModems = 0; - - ui.modeA->setCurrentIndex(speed[0]); - ui.modeB->setCurrentIndex(speed[1]); - ui.modeC->setCurrentIndex(speed[2]); - ui.modeD->setCurrentIndex(speed[3]); - ui.centerA->setValue(rx_freq[0]); - ui.centerB->setValue(rx_freq[1]); - ui.centerC->setValue(rx_freq[2]); - ui.centerD->setValue(rx_freq[3]); - } - - show_grid(); -} - -void QtSoundModem::returnPressed() -{ - char Name[32]; - int Chan; - QString val; - - strcpy(Name, sender()->objectName().toUtf8()); - - Chan = Name[8] - 'A'; - - val = chanOffsetLabel[Chan]->text(); - - chanOffset[Chan] = val.toInt(); - needSetOffset[Chan] = 1; // Update GUI - - -} - - -void QtSoundModem::clickedSlotI(int i) -{ - char Name[32]; - - strcpy(Name, sender()->objectName().toUtf8()); - - if (strcmp(Name, "modeA") == 0) - { - ModemA = ui.modeA->currentIndex(); - set_speed(0, ModemA); - saveSettings(); - AGW_Report_Modem_Change(0); - return; - } - - if (strcmp(Name, "modeB") == 0) - { - ModemB = ui.modeB->currentIndex(); - set_speed(1, ModemB); - saveSettings(); - AGW_Report_Modem_Change(1); - return; - } - - if (strcmp(Name, "modeC") == 0) - { - ModemC = ui.modeC->currentIndex(); - set_speed(2, ModemC); - saveSettings(); - AGW_Report_Modem_Change(2); - return; - } - - if (strcmp(Name, "modeD") == 0) - { - ModemD = ui.modeD->currentIndex(); - set_speed(3, ModemD); - saveSettings(); - AGW_Report_Modem_Change(3); - return; - } - - if (strcmp(Name, "centerA") == 0) - { - if (i > 300) - { - QSettings * settings = new QSettings("QtSoundModem.ini", QSettings::IniFormat); - ui.centerA->setValue(Freq_Change(0, i)); - settings->setValue("Modem/RXFreq1", ui.centerA->value()); - AGW_Report_Modem_Change(0); - - } - return; - } - - if (strcmp(Name, "centerB") == 0) - { - if (i > 300) - { - QSettings * settings = new QSettings("QtSoundModem.ini", QSettings::IniFormat); - ui.centerB->setValue(Freq_Change(1, i)); - settings->setValue("Modem/RXFreq2", ui.centerB->value()); - AGW_Report_Modem_Change(1); - } - return; - } - - if (strcmp(Name, "centerC") == 0) - { - if (i > 300) - { - QSettings * settings = new QSettings("QtSoundModem.ini", QSettings::IniFormat); - ui.centerC->setValue(Freq_Change(2, i)); - settings->setValue("Modem/RXFreq3", ui.centerC->value()); - AGW_Report_Modem_Change(2); - } - return; - } - - if (strcmp(Name, "centerD") == 0) - { - if (i > 300) - { - QSettings * settings = new QSettings("QtSoundModem.ini", QSettings::IniFormat); - ui.centerD->setValue(Freq_Change(3, i)); - settings->setValue("Modem/RXFreq4", ui.centerD->value()); - AGW_Report_Modem_Change(3); - } - return; - } - - if (strcmp(Name, "DCDSlider") == 0) - { - dcd_threshold = i; - saveSettings(); - return; - } - - if (strcmp(Name, "RXOffset") == 0) - { - char valChar[32]; - rxOffset = i; - sprintf(valChar, "RX Offset %d",rxOffset); - ui.RXOffsetLabel->setText(valChar); - - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); - - pnt_change[0] = 1; - pnt_change[1] = 1; - pnt_change[2] = 1; - pnt_change[3] = 1; - - saveSettings(); - return; - } - - - QMessageBox msgBox; - msgBox.setWindowTitle("MessageBox Title"); - msgBox.setText("You Clicked " + ((QPushButton*)sender())->objectName()); - msgBox.exec(); -} - - -void QtSoundModem::clickedSlot() -{ - char Name[32]; - - strcpy(Name, sender()->objectName().toUtf8()); - - if (strcmp(Name, "actDevices") == 0) - { - doDevices(); - return; - } - - if (strcmp(Name, "actModems") == 0) - { - doModems(); - return; - } - - if (strcmp(Name, "showBPF_A") == 0) - { - doFilter(0, 0); - return; - } - - if (strcmp(Name, "showTXBPF_A") == 0) - { - doFilter(0, 1); - return; - } - - if (strcmp(Name, "showLPF_A") == 0) - { - doFilter(0, 2); - return; - } - - - if (strcmp(Name, "showBPF_B") == 0) - { - doFilter(1, 0); - return; - } - - if (strcmp(Name, "showTXBPF_B") == 0) - { - doFilter(1, 1); - return; - } - - if (strcmp(Name, "showLPF_B") == 0) - { - doFilter(1, 2); - return; - } - - if (strcmp(Name, "Low_A") == 0) - { - handleButton(0, 1); - return; - } - - if (strcmp(Name, "High_A") == 0) - { - handleButton(0, 2); - return; - } - - if (strcmp(Name, "Both_A") == 0) - { - handleButton(0, 3); - return; - } - - if (strcmp(Name, "Stop_A") == 0) - { - handleButton(0, 0); - return; - } - - - if (strcmp(Name, "Low_B") == 0) - { - handleButton(1, 1); - return; - } - - if (strcmp(Name, "High_B") == 0) - { - handleButton(1, 2); - return; - } - - if (strcmp(Name, "Both_B") == 0) - { - handleButton(1, 3); - return; - } - - if (strcmp(Name, "Stop_B") == 0) - { - handleButton(1, 0); - return; - } - - if (strcmp(Name, "Low_C") == 0) - { - handleButton(2, 1); - return; - } - - if (strcmp(Name, "High_C") == 0) - { - handleButton(2, 2); - return; - } - - if (strcmp(Name, "Both_C") == 0) - { - handleButton(2, 3); - return; - } - - if (strcmp(Name, "Stop_C") == 0) - { - handleButton(2, 0); - return; - } - - if (strcmp(Name, "Low_D") == 0) - { - handleButton(3, 1); - return; - } - - if (strcmp(Name, "High_D") == 0) - { - handleButton(3, 2); - return; - } - - if (strcmp(Name, "Both_D") == 0) - { - handleButton(3, 3); - return; - } - - if (strcmp(Name, "Stop_D") == 0) - { - handleButton(3, 0); - return; - } - - QMessageBox msgBox; - msgBox.setWindowTitle("MessageBox Title"); - msgBox.setText("You Clicked " + ((QPushButton*)sender())->objectName()); - msgBox.exec(); -} - -Ui_ModemDialog * Dlg; - -QDialog * modemUI; -QDialog * deviceUI; - -void QtSoundModem::doModems() -{ - Dlg = new(Ui_ModemDialog); - - QDialog UI; - char valChar[10]; - - Dlg->setupUi(&UI); - - modemUI = &UI; - deviceUI = 0; - - myResize *resize = new myResize(); - - UI.installEventFilter(resize); - - sprintf(valChar, "%d", bpf[0]); - Dlg->BPFWidthA->setText(valChar); - sprintf(valChar, "%d", bpf[1]); - Dlg->BPFWidthB->setText(valChar); - sprintf(valChar, "%d", bpf[2]); - Dlg->BPFWidthC->setText(valChar); - sprintf(valChar, "%d", bpf[3]); - Dlg->BPFWidthD->setText(valChar); - - sprintf(valChar, "%d", txbpf[0]); - Dlg->TXBPFWidthA->setText(valChar); - sprintf(valChar, "%d", txbpf[1]); - Dlg->TXBPFWidthB->setText(valChar); - sprintf(valChar, "%d", txbpf[2]); - Dlg->TXBPFWidthC->setText(valChar); - sprintf(valChar, "%d", txbpf[3]); - Dlg->TXBPFWidthD->setText(valChar); - - sprintf(valChar, "%d", lpf[0]); - Dlg->LPFWidthA->setText(valChar); - sprintf(valChar, "%d", lpf[1]); - Dlg->LPFWidthB->setText(valChar); - sprintf(valChar, "%d", lpf[2]); - Dlg->LPFWidthC->setText(valChar); - sprintf(valChar, "%d", lpf[4]); - Dlg->LPFWidthD->setText(valChar); - - sprintf(valChar, "%d", BPF_tap[0]); - Dlg->BPFTapsA->setText(valChar); - sprintf(valChar, "%d", BPF_tap[1]); - Dlg->BPFTapsB->setText(valChar); - sprintf(valChar, "%d", BPF_tap[2]); - Dlg->BPFTapsC->setText(valChar); - sprintf(valChar, "%d", BPF_tap[3]); - Dlg->BPFTapsD->setText(valChar); - - sprintf(valChar, "%d", LPF_tap[0]); - Dlg->LPFTapsA->setText(valChar); - sprintf(valChar, "%d", LPF_tap[1]); - Dlg->LPFTapsB->setText(valChar); - sprintf(valChar, "%d", LPF_tap[2]); - Dlg->LPFTapsC->setText(valChar); - sprintf(valChar, "%d", LPF_tap[3]); - Dlg->LPFTapsD->setText(valChar); - - Dlg->preEmphAllA->setChecked(emph_all[0]); - - if (emph_all[0]) - Dlg->preEmphA->setDisabled(TRUE); - else - Dlg->preEmphA->setCurrentIndex(emph_db[0]); - - Dlg->preEmphAllB->setChecked(emph_all[1]); - - if (emph_all[1]) - Dlg->preEmphB->setDisabled(TRUE); - else - Dlg->preEmphB->setCurrentIndex(emph_db[1]); - - Dlg->preEmphAllC->setChecked(emph_all[2]); - - if (emph_all[2]) - Dlg->preEmphC->setDisabled(TRUE); - else - Dlg->preEmphC->setCurrentIndex(emph_db[2]); - - Dlg->preEmphAllD->setChecked(emph_all[3]); - - if (emph_all[3]) - Dlg->preEmphD->setDisabled(TRUE); - else - Dlg->preEmphD->setCurrentIndex(emph_db[3]); - - - Dlg->nonAX25A->setChecked(NonAX25[0]); - Dlg->nonAX25B->setChecked(NonAX25[1]); - Dlg->nonAX25C->setChecked(NonAX25[2]); - Dlg->nonAX25D->setChecked(NonAX25[3]); - - Dlg->KISSOptA->setChecked(KISS_opt[0]); - Dlg->KISSOptB->setChecked(KISS_opt[1]); - Dlg->KISSOptC->setChecked(KISS_opt[2]); - Dlg->KISSOptD->setChecked(KISS_opt[3]); - - sprintf(valChar, "%d", txdelay[0]); - Dlg->TXDelayA->setText(valChar); - sprintf(valChar, "%d", txdelay[1]); - Dlg->TXDelayB->setText(valChar); - sprintf(valChar, "%d", txdelay[2]); - Dlg->TXDelayC->setText(valChar); - sprintf(valChar, "%d", txdelay[3]); - Dlg->TXDelayD->setText(valChar); - - sprintf(valChar, "%d", txtail[0]); - Dlg->TXTailA->setText(valChar); - sprintf(valChar, "%d", txtail[1]); - Dlg->TXTailB->setText(valChar); - sprintf(valChar, "%d", txtail[2]); - Dlg->TXTailC->setText(valChar); - sprintf(valChar, "%d", txtail[3]); - Dlg->TXTailD->setText(valChar); - - Dlg->FrackA->setText(QString::number(frack_time[0])); - Dlg->FrackB->setText(QString::number(frack_time[1])); - Dlg->FrackC->setText(QString::number(frack_time[2])); - Dlg->FrackD->setText(QString::number(frack_time[3])); - - Dlg->RetriesA->setText(QString::number(fracks[0])); - Dlg->RetriesB->setText(QString::number(fracks[1])); - Dlg->RetriesC->setText(QString::number(fracks[2])); - Dlg->RetriesD->setText(QString::number(fracks[3])); - - sprintf(valChar, "%d", RCVR[0]); - Dlg->AddRXA->setText(valChar); - sprintf(valChar, "%d", RCVR[1]); - Dlg->AddRXB->setText(valChar); - sprintf(valChar, "%d", RCVR[2]); - Dlg->AddRXC->setText(valChar); - sprintf(valChar, "%d", RCVR[3]); - Dlg->AddRXD->setText(valChar); - - sprintf(valChar, "%d", rcvr_offset[0]); - Dlg->RXShiftA->setText(valChar); - - sprintf(valChar, "%d", rcvr_offset[1]); - Dlg->RXShiftB->setText(valChar); - - sprintf(valChar, "%d", rcvr_offset[2]); - Dlg->RXShiftC->setText(valChar); - sprintf(valChar, "%d", rcvr_offset[3]); - Dlg->RXShiftD->setText(valChar); - - // speed[1] - // speed[2]; - - Dlg->recoverBitA->setCurrentIndex(recovery[0]); - Dlg->recoverBitB->setCurrentIndex(recovery[1]); - Dlg->recoverBitC->setCurrentIndex(recovery[2]); - Dlg->recoverBitD->setCurrentIndex(recovery[3]); - - Dlg->fx25ModeA->setCurrentIndex(fx25_mode[0]); - Dlg->fx25ModeB->setCurrentIndex(fx25_mode[1]); - Dlg->fx25ModeC->setCurrentIndex(fx25_mode[2]); - Dlg->fx25ModeD->setCurrentIndex(fx25_mode[3]); - - Dlg->IL2PModeA->setCurrentIndex(il2p_mode[0]); - Dlg->IL2PModeB->setCurrentIndex(il2p_mode[1]); - Dlg->IL2PModeC->setCurrentIndex(il2p_mode[2]); - Dlg->IL2PModeD->setCurrentIndex(il2p_mode[3]); - - Dlg->CWIDCall->setText(CWIDCall); - Dlg->CWIDInterval->setText(QString::number(CWIDInterval)); - - if (CWIDType) - Dlg->radioButton_2->setChecked(1); - else - Dlg->CWIDType->setChecked(1); - - Dlg->RSIDSABM_A->setChecked(RSID_SABM[0]); - Dlg->RSIDSABM_B->setChecked(RSID_SABM[1]); - Dlg->RSIDSABM_C->setChecked(RSID_SABM[2]); - Dlg->RSIDSABM_D->setChecked(RSID_SABM[3]); - - Dlg->RSIDUI_A->setChecked(RSID_UI[0]); - Dlg->RSIDUI_B->setChecked(RSID_UI[1]); - Dlg->RSIDUI_C->setChecked(RSID_UI[2]); - Dlg->RSIDUI_D->setChecked(RSID_UI[3]); - - Dlg->DigiCallsA->setText(MyDigiCall[0]); - Dlg->DigiCallsB->setText(MyDigiCall[1]); - Dlg->DigiCallsC->setText(MyDigiCall[2]); - Dlg->DigiCallsD->setText(MyDigiCall[3]); - - Dlg->RSID_1_SETMODEM->setChecked(RSID_SetModem[0]); - Dlg->RSID_2_SETMODEM->setChecked(RSID_SetModem[1]); - Dlg->RSID_3_SETMODEM->setChecked(RSID_SetModem[2]); - Dlg->RSID_4_SETMODEM->setChecked(RSID_SetModem[3]); - - connect(Dlg->showBPF_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showTXBPF_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showLPF_A, SIGNAL(released()), this, SLOT(clickedSlot())); - - connect(Dlg->showBPF_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showTXBPF_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showLPF_B, SIGNAL(released()), this, SLOT(clickedSlot())); - - connect(Dlg->showBPF_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showTXBPF_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showLPF_C, SIGNAL(released()), this, SLOT(clickedSlot())); - - connect(Dlg->showBPF_D, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showTXBPF_D, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Dlg->showLPF_D, SIGNAL(released()), this, SLOT(clickedSlot())); - - connect(Dlg->okButton, SIGNAL(clicked()), this, SLOT(modemaccept())); - connect(Dlg->modemSave, SIGNAL(clicked()), this, SLOT(modemSave())); - connect(Dlg->cancelButton, SIGNAL(clicked()), this, SLOT(modemreject())); - - connect(Dlg->SendRSID_1, SIGNAL(clicked()), this, SLOT(doRSIDA())); - connect(Dlg->SendRSID_2, SIGNAL(clicked()), this, SLOT(doRSIDB())); - connect(Dlg->SendRSID_3, SIGNAL(clicked()), this, SLOT(doRSIDC())); - connect(Dlg->SendRSID_4, SIGNAL(clicked()), this, SLOT(doRSIDD())); - - connect(Dlg->preEmphAllA, SIGNAL(stateChanged(int)), this, SLOT(preEmphAllAChanged(int))); - connect(Dlg->preEmphAllB, SIGNAL(stateChanged(int)), this, SLOT(preEmphAllBChanged(int))); - connect(Dlg->preEmphAllC, SIGNAL(stateChanged(int)), this, SLOT(preEmphAllCChanged(int))); - connect(Dlg->preEmphAllD, SIGNAL(stateChanged(int)), this, SLOT(preEmphAllDChanged(int))); - - UI.exec(); -} - -void QtSoundModem::preEmphAllAChanged(int state) -{ - Dlg->preEmphA->setDisabled(state); -} - -void QtSoundModem::preEmphAllBChanged(int state) -{ - Dlg->preEmphB->setDisabled(state); -} - -void QtSoundModem::preEmphAllCChanged(int state) -{ - Dlg->preEmphC->setDisabled(state); -} - -void QtSoundModem::preEmphAllDChanged(int state) -{ - Dlg->preEmphD->setDisabled(state); -} - -extern "C" void get_exclude_list(char * line, TStringList * list); - -void QtSoundModem::modemaccept() -{ - modemSave(); - delete(Dlg); - saveSettings(); - - modemUI->accept(); - -} - -void QtSoundModem::modemSave() -{ - QVariant Q; - - emph_all[0] = Dlg->preEmphAllA->isChecked(); - emph_db[0] = Dlg->preEmphA->currentIndex(); - - emph_all[1] = Dlg->preEmphAllB->isChecked(); - emph_db[1] = Dlg->preEmphB->currentIndex(); - - emph_all[2] = Dlg->preEmphAllC->isChecked(); - emph_db[2] = Dlg->preEmphC->currentIndex(); - - emph_all[3] = Dlg->preEmphAllD->isChecked(); - emph_db[3] = Dlg->preEmphD->currentIndex(); - - NonAX25[0] = Dlg->nonAX25A->isChecked(); - NonAX25[1] = Dlg->nonAX25B->isChecked(); - NonAX25[2] = Dlg->nonAX25C->isChecked(); - NonAX25[3] = Dlg->nonAX25D->isChecked(); - - KISS_opt[0] = Dlg->KISSOptA->isChecked(); - KISS_opt[1] = Dlg->KISSOptB->isChecked(); - KISS_opt[2] = Dlg->KISSOptC->isChecked(); - KISS_opt[3] = Dlg->KISSOptD->isChecked(); - - if (emph_db[0] < 0 || emph_db[0] > nr_emph) - emph_db[0] = 0; - - if (emph_db[1] < 0 || emph_db[1] > nr_emph) - emph_db[1] = 0; - - if (emph_db[2] < 0 || emph_db[2] > nr_emph) - emph_db[2] = 0; - - if (emph_db[3] < 0 || emph_db[3] > nr_emph) - emph_db[3] = 0; - - Q = Dlg->TXDelayA->text(); - txdelay[0] = Q.toInt(); - - Q = Dlg->TXDelayB->text(); - txdelay[1] = Q.toInt(); - - Q = Dlg->TXDelayC->text(); - txdelay[2] = Q.toInt(); - - Q = Dlg->TXDelayD->text(); - txdelay[3] = Q.toInt(); - - Q = Dlg->TXTailA->text(); - txtail[0] = Q.toInt(); - - Q = Dlg->TXTailB->text(); - txtail[1] = Q.toInt(); - - Q = Dlg->TXTailC->text(); - txtail[2] = Q.toInt(); - - txtail[3] = Dlg->TXTailD->text().toInt(); - - frack_time[0] = Dlg->FrackA->text().toInt(); - frack_time[1] = Dlg->FrackB->text().toInt(); - frack_time[2] = Dlg->FrackC->text().toInt(); - frack_time[3] = Dlg->FrackD->text().toInt(); - - fracks[0] = Dlg->RetriesA->text().toInt(); - fracks[1] = Dlg->RetriesB->text().toInt(); - fracks[2] = Dlg->RetriesC->text().toInt(); - fracks[3] = Dlg->RetriesD->text().toInt(); - - Q = Dlg->AddRXA->text(); - RCVR[0] = Q.toInt(); - - Q = Dlg->AddRXB->text(); - RCVR[1] = Q.toInt(); - - Q = Dlg->AddRXC->text(); - RCVR[2] = Q.toInt(); - - Q = Dlg->AddRXD->text(); - RCVR[3] = Q.toInt(); - - Q = Dlg->RXShiftA->text(); - rcvr_offset[0] = Q.toInt(); - - Q = Dlg->RXShiftB->text(); - rcvr_offset[1] = Q.toInt(); - - Q = Dlg->RXShiftC->text(); - rcvr_offset[2] = Q.toInt(); - - Q = Dlg->RXShiftD->text(); - rcvr_offset[3] = Q.toInt(); - - fx25_mode[0] = Dlg->fx25ModeA->currentIndex(); - fx25_mode[1] = Dlg->fx25ModeB->currentIndex(); - fx25_mode[2] = Dlg->fx25ModeC->currentIndex(); - fx25_mode[3] = Dlg->fx25ModeD->currentIndex(); - - il2p_mode[0] = Dlg->IL2PModeA->currentIndex(); - il2p_mode[1] = Dlg->IL2PModeB->currentIndex(); - il2p_mode[2] = Dlg->IL2PModeC->currentIndex(); - il2p_mode[3] = Dlg->IL2PModeD->currentIndex(); - - recovery[0] = Dlg->recoverBitA->currentIndex(); - recovery[1] = Dlg->recoverBitB->currentIndex(); - recovery[2] = Dlg->recoverBitC->currentIndex(); - recovery[3] = Dlg->recoverBitD->currentIndex(); - - - strcpy(CWIDCall, Dlg->CWIDCall->text().toUtf8().toUpper()); - CWIDInterval = Dlg->CWIDInterval->text().toInt(); - CWIDType = Dlg->radioButton_2->isChecked(); - - if (CWIDInterval) - cwidtimer->start(CWIDInterval * 60000); - else - cwidtimer->stop(); - - - RSID_SABM[0] = Dlg->RSIDSABM_A->isChecked(); - RSID_SABM[1] = Dlg->RSIDSABM_B->isChecked(); - RSID_SABM[2] = Dlg->RSIDSABM_C->isChecked(); - RSID_SABM[3] = Dlg->RSIDSABM_D->isChecked(); - - RSID_UI[0] = Dlg->RSIDUI_A->isChecked(); - RSID_UI[1] = Dlg->RSIDUI_B->isChecked(); - RSID_UI[2] = Dlg->RSIDUI_C->isChecked(); - RSID_UI[3] = Dlg->RSIDUI_D->isChecked(); - - RSID_SetModem[0] = Dlg->RSID_1_SETMODEM->isChecked(); - RSID_SetModem[1] = Dlg->RSID_2_SETMODEM->isChecked(); - RSID_SetModem[2] = Dlg->RSID_3_SETMODEM->isChecked(); - RSID_SetModem[3] = Dlg->RSID_4_SETMODEM->isChecked(); - - Q = Dlg->DigiCallsA->text(); - strcpy(MyDigiCall[0], Q.toString().toUtf8().toUpper()); - - Q = Dlg->DigiCallsB->text(); - strcpy(MyDigiCall[1], Q.toString().toUtf8().toUpper()); - - Q = Dlg->DigiCallsC->text(); - strcpy(MyDigiCall[2], Q.toString().toUtf8().toUpper()); - - Q = Dlg->DigiCallsD->text(); - strcpy(MyDigiCall[3], Q.toString().toUtf8().toUpper()); - - int i; - - for (i = 0; i < 4; i++) - { - initTStringList(&list_digi_callsigns[i]); - - get_exclude_list(MyDigiCall[i], &list_digi_callsigns[i]); - } - -} - -void QtSoundModem::modemreject() -{ - delete(Dlg); - modemUI->reject(); -} - -void QtSoundModem::doRSIDA() -{ - needRSID[0] = 1; -} - -void QtSoundModem::doRSIDB() -{ - needRSID[1] = 1; -} - -void QtSoundModem::doRSIDC() -{ - needRSID[2] = 1; -} - -void QtSoundModem::doRSIDD() -{ - needRSID[3] = 1; -} - - - - -void QtSoundModem::doFilter(int Chan, int Filter) -{ - Ui_Dialog Dev; - QImage * bitmap; - - QDialog UI; - - Dev.setupUi(&UI); - - bitmap = new QImage(642, 312, QImage::Format_RGB32); - - bitmap->fill(qRgb(255, 255, 255)); - - QPainter qPainter(bitmap); - qPainter.setBrush(Qt::NoBrush); - qPainter.setPen(Qt::black); - - if (Filter == 0) - make_graph_buf(DET[0][0].BPF_core[Chan], BPF_tap[Chan], &qPainter); - else if (Filter == 1) - make_graph_buf(tx_BPF_core[Chan], tx_BPF_tap[Chan], &qPainter); - else - make_graph_buf(LPF_core[Chan], LPF_tap[Chan], &qPainter); - - qPainter.end(); - Dev.label->setPixmap(QPixmap::fromImage(*bitmap)); - - UI.exec(); - -} - -Ui_devicesDialog * Dev; - -char NewPTTPort[80]; - -int newSoundMode = 0; -int oldSoundMode = 0; - -void QtSoundModem::SoundModeChanged(bool State) -{ - UNUSED(State); - - // Mustn't change SoundMode until dialog is accepted - - if (Dev->UDP->isChecked()) - newSoundMode = 3; - else if (Dev->PULSE->isChecked()) - newSoundMode = 2; - else - newSoundMode = Dev->OSS->isChecked(); - -} - -void QtSoundModem::DualPTTChanged(bool State) -{ - UNUSED(State); - - // Forse Evaluation of Cat Port setting - - PTTPortChanged(0); -} - -void QtSoundModem::CATChanged(bool State) -{ - UNUSED(State); - PTTPortChanged(0); -} - -void QtSoundModem::PTTPortChanged(int Selected) -{ - UNUSED(Selected); - - QVariant Q = Dev->PTTPort->currentText(); - strcpy(NewPTTPort, Q.toString().toUtf8()); - - Dev->RTSDTR->setVisible(false); - Dev->CAT->setVisible(false); - - Dev->PTTOnLab->setVisible(false); - Dev->PTTOn->setVisible(false); - Dev->PTTOff->setVisible(false); - Dev->PTTOffLab->setVisible(false); - Dev->CATLabel->setVisible(false); - Dev->CATSpeed->setVisible(false); - - Dev->GPIOLab->setVisible(false); - Dev->GPIOLeft->setVisible(false); - Dev->GPIORight->setVisible(false); - Dev->GPIOLab2->setVisible(false); - - Dev->CM108Label->setVisible(false); - Dev->VIDPID->setVisible(false); - - if (strcmp(NewPTTPort, "None") == 0) - { - } - else if (strcmp(NewPTTPort, "GPIO") == 0) - { - Dev->GPIOLab->setVisible(true); - Dev->GPIOLeft->setVisible(true); - if (Dev->DualPTT->isChecked()) - { - Dev->GPIORight->setVisible(true); - Dev->GPIOLab2->setVisible(true); - } - } - - else if (strcmp(NewPTTPort, "CM108") == 0) - { - Dev->CM108Label->setVisible(true); -//#ifdef __ARM_ARCHX - Dev->CM108Label->setText("CM108 Device"); -//#else -// Dev->CM108Label->setText("CM108 VID/PID"); -//#endif - Dev->VIDPID->setText(CM108Addr); - Dev->VIDPID->setVisible(true); - } - else if (strcmp(NewPTTPort, "HAMLIB") == 0) - { - Dev->CM108Label->setVisible(true); - Dev->CM108Label->setText("rigctrld Port"); - Dev->VIDPID->setText(QString::number(HamLibPort)); - Dev->VIDPID->setVisible(true); - Dev->PTTOnLab->setText("rigctrld Host"); - Dev->PTTOnLab->setVisible(true); - Dev->PTTOn->setText(HamLibHost); - Dev->PTTOn->setVisible(true); - } - else - { - Dev->RTSDTR->setVisible(true); - Dev->CAT->setVisible(true); - - if (Dev->CAT->isChecked()) - { - Dev->PTTOnLab->setVisible(true); - Dev->PTTOnLab->setText("PTT On String"); - Dev->PTTOn->setText(PTTOnString); - Dev->PTTOn->setVisible(true); - Dev->PTTOff->setVisible(true); - Dev->PTTOff->setText(PTTOffString); - Dev->PTTOffLab->setVisible(true); - Dev->CATLabel->setVisible(true); - Dev->CATSpeed->setVisible(true); - } - } -} - -bool myResize::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::Resize) - { - QResizeEvent *resizeEvent = static_cast(event); - QSize size = resizeEvent->size(); - int h = size.height(); - int w = size.width(); - - if (obj == deviceUI) - Dev->scrollArea->setGeometry(QRect(5, 5, w - 10, h - 10)); - else - Dlg->scrollArea->setGeometry(QRect(5, 5, w - 10, h - 10)); - - return true; - } - return QObject::eventFilter(obj, event); -} - -void QtSoundModem::doDevices() -{ - char valChar[10]; - - Dev = new(Ui_devicesDialog); - - QDialog UI; - - int i; - - Dev->setupUi(&UI); - - deviceUI = &UI; - modemUI = 0; - - myResize *resize = new myResize(); - - UI.installEventFilter(resize); - - newSoundMode = SoundMode; - oldSoundMode = SoundMode; - -#ifdef WIN32 - Dev->ALSA->setText("WaveOut"); - Dev->OSS->setVisible(0); - Dev->PULSE->setVisible(0); -#endif - - if (SoundMode == 0) - Dev->ALSA->setChecked(1); - else if (SoundMode == 1) - Dev->OSS->setChecked(1); - else if (SoundMode == 2) - Dev->PULSE->setChecked(1); - else if (SoundMode == 2) - Dev->UDP->setChecked(1); - - connect(Dev->ALSA, SIGNAL(toggled(bool)), this, SLOT(SoundModeChanged(bool))); - connect(Dev->OSS, SIGNAL(toggled(bool)), this, SLOT(SoundModeChanged(bool))); - connect(Dev->PULSE, SIGNAL(toggled(bool)), this, SLOT(SoundModeChanged(bool))); - connect(Dev->UDP, SIGNAL(toggled(bool)), this, SLOT(SoundModeChanged(bool))); - - for (i = 0; i < PlaybackCount; i++) - Dev->outputDevice->addItem(&PlaybackNames[i][0]); - - i = Dev->outputDevice->findText(PlaybackDevice, Qt::MatchContains); - - - if (i == -1) - { - // Add device to list - - Dev->outputDevice->addItem(PlaybackDevice); - i = Dev->outputDevice->findText(PlaybackDevice, Qt::MatchContains); - } - - Dev->outputDevice->setCurrentIndex(i); - - for (i = 0; i < CaptureCount; i++) - Dev->inputDevice->addItem(&CaptureNames[i][0]); - - i = Dev->inputDevice->findText(CaptureDevice, Qt::MatchContains); - - if (i == -1) - { - // Add device to list - - Dev->inputDevice->addItem(CaptureDevice); - i = Dev->inputDevice->findText(CaptureDevice, Qt::MatchContains); - } - Dev->inputDevice->setCurrentIndex(i); - - Dev->Modem_1_Chan->setCurrentIndex(soundChannel[0]); - Dev->Modem_2_Chan->setCurrentIndex(soundChannel[1]); - Dev->Modem_3_Chan->setCurrentIndex(soundChannel[2]); - Dev->Modem_4_Chan->setCurrentIndex(soundChannel[3]); - - // Disable "None" option in first modem - - QStandardItemModel *model = dynamic_cast(Dev->Modem_1_Chan->model()); - QStandardItem * item = model->item(0, 0); - item->setEnabled(false); - - Dev->singleChannelOutput->setChecked(SCO); - Dev->colourWaterfall->setChecked(raduga); - - sprintf(valChar, "%d", KISSPort); - Dev->KISSPort->setText(valChar); - Dev->KISSEnabled->setChecked(KISSServ); - - sprintf(valChar, "%d", AGWPort); - Dev->AGWPort->setText(valChar); - Dev->AGWEnabled->setChecked(AGWServ); - - Dev->PTTOn->setText(PTTOnString); - Dev->PTTOff->setText(PTTOffString); - - sprintf(valChar, "%d", PTTBAUD); - Dev->CATSpeed->setText(valChar); - - sprintf(valChar, "%d", UDPClientPort); - Dev->UDPPort->setText(valChar); - Dev->UDPTXHost->setText(UDPHost); - - if (UDPServerPort != TXPort) - sprintf(valChar, "%d/%d", UDPServerPort, TXPort); - else - sprintf(valChar, "%d", UDPServerPort); - - Dev->UDPTXPort->setText(valChar); - - Dev->UDPEnabled->setChecked(UDPServ); - - sprintf(valChar, "%d", pttGPIOPin); - Dev->GPIOLeft->setText(valChar); - sprintf(valChar, "%d", pttGPIOPinR); - Dev->GPIORight->setText(valChar); - - Dev->VIDPID->setText(CM108Addr); - - QStringList items; - - connect(Dev->CAT, SIGNAL(toggled(bool)), this, SLOT(CATChanged(bool))); - connect(Dev->DualPTT, SIGNAL(toggled(bool)), this, SLOT(DualPTTChanged(bool))); - connect(Dev->PTTPort, SIGNAL(currentIndexChanged(int)), this, SLOT(PTTPortChanged(int))); - - - - if (PTTMode == PTTCAT) - Dev->CAT->setChecked(true); - else - Dev->RTSDTR->setChecked(true); - - for (const QSerialPortInfo &info : Ports) - { - items.append(info.portName()); - } - - items.sort(); - - Dev->PTTPort->addItem("None"); - Dev->PTTPort->addItem("CM108"); - - //#ifdef __ARM_ARCH - - Dev->PTTPort->addItem("GPIO"); - - //#endif - - Dev->PTTPort->addItem("HAMLIB"); - - for (const QString &info : items) - { - Dev->PTTPort->addItem(info); - } - - Dev->PTTPort->setCurrentIndex(Dev->PTTPort->findText(PTTPort, Qt::MatchFixedString)); - - PTTPortChanged(0); // Force reevaluation - - Dev->txRotation->setChecked(TX_rotate); - Dev->DualPTT->setChecked(DualPTT); - - Dev->multiCore->setChecked(multiCore); - - QObject::connect(Dev->okButton, SIGNAL(clicked()), this, SLOT(deviceaccept())); - QObject::connect(Dev->cancelButton, SIGNAL(clicked()), this, SLOT(devicereject())); - - UI.exec(); - -} - -void QtSoundModem::deviceaccept() -{ - QVariant Q = Dev->inputDevice->currentText(); - int cardChanged = 0; - char portString[32]; - - if (Dev->UDP->isChecked()) - { - // cant have server and slave - - if (Dev->UDPEnabled->isChecked()) - { - QMessageBox::about(this, tr("QtSoundModem"), - tr("Can't have UDP sound source and UDP server at same time")); - return; - } - } - - if (oldSoundMode != newSoundMode) - { - QMessageBox msgBox; - - msgBox.setText("QtSoundModem must restart to change Sound Mode.\n" - "Program will close if you hit Ok\n" - "You will need to reselect audio devices after restarting"); - - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - - int i = msgBox.exec(); - - if (i == QMessageBox::Ok) - { - SoundMode = newSoundMode; - - saveSettings(); - - Closing = 1; - return; - } - - if (oldSoundMode == 0) - Dev->ALSA->setChecked(1); - else if (oldSoundMode == 1) - Dev->OSS->setChecked(1); - else if (oldSoundMode == 2) - Dev->PULSE->setChecked(1); - else if (oldSoundMode == 3) - Dev->UDP->setChecked(1); - - QMessageBox::about(this, tr("Info"), - tr("

Changes not saved

")); - - return; - - } - - if (strcmp(CaptureDevice, Q.toString().toUtf8()) != 0) - { - strcpy(CaptureDevice, Q.toString().toUtf8()); - cardChanged = 1; - } - - CaptureIndex = Dev->inputDevice->currentIndex(); - - Q = Dev->outputDevice->currentText(); - - if (strcmp(PlaybackDevice, Q.toString().toUtf8()) != 0) - { - strcpy(PlaybackDevice, Q.toString().toUtf8()); - cardChanged = 1; - } - - PlayBackIndex = Dev->outputDevice->currentIndex(); - - soundChannel[0] = Dev->Modem_1_Chan->currentIndex(); - soundChannel[1] = Dev->Modem_2_Chan->currentIndex(); - soundChannel[2] = Dev->Modem_3_Chan->currentIndex(); - soundChannel[3] = Dev->Modem_4_Chan->currentIndex(); - - UsingLeft = 0; - UsingRight = 0; - UsingBothChannels = 0; - - for (int i = 0; i < 4; i++) - { - if (soundChannel[i] == LEFT) - { - UsingLeft = 1; - modemtoSoundLR[i] = 0; - } - else if (soundChannel[i] == RIGHT) - { - UsingRight = 1; - modemtoSoundLR[i] = 1; - } - } - - if (UsingLeft && UsingRight) - UsingBothChannels = 1; - - - SCO = Dev->singleChannelOutput->isChecked(); - raduga = Dev->colourWaterfall->isChecked(); - AGWServ = Dev->AGWEnabled->isChecked(); - KISSServ = Dev->KISSEnabled->isChecked(); - - Q = Dev->KISSPort->text(); - KISSPort = Q.toInt(); - - Q = Dev->AGWPort->text(); - AGWPort = Q.toInt(); - - Q = Dev->PTTPort->currentText(); - strcpy(PTTPort, Q.toString().toUtf8()); - - DualPTT = Dev->DualPTT->isChecked(); - TX_rotate = Dev->txRotation->isChecked(); - multiCore = Dev->multiCore->isChecked(); - - if (Dev->CAT->isChecked()) - PTTMode = PTTCAT; - else - PTTMode = PTTRTS; - - Q = Dev->PTTOn->text(); - strcpy(PTTOnString, Q.toString().toUtf8()); - Q = Dev->PTTOff->text(); - strcpy(PTTOffString, Q.toString().toUtf8()); - - Q = Dev->CATSpeed->text(); - PTTBAUD = Q.toInt(); - - Q = Dev->UDPPort->text(); - UDPClientPort = Q.toInt(); - - - Q = Dev->UDPTXPort->text(); - strcpy(portString, Q.toString().toUtf8()); - UDPServerPort = atoi(portString); - - if (strchr(portString, '/')) - { - char * ptr = strlop(portString, '/'); - TXPort = atoi(ptr); - } - else - TXPort = UDPServerPort; - - Q = Dev->UDPTXHost->text(); - strcpy(UDPHost, Q.toString().toUtf8()); - - UDPServ = Dev->UDPEnabled->isChecked(); - - Q = Dev->GPIOLeft->text(); - pttGPIOPin = Q.toInt(); - - Q = Dev->GPIORight->text(); - pttGPIOPinR = Q.toInt(); - - Q = Dev->VIDPID->text(); - - if (strcmp(PTTPort, "CM108") == 0) - strcpy(CM108Addr, Q.toString().toUtf8()); - else if (strcmp(PTTPort, "HAMLIB") == 0) - { - HamLibPort = Q.toInt(); - Q = Dev->PTTOn->text(); - strcpy(HamLibHost, Q.toString().toUtf8()); - } - - ClosePTTPort(); - OpenPTTPort(); - - wf_pointer(soundChannel[0]); - wf_pointer(soundChannel[1]); - - delete(Dev); - saveSettings(); - deviceUI->accept(); - - if (cardChanged) - { - InitSound(1); - } - - // Reset title and tooltip in case ports changed - - char Title[128]; - sprintf(Title, "QtSoundModem Version %s Ports %d/%d", VersionString, AGWPort, KISSPort); - w->setWindowTitle(Title); - - sprintf(Title, "QtSoundModem %d %d", AGWPort, KISSPort); - if (trayIcon) - trayIcon->setToolTip(Title); - - QSize newSize(this->size()); - QSize oldSize(this->size()); - - QResizeEvent *myResizeEvent = new QResizeEvent(newSize, oldSize); - - QCoreApplication::postEvent(this, myResizeEvent); -} - -void QtSoundModem::devicereject() -{ - delete(Dev); - deviceUI->reject(); -} - -void QtSoundModem::handleButton(int Port, int Type) -{ - // interlock calib with CWID - - if (calib_mode[0] == 4) // CWID - return; - - doCalib(Port, Type); -} - -void QtSoundModem::doRestartWF() -{ - if (Firstwaterfall) - { - initWaterfall(0, 0); - initWaterfall(0, 1); - } - - if (Secondwaterfall) - { - initWaterfall(1, 0); - initWaterfall(1, 1); - } -} - - -void QtSoundModem::doAbout() -{ - QMessageBox::about(this, tr("About"), - tr("G8BPQ's port of UZ7HO's Soundmodem\n\nCopyright (C) 2019-2020 Andrei Kopanchuk UZ7HO")); -} - -void QtSoundModem::doCalibrate() -{ - Ui_calDialog Calibrate; - { - QDialog UI; - Calibrate.setupUi(&UI); - - connect(Calibrate.Low_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.High_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Both_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Stop_A, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Low_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.High_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Both_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Stop_B, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Low_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.High_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Both_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Stop_C, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Low_D, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.High_D, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Both_D, SIGNAL(released()), this, SLOT(clickedSlot())); - connect(Calibrate.Stop_D, SIGNAL(released()), this, SLOT(clickedSlot())); - - /* - - connect(Calibrate.Low_A, &QPushButton::released, this, [=] { handleButton(0, 1); }); - connect(Calibrate.High_A, &QPushButton::released, this, [=] { handleButton(0, 2); }); - connect(Calibrate.Both_A, &QPushButton::released, this, [=] { handleButton(0, 3); }); - connect(Calibrate.Stop_A, &QPushButton::released, this, [=] { handleButton(0, 0); }); - connect(Calibrate.Low_B, &QPushButton::released, this, [=] { handleButton(1, 1); }); - connect(Calibrate.High_B, &QPushButton::released, this, [=] { handleButton(1, 2); }); - connect(Calibrate.Both_B, &QPushButton::released, this, [=] { handleButton(1, 3); }); - connect(Calibrate.Stop_B, &QPushButton::released, this, [=] { handleButton(1, 0); }); - -// connect(Calibrate.High_A, SIGNAL(released()), this, SLOT(handleButton(1, 2))); -*/ - UI.exec(); - } -} - -void QtSoundModem::RefreshSpectrum(unsigned char * Data) -{ - int i; - - // Last 4 bytes are level busy and Tuning lines - - Waterfall[0]->fill(Black); - - if (Data[206] != LastLevel) - { - LastLevel = Data[206]; -// RefreshLevel(LastLevel); - } - - if (Data[207] != LastBusy) - { - LastBusy = Data[207]; -// Busy->setVisible(LastBusy); - } - - for (i = 0; i < 205; i++) - { - int val = Data[0]; - - if (val > 63) - val = 63; - - Waterfall[0]->setPixel(i, val, Yellow); - if (val < 62) - Waterfall[0]->setPixel(i, val + 1, Gold); - Data++; - } - - ui.WaterfallA->setPixmap(QPixmap::fromImage(*Waterfall[0])); - -} - -void QtSoundModem::RefreshWaterfall(int snd_ch, unsigned char * Data) -{ - int j; - unsigned char * Line; - int len = Waterfall[0]->bytesPerLine(); - int TopLine = NextWaterfallLine[snd_ch]; - - // Write line to cyclic buffer then draw starting with the line just written - - // Length is 208 bytes, including Level and Busy flags - - memcpy(&WaterfallLines[snd_ch][NextWaterfallLine[snd_ch]++][0], Data, 206); - if (NextWaterfallLine[snd_ch] > 63) - NextWaterfallLine[snd_ch] = 0; - - for (j = 63; j > 0; j--) - { - Line = Waterfall[0]->scanLine(j); - memcpy(Line, &WaterfallLines[snd_ch][TopLine++][0], len); - if (TopLine > 63) - TopLine = 0; - } - - ui.WaterfallA->setPixmap(QPixmap::fromImage(*Waterfall[0])); -} - - -void QtSoundModem::sendtoTrace(char * Msg, int tx) -{ - const QTextCursor old_cursor = monWindowCopy->textCursor(); - const int old_scrollbar_value = monWindowCopy->verticalScrollBar()->value(); - const bool is_scrolled_down = old_scrollbar_value == monWindowCopy->verticalScrollBar()->maximum(); - - // Move the cursor to the end of the document. - monWindowCopy->moveCursor(QTextCursor::End); - - // Insert the text at the position of the cursor (which is the end of the document). - - if (tx) - monWindowCopy->setTextColor(qRgb(192, 0, 0)); - else - monWindowCopy->setTextColor(qRgb(0, 0, 192)); - - monWindowCopy->textCursor().insertText(Msg); - - if (old_cursor.hasSelection() || !is_scrolled_down) - { - // The user has selected text or scrolled away from the bottom: maintain position. - monWindowCopy->setTextCursor(old_cursor); - monWindowCopy->verticalScrollBar()->setValue(old_scrollbar_value); - } - else - { - // The user hasn't selected any text and the scrollbar is at the bottom: scroll to the bottom. - monWindowCopy->moveCursor(QTextCursor::End); - monWindowCopy->verticalScrollBar()->setValue(monWindowCopy->verticalScrollBar()->maximum()); - } - - free(Msg); -} - - -// I think this does the waterfall - -typedef struct TRGBQ_t -{ - Byte b, g, r, re; - -} TRGBWQ; - -typedef struct tagRECT -{ - int left; - int top; - int right; - int bottom; -} RECT; - -unsigned int RGBWF[256] ; - - -extern "C" void init_raduga() -{ - Byte offset[6] = {0, 51, 102, 153, 204}; - Byte i, n; - - for (n = 0; n < 52; n++) - { - i = n * 5; - - RGBWF[n + offset[0]] = qRgb(0, 0, i); - RGBWF[n + offset[1]] = qRgb(0, i, 255); - RGBWF[n + offset[2]] = qRgb(0, 255, 255 - i); - RGBWF[n + offset[3]] = qRgb(1, 255, 0); - RGBWF[n + offset[4]] = qRgb(255, 255 - 1, 0); - } -} - -extern "C" int nonGUIMode; - - -// This draws the Frequency Scale on Waterfall - -extern "C" void wf_Scale(int Chan) -{ - if (nonGUIMode) - return; - - float k; - int maxfreq, x, i; - char Textxx[20]; - QImage * bm = Header[Chan]; - - QPainter qPainter(bm); - qPainter.setBrush(Qt::black); - qPainter.setPen(Qt::white); - - maxfreq = roundf(RX_Samplerate*0.005); - k = 100 * fft_size / RX_Samplerate; - - if (Chan == 0) - sprintf(Textxx, "Left"); - else - sprintf(Textxx, "Right"); - - qPainter.drawText(2, 1, - 100, 20, 0, Textxx); - - for (i = 0; i < maxfreq; i++) - { - x = round(k*i); - if (x < 1025) - { - if ((i % 5) == 0) - qPainter.drawLine(x, 20, x, 13); - else - qPainter.drawLine(x, 20, x, 16); - - if ((i % 10) == 0) - { - sprintf(Textxx, "%d", i * 100); - - qPainter.drawText(x - 12, 1, - 100, 20, 0, Textxx); - } - } - } - HeaderCopy[Chan]->setPixmap(QPixmap::fromImage(*bm)); - -} - -// This draws the frequency Markers on the Waterfall - - -void do_pointer(int waterfall) -{ - if (nonGUIMode) - return; - - float x; - - int x1, x2, k, pos1, pos2, pos3; - QImage * bm = Header[waterfall]; - - QPainter qPainter(bm); - qPainter.setBrush(Qt::NoBrush); - qPainter.setPen(Qt::white); - - // bm->fill(black); - - qPainter.fillRect(0, 26, 1024, 9, Qt::black); - - k = 29; - x = fft_size / RX_Samplerate; - - // draw all enabled ports on the ports on this soundcard - - // First Modem is always on the first waterfall - // If second is enabled it is on the first unless different - // channel from first - - for (int i = 0; i < 4; i++) - { - if (UsingBothChannels == 0) - { - // Only One Waterfall. If first chan is - - if ((waterfall == 0 && soundChannel[i] == RIGHT) || (waterfall == 1 && soundChannel[i] == LEFT)) - return; - } - - if (soundChannel[i] == 0) - continue; - - - if (UsingBothChannels == 1) - if ((waterfall == 0 && soundChannel[i] == RIGHT) || (waterfall == 1 && soundChannel[i] == LEFT)) - continue; - - pos1 = roundf(((rxOffset + chanOffset[i] + rx_freq[i]) - 0.5*rx_shift[i])*x) - 5; - pos2 = roundf(((rxOffset + chanOffset[i] + rx_freq[i]) + 0.5*rx_shift[i])*x) - 5; - pos3 = roundf((rxOffset + chanOffset[i] + rx_freq[i]) * x); - x1 = pos1 + 5; - x2 = pos2 + 5; - - qPainter.setPen(Qt::white); - qPainter.drawLine(x1, k, x2, k); - qPainter.drawLine(x1, k - 3, x1, k + 3); - qPainter.drawLine(x2, k - 3, x2, k + 3); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - - if (rxOffset || chanOffset[i]) - { - // Draw TX posn if rxOffset used - - pos3 = roundf(rx_freq[i] * x); - qPainter.setPen(Qt::magenta); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - qPainter.drawLine(pos3, k - 3, pos3, k + 3); - qPainter.drawLine(pos3 - 2, k - 3, pos3 + 2, k - 3); - - } - } - HeaderCopy[waterfall]->setPixmap(QPixmap::fromImage(*bm)); -} - -void wf_pointer(int snd_ch) -{ - UNUSED(snd_ch); - - do_pointer(0); - do_pointer(1); -// do_pointer(2); -// do_pointer(3); -} - - -void doWaterfallThread(void * param); - -/* -#ifdef WIN32 - -#define pthread_t uintptr_t - -extern "C" uintptr_t _beginthread(void(__cdecl *start_address)(void *), unsigned stack_size, void *arglist); - -#else - -#include - -extern "C" pthread_t _beginthread(void(*start_address)(void *), unsigned stack_size, void * arglist) -{ - pthread_t thread; - - if (pthread_create(&thread, NULL, (void * (*)(void *))start_address, (void*)arglist) != 0) - perror("New Thread"); - else - pthread_detach(thread); - - return thread; -} - -#endif -*/ -extern "C" void doWaterfall(int snd_ch) -{ - if (nonGUIMode) - return; - - if (Closing) - return; - -// if (multiCore) // Run modems in separate threads -// _beginthread(doWaterfallThread, 0, xx); -// else - doWaterfallThread((void *)(size_t)snd_ch); - -} - - -extern "C" float aFFTAmpl[1024]; - -void doWaterfallThread(void * param) -{ - int snd_ch = (int)(size_t)param; - - QImage * bm = Waterfall[snd_ch]; - - word i, wid; - single mag; - UCHAR * p; - UCHAR Line[4096]; - - int lineLen; - word hfft_size; - Byte n; - float RealOut[4096] = { 0 }; - float ImagOut[4096]; - - QRegion exposed; - - hfft_size = fft_size / 2; - - // I think an FFT should produce n/2 bins, each of Samp/n Hz - // Looks like my code only works with n a power of 2 - - // So can use 1024 or 4096. 1024 gives 512 bins of 11.71875 and a 512 pixel - // display (is this enough?) - - // This does 2048 - - if (0) //RSID_WF - { - // Use the Magnitudes in float aFFTAmpl[RSID_FFT_SIZE]; - - for (i = 0; i < hfft_size; i++) - { - mag = aFFTAmpl[i]; - - mag *= 0.00000042f; - - if (mag < 0.00001f) - mag = 0.00001f; - - if (mag > 1.0f) - mag = 1.0f; - - mag = 22 * log2f(mag) + 255; - - if (mag < 0) - mag = 0; - - fft_disp[snd_ch][i] = round(mag); - } - } - else - { - dofft(&fft_buf[snd_ch][0], RealOut, ImagOut); - - // FourierTransform(1024, &fft_buf[snd_ch][0], RealOut, ImagOut, 0); - - for (i = 0; i < hfft_size; i++) - { - //mag: = ComplexMag(fft_d[i])*0.00000042; - - // mag = sqrtf(powf(RealOut[i], 2) + powf(ImagOut[i], 2)) * 0.00000042f; - - mag = powf(RealOut[i], 2); - mag += powf(ImagOut[i], 2); - mag = sqrtf(mag); - mag *= 0.00000042f; - - - if (mag > MaxMagOut) - { - MaxMagOut = mag; - MaxMagIndex = i; - } - - if (mag < 0.00001f) - mag = 0.00001f; - - if (mag > 1.0f) - mag = 1.0f; - - mag = 22 * log2f(mag) + 255; - - if (mag < 0) - mag = 0; - - MagOut[i] = mag; - fft_disp[snd_ch][i] = round(mag); - } - } - - - - /* - for (i = 0; i < hfft_size; i++) - fft[i] = (powf(RealOut[i], 2) + powf(ImagOut[i], 2)); - - for (i = 0; i < hfft_size; i++) - { - if (fft[i] > max) - { - max = fft[i]; - imax = i; - } - } - - if (max > 0) - { - for (i = 0; i < hfft_size; i++) - fft[i] = fft[i] / max; - } - - - for (i = 0; i < hfft_size; i++) - { - mag = fft[i]; - - if (mag < 0.00001f) - mag = 0.00001f; - - if (mag > 1.0f) - mag = 1.0f; - - mag = 22 * log2f(mag) + 255; - - if (mag < 0) - mag = 0; - - fft_disp[snd_ch][i] = round(mag); - } - - */ - - // bm[snd_ch].Canvas.CopyRect(d, bm[snd_ch].canvas, s) - - //pm->scroll(0, 1, 0, 0, 1024, 80, &exposed); - - // Each bin is 12000 /2048 = 5.859375 - // I think we plot at 6 Hz per pixel. - - wid = bm->width(); - if (wid > hfft_size) - wid = hfft_size; - - wid = wid - 1; - - p = Line; - lineLen = bm->bytesPerLine(); - - if (wid > lineLen / 4) - wid = lineLen / 4; - - if (raduga == DISP_MONO) - { - for (i = 0; i < wid; i++) - { - n = fft_disp[snd_ch][i]; - *(p++) = n; // all colours the same - *(p++) = n; - *(p++) = n; - p++; - } - } - else - { - for (i = 0; i < wid; i++) - { - n = fft_disp[snd_ch][i]; - - memcpy(p, &RGBWF[n], 4); - p += 4; - } - } - - // Scroll - - int TopLine = NextWaterfallLine[snd_ch]; - - // Write line to cyclic buffer then draw starting with the line just written - - memcpy(&WaterfallLines[snd_ch][NextWaterfallLine[snd_ch]++][0], Line, 4096); - if (NextWaterfallLine[snd_ch] > 79) - NextWaterfallLine[snd_ch] = 0; - - for (int j = 79; j > 0; j--) - { - p = bm->scanLine(j); - memcpy(p, &WaterfallLines[snd_ch][TopLine][0], lineLen); - TopLine++; - if (TopLine > 79) - TopLine = 0; - } - - WaterfallCopy[snd_ch]->setPixmap(QPixmap::fromImage(*bm)); - // WaterfallCopy[snd_ch - 1]->setPixmap(*pm); - // WaterfallCopy[1]->setPixmap(QPixmap::fromImage(*bm)); - -} - - - -void QtSoundModem::changeEvent(QEvent* e) -{ - if (e->type() == QEvent::WindowStateChange) - { - QWindowStateChangeEvent* ev = static_cast(e); - - qDebug() << windowState(); - - if (!(ev->oldState() & Qt::WindowMinimized) && windowState() & Qt::WindowMinimized) - { - if (trayIcon) - setVisible(false); - } -// if (!(ev->oldState() != Qt::WindowNoState) && windowState() == Qt::WindowNoState) -// { -// QMessageBox::information(this, "", "Window has been restored"); -// } - - } - QWidget::changeEvent(e); -} - -#include - -void QtSoundModem::closeEvent(QCloseEvent *event) -{ - UNUSED(event); - - QSettings mysettings("QtSoundModem.ini", QSettings::IniFormat); - mysettings.setValue("geometry", QWidget::saveGeometry()); - mysettings.setValue("windowState", saveState()); - - Closing = TRUE; - qDebug() << "Closing"; - - QThread::msleep(100); -} - - -QtSoundModem::~QtSoundModem() -{ - qDebug() << "Saving Settings"; - - QSettings mysettings("QtSoundModem.ini", QSettings::IniFormat); - mysettings.setValue("geometry", saveGeometry()); - mysettings.setValue("windowState", saveState()); - - saveSettings(); - Closing = TRUE; - qDebug() << "Closing"; - - QThread::msleep(100); -} - -extern "C" void QSleep(int ms) -{ - QThread::msleep(ms); -} - -int upd_time = 30; - -void QtSoundModem::show_grid() -{ - // This refeshes the session list - - int snd_ch, i, num_rows, row_idx; - QTableWidgetItem *item; - const char * msg; - - int speed_tx, speed_rx; - - if (grid_time < 10) - { - grid_time++; - return; - } - - grid_time = 0; - - //label7.Caption = inttostr(stat_r_mem); mem_arq - - num_rows = 0; - row_idx = 0; - - for (snd_ch = 0; snd_ch < 4; snd_ch++) - { - for (i = 0; i < port_num; i++) - { - if (AX25Port[snd_ch][i].status != STAT_NO_LINK) - num_rows++; - } - } - - if (num_rows == 0) - { - sessionTable->clearContents(); - sessionTable->setRowCount(0); - sessionTable->setRowCount(1); - } - else - sessionTable->setRowCount(num_rows); - - - for (snd_ch = 0; snd_ch < 4; snd_ch++) - { - for (i = 0; i < port_num; i++) - { - if (AX25Port[snd_ch][i].status != STAT_NO_LINK) - { - switch (AX25Port[snd_ch][i].status) - { - case STAT_NO_LINK: - - msg = "No link"; - break; - - case STAT_LINK: - - msg = "Link"; - break; - - case STAT_CHK_LINK: - - msg = "Chk link"; - break; - - case STAT_WAIT_ANS: - - msg = "Wait ack"; - break; - - case STAT_TRY_LINK: - - msg = "Try link"; - break; - - case STAT_TRY_UNLINK: - - msg = "Try unlink"; - } - - - item = new QTableWidgetItem((char *)AX25Port[snd_ch][i].mycall); - sessionTable->setItem(row_idx, 0, item); - - item = new QTableWidgetItem(AX25Port[snd_ch][i].kind); - sessionTable->setItem(row_idx, 11, item); - - item = new QTableWidgetItem((char *)AX25Port[snd_ch][i].corrcall); - sessionTable->setItem(row_idx, 1, item); - - item = new QTableWidgetItem(msg); - sessionTable->setItem(row_idx, 2, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_s_pkt)); - sessionTable->setItem(row_idx, 3, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_s_byte)); - sessionTable->setItem(row_idx, 4, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_r_pkt)); - sessionTable->setItem(row_idx, 5, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_r_byte)); - sessionTable->setItem(row_idx, 6, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_r_fc)); - sessionTable->setItem(row_idx, 7, item); - - item = new QTableWidgetItem(QString::number(AX25Port[snd_ch][i].info.stat_fec_count)); - sessionTable->setItem(row_idx, 8, item); - - if (grid_timer != upd_time) - grid_timer++; - else - { - grid_timer = 0; - speed_tx = round(abs(AX25Port[snd_ch][i].info.stat_s_byte - AX25Port[snd_ch][i].info.stat_l_s_byte) / upd_time); - speed_rx = round(abs(AX25Port[snd_ch][i].info.stat_r_byte - AX25Port[snd_ch][i].info.stat_l_r_byte) / upd_time); - - item = new QTableWidgetItem(QString::number(speed_tx)); - sessionTable->setItem(row_idx, 9, item); - - item = new QTableWidgetItem(QString::number(speed_rx)); - sessionTable->setItem(row_idx, 10, item); - - AX25Port[snd_ch][i].info.stat_l_r_byte = AX25Port[snd_ch][i].info.stat_r_byte; - AX25Port[snd_ch][i].info.stat_l_s_byte = AX25Port[snd_ch][i].info.stat_s_byte; - } - - row_idx++; - } - } - } -} - -// "Copy on Select" Code - -void QtSoundModem::onTEselectionChanged() -{ - QTextEdit * x = static_cast(QObject::sender()); - x->copy(); -} - diff --git a/QtSoundModem.h b/QtSoundModem.h index fc21d79..626ddd9 100644 --- a/QtSoundModem.h +++ b/QtSoundModem.h @@ -29,7 +29,7 @@ public: ~QtSoundModem(); void RefreshWaterfall(int snd_ch, unsigned char * Data); - void initWaterfall(int chan, int state); + void initWaterfall(int state); void show_grid(); void checkforCWID(); @@ -39,6 +39,7 @@ private slots: void CWIDTimer(); void doDevices(); + void mysetstyle(); void updateFont(); void MinimizetoTray(); void TrayActivated(QSystemTrayIcon::ActivationReason reason); @@ -111,3 +112,9 @@ protected: bool eventFilter(QObject *obj, QEvent *event) override; }; + +#define WaterfallDisplayPixels 80 +#define WaterfallHeaderPixels 38 +#define WaterfallTotalPixels WaterfallDisplayPixels + WaterfallHeaderPixels +#define WaterfallImageHeight (WaterfallTotalPixels + WaterfallTotalPixels) + diff --git a/QtSoundModem.ui b/QtSoundModem.ui index e264b7d..1d7b110 100644 --- a/QtSoundModem.ui +++ b/QtSoundModem.ui @@ -6,8 +6,8 @@ 0 0 - 962 - 721 + 993 + 900 @@ -50,48 +50,6 @@ - - - - 0 - 586 - 959 - 80 - - - - - 0 - 0 - - - - - 600 - 80 - - - - - 5000 - 100 - - - - - 8 - - - - QFrame::Box - - - QFrame::Plain - - - Waterfall - - @@ -121,25 +79,25 @@ 1500 - + 80 488 881 - 80 + 100 600 - 80 + 100 5000 - 100 + 250 @@ -171,9 +129,9 @@ 690 - 0 + 2 73 - 16 + 13 @@ -215,78 +173,6 @@ 10 - - - - 25 - 460 - 1076 - 38 - - - - - 600 - 10 - - - - - 5000 - 100 - - - - - 8 - - - - QFrame::Box - - - QFrame::Plain - - - Waterfall - - - - - - 10 - 560 - 1076 - 38 - - - - - 600 - 10 - - - - - 5000 - 100 - - - - - 8 - - - - QFrame::Box - - - QFrame::Plain - - - Waterfall - - @@ -412,7 +298,7 @@ 600 2 87 - 16 + 13 @@ -487,9 +373,9 @@ 780 - 17 + 14 150 - 12 + 11 @@ -508,7 +394,7 @@ 780 0 91 - 16 + 13 @@ -526,13 +412,32 @@ true + + + + 780 + 23 + 150 + 11 + + + + QFrame::Box + + + QFrame::Sunken + + + + + 0 0 - 962 + 993 21 diff --git a/QtSoundModem.vcxproj-DESKTOP-MHE5LO8.user b/QtSoundModem.vcxproj-DESKTOP-MHE5LO8.user deleted file mode 100644 index a71d175..0000000 --- a/QtSoundModem.vcxproj-DESKTOP-MHE5LO8.user +++ /dev/null @@ -1,34 +0,0 @@ - - - - C:\DevProgs\BPQ32\SMTest - WindowsLocalDebugger - - - - - c:\devprogs\bpq32\SMSAT2 - WindowsLocalDebugger - < d:\samples.wav - - - .\debug - WindowsLocalDebugger - - - C:\DevProgs\BPQ32\SMSat - WindowsLocalDebugger - - - 2023-08-21T20:12:53.1523329Z - - - 2022-03-11T19:38:31.5906689Z - - - 2023-08-18T07:29:42.4175478Z - - - 2022-03-11T19:38:33.3845083Z - - \ No newline at end of file diff --git a/QtSoundModem.vcxproj-HPLaptop.user b/QtSoundModem.vcxproj-HPLaptop.user deleted file mode 100644 index 8995d93..0000000 --- a/QtSoundModem.vcxproj-HPLaptop.user +++ /dev/null @@ -1,34 +0,0 @@ - - - - C:\Devprogs\bpq32\SMSat2 - WindowsLocalDebugger - - - - - c:\devprogs\bpq32\SMSAT2 - WindowsLocalDebugger - < d:\samples.wav - - - C:\DevProgs\BPQ32\SMSat - WindowsLocalDebugger - - - C:\DevProgs\BPQ32\SMSat - WindowsLocalDebugger - - - 2022-12-30T15:55:55.0433562Z - - - 2022-03-11T19:38:31.5906689Z - - - 2022-12-30T15:55:55.2283725Z - - - 2022-03-11T19:38:33.3845083Z - - \ No newline at end of file diff --git a/QtSoundModem.vcxproj.user b/QtSoundModem.vcxproj.user index 65f157d..8b8926c 100644 --- a/QtSoundModem.vcxproj.user +++ b/QtSoundModem.vcxproj.user @@ -3,8 +3,7 @@ C:\DevProgs\BPQ32\SMTest WindowsLocalDebugger - - + -stylesheet StyleSheet.css c:\devprogs\bpq32\SMSAT2 @@ -12,23 +11,24 @@ < d:\samples.wav - .\debug + C:\DevProgs\BPQ32\SMTest WindowsLocalDebugger + -stylesheet StyleSheet.css C:\DevProgs\BPQ32\SMSat WindowsLocalDebugger - 2023-09-26T11:58:59.9128543Z + 2023-10-15T11:35:54.9027336Z - 2023-09-26T11:59:00.0378577Z + 2023-10-15T11:35:55.0741785Z - 2023-09-26T11:59:00.1388610Z + 2023-10-15T11:35:55.2661628Z - 2023-09-26T11:59:00.2228656Z + 2023-10-15T11:35:55.4659021Z \ No newline at end of file diff --git a/SMMain-DESKTOP-MHE5LO8.c b/SMMain-DESKTOP-MHE5LO8.c deleted file mode 100644 index 8fc249e..0000000 --- a/SMMain-DESKTOP-MHE5LO8.c +++ /dev/null @@ -1,1433 +0,0 @@ -/* -Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO - -This file is part of QtSoundModem - -QtSoundModem 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 3 of the License, or -(at your option) any later version. - -QtSoundModem 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 QtSoundModem. If not, see http://www.gnu.org/licenses - -*/ - -// UZ7HO Soundmodem Port by John Wiseman G8BPQ - -#include "UZ7HOStuff.h" -#include "fftw3.h" -#include -#include "ecc.h" // RS Constants -#include "hidapi.h" -#include -#include -#include - -BOOL KISSServ; -int KISSPort; - -BOOL AGWServ; -int AGWPort; - -int Number = 0; // Number waiting to be sent - -int SoundIsPlaying = 0; -int UDPSoundIsPlaying = 0; -int Capturing = 0; - -extern unsigned short buffer[2][1200]; -extern int SoundMode; -extern int needRSID[4]; - -extern short * DMABuffer; - -unsigned short * SendtoCard(unsigned short * buf, int n); -short * SoundInit(); -void DoTX(int Chan); -void UDPPollReceivedSamples(); - - -extern int SampleNo; - -extern int pnt_change[5]; // Freq Changed Flag - -// fftw library interface - - -fftwf_complex *in, *out; -fftwf_plan p; - -int FFTSize = 4096; - -char * Wisdom; - -void initfft() -{ - fftwf_import_wisdom_from_string(Wisdom); - fftwf_set_timelimit(30); - -#ifndef WIN32 - printf("It may take up to 30 seconds for the program to start for the first time\n"); -#endif - - in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * 10000); - out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * 10000); - p = fftwf_plan_dft_1d(FFTSize, in, out, FFTW_FORWARD, FFTW_PATIENT); - - Wisdom = fftwf_export_wisdom_to_string(); -} - -void dofft(short * inp, float * outr, float * outi) -{ - int i; - - fftwf_complex * fft = in; - - for (i = 0; i < FFTSize; i++) - { - fft[0][0] = inp[0] * 1.0f; - fft[0][1] = 0; - fft++; - inp++; - } - - fftwf_execute(p); - - fft = out; - - for (i = 0; i < FFTSize; i++) - { - outr[0] = fft[0][0]; - outi[0] = fft[0][1]; - fft++; - outi++; - outr++; - } -} - -void freefft() -{ - fftwf_destroy_plan(p); - fftwf_free(in); - fftwf_free(out); -} - -int nonGUIMode = 0; - -void soundMain() -{ - // non platform specific initialisation - - platformInit(); - - // initialise fft library - - RsCreate(); // RS code for MPSK - - detector_init(); - KISS_init(); - ax25_init(); - init_raduga(); // Set up waterfall colour table - - initfft(); - - if (nonGUIMode) - { - Firstwaterfall = 0; - Secondwaterfall = 0; - } - - OpenPTTPort(); -} - - -void SampleSink(int LR, short Sample) -{ - // This version is passed samples one at a time, as we don't have - // enough RAM in embedded systems to hold a full audio frame - - // LR - 1 == Right Chan - -#ifdef TEENSY - int work = Sample; - DMABuffer[Number++] = (work + 32768) >> 4; // 12 bit left justify -#else - if (SCO) // Single Channel Output - same to both L and R - { - DMABuffer[2 * Number] = Sample; - DMABuffer[1 + 2 * Number] = Sample; - - } - else - { - if (LR) // Right - { - DMABuffer[1 + 2 * Number] = Sample; - DMABuffer[2 * Number] = 0; - } - else - { - DMABuffer[2 * Number] = Sample; - DMABuffer[1 + 2 * Number] = 0; - } - } - if (using48000) - { - // Need to upsample to 48K. Try just duplicating sample - - uint32_t * ptr = &DMABuffer[2 * Number]; - - *(&ptr[1]) = *(ptr); - *(&ptr[2]) = *(ptr); - *(&ptr[3]) = *(ptr); - - Number += 3; - } - Number++; -#endif - if (Number >= SendSize) - { - // send this buffer to sound interface - - DMABuffer = SendtoCard(DMABuffer, SendSize); - Number = 0; - } - - -// Last120[Last120Put++] = Sample; - -// if (Last120Put == (intN + 1)) -// Last120Put = 0; - - SampleNo++; -} - - -void Flush() -{ - SoundFlush(Number); -} - -int ipow(int base, int exp) -{ - int result = 1; - while (exp) - { - if (exp & 1) - result *= base; - exp >>= 1; - base *= base; - } - - return result; -} - -int NumberOfBitsNeeded(int PowerOfTwo) -{ - int i; - - for (i = 0; i <= 16; i++) - { - if ((PowerOfTwo & ipow(2, i)) != 0) - return i; - - } - return 0; -} - - -int ReverseBits(int Index, int NumBits) -{ - int i, Rev = 0; - - for (i = 0; i < NumBits; i++) - { - Rev = (Rev * 2) | (Index & 1); - Index = Index / 2; - } - - return Rev; -} - - -void FourierTransform(int NumSamples, short * RealIn, float * RealOut, float * ImagOut, int InverseTransform) -{ - float AngleNumerator; - unsigned char NumBits; - - int i, j, K, n, BlockSize, BlockEnd; - float DeltaAngle, DeltaAr; - float Alpha, Beta; - float TR, TI, AR, AI; - - if (InverseTransform) - AngleNumerator = -2.0f * M_PI; - else - AngleNumerator = 2.0f * M_PI; - - NumBits = NumberOfBitsNeeded(NumSamples); - - for (i = 0; i < NumSamples; i++) - { - j = ReverseBits(i, NumBits); - RealOut[j] = RealIn[i]; - ImagOut[j] = 0.0f; // Not using i in ImageIn[i]; - } - - BlockEnd = 1; - BlockSize = 2; - - while (BlockSize <= NumSamples) - { - DeltaAngle = AngleNumerator / BlockSize; - Alpha = sinf(0.5f * DeltaAngle); - Alpha = 2.0f * Alpha * Alpha; - Beta = sinf(DeltaAngle); - - i = 0; - - while (i < NumSamples) - { - AR = 1.0f; - AI = 0.0f; - - j = i; - - for (n = 0; n < BlockEnd; n++) - { - K = j + BlockEnd; - TR = AR * RealOut[K] - AI * ImagOut[K]; - TI = AI * RealOut[K] + AR * ImagOut[K]; - RealOut[K] = RealOut[j] - TR; - ImagOut[K] = ImagOut[j] - TI; - RealOut[j] = RealOut[j] + TR; - ImagOut[j] = ImagOut[j] + TI; - DeltaAr = Alpha * AR + Beta * AI; - AI = AI - (Alpha * AI - Beta * AR); - AR = AR - DeltaAr; - j = j + 1; - } - i = i + BlockSize; - } - BlockEnd = BlockSize; - BlockSize = BlockSize * 2; - } - - if (InverseTransform) - { - // Normalize the resulting time samples... - - for (i = 0; i < NumSamples; i++) - { - RealOut[i] = RealOut[i] / NumSamples; - ImagOut[i] = ImagOut[i] / NumSamples; - } - } -} - - - -int LastBusyCheck = 0; - -extern UCHAR CurrentLevel; - -#ifdef PLOTSPECTRUM -float dblMagSpectrum[206]; -float dblMaxScale = 0.0f; -extern UCHAR Pixels[4096]; -extern UCHAR * pixelPointer; -#endif - -extern int blnBusyStatus; -BusyDet = 5; - -#define PLOTWATERFALL - -int WaterfallActive = 1; -int SpectrumActive; - -float BinSize; - -extern int intLastStart; -extern int intLastStop; - -void SMSortSignals2(float * dblMag, int intStartBin, int intStopBin, int intNumBins, float * dblAVGSignalPerBin, float * dblAVGBaselinePerBin); - - -BOOL SMBusyDetect3(float * dblMag, int intStart, int intStop) // this only called while searching for leader ...once leader detected, no longer called. -{ - // First sort signals and look at highes signals:baseline ratio.. - - float dblAVGSignalPerBinNarrow, dblAVGSignalPerBinWide, dblAVGBaselineNarrow, dblAVGBaselineWide; - float dblSlowAlpha = 0.2f; - float dblAvgStoNNarrow = 0, dblAvgStoNWide = 0; - int intNarrow = 8; // 8 x 11.72 Hz about 94 z - int intWide = ((intStop - intStart) * 2) / 3; //* 0.66); - int blnBusy = FALSE; - int BusyDet4th = BusyDet * BusyDet * BusyDet * BusyDet; - - // First sort signals and look at highest signals:baseline ratio.. - // First narrow band (~94Hz) - - SMSortSignals2(dblMag, intStart, intStop, intNarrow, &dblAVGSignalPerBinNarrow, &dblAVGBaselineNarrow); - - if (intLastStart == intStart && intLastStop == intStop) - dblAvgStoNNarrow = (1 - dblSlowAlpha) * dblAvgStoNNarrow + dblSlowAlpha * dblAVGSignalPerBinNarrow / dblAVGBaselineNarrow; - else - { - // This initializes the Narrow average after a bandwidth change - - dblAvgStoNNarrow = dblAVGSignalPerBinNarrow / dblAVGBaselineNarrow; - intLastStart = intStart; - intLastStop = intStop; - } - - // Wide band (66% of current bandwidth) - - SMSortSignals2(dblMag, intStart, intStop, intWide, &dblAVGSignalPerBinWide, &dblAVGBaselineWide); - - if (intLastStart == intStart && intLastStop == intStop) - dblAvgStoNWide = (1 - dblSlowAlpha) * dblAvgStoNWide + dblSlowAlpha * dblAVGSignalPerBinWide / dblAVGBaselineWide; - else - { - // This initializes the Wide average after a bandwidth change - - dblAvgStoNWide = dblAVGSignalPerBinWide / dblAVGBaselineWide; - intLastStart = intStart; - intLastStop = intStop; - } - - // Preliminary calibration...future a function of bandwidth and BusyDet. - - - blnBusy = (dblAvgStoNNarrow > (3 + 0.008 * BusyDet4th)) || (dblAvgStoNWide > (5 + 0.02 * BusyDet4th)); - -// if (BusyDet == 0) -// blnBusy = FALSE; // 0 Disables check ?? Is this the best place to do this? - -// WriteDebugLog(LOGDEBUG, "Busy %d Wide %f Narrow %f", blnBusy, dblAvgStoNWide, dblAvgStoNNarrow); - - return blnBusy; -} - -extern int compare(const void *p1, const void *p2); - -void SMSortSignals2(float * dblMag, int intStartBin, int intStopBin, int intNumBins, float * dblAVGSignalPerBin, float * dblAVGBaselinePerBin) -{ - // puts the top intNumber of bins between intStartBin and intStopBin into dblAVGSignalPerBin, the rest into dblAvgBaselinePerBin - // for decent accuracy intNumBins should be < 75% of intStopBin-intStartBin) - - // This version uses a native sort function which is much faster and reduces CPU loading significantly on wide bandwidths. - - float dblSort[8192]; - float dblSum1 = 0, dblSum2 = 0; - int numtoSort = (intStopBin - intStartBin) + 1, i; - - memcpy(dblSort, &dblMag[intStartBin], numtoSort * sizeof(float)); - - qsort((void *)dblSort, numtoSort, sizeof(float), compare); - - for (i = numtoSort - 1; i >= 0; i--) - { - if (i >= (numtoSort - intNumBins)) - dblSum1 += dblSort[i]; - else - dblSum2 += dblSort[i]; - } - - *dblAVGSignalPerBin = dblSum1 / intNumBins; - *dblAVGBaselinePerBin = dblSum2 / (intStopBin - intStartBin - intNumBins - 1); -} - - - -void SMUpdateBusyDetector(int LR, float * Real, float *Imag) -{ - // Energy based detector for each channel. - // Fed from FFT generated for waterfall display - // FFT size is 4096 - - float dblMag[4096]; - - static BOOL blnLastBusyStatus[4]; - - float dblMagAvg = 0; - int intTuneLineLow, intTuneLineHi, intDelta; - int i, chan; - - return; - - if (Now - LastBusyCheck < 100) // ?? - return; - - LastBusyCheck = Now; - - // We need to run busy test on the frequncies used by each modem. - - for (chan = 0; chan < 4; chan++) - { - int Low, High, Start, End; - - if (soundChannel[chan] != (LR + 1)) // on this side of soundcard - continue; - - Low = tx_freq[chan] - txbpf[chan] / 2; - High = tx_freq[chan] + txbpf[chan] / 2; - - // BinSize is width of each fft bin in Hz - - Start = (Low / BinSize); // First and last bins to process - End = (High / BinSize); - - - for (i = Start; i < End; i++) - { - dblMag[i] = powf(Real[i], 2) + powf(Imag[i], 2); // first pass - dblMagAvg += dblMag[i]; - } - - blnBusyStatus = SMBusyDetect3(dblMag, Start, End); - - if (blnBusyStatus && !blnLastBusyStatus[chan]) - { - Debugprintf("Ch %d Busy True", chan); - } - else if (blnLastBusyStatus[chan] && !blnBusyStatus) - { - Debugprintf("Ch %d Busy False", chan); - } - // stcStatus.Text = "FALSE" - // queTNCStatus.Enqueue(stcStatus) - // 'Debug.WriteLine("BUSY FALSE @ " & Format(DateTime.UtcNow, "HH:mm:ss")) - - blnLastBusyStatus[chan] = blnBusyStatus; - } -} - - -extern short rawSamples[2400]; // Get Frame Type need 2400 and we may add 1200 -int rawSamplesLength = 0; -extern int maxrawSamplesLength; - -void ProcessNewSamples(short * Samples, int nSamples) -{ - if (SoundIsPlaying == FALSE && UDPSoundIsPlaying == FALSE) - BufferFull(Samples, nSamples); -}; - -void doCalib(int Chan, int Act) -{ - if (Chan == 0 && calib_mode[1]) - return; - - if (Chan == 1 && calib_mode[0]) - return; - - calib_mode[Chan] = Act; - - if (Act == 0) - { - tx_status[Chan] = TX_SILENCE; // Stop TX - Flush(); - RadioPTT(Chan, 0); - Debugprintf("Stop Calib"); - } -} - -int Freq_Change(int Chan, int Freq) -{ - int low, high; - - low = round(rx_shift[1] / 2 + RCVR[Chan] * rcvr_offset[Chan] + 1); - high = round(RX_Samplerate / 2 - (rx_shift[Chan] / 2 + RCVR[Chan] * rcvr_offset[Chan])); - - if (Freq < low) - return rx_freq[Chan]; // Dont allow change - - if (Freq > high) - return rx_freq[Chan]; // Dont allow change - - rx_freq[Chan] = Freq; - tx_freq[Chan] = Freq; - - pnt_change[Chan] = TRUE; - wf_pointer(soundChannel[Chan]); - - return Freq; -} - -void MainLoop() -{ - // Called by background thread every 10 ms (maybe) - - // Actually we may have two cards - - // Original only allowed one channel per card. - // I think we should be able to run more, ie two or more - // modems on same soundcard channel - - // So All the soundcard stuff will need to be generalised - - if (UDPServ) - UDPPollReceivedSamples(); - - if (SoundMode == 3) - UDPPollReceivedSamples(); - else - PollReceivedSamples(); - - - for (int i = 0; i < 4; i++) - { - if (modem_mode[i] == MODE_ARDOP) - { - chk_dcd1(i, 512); - } - } - DoTX(0); - DoTX(1); - DoTX(2); - DoTX(3); - -} - -int ARDOPSendToCard(int Chan, int Len) -{ - // Send Next Block of samples to the soundcard - - - short * in = &ARDOPTXBuffer[Chan][ARDOPTXPtr[Chan]]; // Enough to hold whole frame of samples - short * out = DMABuffer; - - int LR = modemtoSoundLR[Chan]; - - int i; - - for (i = 0; i < Len; i++) - { - if (SCO) // Single Channel Output - same to both L and R - { - *out++ = *in; - *out++ = *in++; - } - else - { - if (LR) // Right - { - *out++ = 0; - *out++ = *in++; - } - else - { - *out++ = *in++; - *out++ = 0; - } - } - } - - DMABuffer = SendtoCard(DMABuffer, Len); - - ARDOPTXPtr[Chan] += Len; - - // See if end of buffer - - if (ARDOPTXPtr[Chan] > ARDOPTXLen[Chan]) - return 1; - - return 0; -} -void DoTX(int Chan) -{ - // This kicks off a send sequence or calibrate - -// printtick("dotx"); - - if (calib_mode[Chan]) - { - // Maybe new calib or continuation - - if (pnt_change[Chan]) - { - make_core_BPF(Chan, rx_freq[Chan], bpf[Chan]); - make_core_TXBPF(Chan, tx_freq[Chan], txbpf[Chan]); - pnt_change[Chan] = FALSE; - } - - // Note this may block in SendtoCard - - modulator(Chan, tx_bufsize); - return; - } - - // I think we have to detect NO_DATA here and drop PTT and return to SILENCE - - if (tx_status[Chan] == TX_NO_DATA) - { - Flush(); - Debugprintf("TX Complete"); - RadioPTT(0, 0); - Continuation[Chan] = 0; - - tx_status[Chan] = TX_SILENCE; - - // We should now send any ackmode acks as the channel is now free for dest to reply - - sendAckModeAcks(Chan); - } - - if (tx_status[Chan] != TX_SILENCE) - { - // Continue the send - - if (modem_mode[Chan] == MODE_ARDOP || modem_mode[Chan] == MODE_RUH) - { -// if (SeeIfCardBusy()) -// return 0; - - if (ARDOPSendToCard(Chan, SendSize) == 1) - { - // End of TX - - Number = 0; - Flush(); - - // See if more to send. If so, don't drop PTT - - if (all_frame_buf[Chan].Count) - { - SoundIsPlaying = TRUE; - Number = 0; - - Continuation[Chan] = 1; - - Debugprintf("TX Continuing"); - - string * myTemp = Strings(&all_frame_buf[Chan], 0); // get message - string * tx_data; - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[Chan], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data = duplicateString(myTemp); // so can free original below - - Delete(&all_frame_buf[Chan], 0); // This will invalidate temp - - AGW_AX25_frame_analiz(Chan, FALSE, tx_data); - - put_frame(Chan, tx_data, "", TRUE, FALSE); - - if (modem_mode[Chan] == MODE_ARDOP) - PktARDOPEncode(tx_data->Data, tx_data->Length - 2, Chan); - else - RUHEncode(tx_data->Data, tx_data->Length - 2, Chan); - - freeString(tx_data); - - // Samples are now in DMABuffer = Send first block - - DMABuffer = SoundInit(); - - ARDOPSendToCard(Chan, SendSize); - tx_status[Chan] = TX_FRAME; - return; - } - - Debugprintf("TX Complete"); - RadioPTT(0, 0); - Continuation[Chan] = 0; - - tx_status[Chan] = TX_SILENCE; - - // We should now send any ackmode acks as the channel is now free for dest to reply - } - - return; - } - - modulator(Chan, tx_bufsize); - return; - } - - if (SoundIsPlaying || UDPSoundIsPlaying) - return; - - // Not doing anything so see if we have anything new to send - - // See if frequency has changed - - if (pnt_change[Chan]) - { - make_core_BPF(Chan, rx_freq[Chan], bpf[Chan]); - make_core_TXBPF(Chan, tx_freq[Chan], txbpf[Chan]); - pnt_change[Chan] = FALSE; - } - - // See if we need an RSID - - if (needRSID[Chan]) - { - needRSID[Chan] = 0; - - // Note this may block in SampleSink - - Debugprintf("Sending RSID"); - sendRSID(Chan, all_frame_buf[Chan].Count == 0); - return; - } - - if (all_frame_buf[Chan].Count == 0) - return; - - // Start a new send. modulator should handle TXD etc - - Debugprintf("TX Start"); - SampleNo = 0; - - SoundIsPlaying = TRUE; - RadioPTT(Chan, 1); - Number = 0; - - if (modem_mode[Chan] == MODE_ARDOP) - { - // I think ARDOP will have to generate a whole frame of samples - // then send them out a bit at a time to avoid stopping here for - // possibly 10's of seconds - - // Can do this here as unlike normal ardop we don't need to run on Teensy - // to 12000 sample rate we need either 24K or 48K per second, depending on - // where we do the stereo mux. - - // Slowest rate is 50 baud, so a 255 byte packet would take about a minute - // allowing for RS overhead. Not really realistic put perhaps should be possible. - // RAM isn't an issue so maybe allocate 2 MB. - - // ?? Should we allow two ARDOP modems - could make sense if we can run sound - // card channels independently - - string * myTemp = Strings(&all_frame_buf[Chan], 0); // get message - string * tx_data; - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[Chan], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data = duplicateString(myTemp); // so can free original below - - Delete(&all_frame_buf[Chan], 0); // This will invalidate temp - - AGW_AX25_frame_analiz(Chan, FALSE, tx_data); - - put_frame(Chan, tx_data, "", TRUE, FALSE); - - PktARDOPEncode(tx_data->Data, tx_data->Length - 2, Chan); - - freeString(tx_data); - - // Samples are now in DMABuffer = Send first block - - ARDOPSendToCard(Chan, SendSize); - tx_status[Chan] = TX_FRAME; - - } - else if (modem_mode[Chan] == MODE_RUH) - { - // Same as for ARDOP. Generate a whole frame of samples - // then send them out a bit at a time to avoid stopping here - - // We allow two RUH modems - - string * myTemp = Strings(&all_frame_buf[Chan], 0); // get message - string * tx_data; - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[Chan], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data = duplicateString(myTemp); // so can free original below - - Delete(&all_frame_buf[Chan], 0); // This will invalidate temp - - AGW_AX25_frame_analiz(Chan, FALSE, tx_data); - - put_frame(Chan, tx_data, "", TRUE, FALSE); - - RUHEncode(tx_data->Data, tx_data->Length - 2, Chan); - - freeString(tx_data); - - // Samples are now in DMABuffer = Send first block - - ARDOPSendToCard(Chan, SendSize); - tx_status[Chan] = TX_FRAME; - - } - else - modulator(Chan, tx_bufsize); - - return; -} - -void RX2TX(int snd_ch) -{ - if (snd_status[snd_ch] == SND_IDLE) - { - DoTX(snd_ch); - } -} - -// PTT Stuff - -int hPTTDevice = 0; -char PTTPort[80] = ""; // Port for Hardware PTT - may be same as control port. -int PTTBAUD = 19200; -int PTTMode = PTTRTS; // PTT Control Flags. - -char PTTOnString[128] = ""; -char PTTOffString[128] = ""; - -UCHAR PTTOnCmd[64]; -UCHAR PTTOnCmdLen = 0; - -UCHAR PTTOffCmd[64]; -UCHAR PTTOffCmdLen = 0; - -int pttGPIOPin = 17; // Default -int pttGPIOPinR = 17; -BOOL pttGPIOInvert = FALSE; -BOOL useGPIO = FALSE; -BOOL gotGPIO = FALSE; - -int HamLibPort = 4532; -char HamLibHost[32] = "192.168.1.14"; - -char CM108Addr[80] = ""; - -int VID = 0; -int PID = 0; - -// CM108 Code - -char * CM108Device = NULL; - -void DecodeCM108(char * ptr) -{ - // Called if Device Name or PTT = Param is CM108 - -#ifdef WIN32 - - // Next Param is VID and PID - 0xd8c:0x8 or Full device name - // On Windows device name is very long and difficult to find, so - // easier to use VID/PID, but allow device in case more than one needed - - char * next; - long VID = 0, PID = 0; - char product[256] = "Unknown"; - - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - if (strlen(ptr) > 16) - CM108Device = _strdup(ptr); - else - { - VID = strtol(ptr, &next, 0); - if (next) - PID = strtol(++next, &next, 0); - - // Look for Device - - devs = hid_enumerate((unsigned short)VID, (unsigned short)PID); - cur_dev = devs; - - while (cur_dev) - { - if (cur_dev->product_string) - wcstombs(product, cur_dev->product_string, 255); - - Debugprintf("HID Device %s VID %X PID %X", product, cur_dev->vendor_id, cur_dev->product_id); - if (cur_dev->vendor_id == VID && cur_dev->product_id == PID) - { - path_to_open = cur_dev->path; - break; - } - cur_dev = cur_dev->next; - } - - if (path_to_open) - { - handle = hid_open_path(path_to_open); - - if (handle) - { - hid_close(handle); - CM108Device = _strdup(path_to_open); - } - else - { - Debugprintf("Unable to open CM108 device %x %x", VID, PID); - } - } - else - Debugprintf("Couldn't find CM108 device %x %x", VID, PID); - - hid_free_enumeration(devs); - } -#else - - // Linux - Next Param HID Device, eg /dev/hidraw0 - - CM108Device = _strdup(ptr); -#endif -} - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++ = 0; - return ptr; -} - -void OpenPTTPort() -{ - PTTMode &= ~PTTCM108; - PTTMode &= ~PTTHAMLIB; - - if (PTTPort[0] && strcmp(PTTPort, "None") != 0) - { - if (PTTMode == PTTCAT) - { - // convert config strings from Hex - - char * ptr1 = PTTOffString; - UCHAR * ptr2 = PTTOffCmd; - char c; - int val; - - while (c = *(ptr1++)) - { - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(ptr2++) = val; - } - - PTTOffCmdLen = ptr2 - PTTOffCmd; - - ptr1 = PTTOnString; - ptr2 = PTTOnCmd; - - while (c = *(ptr1++)) - { - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(ptr2++) = val; - } - - PTTOnCmdLen = ptr2 - PTTOnCmd; - } - - if (stricmp(PTTPort, "GPIO") == 0) - { - // Initialise GPIO for PTT if available - -#ifdef __ARM_ARCH - - if (gpioInitialise() == 0) - { - printf("GPIO interface for PTT available\n"); - gotGPIO = TRUE; - - SetupGPIOPTT(); - } - else - printf("Couldn't initialise GPIO interface for PTT\n"); - -#else - printf("GPIO interface for PTT not available on this platform\n"); -#endif - - } - else if (stricmp(PTTPort, "CM108") == 0) - { - DecodeCM108(CM108Addr); - PTTMode |= PTTCM108; - } - - else if (stricmp(PTTPort, "HAMLIB") == 0) - { - PTTMode |= PTTHAMLIB; - HAMLIBSetPTT(0); // to open port - return; - } - - else // Not GPIO - { - hPTTDevice = OpenCOMPort(PTTPort, PTTBAUD, FALSE, FALSE, FALSE, 0); - } - } -} - -void ClosePTTPort() -{ - CloseCOMPort(hPTTDevice); - hPTTDevice = 0; -} -void CM108_set_ptt(int PTTState) -{ - char io[5]; - hid_device *handle; - int n; - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - if (CM108Device == NULL) - return; - -#ifdef WIN32 - handle = hid_open_path(CM108Device); - - if (!handle) { - printf("unable to open device\n"); - return; - } - - n = hid_write(handle, io, 5); - if (n < 0) - { - printf("Unable to write()\n"); - printf("Error: %ls\n", hid_error(handle)); - } - - hid_close(handle); - -#else - - int fd; - - fd = open(CM108Device, O_WRONLY); - - if (fd == -1) - { - printf("Could not open %s for write, errno=%d\n", CM108Device, errno); - return; - } - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - n = write(fd, io, 5); - if (n != 5) - { - printf("Write to %s failed, n=%d, errno=%d\n", CM108Device, n, errno); - } - - close(fd); -#endif - return; - -} - - - -void RadioPTT(int snd_ch, BOOL PTTState) -{ - snd_status[snd_ch] = PTTState; // SND_IDLE = 0 SND_TX = 1 - -#ifdef __ARM_ARCH - if (useGPIO) - { - if (DualPTT && modemtoSoundLR[snd_ch] == 1) - gpioWrite(pttGPIOPinR, (pttGPIOInvert ? (1 - PTTState) : (PTTState))); - else - gpioWrite(pttGPIOPin, (pttGPIOInvert ? (1 - PTTState) : (PTTState))); - - return; - } - -#endif - - if ((PTTMode & PTTCM108)) - { - CM108_set_ptt(PTTState); - return; - } - - if ((PTTMode & PTTHAMLIB)) - { - HAMLIBSetPTT(PTTState); - return; - } - if (hPTTDevice == 0) - return; - - if ((PTTMode & PTTCAT)) - { - if (PTTState) - WriteCOMBlock(hPTTDevice, PTTOnCmd, PTTOnCmdLen); - else - WriteCOMBlock(hPTTDevice, PTTOffCmd, PTTOffCmdLen); - - return; - } - - if (DualPTT && modemtoSoundLR[snd_ch] == 1) // use DTR - { - if (PTTState) - COMSetDTR(hPTTDevice); - else - COMClearDTR(hPTTDevice); - } - else - { - if ((PTTMode & PTTRTS)) - { - if (PTTState) - COMSetRTS(hPTTDevice); - else - COMClearRTS(hPTTDevice); - } - } - -} - -char ShortDT[] = "HH:MM:SS"; - -char * ShortDateTime() -{ - struct tm * tm; - time_t NOW = time(NULL); - - tm = gmtime(&NOW); - - sprintf(ShortDT, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - return ShortDT; -} - - -// Reed Solomon Stuff - - -int NPAR = -1; // Number of Parity Bytes - used in RS Code - -int xMaxErrors = 0; - -int RSEncode(UCHAR * bytToRS, UCHAR * RSBytes, int DataLen, int RSLen) -{ - // This just returns the Parity Bytes. I don't see the point - // in copying the message about - - unsigned char Padded[256]; // The padded Data - - int Length = DataLen + RSLen; // Final Length of packet - int PadLength = 255 - Length; // Padding bytes needed for shortened RS codes - - // subroutine to do the RS encode. For full length and shortend RS codes up to 8 bit symbols (mm = 8) - - if (NPAR != RSLen) // Changed RS Len, so recalc constants; - { - NPAR = RSLen; - xMaxErrors = NPAR / 2; - initialize_ecc(); - } - - // Copy the supplied data to end of data array. - - memset(Padded, 0, PadLength); - memcpy(&Padded[PadLength], bytToRS, DataLen); - - encode_data(Padded, 255 - RSLen, RSBytes); - - return RSLen; -} - -// Main RS decode function - -extern int index_of[]; -extern int recd[]; -extern int Corrected[256]; -extern int tt; // number of errors that can be corrected -extern int kk; // Info Symbols - -extern BOOL blnErrorsCorrected; - - -BOOL RSDecode(UCHAR * bytRcv, int Length, int CheckLen, BOOL * blnRSOK) -{ - - - // Using a modified version of Henry Minsky's code - - //Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 - - // Rick's Implementation processes the byte array in reverse. and also - // has the check bytes in the opposite order. I've modified the encoder - // to allow for this, but so far haven't found a way to mske the decoder - // work, so I have to reverse the data and checksum to decode G8BPQ Nov 2015 - - // returns TRUE if was ok or correction succeeded, FALSE if correction impossible - - UCHAR intTemp[256]; // WOrk Area to pass to Decoder - int i; - UCHAR * ptr2 = intTemp; - UCHAR * ptr1 = &bytRcv[Length - CheckLen - 1]; // Last Byte of Data - - int DataLen = Length - CheckLen; - int PadLength = 255 - Length; // Padding bytes needed for shortened RS codes - - *blnRSOK = FALSE; - - if (Length > 255 || Length < (1 + CheckLen)) //Too long or too short - return FALSE; - - if (NPAR != CheckLen) // Changed RS Len, so recalc constants; - { - NPAR = CheckLen; - xMaxErrors = NPAR / 2; - - initialize_ecc(); - } - - - // We reverse the data while zero padding it to speed things up - - // We Need (Data Reversed) (Zero Padding) (Checkbytes Reversed) - - // Reverse Data - - for (i = 0; i < DataLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - // Clear padding - - memset(ptr2, 0, PadLength); - - ptr2 += PadLength; - - // Error Bits - - ptr1 = &bytRcv[Length - 1]; // End of check bytes - - for (i = 0; i < CheckLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - decode_data(intTemp, 255); - - // check if syndrome is all zeros - - if (check_syndrome() == 0) - { - // RS ok, so no need to correct - - *blnRSOK = TRUE; - return TRUE; // No Need to Correct - } - - if (correct_errors_erasures(intTemp, 255, 0, 0) == 0) // Dont support erasures at the momnet - - // Uncorrectable - - return FALSE; - - // Data has been corrected, so need to reverse again - - ptr1 = &intTemp[DataLen - 1]; - ptr2 = bytRcv; // Last Byte of Data - - for (i = 0; i < DataLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - // ?? Do we need to return the check bytes ?? - - // Yes, so we can redo RS Check on supposedly connected frame - - ptr1 = &intTemp[254]; // End of Check Bytes - - for (i = 0; i < CheckLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - return TRUE; -} - -extern TStringList detect_list[5]; -extern TStringList detect_list_c[5]; - -void ProcessPktFrame(int snd_ch, UCHAR * Data, int frameLen) -{ - string * pkt = newString(); - - stringAdd(pkt, Data, frameLen + 2); // 2 for crc (not actually there) - - analiz_frame(snd_ch, pkt, "ARDOP", 1); - -} diff --git a/SMMain-HPLaptop.c b/SMMain-HPLaptop.c deleted file mode 100644 index 8daaf17..0000000 --- a/SMMain-HPLaptop.c +++ /dev/null @@ -1,1381 +0,0 @@ -/* -Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO - -This file is part of QtSoundModem - -QtSoundModem 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 3 of the License, or -(at your option) any later version. - -QtSoundModem 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 QtSoundModem. If not, see http://www.gnu.org/licenses - -*/ - -// UZ7HO Soundmodem Port by John Wiseman G8BPQ - -#include "UZ7HOStuff.h" -#include "fftw3.h" -#include -#include "ecc.h" // RS Constants -#include "hidapi.h" -#include -#include - -BOOL KISSServ; -int KISSPort; - -BOOL AGWServ; -int AGWPort; - -int Number = 0; // Number waiting to be sent - -int SoundIsPlaying = 0; -int UDPSoundIsPlaying = 0; -int Capturing = 0; - -extern unsigned short buffer[2][1200]; -extern int SoundMode; -extern int needRSID[4]; - -extern short * DMABuffer; - -unsigned short * SendtoCard(unsigned short * buf, int n); -short * SoundInit(); -void DoTX(int Chan); -void UDPPollReceivedSamples(); - - -extern int SampleNo; - -extern int pnt_change[5]; // Freq Changed Flag - -// fftw library interface - - -fftwf_complex *in, *out; -fftwf_plan p; - -#define N 2048 - -void initfft() -{ - in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * N); - out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * N); - p = fftwf_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE); -} - -void dofft(short * inp, float * outr, float * outi) -{ - int i; - - fftwf_complex * fft = in; - - for (i = 0; i < N; i++) - { - fft[0][0] = inp[0] * 1.0f; - fft[0][1] = 0; - fft++; - inp++; - } - - fftwf_execute(p); - - fft = out; - - for (i = 0; i < N; i++) - { - outr[0] = fft[0][0]; - outi[0] = fft[0][1]; - fft++; - outi++; - outr++; - } -} - -void freefft() -{ - fftwf_destroy_plan(p); - fftwf_free(in); - fftwf_free(out); -} - -int nonGUIMode = 0; - -void soundMain() -{ - // non platform specific initialisation - - platformInit(); - - // initialise fft library - - RsCreate(); // RS code for MPSK - - detector_init(); - KISS_init(); - ax25_init(); - init_raduga(); // Set up waterfall colour table - - initfft(); - - if (nonGUIMode) - { - Firstwaterfall = 0; - Secondwaterfall = 0; - } - - OpenPTTPort(); -} - - -void SampleSink(int LR, short Sample) -{ - // This version is passed samples one at a time, as we don't have - // enough RAM in embedded systems to hold a full audio frame - - // LR - 1 == Right Chan - -#ifdef TEENSY - int work = Sample; - DMABuffer[Number++] = (work + 32768) >> 4; // 12 bit left justify -#else - if (SCO) // Single Channel Output - same to both L and R - { - DMABuffer[2 * Number] = Sample; - DMABuffer[1 + 2 * Number] = Sample; - - } - else - { - if (LR) // Right - { - DMABuffer[1 + 2 * Number] = Sample; - DMABuffer[2 * Number] = 0; - } - else - { - DMABuffer[2 * Number] = Sample; - DMABuffer[1 + 2 * Number] = 0; - } - } - Number++; -#endif - if (Number >= SendSize) - { - // send this buffer to sound interface - - DMABuffer = SendtoCard(DMABuffer, SendSize); - Number = 0; - } - - -// Last120[Last120Put++] = Sample; - -// if (Last120Put == (intN + 1)) -// Last120Put = 0; - - SampleNo++; -} - - -void Flush() -{ - SoundFlush(Number); -} - -int ipow(int base, int exp) -{ - int result = 1; - while (exp) - { - if (exp & 1) - result *= base; - exp >>= 1; - base *= base; - } - - return result; -} - -int NumberOfBitsNeeded(int PowerOfTwo) -{ - int i; - - for (i = 0; i <= 16; i++) - { - if ((PowerOfTwo & ipow(2, i)) != 0) - return i; - - } - return 0; -} - - -int ReverseBits(int Index, int NumBits) -{ - int i, Rev = 0; - - for (i = 0; i < NumBits; i++) - { - Rev = (Rev * 2) | (Index & 1); - Index = Index / 2; - } - - return Rev; -} - - -void FourierTransform(int NumSamples, short * RealIn, float * RealOut, float * ImagOut, int InverseTransform) -{ - float AngleNumerator; - unsigned char NumBits; - - int i, j, K, n, BlockSize, BlockEnd; - float DeltaAngle, DeltaAr; - float Alpha, Beta; - float TR, TI, AR, AI; - - if (InverseTransform) - AngleNumerator = -2.0f * M_PI; - else - AngleNumerator = 2.0f * M_PI; - - NumBits = NumberOfBitsNeeded(NumSamples); - - for (i = 0; i < NumSamples; i++) - { - j = ReverseBits(i, NumBits); - RealOut[j] = RealIn[i]; - ImagOut[j] = 0.0f; // Not using i in ImageIn[i]; - } - - BlockEnd = 1; - BlockSize = 2; - - while (BlockSize <= NumSamples) - { - DeltaAngle = AngleNumerator / BlockSize; - Alpha = sinf(0.5f * DeltaAngle); - Alpha = 2.0f * Alpha * Alpha; - Beta = sinf(DeltaAngle); - - i = 0; - - while (i < NumSamples) - { - AR = 1.0f; - AI = 0.0f; - - j = i; - - for (n = 0; n < BlockEnd; n++) - { - K = j + BlockEnd; - TR = AR * RealOut[K] - AI * ImagOut[K]; - TI = AI * RealOut[K] + AR * ImagOut[K]; - RealOut[K] = RealOut[j] - TR; - ImagOut[K] = ImagOut[j] - TI; - RealOut[j] = RealOut[j] + TR; - ImagOut[j] = ImagOut[j] + TI; - DeltaAr = Alpha * AR + Beta * AI; - AI = AI - (Alpha * AI - Beta * AR); - AR = AR - DeltaAr; - j = j + 1; - } - i = i + BlockSize; - } - BlockEnd = BlockSize; - BlockSize = BlockSize * 2; - } - - if (InverseTransform) - { - // Normalize the resulting time samples... - - for (i = 0; i < NumSamples; i++) - { - RealOut[i] = RealOut[i] / NumSamples; - ImagOut[i] = ImagOut[i] / NumSamples; - } - } -} - - - -int LastBusyCheck = 0; - -extern UCHAR CurrentLevel; - -#ifdef PLOTSPECTRUM -float dblMagSpectrum[206]; -float dblMaxScale = 0.0f; -extern UCHAR Pixels[4096]; -extern UCHAR * pixelPointer; -#endif - -extern int blnBusyStatus; -BusyDet = 0; - -#define PLOTWATERFALL - -int WaterfallActive = 1; -int SpectrumActive; - -/* - -void UpdateBusyDetector(short * bytNewSamples) -{ - float dblReF[1024]; - float dblImF[1024]; - float dblMag[206]; -#ifdef PLOTSPECTRUM - float dblMagMax = 0.0000000001f; - float dblMagMin = 10000000000.0f; -#endif - UCHAR Waterfall[256]; // Colour index values to send to GUI - int clrTLC = Lime; // Default Bandwidth lines on waterfall - - static BOOL blnLastBusyStatus; - - float dblMagAvg = 0; - int intTuneLineLow, intTuneLineHi, intDelta; - int i; - - // if (State != SearchingForLeader) - // return; // only when looking for leader - - if (Now - LastBusyCheck < 100) - return; - - LastBusyCheck = Now; - - FourierTransform(1024, bytNewSamples, &dblReF[0], &dblImF[0], FALSE); - - for (i = 0; i < 206; i++) - { - // starting at ~300 Hz to ~2700 Hz Which puts the center of the signal in the center of the window (~1500Hz) - - dblMag[i] = powf(dblReF[i + 25], 2) + powf(dblImF[i + 25], 2); // first pass - dblMagAvg += dblMag[i]; -#ifdef PLOTSPECTRUM - dblMagSpectrum[i] = 0.2f * dblMag[i] + 0.8f * dblMagSpectrum[i]; - dblMagMax = max(dblMagMax, dblMagSpectrum[i]); - dblMagMin = min(dblMagMin, dblMagSpectrum[i]); -#endif - } - - // LookforPacket(dblMag, dblMagAvg, 206, &dblReF[25], &dblImF[25]); - // packet_process_samples(bytNewSamples, 1200); - - intDelta = roundf(500 / 2) + 50 / 11.719f; - - intTuneLineLow = max((103 - intDelta), 3); - intTuneLineHi = min((103 + intDelta), 203); - -// if (ProtocolState == DISC) // ' Only process busy when in DISC state - { - // blnBusyStatus = BusyDetect3(dblMag, intTuneLineLow, intTuneLineHi); - - if (blnBusyStatus && !blnLastBusyStatus) - { -// QueueCommandToHost("BUSY TRUE"); -// newStatus = TRUE; // report to PTC - - if (!WaterfallActive && !SpectrumActive) - { - UCHAR Msg[2]; - -// Msg[0] = blnBusyStatus; -// SendtoGUI('B', Msg, 1); - } - } - // stcStatus.Text = "TRUE" - // queTNCStatus.Enqueue(stcStatus) - // 'Debug.WriteLine("BUSY TRUE @ " & Format(DateTime.UtcNow, "HH:mm:ss")) - - else if (blnLastBusyStatus && !blnBusyStatus) - { -// QueueCommandToHost("BUSY FALSE"); -// newStatus = TRUE; // report to PTC - - if (!WaterfallActive && !SpectrumActive) - { - UCHAR Msg[2]; - - Msg[0] = blnBusyStatus; -// SendtoGUI('B', Msg, 1); - } - } - // stcStatus.Text = "FALSE" - // queTNCStatus.Enqueue(stcStatus) - // 'Debug.WriteLine("BUSY FALSE @ " & Format(DateTime.UtcNow, "HH:mm:ss")) - - blnLastBusyStatus = blnBusyStatus; - } - - if (BusyDet == 0) - clrTLC = Goldenrod; - else if (blnBusyStatus) - clrTLC = Fuchsia; - - // At the moment we only get here what seaching for leader, - // but if we want to plot spectrum we should call - // it always - - - - if (WaterfallActive) - { -#ifdef PLOTWATERFALL - dblMagAvg = log10f(dblMagAvg / 5000.0f); - - for (i = 0; i < 206; i++) - { - // The following provides some AGC over the waterfall to compensate for avg input level. - - float y1 = (0.25f + 2.5f / dblMagAvg) * log10f(0.01 + dblMag[i]); - int objColor; - - // Set the pixel color based on the intensity (log) of the spectral line - if (y1 > 6.5) - objColor = Orange; // Strongest spectral line - else if (y1 > 6) - objColor = Khaki; - else if (y1 > 5.5) - objColor = Cyan; - else if (y1 > 5) - objColor = DeepSkyBlue; - else if (y1 > 4.5) - objColor = RoyalBlue; - else if (y1 > 4) - objColor = Navy; - else - objColor = Black; - - if (i == 102) - Waterfall[i] = Tomato; // 1500 Hz line (center) - else if (i == intTuneLineLow || i == intTuneLineLow - 1 || i == intTuneLineHi || i == intTuneLineHi + 1) - Waterfall[i] = clrTLC; - else - Waterfall[i] = objColor; // ' Else plot the pixel as received - } - - // Send Signal level and Busy indicator to save extra packets - - Waterfall[206] = CurrentLevel; - Waterfall[207] = blnBusyStatus; - - doWaterfall(Waterfall); -#endif - } - else if (SpectrumActive) - { -#ifdef PLOTSPECTRUM - // This performs an auto scaling mechansim with fast attack and slow release - if (dblMagMin / dblMagMax < 0.0001) // more than 10000:1 difference Max:Min - dblMaxScale = max(dblMagMax, dblMaxScale * 0.9f); - else - dblMaxScale = max(10000 * dblMagMin, dblMagMax); - -// clearDisplay(); - - for (i = 0; i < 206; i++) - { - // The following provides some AGC over the spectrum to compensate for avg input level. - - float y1 = -0.25f * (SpectrumHeight - 1) * log10f((max(dblMagSpectrum[i], dblMaxScale / 10000)) / dblMaxScale); // ' range should be 0 to bmpSpectrumHeight -1 - int objColor = Yellow; - - Waterfall[i] = round(y1); - } - - // Send Signal level and Busy indicator to save extra packets - - Waterfall[206] = CurrentLevel; - Waterfall[207] = blnBusyStatus; - Waterfall[208] = intTuneLineLow; - Waterfall[209] = intTuneLineHi; - -// SendtoGUI('X', Waterfall, 210); -#endif - } -} - -*/ - -extern short rawSamples[2400]; // Get Frame Type need 2400 and we may add 1200 -int rawSamplesLength = 0; -extern int maxrawSamplesLength; - -void ProcessNewSamples(short * Samples, int nSamples) -{ - if (SoundIsPlaying == FALSE && UDPSoundIsPlaying == FALSE) - BufferFull(Samples, nSamples); -}; - -void doCalib(int Chan, int Act) -{ - if (Chan == 0 && calib_mode[1]) - return; - - if (Chan == 1 && calib_mode[0]) - return; - - calib_mode[Chan] = Act; - - if (Act == 0) - { - tx_status[Chan] = TX_SILENCE; // Stop TX - Flush(); - RadioPTT(Chan, 0); - Debugprintf("Stop Calib"); - } -} - -int Freq_Change(int Chan, int Freq) -{ - int low, high; - - low = round(rx_shift[1] / 2 + RCVR[Chan] * rcvr_offset[Chan] + 1); - high = round(RX_Samplerate / 2 - (rx_shift[Chan] / 2 + RCVR[Chan] * rcvr_offset[Chan])); - - if (Freq < low) - return rx_freq[Chan]; // Dont allow change - - if (Freq > high) - return rx_freq[Chan]; // Dont allow change - - rx_freq[Chan] = Freq; - tx_freq[Chan] = Freq; - - pnt_change[Chan] = TRUE; - wf_pointer(soundChannel[Chan]); - - return Freq; -} - -void MainLoop() -{ - // Called by background thread every 10 ms (maybe) - - // Actually we may have two cards - - // Original only allowed one channel per card. - // I think we should be able to run more, ie two or more - // modems on same soundcard channel - - // So All the soundcard stuff will need to be generalised - - if (UDPServ) - UDPPollReceivedSamples(); - - if (SoundMode == 3) - UDPPollReceivedSamples(); - else - PollReceivedSamples(); - - - if (modem_mode[0] == MODE_ARDOP) - { - chk_dcd1(0, 512); - } - - DoTX(0); - DoTX(1); - DoTX(2); - DoTX(3); - -} - -int ARDOPSendToCard(int Chan, int Len) -{ - // Send Next Block of samples to the soundcard - - short * in = &ARDOPTXBuffer[Chan][ARDOPTXPtr[Chan]]; // Enough to hold whole frame of samples - short * out = DMABuffer; - - int LR = modemtoSoundLR[Chan]; - - int i; - - for (i = 0; i < Len; i++) - { - if (SCO) // Single Channel Output - same to both L and R - { - *out++ = *in; - *out++ = *in++; - } - else - { - if (LR) // Right - { - *out++ = 0; - *out++ = *in++; - } - else - { - *out++ = *in++; - *out++ = 0; - } - } - } - DMABuffer = SendtoCard(DMABuffer, Len); - - ARDOPTXPtr[Chan] += Len; - - // See if end of buffer - - if (ARDOPTXPtr[Chan] > ARDOPTXLen[Chan]) - return 1; - - return 0; -} -void DoTX(int Chan) -{ - // This kicks off a send sequence or calibrate - -// printtick("dotx"); - - if (calib_mode[Chan]) - { - // Maybe new calib or continuation - - if (pnt_change[Chan]) - { - make_core_BPF(Chan, rx_freq[Chan], bpf[Chan]); - make_core_TXBPF(Chan, tx_freq[Chan], txbpf[Chan]); - pnt_change[Chan] = FALSE; - } - - // Note this may block in SendtoCard - - modulator(Chan, tx_bufsize); - return; - } - - // I think we have to detect NO_DATA here and drop PTT and return to SILENCE - - if (tx_status[Chan] == TX_NO_DATA) - { - Flush(); - Debugprintf("TX Complete"); - RadioPTT(0, 0); - tx_status[Chan] = TX_SILENCE; - - // We should now send any ackmode acks as the channel is now free for dest to reply - - sendAckModeAcks(Chan); - } - - if (tx_status[Chan] != TX_SILENCE) - { - // Continue the send - - if (modem_mode[Chan] == MODE_ARDOP) - { -// if (SeeIfCardBusy()) -// return 0; - - if (ARDOPSendToCard(Chan, SendSize) == 1) - { - // End of TX - - Number = 0; - Flush(); - - // See if more to send. If so, don't drop PTT - - if (all_frame_buf[Chan].Count) - { - SoundIsPlaying = TRUE; - Number = 0; - - Debugprintf("TX Continuing"); - - string * myTemp = Strings(&all_frame_buf[Chan], 0); // get message - string * tx_data; - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[Chan], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data = duplicateString(myTemp); // so can free original below - - Delete(&all_frame_buf[Chan], 0); // This will invalidate temp - - AGW_AX25_frame_analiz(Chan, FALSE, tx_data); - - put_frame(Chan, tx_data, "", TRUE, FALSE); - - PktARDOPEncode(tx_data->Data, tx_data->Length - 2, Chan); - - freeString(tx_data); - - // Samples are now in DMABuffer = Send first block - - ARDOPSendToCard(Chan, SendSize); - tx_status[Chan] = TX_FRAME; - return; - } - - Debugprintf("TX Complete"); - RadioPTT(0, 0); - tx_status[Chan] = TX_SILENCE; - - // We should now send any ackmode acks as the channel is now free for dest to reply - } - - return; - } - - modulator(Chan, tx_bufsize); - return; - } - - if (SoundIsPlaying || UDPSoundIsPlaying) - return; - - // Not doing anything so see if we have anything new to send - - // See if frequency has changed - - if (pnt_change[Chan]) - { - make_core_BPF(Chan, rx_freq[Chan], bpf[Chan]); - make_core_TXBPF(Chan, tx_freq[Chan], txbpf[Chan]); - pnt_change[Chan] = FALSE; - } - - // See if we need an RSID - - if (needRSID[Chan]) - { - needRSID[Chan] = 0; - - // Note this may block in SampleSink - - Debugprintf("Sending RSID"); - sendRSID(Chan, all_frame_buf[Chan].Count == 0); - return; - } - - if (all_frame_buf[Chan].Count == 0) - return; - - // Start a new send. modulator should handle TXD etc - - Debugprintf("TX Start"); - SampleNo = 0; - - SoundIsPlaying = TRUE; - RadioPTT(Chan, 1); - Number = 0; - - if (modem_mode[Chan] == MODE_ARDOP) - { - // I think ARDOP will have to generate a whole frame of samples - // then send them out a bit at a time to avoid stopping here for - // possibly 10's of seconds - - // Can do this here as unlike normal ardop we don't need to run on Teensy - // to 12000 sample rate we need either 24K or 48K per second, depending on - // where we do the stereo mux. - - // Slowest rate is 50 baud, so a 255 byte packet would take about a minute - // allowing for RS overhead. Not really realistic put perhaps should be possible. - // RAM isn't an issue so maybe allocate 2 MB. - - // ?? Should we allow two ARDOP modems - could make sense if we can run sound - // card channels independently - - string * myTemp = Strings(&all_frame_buf[Chan], 0); // get message - string * tx_data; - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[Chan], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data = duplicateString(myTemp); // so can free original below - - Delete(&all_frame_buf[Chan], 0); // This will invalidate temp - - AGW_AX25_frame_analiz(Chan, FALSE, tx_data); - - put_frame(Chan, tx_data, "", TRUE, FALSE); - - PktARDOPEncode(tx_data->Data, tx_data->Length - 2, Chan); - - freeString(tx_data); - - // Samples are now in DMABuffer = Send first block - - ARDOPSendToCard(Chan, SendSize); - tx_status[Chan] = TX_FRAME; - - } - else - modulator(Chan, tx_bufsize); - - return; -} - -void stoptx(int snd_ch) -{ - Flush(); - Debugprintf("TX Complete"); - RadioPTT(snd_ch, 0); - tx_status[snd_ch] = TX_SILENCE; - - snd_status[snd_ch] = SND_IDLE; -} - -void RX2TX(int snd_ch) -{ - if (snd_status[snd_ch] == SND_IDLE) - { - DoTX(snd_ch); - } -} - -// PTT Stuff - -int hPTTDevice = 0; -char PTTPort[80] = ""; // Port for Hardware PTT - may be same as control port. -int PTTBAUD = 19200; -int PTTMode = PTTRTS; // PTT Control Flags. - -char PTTOnString[128] = ""; -char PTTOffString[128] = ""; - -UCHAR PTTOnCmd[64]; -UCHAR PTTOnCmdLen = 0; - -UCHAR PTTOffCmd[64]; -UCHAR PTTOffCmdLen = 0; - -int pttGPIOPin = 17; // Default -int pttGPIOPinR = 17; -BOOL pttGPIOInvert = FALSE; -BOOL useGPIO = FALSE; -BOOL gotGPIO = FALSE; - -int HamLibPort = 4532; -char HamLibHost[32] = "192.168.1.14"; - -char CM108Addr[80] = ""; - -int VID = 0; -int PID = 0; - -// CM108 Code - -char * CM108Device = NULL; - -void DecodeCM108(char * ptr) -{ - // Called if Device Name or PTT = Param is CM108 - -#ifdef WIN32 - - // Next Param is VID and PID - 0xd8c:0x8 or Full device name - // On Windows device name is very long and difficult to find, so - // easier to use VID/PID, but allow device in case more than one needed - - char * next; - long VID = 0, PID = 0; - char product[256] = "Unknown"; - - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - if (strlen(ptr) > 16) - CM108Device = _strdup(ptr); - else - { - VID = strtol(ptr, &next, 0); - if (next) - PID = strtol(++next, &next, 0); - - // Look for Device - - devs = hid_enumerate((unsigned short)VID, (unsigned short)PID); - cur_dev = devs; - - while (cur_dev) - { - if (cur_dev->product_string) - wcstombs(product, cur_dev->product_string, 255); - - Debugprintf("HID Device %s VID %X PID %X", product, cur_dev->vendor_id, cur_dev->product_id); - if (cur_dev->vendor_id == VID && cur_dev->product_id == PID) - { - path_to_open = cur_dev->path; - break; - } - cur_dev = cur_dev->next; - } - - if (path_to_open) - { - handle = hid_open_path(path_to_open); - - if (handle) - { - hid_close(handle); - CM108Device = _strdup(path_to_open); - } - else - { - Debugprintf("Unable to open CM108 device %x %x", VID, PID); - } - } - else - Debugprintf("Couldn't find CM108 device %x %x", VID, PID); - - hid_free_enumeration(devs); - } -#else - - // Linux - Next Param HID Device, eg /dev/hidraw0 - - CM108Device = _strdup(ptr); -#endif -} - -char * strlop(char * buf, char delim) -{ - // Terminate buf at delim, and return rest of string - - char * ptr = strchr(buf, delim); - - if (ptr == NULL) return NULL; - - *(ptr)++ = 0; - return ptr; -} - -void OpenPTTPort() -{ - PTTMode &= ~PTTCM108; - PTTMode &= ~PTTHAMLIB; - - if (PTTPort[0] && strcmp(PTTPort, "None") != 0) - { - if (PTTMode == PTTCAT) - { - // convert config strings from Hex - - char * ptr1 = PTTOffString; - UCHAR * ptr2 = PTTOffCmd; - char c; - int val; - - while (c = *(ptr1++)) - { - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(ptr2++) = val; - } - - PTTOffCmdLen = ptr2 - PTTOffCmd; - - ptr1 = PTTOnString; - ptr2 = PTTOnCmd; - - while (c = *(ptr1++)) - { - val = c - 0x30; - if (val > 15) val -= 7; - val <<= 4; - c = *(ptr1++) - 0x30; - if (c > 15) c -= 7; - val |= c; - *(ptr2++) = val; - } - - PTTOnCmdLen = ptr2 - PTTOnCmd; - } - - if (stricmp(PTTPort, "GPIO") == 0) - { - // Initialise GPIO for PTT if available - -#ifdef __ARM_ARCH - - if (gpioInitialise() == 0) - { - printf("GPIO interface for PTT available\n"); - gotGPIO = TRUE; - - SetupGPIOPTT(); - } - else - printf("Couldn't initialise GPIO interface for PTT\n"); - -#else - printf("GPIO interface for PTT not available on this platform\n"); -#endif - - } - else if (stricmp(PTTPort, "CM108") == 0) - { - DecodeCM108(CM108Addr); - PTTMode |= PTTCM108; - } - - else if (stricmp(PTTPort, "HAMLIB") == 0) - { - PTTMode |= PTTHAMLIB; - HAMLIBSetPTT(0); // to open port - return; - } - - else // Not GPIO - { - hPTTDevice = OpenCOMPort(PTTPort, PTTBAUD, FALSE, FALSE, FALSE, 0); - } - } -} - -void ClosePTTPort() -{ - CloseCOMPort(hPTTDevice); - hPTTDevice = 0; -} -void CM108_set_ptt(int PTTState) -{ - char io[5]; - hid_device *handle; - int n; - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - if (CM108Device == NULL) - return; - -#ifdef WIN32 - handle = hid_open_path(CM108Device); - - if (!handle) { - printf("unable to open device\n"); - return; - } - - n = hid_write(handle, io, 5); - if (n < 0) - { - printf("Unable to write()\n"); - printf("Error: %ls\n", hid_error(handle)); - } - - hid_close(handle); - -#else - - int fd; - - fd = open(CM108Device, O_WRONLY); - - if (fd == -1) - { - printf("Could not open %s for write, errno=%d\n", CM108Device, errno); - return; - } - - io[0] = 0; - io[1] = 0; - io[2] = 1 << (3 - 1); - io[3] = PTTState << (3 - 1); - io[4] = 0; - - n = write(fd, io, 5); - if (n != 5) - { - printf("Write to %s failed, n=%d, errno=%d\n", CM108Device, n, errno); - } - - close(fd); -#endif - return; - -} - - - -void RadioPTT(int snd_ch, BOOL PTTState) -{ -#ifdef __ARM_ARCH - if (useGPIO) - { - if (DualPTT && modemtoSoundLR[snd_ch] == 1) - gpioWrite(pttGPIOPinR, (pttGPIOInvert ? (1 - PTTState) : (PTTState))); - else - gpioWrite(pttGPIOPin, (pttGPIOInvert ? (1 - PTTState) : (PTTState))); - - return; - } - -#endif - - if ((PTTMode & PTTCM108)) - { - CM108_set_ptt(PTTState); - return; - } - - if ((PTTMode & PTTHAMLIB)) - { - HAMLIBSetPTT(PTTState); - return; - } - if (hPTTDevice == 0) - return; - - if ((PTTMode & PTTCAT)) - { - if (PTTState) - WriteCOMBlock(hPTTDevice, PTTOnCmd, PTTOnCmdLen); - else - WriteCOMBlock(hPTTDevice, PTTOffCmd, PTTOffCmdLen); - - return; - } - - if (DualPTT && modemtoSoundLR[snd_ch] == 1) // use DTR - { - if (PTTState) - COMSetDTR(hPTTDevice); - else - COMClearDTR(hPTTDevice); - } - else - { - if ((PTTMode & PTTRTS)) - { - if (PTTState) - COMSetRTS(hPTTDevice); - else - COMClearRTS(hPTTDevice); - } - } - -} - -char ShortDT[] = "HH:MM:SS"; - -char * ShortDateTime() -{ - struct tm * tm; - time_t NOW = time(NULL); - - tm = gmtime(&NOW); - - sprintf(ShortDT, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - return ShortDT; -} - - -// Reed Solomon Stuff - - -int NPAR = -1; // Number of Parity Bytes - used in RS Code - -int xMaxErrors = 0; - -int RSEncode(UCHAR * bytToRS, UCHAR * RSBytes, int DataLen, int RSLen) -{ - // This just returns the Parity Bytes. I don't see the point - // in copying the message about - - unsigned char Padded[256]; // The padded Data - - int Length = DataLen + RSLen; // Final Length of packet - int PadLength = 255 - Length; // Padding bytes needed for shortened RS codes - - // subroutine to do the RS encode. For full length and shortend RS codes up to 8 bit symbols (mm = 8) - - if (NPAR != RSLen) // Changed RS Len, so recalc constants; - { - NPAR = RSLen; - xMaxErrors = NPAR / 2; - initialize_ecc(); - } - - // Copy the supplied data to end of data array. - - memset(Padded, 0, PadLength); - memcpy(&Padded[PadLength], bytToRS, DataLen); - - encode_data(Padded, 255 - RSLen, RSBytes); - - return RSLen; -} - -// Main RS decode function - -extern int index_of[]; -extern int recd[]; -extern int Corrected[256]; -extern int tt; // number of errors that can be corrected -extern int kk; // Info Symbols - -extern BOOL blnErrorsCorrected; - - -BOOL RSDecode(UCHAR * bytRcv, int Length, int CheckLen, BOOL * blnRSOK) -{ - - - // Using a modified version of Henry Minsky's code - - //Copyright Henry Minsky (hqm@alum.mit.edu) 1991-2009 - - // Rick's Implementation processes the byte array in reverse. and also - // has the check bytes in the opposite order. I've modified the encoder - // to allow for this, but so far haven't found a way to mske the decoder - // work, so I have to reverse the data and checksum to decode G8BPQ Nov 2015 - - // returns TRUE if was ok or correction succeeded, FALSE if correction impossible - - UCHAR intTemp[256]; // WOrk Area to pass to Decoder - int i; - UCHAR * ptr2 = intTemp; - UCHAR * ptr1 = &bytRcv[Length - CheckLen - 1]; // Last Byte of Data - - int DataLen = Length - CheckLen; - int PadLength = 255 - Length; // Padding bytes needed for shortened RS codes - - *blnRSOK = FALSE; - - if (Length > 255 || Length < (1 + CheckLen)) //Too long or too short - return FALSE; - - if (NPAR != CheckLen) // Changed RS Len, so recalc constants; - { - NPAR = CheckLen; - xMaxErrors = NPAR / 2; - - initialize_ecc(); - } - - - // We reverse the data while zero padding it to speed things up - - // We Need (Data Reversed) (Zero Padding) (Checkbytes Reversed) - - // Reverse Data - - for (i = 0; i < DataLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - // Clear padding - - memset(ptr2, 0, PadLength); - - ptr2 += PadLength; - - // Error Bits - - ptr1 = &bytRcv[Length - 1]; // End of check bytes - - for (i = 0; i < CheckLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - decode_data(intTemp, 255); - - // check if syndrome is all zeros - - if (check_syndrome() == 0) - { - // RS ok, so no need to correct - - *blnRSOK = TRUE; - return TRUE; // No Need to Correct - } - - if (correct_errors_erasures(intTemp, 255, 0, 0) == 0) // Dont support erasures at the momnet - - // Uncorrectable - - return FALSE; - - // Data has been corrected, so need to reverse again - - ptr1 = &intTemp[DataLen - 1]; - ptr2 = bytRcv; // Last Byte of Data - - for (i = 0; i < DataLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - // ?? Do we need to return the check bytes ?? - - // Yes, so we can redo RS Check on supposedly connected frame - - ptr1 = &intTemp[254]; // End of Check Bytes - - for (i = 0; i < CheckLen; i++) - { - *(ptr2++) = *(ptr1--); - } - - return TRUE; -} - -extern TStringList detect_list[5]; -extern TStringList detect_list_c[5]; - -void ProcessPktFrame(int snd_ch, UCHAR * Data, int frameLen) -{ - string * pkt = newString(); - - stringAdd(pkt, Data, frameLen + 2); // 2 for crc (not actually there) - - analiz_frame(snd_ch, pkt, "ARDOP", 1); - -} diff --git a/SMMain.c b/SMMain.c index 141947b..24f6159 100644 --- a/SMMain.c +++ b/SMMain.c @@ -32,6 +32,8 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses BOOL KISSServ; int KISSPort; +int NeedWaterfallHeaders = 0; + BOOL AGWServ; int AGWPort; @@ -566,7 +568,7 @@ int Freq_Change(int Chan, int Freq) tx_freq[Chan] = Freq; pnt_change[Chan] = TRUE; - wf_pointer(Chan); + NeedWaterfallHeaders = TRUE; return Freq; } @@ -1203,7 +1205,7 @@ void CM108_set_ptt(int PTTState) } -float amplitudes[4] = { 32767, 32767, 32767, 32767 }; +float amplitudes[4] = { 32000, 32000, 32000, 32000 }; extern float amplitude; void RadioPTT(int snd_ch, BOOL PTTState) diff --git a/UZ7HOStuff-DESKTOP-MHE5LO8.h b/UZ7HOStuff-DESKTOP-MHE5LO8.h deleted file mode 100644 index 20721cc..0000000 --- a/UZ7HOStuff-DESKTOP-MHE5LO8.h +++ /dev/null @@ -1,1110 +0,0 @@ -#pragma once - -// -// My port of UZ7HO's Soundmodem -// - -#define VersionString "0.0.0.67alpha-6" -#define VersionBytes {0, 0, 0, 67} - -// Added FX25. 4x100 FEC and V27 not Working and disabled - -// 0.8 V27 now OK. - -// 0.9 Digipeating added - -// 0.10 Fix second channel tones and calibrate - -// 0.11 Fix allocation of sessions to correct modem -// Fix DCD -// Fix Monitoring of Multiline packets -// Fix possible saving of wrong center freq -// Limit TX sample Q in Linux -// - -// 0.12 Add AGWPE monitoring of received frames -// Fix DCD Threshold -// Fix KISS transparency issue - -// 0.13 Fix sending last few bits in FX.25 Mode - -// 0.14 Add "Copy on Select" to Trace Window - -// 0.15 Limit Trace window to 10000 lines - -// 0.16 Fix overwriting monitor window after scrollback - -// 0.17 Add GPIO and CAT PTT - -// 0.18 Add CM108/119 PTT - -// 0.19 Fix scheduling KISS frames - -// 0.20 Debug code added to RR processing - -// 0.21 Fix AGW monitor of multiple line packets -// Close ax.25 sessions if AGW Host session closes - -// 0.22 Add FEC Count to Session Stats - -// 0.23 Retry DISC until UA received or retry count exceeded - -// 0.24 More fixes to DISC handling - -// 0.26 Add OSS PulseAudio and HAMLIB support - -// 0.27 Dynamically load PulseAudio modules - -// 0.28 Add ARDOPPacket Mode - -// 0.29 Fix saving settings and geometry on close -// 0.30 Retructure code to build with Qt 5.3 -// Fix crash in nogui mode if pulse requested but not available -// Try to fix memory leaks - -// 0.31 Add option to run modems in seprate threads - -// 0.32 Fix timing problem with AGW connect at startup -// Add Memory ARQ -// Add Single bit "Correction" -// Fix error in 31 when using multiple decoders - -// 0.33 Fix Single bit correction -// More memory leak fixes - -// 0.34 Add API to set Modem and Center Frequency -// Fix crash in delete_incoming_mycalls - -// 0.35 Return Version in AGW Extended g response - -// 0.36 Fix timing problem on startup - -// 0.37 Add scrollbars to Device and Modem dialogs - -// 0.38 Change default CM108 name to /dev/hidraw0 on Linux - -// 0.39 Dont try to display Message Boxes in nogui mode. -// Close Device and Modem dialogs on Accept or Reject -// Fix using HAMLIB in nogui mode - -// 0.40 Fix bug in frame optimize when using 6 char calls - -// 0.41 Fix "glitch" on waterfall markers when changing modem freqs - -// 0.42 Add "Minimize to Tray" option - -// 0.43 Add Andy's on_SABM fix. -// Fix Crash if KISS Data sent to AGW port - -// 0.44 Add UDP bridge. - -// 0.45 Add two more modems. -// 0.46 Fix two more modems. - -// 0.47 Fix suprious DM when host connection lost -// Add CWID - -// 0.48 Send FRMR for unrecognised frame types - -// 0.49 Add Andy's FEC Tag correlation coode - -// 0.50 Fix Waterfall display when only using right channel -// Allow 1200 baud fsk at other center freqs -// Add Port numbers to Window title and Try Icon tooltip -// Fix calculation of filters for multiple decoders -// Add RX Offset setting (for satellite operation - -// 0.51 Fix Multithreading with more that 2 modems - -// 0.52 Add Stdin as source on Linux - -// 0.53 Use Byte instead of byte as byte is defined in newer versions of gcc - -// 0.54 Fix for ALSA problem on new pi OS - -// 0.55 Fix for compiler error with newer compiler - -// 0.56 Fix errors in Config.cpp June 22 - -// 0.57 Add Restart Waterfall action August 22 - -// 0.58 Add RSID Sept 2022 - -// 0.59 Add config of Digi Calls Dec 2022 - -// 0.60 Allow ARDOP Packet on modems 2 to 4 March 2023 - -// 0.61 Add il2p support April 2023 - -// 0.62 April 2023 -// Add option to specify sound devices that aren't in list -// Add Save button to Modem dialog to save current tab without closing dialog -// Don't add plug: to Linux device addresses unless addr contains : (allows use of eg ARDOP) - -// 0.64 Fix sending ax.25 (broken in .61) - -// 0.65 Allow Set Modem command to use modem index as well as modem name - -// 0.66 Allow configuration of waterfall span June 23 -// Add Exclude - -// .67 Add extra modes RUH 4800 RUH 9600 QPSK 600 QPSK 2400 July 23 -// 8PSK 900 added but not working -// Fix loading txtail -// Fix digipeating -// Add MaxFrame to Modem Dialog - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNUSED(x) (void)(x) - -#ifdef M_PI -#undef M_PI -#endif - -#define M_PI 3.1415926f - -#define pi M_PI - -#ifndef WIN32 -#define _strdup strdup -#endif - - //#define NULL ((void *)0) - - //Delphi Types remember case insensitive - -#define single float -#define boolean int -#define Byte unsigned char // 0 to 255 -#define Word unsigned short // 0 to 65,535 -#define SmallInt short // -32,768 to 32,767 -#define LongWord unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define LongInt int // -2,147,483,648 to 2,147,483,647 -#define Integer int // -2,147,483,648 to 2,147,483,647 -//#define Int64 long long // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 - -//#define Byte unsigned char // 0 to 255 -#define word unsigned short // 0 to 65,535 -#define smallint short // -32,768 to 32,767 -#define longword unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define longint int // -2,147,483,648 to 2,147,483,647 -#define integer int // -2,147,483,648 to 2,147,483,647 - -typedef unsigned long ULONG; - -#define UCHAR unsigned char -#define UINT unsigned int -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -// Soundcard Channels - -#define NONE 0 -#define LEFT 1 -#define RIGHT 2 - -#define nr_emph 2 - -#define decodedNormal 4 //'-' -#define decodedFEC 3 //'F' -#define decodedMEM 2 //'#' -#define decodedSingle 1 //'$' - - -// Think about implications of changing this !! -extern int FFTSize; - -// Seems to use Delphi TStringList for a lot of queues. This seems to be a list of pointers and a count -// Each pointer is to a Data/Length pair -//Maybe something like - -typedef struct string_T -{ - unsigned char * Data; - int Length; - int AllocatedLength; // A reasonable sized block is allocated at the start to speed up adding chars - -}string; - -typedef struct TStringList_T -{ - int Count; - string ** Items; - -} TStringList; - -// QPSK struct - -typedef struct TQPSK_t -{ - UCHAR tx[4]; - int count[4]; - UCHAR rx[4]; - UCHAR mode; -} TPQSK; - - -typedef struct TKISSMode_t -{ - string * data_in; - void * Socket; // Used as a key - - // Not sure what rest are used for. Seems to be one per channel - - TStringList buffer[4]; // Outgoing Frames - -} TKISSMode; - -typedef struct TMChannel_t -{ - - single prev_LPF1I_buf[4096]; - single prev_LPF1Q_buf[4096]; - single prev_dLPFI_buf[4096]; - single prev_dLPFQ_buf[4096]; - single prev_AFCI_buf[4096]; - single prev_AFCQ_buf[4096]; - single AngleCorr; - single MUX_osc; - single AFC_IZ1; - single AFC_IZ2; - single AFC_QZ1; - single AFC_QZ2; - single AFC_bit_buf1I[1024]; - single AFC_bit_buf1Q[1024]; - single AFC_bit_buf2[1024]; - single AFC_IIZ1; - single AFC_QQZ1; - -} TMChannel; - -typedef struct TFX25_t -{ - string data; - Byte status; - Byte bit_cnt; - Byte byte_rx; - unsigned long long tag; - Byte size; - Byte rs_size; - Byte size_cnt; -} TFX25; - - - -typedef struct TDetector_t -{ - struct TFX25_t fx25[4]; - TStringList mem_ARQ_F_buf[5]; - TStringList mem_ARQ_buf[5]; - float pll_loop[5]; - float last_sample[5]; - UCHAR ones[5]; - UCHAR zeros[5]; - float bit_buf[5][1024]; - float bit_buf1[5][1024]; - UCHAR sample_cnt[5]; - UCHAR last_bit[5]; - float PSK_IZ1[5]; - float PSK_QZ1[5]; - float PkAmpI[5]; - float PkAmpQ[5]; - float PkAmp[5]; - float PkAmpMax[5]; - int newpkpos[5]; - float AverageAmp[5]; - float AngleCorr[5]; - float MinAmp[5]; - float MaxAmp[5]; - float MUX3_osc[5]; - float MUX3_1_osc[5]; - float MUX3_2_osc[5]; - float Preemphasis6[5]; - float Preemphasis12[5]; - float PSK_AGC[5]; - float AGC[5]; - float AGC1[5]; - float AGC2[5]; - float AGC3[5]; - float AGC_max[5]; - float AGC_min[5]; - float AFC_IZ1[5]; - float AFC_IZ2[5]; - float AFC_QZ1[5]; - float AFC_QZ2[5]; - - UCHAR last_rx_bit[5]; - UCHAR bit_stream[5]; - UCHAR byte_rx[5]; - UCHAR bit_stuff_cnt[5]; - UCHAR bit_cnt[5]; - float bit_osc[5]; - UCHAR frame_status[5]; - string rx_data[5]; - string FEC_rx_data[5]; - // - UCHAR FEC_pol[5]; - unsigned short FEC_err[5]; - unsigned long long FEC_header1[5][2]; - unsigned short FEC_blk_int[5]; - unsigned short FEC_len_int[5]; - unsigned short FEC_len[5]; - - unsigned short FEC_len_cnt[5]; - - UCHAR rx_intv_tbl[5][4]; - UCHAR rx_intv_sym[5]; - UCHAR rx_viterbi[5]; - UCHAR viterbi_cnt[5]; - // SurvivorStates [1..4,0..511] of TSurvivor; - // - TMChannel MChannel[5][4]; - - float AFC_dF_avg[5]; - float AFC_dF[5]; - float AFC_bit_osc[5]; - float AFC_bit_buf[5][1024]; - unsigned short AFC_cnt[5]; - - string raw_bits1[5]; - string raw_bits[5]; - UCHAR last_nrzi_bit[5]; - - float BPF_core[5][2048]; - float LPF_core[5][2048]; - - float src_INTR_buf[5][8192]; - float src_INTRI_buf[5][8192]; - float src_INTRQ_buf[5][8192]; - float src_LPF1I_buf[5][8192]; - float src_LPF1Q_buf[5][8192]; - - float src_BPF_buf[5][2048]; - float src_Loop_buf[5][8192]; - float prev_BPF_buf[5][4096]; - - float prev_LPF1I_buf[5][4096]; - float prev_LPF1Q_buf[5][4096]; - float prev_INTR_buf[5][16384]; - float prev_INTRI_buf[5][16384]; - float prev_INTRQ_buf[5][16384]; - - Byte emph_decoded; - Byte rx_decoded; - Byte errors; - -} TDetector; - - - -typedef struct AGWUser_t -{ - void *socket; - string * data_in; - TStringList AGW_frame_buf; - boolean Monitor; - boolean Monitor_raw; - boolean reportFreqAndModem; // Can report modem and frequency to host - -} AGWUser; - -typedef struct TAX25Info_t -{ - longint stat_s_pkt; - longint stat_s_byte; - longint stat_r_pkt; - longint stat_r_byte; - longint stat_r_fc; - longint stat_fec_count; - time_t stat_begin_ses; - time_t stat_end_ses; - longint stat_l_r_byte; - longint stat_l_s_byte; - -} TAX25Info; - -typedef struct TAX25Port_t -{ - Byte hi_vs; - Byte vs; - Byte vr; - Byte PID; - TStringList in_data_buf; - TStringList frm_collector; - string frm_win[8]; - string out_data_buf; - word t1; - word t2; - word t3; - Byte i_lo; - Byte i_hi; - word n1; - word n2; - word IPOLL_cnt; - TStringList frame_buf; //áóôåð êàäðîâ íà ïåðåäà÷ó - TStringList I_frame_buf; - Byte status; - word clk_frack; - char corrcall[10]; - char mycall[10]; - UCHAR digi[56]; - UCHAR Path[80]; // Path in ax25 format - added to save building it each time - UCHAR ReversePath[80]; - int snd_ch; // Simplifies parameter passing - int port; - int pathLen; - void * socket; - char kind[16]; - TAX25Info info; -} TAX25Port; - - -#define LOGEMERGENCY 0 -#define LOGALERT 1 -#define LOGCRIT 2 -#define LOGERROR 3 -#define LOGWARNING 4 -#define LOGNOTICE 5 -#define LOGINFO 6 -#define LOGDEBUG 7 - -#define PTTRTS 1 -#define PTTDTR 2 -#define PTTCAT 4 -#define PTTCM108 8 -#define PTTHAMLIB 16 - -// Status flags - -#define STAT_NO_LINK 0 -#define STAT_LINK 1 -#define STAT_CHK_LINK 2 -#define STAT_WAIT_ANS 3 -#define STAT_TRY_LINK 4 -#define STAT_TRY_UNLINK 5 - - - // Ñmd,Resp,Poll,Final,Digipeater flags -#define SET_P 1 -#define SET_F 0 -#define SET_C 1 -#define SET_R 0 -#define SET_NO_RPT 0 -#define SET_RPT 1 - // Frame ID flags -#define I_FRM 0 -#define S_FRM 1 -#define U_FRM 2 -#define I_I 0 -#define S_RR 1 -#define S_RNR 5 -#define S_REJ 9 -#define S_SREJ 0x0D -#define U_SABM 47 -#define U_DISC 67 -#define U_DM 15 -#define U_UA 99 -#define U_FRMR 135 -#define U_UI 3 - // PID flags -#define PID_X25 0x01 // 00000001-CCIT X25 PLP -#define PID_SEGMENT 0x08 // 00001000-Segmentation fragment -#define PID_TEXNET 0xC3 // 11000011-TEXNET Datagram Protocol -#define PID_LQ 0xC4 // 11001000-Link Quality Protocol -#define PID_APPLETALK 0xCA // 11001010-Appletalk -#define PID_APPLEARP 0xCB // 11001011-Appletalk ARP -#define PID_IP 0xCC // 11001100-ARPA Internet Protocol -#define PID_ARP 0xCD // 11001101-ARPA Address Resolution Protocol -#define PID_NET_ROM 0xCF // 11001111-NET/ROM - - -// Sound interface buffer sizes - -extern int ReceiveSize; -extern int SendSize; - -#define NumberofinBuffers 4 - -#define Now getTicks() - -// #defines from all modules (?? is this a good idaa ?? - -#define WIN_MAXIMIZED 0 -#define WIN_MINIMIZED 1 -#define MODEM_CAPTION 'SoundModem by UZ7HO' -#define MODEM_VERSION '1.06' -#define SND_IDLE 0 -#define SND_TX 1 -#define BUF_EMPTY 0 -#define BUF_FULL 1 -#define DISP_MONO FALSE -#define DISP_RGB TRUE -#define MOD_IDLE 0 -#define MOD_RX 1 -#define MOD_TX 2 -#define MOD_WAIT 3 -#define TIMER_FREE 0 -#define TIMER_BUSY 1 -#define TIMER_OFF 2 -#define TIMER_EVENT_ON 3 -#define TIMER_EVENT_OFF 4 -#define DEBUG_TIMER 1 -#define DEBUG_WATERFALL 2 -#define DEBUG_DECODE 4 -#define DEBUG_SOUND 8 -#define IS_LAST TRUE -#define IS_NOT_LAST FALSE -#define modes_count 20 -#define SPEED_300 0 -#define SPEED_1200 1 -#define SPEED_600 2 -#define SPEED_2400 3 -#define SPEED_P1200 4 -#define SPEED_P600 5 -#define SPEED_P300 6 -#define SPEED_P2400 7 -#define SPEED_Q4800 8 -#define SPEED_Q3600 9 -#define SPEED_Q2400 10 -#define SPEED_MP400 11 -#define SPEED_DW2400 12 -#define SPEED_8P4800 13 -#define SPEED_2400V26B 14 -#define SPEED_ARDOP 15 -#define SPEED_Q300 16 -#define SPEED_8PSK300 17 -#define SPEED_RUH48 18 -#define SPEED_RUH96 19 - -#define MODE_FSK 0 -#define MODE_BPSK 1 -#define MODE_QPSK 2 -#define MODE_MPSK 3 -#define MODE_8PSK 4 -#define MODE_PI4QPSK 5 -#define MODE_ARDOP 6 -#define MODE_RUH 7 - -#define QPSK_SM 0 -#define QPSK_V26 1 - -#define MODEM_8P4800_BPF 3200 -#define MODEM_8P4800_TXBPF 3400 -#define MODEM_8P4800_LPF 1000 -#define MODEM_8P4800_BPF_TAP 64 -#define MODEM_8P4800_LPF_TAP 8 - // -#define MODEM_MP400_BPF 775 -#define MODEM_MP400_TXBPF 850 -#define MODEM_MP400_LPF 70 -#define MODEM_MP400_BPF_TAP 256 -#define MODEM_MP400_LPF_TAP 128 - // -#define MODEM_DW2400_BPF 2400 -#define MODEM_DW2400_TXBPF 2500 -#define MODEM_DW2400_LPF 900 -#define MODEM_DW2400_BPF_TAP 256 //256 -#define MODEM_DW2400_LPF_TAP 32 //128 - // -#define MODEM_Q2400_BPF 2400 -#define MODEM_Q2400_TXBPF 2500 -#define MODEM_Q2400_LPF 900 -#define MODEM_Q2400_BPF_TAP 256 //256 -#define MODEM_Q2400_LPF_TAP 128 //128 - // -#define MODEM_Q3600_BPF 3600 -#define MODEM_Q3600_TXBPF 3750 -#define MODEM_Q3600_LPF 1350 -#define MODEM_Q3600_BPF_TAP 256 -#define MODEM_Q3600_LPF_TAP 128 - // -#define MODEM_Q4800_BPF 4800 -#define MODEM_Q4800_TXBPF 5000 -#define MODEM_Q4800_LPF 1800 -#define MODEM_Q4800_BPF_TAP 256 -#define MODEM_Q4800_LPF_TAP 128 - // -#define MODEM_P2400_BPF 4800 -#define MODEM_P2400_TXBPF 5000 -#define MODEM_P2400_LPF 1800 -#define MODEM_P2400_BPF_TAP 256 -#define MODEM_P2400_LPF_TAP 128 - // -#define MODEM_P1200_BPF 2400 -#define MODEM_P1200_TXBPF 2500 -#define MODEM_P1200_LPF 900 -#define MODEM_P1200_BPF_TAP 256 -#define MODEM_P1200_LPF_TAP 128 - // -#define MODEM_P600_BPF 1200 -#define MODEM_P600_TXBPF 1250 -#define MODEM_P600_LPF 400 -#define MODEM_P600_BPF_TAP 256 -#define MODEM_P600_LPF_TAP 128 - // -#define MODEM_P300_BPF 600 -#define MODEM_P300_TXBPF 625 -#define MODEM_P300_LPF 200 -#define MODEM_P300_BPF_TAP 256 -#define MODEM_P300_LPF_TAP 128 - // -#define MODEM_300_BPF 500 -#define MODEM_300_TXBPF 500 -#define MODEM_300_LPF 155 -#define MODEM_300_BPF_TAP 256 -#define MODEM_300_LPF_TAP 128 - // -#define MODEM_600_BPF 800 -#define MODEM_600_TXBPF 900 -#define MODEM_600_LPF 325 -#define MODEM_600_BPF_TAP 256 -#define MODEM_600_LPF_TAP 128 - // -#define MODEM_1200_BPF 1400 -#define MODEM_1200_TXBPF 1600 -#define MODEM_1200_LPF 650 -#define MODEM_1200_BPF_TAP 256 -#define MODEM_1200_LPF_TAP 128 - // -#define MODEM_2400_BPF 3200 -#define MODEM_2400_TXBPF 3200 -#define MODEM_2400_LPF 1400 -#define MODEM_2400_BPF_TAP 256 -#define MODEM_2400_LPF_TAP 128 - -#define TX_SILENCE 0 -#define TX_DELAY 1 -#define TX_TAIL 2 -#define TX_NO_DATA 3 -#define TX_FRAME 4 -#define TX_WAIT_BPF 5 - - -#define FRAME_WAIT 0 -#define FRAME_LOAD 1 -#define RX_BIT0 0 -#define RX_BIT1 128 -#define DCD_WAIT_SLOT 0 -#define DCD_WAIT_PERSIST 1 - -#define FX25_MODE_NONE 0 -#define FX25_MODE_RX 1 -#define FX25_MODE_TXRX 2 -#define FX25_TAG 0 -#define FX25_LOAD 1 - -#define IL2P_MODE_NONE 0 -#define IL2P_MODE_RX 1 // RX il2p + HDLC -#define IL2P_MODE_TXRX 2 -#define IL2P_MODE_ONLY 3 // RX only il2p, TX il2p - - -#define MODE_OUR 0 -#define MODE_OTHER 1 -#define MODE_RETRY 2 - -#define FRAME_FLAG 126 // 7e - -#define port_num 32 // ?? Max AGW sessions -#define PKT_ERR 17 // Minimum packet size, bytes -#define I_MAX 7 // Maximum number of packets - - - // externs for all modules - -#define ARDOPBufferSize 12000 * 100 - -extern short ARDOPTXBuffer[4][ARDOPBufferSize]; // Enough to hold whole frame of samples - -extern int ARDOPTXLen[4]; // Length of frame -extern int ARDOPTXPtr[4]; // Tx Pointer - -extern BOOL KISSServ; -extern int KISSPort; - -extern BOOL AGWServ; -extern int AGWPort; - -extern TStringList KISS_acked[]; -extern TStringList KISS_iacked[]; - -extern TStringList all_frame_buf[5]; - -extern unsigned short pkt_raw_min_len; -extern int stat_r_mem; - -extern UCHAR diddles; - -extern int stdtones; -extern int fullduplex; - -extern struct TQPSK_t qpsk_set[4]; - -extern int NonAX25[5]; - -extern short txtail[5]; -extern short txdelay[5]; - -extern short modem_def[5]; - -extern int emph_db[5]; -extern UCHAR emph_all[5]; - -extern UCHAR modem_mode[5]; - -extern UCHAR RCVR[5]; -extern int soundChannel[5]; -extern int modemtoSoundLR[4]; - -extern short rx_freq[5]; -extern short active_rx_freq[5]; -extern short rx_shift[5]; -extern short rx_baudrate[5]; -extern short rcvr_offset[5]; - -extern int tx_hitoneraisedb[5]; -extern float tx_hitoneraise[5]; - - -extern UCHAR tx_status[5]; -extern float tx_freq[5]; -extern float tx_shift[5]; -extern unsigned short tx_baudrate[5]; -extern unsigned short tx_bitrate[5]; - -extern unsigned short bpf[5]; -extern unsigned short lpf[5]; - -extern unsigned short txbpf[5]; - -extern unsigned short tx_BPF_tap[5]; -extern unsigned short tx_BPF_timer[5]; - -extern unsigned short BPF_tap[5]; -extern unsigned short LPF_tap[5]; - -extern float tx_BPF_core[5][32768]; -extern float LPF_core[5][2048]; - -extern UCHAR xData[256]; -extern UCHAR xEncoded[256]; -extern UCHAR xDecoded[256]; - -extern float PI125; -extern float PI375; -extern float PI625; -extern float PI875; -extern float PI5; -extern float PI25; -extern float PI75; - -extern int max_frame_collector[4]; -extern boolean KISS_opt[4]; - -#define MaxErrors 4 - -extern BOOL MinOnStart; - -//RS TReedSolomon; -// Form1 TForm1; -// WaveFormat TWaveFormatEx; - -extern int UDPServ; -extern long long udpServerSeqno; - -extern int Channels; -extern int BitsPerSample; -extern float TX_Samplerate; -extern float RX_Samplerate; -extern int RX_SR; -extern int TX_SR; -extern int RX_PPM; -extern int TX_PPM; -extern int tx_bufsize; -extern int rx_bufsize; -extern int tx_bufcount; -extern int rx_bufcount; -extern int fft_size; -extern int mouse_down[2]; -//UCHAR * RX_pBuf array[257]; -// RX_header array[1..256] of TWaveHdr; -// TX_pBuf array[1..4,1..256] of pointer; -//TX_header array[1..4,1..256] of TWaveHdr; -extern UCHAR calib_mode[5]; -extern UCHAR snd_status[5]; -extern UCHAR buf_status[5]; -extern UCHAR tx_buf_num1[5]; -extern UCHAR tx_buf_num[5]; -extern int speed[5]; -extern int panels[6]; - -extern int FFTSize; -#define fft_size FFTSize - -extern float fft_window_arr[2048]; -// fft_s,fft_d array[0..2047] of TComplex; -extern short fft_buf[2][8192]; -extern UCHAR fft_disp[2][1024]; -// bm array[1..4] of TBitMap; -// bm1,bm2,bm3 TBitMap; - -// WaveInHandle hWaveIn; -// WaveOutHandle array[1..4] of hWaveOut; -extern int RXBufferLength; - -// data1 PData16; - -extern int grid_time; -extern int fft_mult; -extern int fft_spd; -extern int grid_timer; -extern int stop_wf; -extern int raduga; -extern char snd_rx_device_name[32]; -extern char snd_tx_device_name[32]; -extern int snd_rx_device; -extern int snd_tx_device; -extern UCHAR mod_icon_status; -extern UCHAR last_mod_icon_status; -extern UCHAR icon_timer; -// TelIni TIniFile; -extern char cur_dir[]; -// TimerId1 cardinal; -// TimerId2 cardinal; -extern UCHAR TimerStat1; -extern UCHAR TimerStat2; -extern int stat_log; - -extern char PTTPort[80]; // Port for Hardware PTT - may be same as control port. -extern int PTTMode; -extern int PTTBAUD ; - -extern char PTTOnString[128]; -extern char PTTOffString[128]; - -extern UCHAR PTTOnCmd[64]; -extern UCHAR PTTOnCmdLen; - -extern UCHAR PTTOffCmd[64]; -extern UCHAR PTTOffCmdLen; - -extern int PTT_device; -extern int RX_device; -extern int TX_device; -extern int TX_rotate; -extern int UsingLeft; -extern int UsingRight; -extern int UsingBothChannels; -extern int pttGPIOPin; -extern int pttGPIOPinR; -extern BOOL pttGPIOInvert; -extern BOOL useGPIO; -extern BOOL gotGPIO; -extern int VID; -extern int PID; -extern char CM108Addr[80]; -extern int HamLibPort; -extern char HamLibHost[]; - -extern int SCO; -extern int DualPTT; -extern UCHAR DebugMode; -extern UCHAR TimerEvent; -extern int nr_monitor_lines; -extern int UTC_Tim; -extern int MainPriority; -// MainThreadHandle THandle; -extern UCHAR w_state; - -extern BOOL Firstwaterfall; -extern BOOL Secondwaterfall; - -extern int dcd_threshold; -extern int rxOffset; -extern int chanOffset[4]; -extern int Continuation[4]; // Sending 2nd or more packet of burst - -extern boolean busy; -extern boolean dcd[5]; - -extern struct TKISSMode_t KISS; - -extern boolean dyn_frack[4] ; -extern Byte recovery[4]; -extern Byte users[4]; - -extern int resptime[4]; -extern int slottime[4]; -extern int persist[4]; -extern int fracks[4]; -extern int frack_time[4]; -extern int idletime[4]; -extern int redtime[4]; -extern int IPOLL[4]; -extern int maxframe[4]; -extern int TXFrmMode[4]; - -extern char MyDigiCall[4][512]; -extern char exclude_callsigns[4][512]; -extern char exclude_APRS_frm[4][512]; - -extern TStringList list_exclude_callsigns[4]; -extern TStringList list_exclude_APRS_frm[4]; -extern TStringList list_digi_callsigns[4]; - - -extern int SoundIsPlaying; -extern int Capturing; - -extern struct TDetector_t DET[nr_emph + 1][16]; - -extern char CaptureDevice[80]; -extern char PlaybackDevice[80]; - -extern TAX25Port AX25Port[4][port_num]; - -extern int fx25_mode[4]; -extern int il2p_mode[4]; - -extern int tx_fx25_size[4]; -extern int tx_fx25_size_cnt[4]; -extern int tx_fx25_mode[4]; - -extern int SatelliteMode; - -extern int using48000; // Set if using 48K sample rate (ie RUH Modem active) - - -// Function prototypes - -void KISS_send_ack(UCHAR port, string * data); -void AGW_AX25_frame_analiz(int snd_ch, int RX, string * frame); -void FIR_filter(float * src, unsigned short buf_size, unsigned short tap, float * core, float * dest, float * prev); -void make_core_TXBPF(UCHAR snd_ch, float freq, float width); -void OpenPTTPort(); -void ClosePTTPort(); - -void RadioPTT(int snd_ch, BOOL PTTState); -void put_frame(int snd_ch, string * frame, char * code, int tx_stat, int excluded); -void CloseCOMPort(int fd); -void COMClearRTS(int fd); -void COMClearDTR(int fd); -unsigned int getTicks(); -char * ShortDateTime(); -void write_ax25_info(TAX25Port * AX25Sess); -void reverse_addr(Byte * path, Byte * revpath, int Len); -string * get_mycall(string * path); -TAX25Port * get_user_port_by_calls(int snd_ch, char * CallFrom, char * CallTo); -TAX25Port * get_free_port(int snd_ch); -void * in_list_incoming_mycall(Byte * path); -boolean add_incoming_mycalls(void * socket, char * src_call); -int get_addr(char * Calls, UCHAR * AXCalls); -void reverse_addr(Byte * path, Byte * revpath, int Len); -void set_link(TAX25Port * AX25Sess, UCHAR * axpath); -void rst_timer(TAX25Port * AX25Sess); -void set_unlink(TAX25Port * AX25Sess, Byte * path); -unsigned short get_fcs(UCHAR * Data, unsigned short len); -void KISSSendtoServer(void * sock, Byte * Msg, int Len); -int ConvFromAX25(unsigned char * incall, char * outcall); -BOOL ConvToAX25(char * callsign, unsigned char * ax25call); -void Debugprintf(const char * format, ...); - -double pila(double x); - -void AGW_Raw_monitor(int snd_ch, string * data); - -// Delphi emulation functions - -string * Strings(TStringList * Q, int Index); -void Clear(TStringList * Q); -int Count(TStringList * List); - -string * newString(); -string * copy(string * Source, int StartChar, int Count); -TStringList * newTStringList(); - -void freeString(string * Msg); - -void initString(string * S); -void initTStringList(TStringList* T); - -// Two delete() This is confusing!! -// Not really - one acts on String, other TStringList - -void Delete(TStringList * Q, int Index); -void mydelete(string * Source, int StartChar, int Count); - -void move(UCHAR * SourcePointer, UCHAR * DestinationPointer, int CopyCount); -void fmove(float * SourcePointer, float * DestinationPointer, int CopyCount); - -void setlength(string * Msg, int Count); // Set string length - -string * stringAdd(string * Msg, UCHAR * Chars, int Count); // Extend string - -void Assign(TStringList * to, TStringList * from); // Duplicate from to to - -string * duplicateString(string * in); - -// This looks for a string in a stringlist. Returns inhex if found, otherwise -1 - -int my_indexof(TStringList * l, string * s); - -boolean compareStrings(string * a, string * b); - -int Add(TStringList * Q, string * Entry); - - -#define IL2P_SYNC_WORD_SIZE 3 -#define IL2P_HEADER_SIZE 13 // Does not include 2 parity. -#define IL2P_HEADER_PARITY 2 - -#define IL2P_MAX_PAYLOAD_SIZE 1023 -#define IL2P_MAX_PAYLOAD_BLOCKS 5 -#define IL2P_MAX_PARITY_SYMBOLS 16 // For payload only. -#define IL2P_MAX_ENCODED_PAYLOAD_SIZE (IL2P_MAX_PAYLOAD_SIZE + IL2P_MAX_PAYLOAD_BLOCKS * IL2P_MAX_PARITY_SYMBOLS) - -struct il2p_context_s { - - enum { IL2P_SEARCHING = 0, IL2P_HEADER, IL2P_PAYLOAD, IL2P_DECODE } state; - - unsigned int acc; // Accumulate most recent 24 bits for sync word matching. - // Lower 8 bits are also used for accumulating bytes for - // the header and payload. - - int bc; // Bit counter so we know when a complete byte has been accumulated. - - int polarity; // 1 if opposite of expected polarity. - - unsigned char shdr[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY]; - // Scrambled header as received over the radio. Includes parity. - int hc; // Number if bytes placed in above. - - unsigned char uhdr[IL2P_HEADER_SIZE]; // Header after FEC and unscrambling. - - int eplen; // Encoded payload length. This is not the nuumber from - // from the header but rather the number of encoded bytes to gather. - - unsigned char spayload[IL2P_MAX_ENCODED_PAYLOAD_SIZE]; - // Scrambled and encoded payload as received over the radio. - int pc; // Number of bytes placed in above. - - int corrected; // Number of symbols corrected by RS FEC. -}; - - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/UZ7HOStuff-HPLaptop.h b/UZ7HOStuff-HPLaptop.h deleted file mode 100644 index dfc2886..0000000 --- a/UZ7HOStuff-HPLaptop.h +++ /dev/null @@ -1,1023 +0,0 @@ -// -// My port of UZ7HO's Soundmodem -// - -#define VersionString "0.0.0.59" -#define VersionBytes {0, 0, 0, 59} - -// Added FX25. 4x100 FEC and V27 not Working and disabled - -// 0.8 V27 now OK. - -// 0.9 Digipeating added - -// 0.10 Fix second channel tones and calibrate - -// 0.11 Fix allocation of sessions to correct modem -// Fix DCD -// Fix Monitoring of Multiline packets -// Fix possible saving of wrong center freq -// Limit TX sample Q in Linux -// - -// 0.12 Add AGWPE monitoring of received frames -// Fix DCD Threshold -// Fix KISS transparency issue - -// 0.13 Fix sending last few bits in FX.25 Mode - -// 0.14 Add "Copy on Select" to Trace Window - -// 0.15 Limit Trace window to 10000 lines - -// 0.16 Fix overwriting monitor window after scrollback - -// 0.17 Add GPIO and CAT PTT - -// 0.18 Add CM108/119 PTT - -// 0.19 Fix scheduling KISS frames - -// 0.20 Debug code added to RR processing - -// 0.21 Fix AGW monitor of multiple line packets -// Close ax.25 sessions if AGW Host session closes - -// 0.22 Add FEC Count to Session Stats - -// 0.23 Retry DISC until UA received or retry count exceeded - -// 0.24 More fixes to DISC handling - -// 0.26 Add OSS PulseAudio and HAMLIB support - -// 0.27 Dynamically load PulseAudio modules - -// 0.28 Add ARDOPPacket Mode - -// 0.29 Fix saving settings and geometry on close -// 0.30 Retructure code to build with Qt 5.3 -// Fix crash in nogui mode if pulse requested but not available -// Try to fix memory leaks - -// 0.31 Add option to run modems in seprate threads - -// 0.32 Fix timing problem with AGW connect at startup -// Add Memory ARQ -// Add Single bit "Correction" -// Fix error in 31 when using multiple decoders - -// 0.33 Fix Single bit correction -// More memory leak fixes - -// 0.34 Add API to set Modem and Center Frequency -// Fix crash in delete_incoming_mycalls - -// 0.35 Return Version in AGW Extended g response - -// 0.36 Fix timing problem on startup - -// 0.37 Add scrollbars to Device and Modem dialogs - -// 0.38 Change default CM108 name to /dev/hidraw0 on Linux - -// 0.39 Dont try to display Message Boxes in nogui mode. -// Close Device and Modem dialogs on Accept or Reject -// Fix using HAMLIB in nogui mode - -// 0.40 Fix bug in frame optimize when using 6 char calls - -// 0.41 Fix "glitch" on waterfall markers when changing modem freqs - -// 0.42 Add "Minimize to Tray" option - -// 0.43 Add Andy's on_SABM fix. -// Fix Crash if KISS Data sent to AGW port - -// 0.44 Add UDP bridge. - -// 0.45 Add two more modems. -// 0.46 Fix two more modems. - -// 0.47 Fix suprious DM when host connection lost -// Add CWID - -// 0.48 Send FRMR for unrecognised frame types - -// 0.49 Add Andy's FEC Tag correlation coode - -// 0.50 Fix Waterfall display when only using right channel -// Allow 1200 baud fsk at other center freqs -// Add Port numbers to Window title and Try Icon tooltip -// Fix calculation of filters for multiple decoders -// Add RX Offset setting (for satellite operation - -// 0.51 Fix Multithreading with more that 2 modems - -// 0.52 Add Stdin as source on Linux - -// 0.53 Use Byte instead of byte as byte is defined in newer versions of gcc - -// 0.54 Fix for ALSA problem on new pi OS - -// 0.55 Fix for compiler error with newer compiler - -// 0.56 Fix errors in Config.cpp June 22 - -// 0.57 Add Restart Waterfall action August 22 - -// 0.58 Add RSID Sept 2022 - -// 0.59 Add config of Digi Calls Dec 2022 - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNUSED(x) (void)(x) - -#ifdef M_PI -#undef M_PI -#endif - -#define M_PI 3.1415926f - -#define pi M_PI - -#ifndef WIN32 -#define _strdup strdup -#endif - - //#define NULL ((void *)0) - - //Delphi Types remember case insensitive - -#define single float -#define boolean int -#define Byte unsigned char // 0 to 255 -#define Word unsigned short // 0 to 65,535 -#define SmallInt short // -32,768 to 32,767 -#define LongWord unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define LongInt int // -2,147,483,648 to 2,147,483,647 -#define Integer int // -2,147,483,648 to 2,147,483,647 -//#define Int64 long long // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 - -//#define Byte unsigned char // 0 to 255 -#define word unsigned short // 0 to 65,535 -#define smallint short // -32,768 to 32,767 -#define longword unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define longint int // -2,147,483,648 to 2,147,483,647 -#define integer int // -2,147,483,648 to 2,147,483,647 - -typedef unsigned long ULONG; - -#define UCHAR unsigned char -#define UINT unsigned int -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -// Soundcard Channels - -#define NONE 0 -#define LEFT 1 -#define RIGHT 2 - -#define nr_emph 2 - -#define decodedNormal 4 //'|' -#define decodedFEC 3 //'F' -#define decodedMEM 2 //'#' -#define decodedSingle 1 //'$' - - -// Seems to use Delphi TStringList for a lot of queues. This seems to be a list of pointers and a count -// Each pointer is to a Data/Length pair -//Maybe something like - -typedef struct string_T -{ - unsigned char * Data; - int Length; - int AllocatedLength; // A reasonable sized block is allocated at the start to speed up adding chars - -}string; - -typedef struct TStringList_T -{ - int Count; - string ** Items; - -} TStringList; - -// QPSK struct - -typedef struct TQPSK_t -{ - UCHAR tx[4]; - int count[4]; - UCHAR rx[4]; - UCHAR mode; -} TPQSK; - - -typedef struct TKISSMode_t -{ - string * data_in; - void * Socket; // Used as a key - - // Not sure what rest are used for. Seems to be one per channel - - TStringList buffer[4]; // Outgoing Frames - -} TKISSMode; - -typedef struct TMChannel_t -{ - - single prev_LPF1I_buf[4096]; - single prev_LPF1Q_buf[4096]; - single prev_dLPFI_buf[4096]; - single prev_dLPFQ_buf[4096]; - single prev_AFCI_buf[4096]; - single prev_AFCQ_buf[4096]; - single AngleCorr; - single MUX_osc; - single AFC_IZ1; - single AFC_IZ2; - single AFC_QZ1; - single AFC_QZ2; - single AFC_bit_buf1I[1024]; - single AFC_bit_buf1Q[1024]; - single AFC_bit_buf2[1024]; - single AFC_IIZ1; - single AFC_QQZ1; - -} TMChannel; - -typedef struct TFX25_t -{ - string data; - Byte status; - Byte bit_cnt; - Byte byte_rx; - unsigned long long tag; - Byte size; - Byte rs_size; - Byte size_cnt; -} TFX25; - - - -typedef struct TDetector_t -{ - struct TFX25_t fx25[4]; - TStringList mem_ARQ_F_buf[5]; - TStringList mem_ARQ_buf[5]; - float pll_loop[5]; - float last_sample[5]; - UCHAR ones[5]; - UCHAR zeros[5]; - float bit_buf[5][1024]; - float bit_buf1[5][1024]; - UCHAR sample_cnt[5]; - UCHAR last_bit[5]; - float PSK_IZ1[5]; - float PSK_QZ1[5]; - float PkAmpI[5]; - float PkAmpQ[5]; - float PkAmp[5]; - float PkAmpMax[5]; - int newpkpos[5]; - float AverageAmp[5]; - float AngleCorr[5]; - float MinAmp[5]; - float MaxAmp[5]; - float MUX3_osc[5]; - float MUX3_1_osc[5]; - float MUX3_2_osc[5]; - float Preemphasis6[5]; - float Preemphasis12[5]; - float PSK_AGC[5]; - float AGC[5]; - float AGC1[5]; - float AGC2[5]; - float AGC3[5]; - float AGC_max[5]; - float AGC_min[5]; - float AFC_IZ1[5]; - float AFC_IZ2[5]; - float AFC_QZ1[5]; - float AFC_QZ2[5]; - - UCHAR last_rx_bit[5]; - UCHAR bit_stream[5]; - UCHAR byte_rx[5]; - UCHAR bit_stuff_cnt[5]; - UCHAR bit_cnt[5]; - float bit_osc[5]; - UCHAR frame_status[5]; - string rx_data[5]; - string FEC_rx_data[5]; - // - UCHAR FEC_pol[5]; - unsigned short FEC_err[5]; - unsigned long long FEC_header1[5][2]; - unsigned short FEC_blk_int[5]; - unsigned short FEC_len_int[5]; - unsigned short FEC_len[5]; - - unsigned short FEC_len_cnt[5]; - - UCHAR rx_intv_tbl[5][4]; - UCHAR rx_intv_sym[5]; - UCHAR rx_viterbi[5]; - UCHAR viterbi_cnt[5]; - // SurvivorStates [1..4,0..511] of TSurvivor; - // - TMChannel MChannel[5][4]; - - float AFC_dF_avg[5]; - float AFC_dF[5]; - float AFC_bit_osc[5]; - float AFC_bit_buf[5][1024]; - unsigned short AFC_cnt[5]; - - string raw_bits1[5]; - string raw_bits[5]; - UCHAR last_nrzi_bit[5]; - - float BPF_core[5][2048]; - float LPF_core[5][2048]; - - float src_INTR_buf[5][8192]; - float src_INTRI_buf[5][8192]; - float src_INTRQ_buf[5][8192]; - float src_LPF1I_buf[5][8192]; - float src_LPF1Q_buf[5][8192]; - - float src_BPF_buf[5][2048]; - float src_Loop_buf[5][8192]; - float prev_BPF_buf[5][4096]; - - float prev_LPF1I_buf[5][4096]; - float prev_LPF1Q_buf[5][4096]; - float prev_INTR_buf[5][16384]; - float prev_INTRI_buf[5][16384]; - float prev_INTRQ_buf[5][16384]; - - Byte emph_decoded; - Byte rx_decoded; - - -} TDetector; - - - -typedef struct AGWUser_t -{ - void *socket; - string * data_in; - TStringList AGW_frame_buf; - boolean Monitor; - boolean Monitor_raw; - boolean reportFreqAndModem; // Can report modem and frequency to host - -} AGWUser; - -typedef struct TAX25Info_t -{ - longint stat_s_pkt; - longint stat_s_byte; - longint stat_r_pkt; - longint stat_r_byte; - longint stat_r_fc; - longint stat_fec_count; - time_t stat_begin_ses; - time_t stat_end_ses; - longint stat_l_r_byte; - longint stat_l_s_byte; - -} TAX25Info; - -typedef struct TAX25Port_t -{ - Byte hi_vs; - Byte vs; - Byte vr; - Byte PID; - TStringList in_data_buf; - TStringList frm_collector; - string frm_win[8]; - string out_data_buf; - word t1; - word t2; - word t3; - Byte i_lo; - Byte i_hi; - word n1; - word n2; - word IPOLL_cnt; - TStringList frame_buf; //áóôåð êàäðîâ íà ïåðåäà÷ó - TStringList I_frame_buf; - Byte status; - word clk_frack; - char corrcall[10]; - char mycall[10]; - UCHAR digi[56]; - UCHAR Path[80]; // Path in ax25 format - added to save building it each time - UCHAR ReversePath[80]; - int snd_ch; // Simplifies parameter passing - int port; - int pathLen; - void * socket; - char kind[16]; - TAX25Info info; -} TAX25Port; - - -#define LOGEMERGENCY 0 -#define LOGALERT 1 -#define LOGCRIT 2 -#define LOGERROR 3 -#define LOGWARNING 4 -#define LOGNOTICE 5 -#define LOGINFO 6 -#define LOGDEBUG 7 - -#define PTTRTS 1 -#define PTTDTR 2 -#define PTTCAT 4 -#define PTTCM108 8 -#define PTTHAMLIB 16 - -// Status flags - -#define STAT_NO_LINK 0 -#define STAT_LINK 1 -#define STAT_CHK_LINK 2 -#define STAT_WAIT_ANS 3 -#define STAT_TRY_LINK 4 -#define STAT_TRY_UNLINK 5 - - - // Ñmd,Resp,Poll,Final,Digipeater flags -#define SET_P 1 -#define SET_F 0 -#define SET_C 1 -#define SET_R 0 -#define SET_NO_RPT 0 -#define SET_RPT 1 - // Frame ID flags -#define I_FRM 0 -#define S_FRM 1 -#define U_FRM 2 -#define I_I 0 -#define S_RR 1 -#define S_RNR 5 -#define S_REJ 9 -#define S_SREJ 0x0D -#define U_SABM 47 -#define U_DISC 67 -#define U_DM 15 -#define U_UA 99 -#define U_FRMR 135 -#define U_UI 3 - // PID flags -#define PID_X25 0x01 // 00000001-CCIT X25 PLP -#define PID_SEGMENT 0x08 // 00001000-Segmentation fragment -#define PID_TEXNET 0xC3 // 11000011-TEXNET Datagram Protocol -#define PID_LQ 0xC4 // 11001000-Link Quality Protocol -#define PID_APPLETALK 0xCA // 11001010-Appletalk -#define PID_APPLEARP 0xCB // 11001011-Appletalk ARP -#define PID_IP 0xCC // 11001100-ARPA Internet Protocol -#define PID_ARP 0xCD // 11001101-ARPA Address Resolution Protocol -#define PID_NET_ROM 0xCF // 11001111-NET/ROM - - -// Sound interface buffer size - -#define SendSize 1024 // 100 mS for now -#define ReceiveSize 512 // try 100 mS for now -#define NumberofinBuffers 4 - -#define Now getTicks() - -// #defines from all modules (?? is this a good idaa ?? - -#define WIN_MAXIMIZED 0 -#define WIN_MINIMIZED 1 -#define MODEM_CAPTION 'SoundModem by UZ7HO' -#define MODEM_VERSION '1.06' -#define SND_IDLE 0 -#define SND_RX 1 -#define SND_TX 2 -#define BUF_EMPTY 0 -#define BUF_FULL 1 -#define DISP_MONO FALSE -#define DISP_RGB TRUE -#define MOD_IDLE 0 -#define MOD_RX 1 -#define MOD_TX 2 -#define MOD_WAIT 3 -#define TIMER_FREE 0 -#define TIMER_BUSY 1 -#define TIMER_OFF 2 -#define TIMER_EVENT_ON 3 -#define TIMER_EVENT_OFF 4 -#define DEBUG_TIMER 1 -#define DEBUG_WATERFALL 2 -#define DEBUG_DECODE 4 -#define DEBUG_SOUND 8 -#define IS_LAST TRUE -#define IS_NOT_LAST FALSE -#define modes_count 16 -#define SPEED_300 0 -#define SPEED_1200 1 -#define SPEED_600 2 -#define SPEED_2400 3 -#define SPEED_P1200 4 -#define SPEED_P600 5 -#define SPEED_P300 6 -#define SPEED_P2400 7 -#define SPEED_Q4800 8 -#define SPEED_Q3600 9 -#define SPEED_Q2400 10 -#define SPEED_MP400 11 -#define SPEED_DW2400 12 -#define SPEED_8P4800 13 -#define SPEED_AE2400 14 -#define SPEED_ARDOP 15 - -#define MODE_FSK 0 -#define MODE_BPSK 1 -#define MODE_QPSK 2 -#define MODE_MPSK 3 -#define MODE_8PSK 4 -#define MODE_PI4QPSK 5 -#define MODE_ARDOP 6 - -#define QPSK_SM 0 -#define QPSK_V26 1 - - -#define MODEM_8P4800_BPF 3200 -#define MODEM_8P4800_TXBPF 3400 -#define MODEM_8P4800_LPF 1000 -#define MODEM_8P4800_BPF_TAP 64 -#define MODEM_8P4800_LPF_TAP 8 - // -#define MODEM_MP400_BPF 775 -#define MODEM_MP400_TXBPF 850 -#define MODEM_MP400_LPF 70 -#define MODEM_MP400_BPF_TAP 256 -#define MODEM_MP400_LPF_TAP 128 - // -#define MODEM_DW2400_BPF 2400 -#define MODEM_DW2400_TXBPF 2500 -#define MODEM_DW2400_LPF 900 -#define MODEM_DW2400_BPF_TAP 256 //256 -#define MODEM_DW2400_LPF_TAP 32 //128 - // -#define MODEM_Q2400_BPF 2400 -#define MODEM_Q2400_TXBPF 2500 -#define MODEM_Q2400_LPF 900 -#define MODEM_Q2400_BPF_TAP 256 //256 -#define MODEM_Q2400_LPF_TAP 128 //128 - // -#define MODEM_Q3600_BPF 3600 -#define MODEM_Q3600_TXBPF 3750 -#define MODEM_Q3600_LPF 1350 -#define MODEM_Q3600_BPF_TAP 256 -#define MODEM_Q3600_LPF_TAP 128 - // -#define MODEM_Q4800_BPF 4800 -#define MODEM_Q4800_TXBPF 5000 -#define MODEM_Q4800_LPF 1800 -#define MODEM_Q4800_BPF_TAP 256 -#define MODEM_Q4800_LPF_TAP 128 - // -#define MODEM_P2400_BPF 4800 -#define MODEM_P2400_TXBPF 5000 -#define MODEM_P2400_LPF 1800 -#define MODEM_P2400_BPF_TAP 256 -#define MODEM_P2400_LPF_TAP 128 - // -#define MODEM_P1200_BPF 2400 -#define MODEM_P1200_TXBPF 2500 -#define MODEM_P1200_LPF 900 -#define MODEM_P1200_BPF_TAP 256 -#define MODEM_P1200_LPF_TAP 128 - // -#define MODEM_P600_BPF 1200 -#define MODEM_P600_TXBPF 1250 -#define MODEM_P600_LPF 400 -#define MODEM_P600_BPF_TAP 256 -#define MODEM_P600_LPF_TAP 128 - // -#define MODEM_P300_BPF 600 -#define MODEM_P300_TXBPF 625 -#define MODEM_P300_LPF 200 -#define MODEM_P300_BPF_TAP 256 -#define MODEM_P300_LPF_TAP 128 - // -#define MODEM_300_BPF 500 -#define MODEM_300_TXBPF 500 -#define MODEM_300_LPF 155 -#define MODEM_300_BPF_TAP 256 -#define MODEM_300_LPF_TAP 128 - // -#define MODEM_600_BPF 800 -#define MODEM_600_TXBPF 900 -#define MODEM_600_LPF 325 -#define MODEM_600_BPF_TAP 256 -#define MODEM_600_LPF_TAP 128 - // -#define MODEM_1200_BPF 1400 -#define MODEM_1200_TXBPF 1600 -#define MODEM_1200_LPF 650 -#define MODEM_1200_BPF_TAP 256 -#define MODEM_1200_LPF_TAP 128 - // -#define MODEM_2400_BPF 3200 -#define MODEM_2400_TXBPF 3200 -#define MODEM_2400_LPF 1400 -#define MODEM_2400_BPF_TAP 256 -#define MODEM_2400_LPF_TAP 128 - -#define TX_SILENCE 0 -#define TX_DELAY 1 -#define TX_TAIL 2 -#define TX_NO_DATA 3 -#define TX_FRAME 4 -#define TX_WAIT_BPF 5 - - -#define FRAME_WAIT 0 -#define FRAME_LOAD 1 -#define RX_BIT0 0 -#define RX_BIT1 128 -#define DCD_WAIT_SLOT 0 -#define DCD_WAIT_PERSIST 1 - -#define FX25_MODE_NONE 0 -#define FX25_MODE_RX 1 -#define FX25_MODE_TXRX 2 -#define FX25_TAG 0 -#define FX25_LOAD 1 - -#define MODE_OUR 0 -#define MODE_OTHER 1 -#define MODE_RETRY 2 - -#define FRAME_FLAG 126 // 7e - -#define port_num 32 // ?? Max AGW sessions -#define PKT_ERR 17 // Minimum packet size, bytes -#define I_MAX 7 // Maximum number of packets - - - // externs for all modules - -#define ARDOPBufferSize 12000 * 100 - -extern short ARDOPTXBuffer[4][12000 * 100]; // Enough to hold whole frame of samples - -extern int ARDOPTXLen[4]; // Length of frame -extern int ARDOPTXPtr[4]; // Tx Pointer - -extern BOOL KISSServ; -extern int KISSPort; - -extern BOOL AGWServ; -extern int AGWPort; - -extern TStringList KISS_acked[]; -extern TStringList KISS_iacked[]; - -extern TStringList all_frame_buf[5]; - -extern unsigned short pkt_raw_min_len; -extern int stat_r_mem; - -extern UCHAR diddles; - -extern int stdtones; -extern int fullduplex; - -extern struct TQPSK_t qpsk_set[4]; - -extern int NonAX25[5]; - -extern short txtail[5]; -extern short txdelay[5]; - -extern short modem_def[5]; - -extern int emph_db[5]; -extern UCHAR emph_all[5]; - -extern UCHAR modem_mode[5]; - -extern UCHAR RCVR[5]; -extern int soundChannel[5]; -extern int modemtoSoundLR[4]; - -extern short rx_freq[5]; -extern short rx_shift[5]; -extern short rx_baudrate[5]; -extern short rcvr_offset[5]; - -extern int tx_hitoneraisedb[5]; -extern float tx_hitoneraise[5]; - - -extern UCHAR tx_status[5]; -extern float tx_freq[5]; -extern float tx_shift[5]; -extern unsigned short tx_baudrate[5]; - -extern unsigned short bpf[5]; -extern unsigned short lpf[5]; - -extern unsigned short txbpf[5]; - -extern unsigned short tx_BPF_tap[5]; -extern unsigned short tx_BPF_timer[5]; - -extern unsigned short BPF_tap[5]; -extern unsigned short LPF_tap[5]; - -extern float tx_BPF_core[5][32768]; -extern float LPF_core[5][2048]; - -extern UCHAR xData[256]; -extern UCHAR xEncoded[256]; -extern UCHAR xDecoded[256]; - -extern float PI125; -extern float PI375; -extern float PI625; -extern float PI875; -extern float PI5; -extern float PI25; -extern float PI75; - -extern int max_frame_collector[4]; -extern boolean KISS_opt[4]; - -#define MaxErrors 4 - -extern BOOL MinOnStart; - -//RS TReedSolomon; -// Form1 TForm1; -// WaveFormat TWaveFormatEx; - -extern int UDPServ; -extern long long udpServerSeqno; - -extern int Channels; -extern int BitsPerSample; -extern float TX_Samplerate; -extern float RX_Samplerate; -extern int RX_SR; -extern int TX_SR; -extern int RX_PPM; -extern int TX_PPM; -extern int tx_bufsize; -extern int rx_bufsize; -extern int tx_bufcount; -extern int rx_bufcount; -extern int fft_size; -extern int mouse_down[2]; -//UCHAR * RX_pBuf array[257]; -// RX_header array[1..256] of TWaveHdr; -// TX_pBuf array[1..4,1..256] of pointer; -//TX_header array[1..4,1..256] of TWaveHdr; -extern UCHAR calib_mode[5]; -extern UCHAR snd_status[5]; -extern UCHAR buf_status[5]; -extern UCHAR tx_buf_num1[5]; -extern UCHAR tx_buf_num[5]; -extern int speed[5]; -extern int panels[6]; - -extern float fft_window_arr[2048]; -// fft_s,fft_d array[0..2047] of TComplex; -extern short fft_buf[5][2048]; -extern UCHAR fft_disp[5][2048]; -// bm array[1..4] of TBitMap; -// bm1,bm2,bm3 TBitMap; - -// WaveInHandle hWaveIn; -// WaveOutHandle array[1..4] of hWaveOut; -extern int RXBufferLength; - -// data1 PData16; - -extern int grid_time; -extern int fft_mult; -extern int fft_spd; -extern int grid_timer; -extern int stop_wf; -extern int raduga; -extern char snd_rx_device_name[32]; -extern char snd_tx_device_name[32]; -extern int snd_rx_device; -extern int snd_tx_device; -extern UCHAR mod_icon_status; -extern UCHAR last_mod_icon_status; -extern UCHAR icon_timer; -// TelIni TIniFile; -extern char cur_dir[]; -// TimerId1 cardinal; -// TimerId2 cardinal; -extern UCHAR TimerStat1; -extern UCHAR TimerStat2; -extern int stat_log; - -extern char PTTPort[80]; // Port for Hardware PTT - may be same as control port. -extern int PTTMode; -extern int PTTBAUD ; - -extern char PTTOnString[128]; -extern char PTTOffString[128]; - -extern UCHAR PTTOnCmd[64]; -extern UCHAR PTTOnCmdLen; - -extern UCHAR PTTOffCmd[64]; -extern UCHAR PTTOffCmdLen; - -extern int PTT_device; -extern int RX_device; -extern int TX_device; -extern int TX_rotate; -extern int UsingLeft; -extern int UsingRight; -extern int UsingBothChannels; -extern int pttGPIOPin; -extern int pttGPIOPinR; -extern BOOL pttGPIOInvert; -extern BOOL useGPIO; -extern BOOL gotGPIO; -extern int VID; -extern int PID; -extern char CM108Addr[80]; -extern int HamLibPort; -extern char HamLibHost[]; - -extern int SCO; -extern int DualPTT; -extern UCHAR DebugMode; -extern UCHAR TimerEvent; -extern int nr_monitor_lines; -extern int UTC_Tim; -extern int MainPriority; -// MainThreadHandle THandle; -extern UCHAR w_state; - -extern BOOL Firstwaterfall; -extern BOOL Secondwaterfall; - -extern int dcd_threshold; -extern int rxOffset; -extern int chanOffset[4]; - -extern boolean busy; -extern boolean dcd[5]; - -extern struct TKISSMode_t KISS; - -extern boolean dyn_frack[4] ; -extern Byte recovery[4]; -extern Byte users[4]; - -extern int resptime[4]; -extern int slottime[4]; -extern int persist[4]; -extern int fracks[4]; -extern int frack_time[4]; -extern int idletime[4]; -extern int redtime[4]; -extern int IPOLL[4]; -extern int maxframe[4]; -extern int TXFrmMode[4]; - -extern char MyDigiCall[4][512]; -extern char exclude_callsigns[4][512]; -extern char exclude_APRS_frm[4][512]; - -extern TStringList list_exclude_callsigns[4]; -extern TStringList list_exclude_APRS_frm[4]; -extern TStringList list_digi_callsigns[4]; - - -extern int SoundIsPlaying; -extern int Capturing; - -extern struct TDetector_t DET[nr_emph + 1][16]; - -extern char CaptureDevice[80]; -extern char PlaybackDevice[80]; - -extern TAX25Port AX25Port[4][port_num]; - -extern int fx25_mode[4]; - -extern int tx_fx25_size[4]; -extern int tx_fx25_size_cnt[4]; -extern int tx_fx25_mode[4]; - -extern int SatelliteMode; - -// Function prototypes - -void KISS_send_ack(UCHAR port, string * data); -void AGW_AX25_frame_analiz(int snd_ch, int RX, string * frame); -void FIR_filter(float * src, unsigned short buf_size, unsigned short tap, float * core, float * dest, float * prev); -void make_core_TXBPF(UCHAR snd_ch, float freq, float width); -void OpenPTTPort(); -void ClosePTTPort(); - -void RadioPTT(int snd_ch, BOOL PTTState); -void put_frame(int snd_ch, string * frame, char * code, int tx_stat, int excluded); -void CloseCOMPort(int fd); -void COMClearRTS(int fd); -void COMClearDTR(int fd); -unsigned int getTicks(); -char * ShortDateTime(); -void write_ax25_info(TAX25Port * AX25Sess); -void reverse_addr(Byte * path, Byte * revpath, int Len); -string * get_mycall(string * path); -TAX25Port * get_user_port_by_calls(int snd_ch, char * CallFrom, char * CallTo); -TAX25Port * get_free_port(int snd_ch); -void * in_list_incoming_mycall(Byte * path); -boolean add_incoming_mycalls(void * socket, char * src_call); -int get_addr(char * Calls, UCHAR * AXCalls); -void reverse_addr(Byte * path, Byte * revpath, int Len); -void set_link(TAX25Port * AX25Sess, UCHAR * axpath); -void rst_timer(TAX25Port * AX25Sess); -void set_unlink(TAX25Port * AX25Sess, Byte * path); -unsigned short get_fcs(UCHAR * Data, unsigned short len); -void KISSSendtoServer(void * sock, Byte * Msg, int Len); -int ConvFromAX25(unsigned char * incall, char * outcall); -BOOL ConvToAX25(char * callsign, unsigned char * ax25call); -void Debugprintf(const char * format, ...); - -double pila(double x); - -void AGW_Raw_monitor(int snd_ch, string * data); - -// Dephi emulation functions - -string * Strings(TStringList * Q, int Index); -void Clear(TStringList * Q); -int Count(TStringList * List); - -string * newString(); -string * copy(string * Source, int StartChar, int Count); -TStringList * newTStringList(); - -void freeString(string * Msg); - -void initString(string * S); -void initTStringList(TStringList* T); - -// Two delete() This is confusing!! -// Not really - one acts on String, other TStringList - -void Delete(TStringList * Q, int Index); -void mydelete(string * Source, int StartChar, int Count); - -void move(UCHAR * SourcePointer, UCHAR * DestinationPointer, int CopyCount); -void fmove(float * SourcePointer, float * DestinationPointer, int CopyCount); - -void setlength(string * Msg, int Count); // Set string length - -string * stringAdd(string * Msg, UCHAR * Chars, int Count); // Extend string - -void Assign(TStringList * to, TStringList * from); // Duplicate from to to - -string * duplicateString(string * in); - -// This looks for a string in a stringlist. Returns inhex if found, otherwise -1 - -int my_indexof(TStringList * l, string * s); - -boolean compareStrings(string * a, string * b); - -int Add(TStringList * Q, string * Entry); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/UZ7HOStuff.h b/UZ7HOStuff.h index f62c123..4a68356 100644 --- a/UZ7HOStuff.h +++ b/UZ7HOStuff.h @@ -4,8 +4,8 @@ // My port of UZ7HO's Soundmodem // -#define VersionString "0.0.0.68" -#define VersionBytes {0, 0, 0, 68} +#define VersionString "0.0.0.71" +#define VersionBytes {0, 0, 0, 71} // Added FX25. 4x100 FEC and V27 not Working and disabled @@ -167,6 +167,18 @@ // Fix Waterfall display when using right channel only // Allow PTT device to be added +// .69 Add basic Dark Theme +// Fix some timing bugs in Waterfall and RX Level refresh +// Only display session table if AGW interface is enabled +// Fix operation with both left and right channels in use + +// .70 Restructure Waterfall area to be a single image + +// .71 Add IL2P CRC Mode +// Improve reliability of waterfall update +// Report and set fx.25 and il2p flags to/from BPQ + + #include @@ -997,6 +1009,7 @@ extern TAX25Port AX25Port[4][port_num]; extern int fx25_mode[4]; extern int il2p_mode[4]; +extern int il2p_crc[4]; extern int tx_fx25_size[4]; extern int tx_fx25_size_cnt[4]; @@ -1098,7 +1111,7 @@ int Add(TStringList * Q, string * Entry); struct il2p_context_s { - enum { IL2P_SEARCHING = 0, IL2P_HEADER, IL2P_PAYLOAD, IL2P_DECODE } state; + enum { IL2P_SEARCHING = 0, IL2P_HEADER, IL2P_PAYLOAD, IL2P_CRC, IL2P_DECODE } state; unsigned int acc; // Accumulate most recent 24 bits for sync word matching. // Lower 8 bits are also used for accumulating bytes for @@ -1122,8 +1135,12 @@ struct il2p_context_s { int pc; // Number of bytes placed in above. int corrected; // Number of symbols corrected by RS FEC. + + int crccount; // fec chars collected + unsigned char crc[4]; // the 4 fec chars }; +extern int NeedWaterfallHeaders; #ifdef __cplusplus } diff --git a/UZ7HOStuff.h.bak b/UZ7HOStuff.h.bak deleted file mode 100644 index b7e5ec8..0000000 --- a/UZ7HOStuff.h.bak +++ /dev/null @@ -1,1049 +0,0 @@ -// -// My port of UZ7HO's Soundmodem -// - -#define VersionString "0.0.0.65" -#define VersionBytes {0, 0, 0, 65} - -// Added FX25. 4x100 FEC and V27 not Working and disabled - -// 0.8 V27 now OK. - -// 0.9 Digipeating added - -// 0.10 Fix second channel tones and calibrate - -// 0.11 Fix allocation of sessions to correct modem -// Fix DCD -// Fix Monitoring of Multiline packets -// Fix possible saving of wrong center freq -// Limit TX sample Q in Linux -// - -// 0.12 Add AGWPE monitoring of received frames -// Fix DCD Threshold -// Fix KISS transparency issue - -// 0.13 Fix sending last few bits in FX.25 Mode - -// 0.14 Add "Copy on Select" to Trace Window - -// 0.15 Limit Trace window to 10000 lines - -// 0.16 Fix overwriting monitor window after scrollback - -// 0.17 Add GPIO and CAT PTT - -// 0.18 Add CM108/119 PTT - -// 0.19 Fix scheduling KISS frames - -// 0.20 Debug code added to RR processing - -// 0.21 Fix AGW monitor of multiple line packets -// Close ax.25 sessions if AGW Host session closes - -// 0.22 Add FEC Count to Session Stats - -// 0.23 Retry DISC until UA received or retry count exceeded - -// 0.24 More fixes to DISC handling - -// 0.26 Add OSS PulseAudio and HAMLIB support - -// 0.27 Dynamically load PulseAudio modules - -// 0.28 Add ARDOPPacket Mode - -// 0.29 Fix saving settings and geometry on close -// 0.30 Retructure code to build with Qt 5.3 -// Fix crash in nogui mode if pulse requested but not available -// Try to fix memory leaks - -// 0.31 Add option to run modems in seprate threads - -// 0.32 Fix timing problem with AGW connect at startup -// Add Memory ARQ -// Add Single bit "Correction" -// Fix error in 31 when using multiple decoders - -// 0.33 Fix Single bit correction -// More memory leak fixes - -// 0.34 Add API to set Modem and Center Frequency -// Fix crash in delete_incoming_mycalls - -// 0.35 Return Version in AGW Extended g response - -// 0.36 Fix timing problem on startup - -// 0.37 Add scrollbars to Device and Modem dialogs - -// 0.38 Change default CM108 name to /dev/hidraw0 on Linux - -// 0.39 Dont try to display Message Boxes in nogui mode. -// Close Device and Modem dialogs on Accept or Reject -// Fix using HAMLIB in nogui mode - -// 0.40 Fix bug in frame optimize when using 6 char calls - -// 0.41 Fix "glitch" on waterfall markers when changing modem freqs - -// 0.42 Add "Minimize to Tray" option - -// 0.43 Add Andy's on_SABM fix. -// Fix Crash if KISS Data sent to AGW port - -// 0.44 Add UDP bridge. - -// 0.45 Add two more modems. -// 0.46 Fix two more modems. - -// 0.47 Fix suprious DM when host connection lost -// Add CWID - -// 0.48 Send FRMR for unrecognised frame types - -// 0.49 Add Andy's FEC Tag correlation coode - -// 0.50 Fix Waterfall display when only using right channel -// Allow 1200 baud fsk at other center freqs -// Add Port numbers to Window title and Try Icon tooltip -// Fix calculation of filters for multiple decoders -// Add RX Offset setting (for satellite operation - -// 0.51 Fix Multithreading with more that 2 modems - -// 0.52 Add Stdin as source on Linux - -// 0.53 Use Byte instead of byte as byte is defined in newer versions of gcc - -// 0.54 Fix for ALSA problem on new pi OS - -// 0.55 Fix for compiler error with newer compiler - -// 0.56 Fix errors in Config.cpp June 22 - -// 0.57 Add Restart Waterfall action August 22 - -// 0.58 Add RSID Sept 2022 - -// 0.59 Add config of Digi Calls Dec 2022 - -// 0.60 Allow ARDOP Packet on modems 2 to 4 March 2023 - -// 0.61 Add il2p support April 2023 - -// 0.62 April 2023 -// Add option to specify sound devices that aren't in list -// Add Save button to Modem dialog to save current tab without closing dialog -// Don't add plug: to Linux device addresses unless addr contains : (allows use of eg ARDOP) - -// 0.64 Fix sending ax.25 (broken in .61) - -// 0.65 Allow Set Modem command to use modem index as well as modem name - - - -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNUSED(x) (void)(x) - -#ifdef M_PI -#undef M_PI -#endif - -#define M_PI 3.1415926f - -#define pi M_PI - -#ifndef WIN32 -#define _strdup strdup -#endif - - //#define NULL ((void *)0) - - //Delphi Types remember case insensitive - -#define single float -#define boolean int -#define Byte unsigned char // 0 to 255 -#define Word unsigned short // 0 to 65,535 -#define SmallInt short // -32,768 to 32,767 -#define LongWord unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define LongInt int // -2,147,483,648 to 2,147,483,647 -#define Integer int // -2,147,483,648 to 2,147,483,647 -//#define Int64 long long // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 - -//#define Byte unsigned char // 0 to 255 -#define word unsigned short // 0 to 65,535 -#define smallint short // -32,768 to 32,767 -#define longword unsigned int // 0 to 4,294,967,295 - // Int6 : Cardinal; // 0 to 4,294,967,295 -#define longint int // -2,147,483,648 to 2,147,483,647 -#define integer int // -2,147,483,648 to 2,147,483,647 - -typedef unsigned long ULONG; - -#define UCHAR unsigned char -#define UINT unsigned int -#define BOOL int -#define TRUE 1 -#define FALSE 0 - -// Soundcard Channels - -#define NONE 0 -#define LEFT 1 -#define RIGHT 2 - -#define nr_emph 2 - -#define decodedNormal 4 //'-' -#define decodedFEC 3 //'F' -#define decodedMEM 2 //'#' -#define decodedSingle 1 //'$' - - -// Seems to use Delphi TStringList for a lot of queues. This seems to be a list of pointers and a count -// Each pointer is to a Data/Length pair -//Maybe something like - -typedef struct string_T -{ - unsigned char * Data; - int Length; - int AllocatedLength; // A reasonable sized block is allocated at the start to speed up adding chars - -}string; - -typedef struct TStringList_T -{ - int Count; - string ** Items; - -} TStringList; - -// QPSK struct - -typedef struct TQPSK_t -{ - UCHAR tx[4]; - int count[4]; - UCHAR rx[4]; - UCHAR mode; -} TPQSK; - - -typedef struct TKISSMode_t -{ - string * data_in; - void * Socket; // Used as a key - - // Not sure what rest are used for. Seems to be one per channel - - TStringList buffer[4]; // Outgoing Frames - -} TKISSMode; - -typedef struct TMChannel_t -{ - - single prev_LPF1I_buf[4096]; - single prev_LPF1Q_buf[4096]; - single prev_dLPFI_buf[4096]; - single prev_dLPFQ_buf[4096]; - single prev_AFCI_buf[4096]; - single prev_AFCQ_buf[4096]; - single AngleCorr; - single MUX_osc; - single AFC_IZ1; - single AFC_IZ2; - single AFC_QZ1; - single AFC_QZ2; - single AFC_bit_buf1I[1024]; - single AFC_bit_buf1Q[1024]; - single AFC_bit_buf2[1024]; - single AFC_IIZ1; - single AFC_QQZ1; - -} TMChannel; - -typedef struct TFX25_t -{ - string data; - Byte status; - Byte bit_cnt; - Byte byte_rx; - unsigned long long tag; - Byte size; - Byte rs_size; - Byte size_cnt; -} TFX25; - - - -typedef struct TDetector_t -{ - struct TFX25_t fx25[4]; - TStringList mem_ARQ_F_buf[5]; - TStringList mem_ARQ_buf[5]; - float pll_loop[5]; - float last_sample[5]; - UCHAR ones[5]; - UCHAR zeros[5]; - float bit_buf[5][1024]; - float bit_buf1[5][1024]; - UCHAR sample_cnt[5]; - UCHAR last_bit[5]; - float PSK_IZ1[5]; - float PSK_QZ1[5]; - float PkAmpI[5]; - float PkAmpQ[5]; - float PkAmp[5]; - float PkAmpMax[5]; - int newpkpos[5]; - float AverageAmp[5]; - float AngleCorr[5]; - float MinAmp[5]; - float MaxAmp[5]; - float MUX3_osc[5]; - float MUX3_1_osc[5]; - float MUX3_2_osc[5]; - float Preemphasis6[5]; - float Preemphasis12[5]; - float PSK_AGC[5]; - float AGC[5]; - float AGC1[5]; - float AGC2[5]; - float AGC3[5]; - float AGC_max[5]; - float AGC_min[5]; - float AFC_IZ1[5]; - float AFC_IZ2[5]; - float AFC_QZ1[5]; - float AFC_QZ2[5]; - - UCHAR last_rx_bit[5]; - UCHAR bit_stream[5]; - UCHAR byte_rx[5]; - UCHAR bit_stuff_cnt[5]; - UCHAR bit_cnt[5]; - float bit_osc[5]; - UCHAR frame_status[5]; - string rx_data[5]; - string FEC_rx_data[5]; - // - UCHAR FEC_pol[5]; - unsigned short FEC_err[5]; - unsigned long long FEC_header1[5][2]; - unsigned short FEC_blk_int[5]; - unsigned short FEC_len_int[5]; - unsigned short FEC_len[5]; - - unsigned short FEC_len_cnt[5]; - - UCHAR rx_intv_tbl[5][4]; - UCHAR rx_intv_sym[5]; - UCHAR rx_viterbi[5]; - UCHAR viterbi_cnt[5]; - // SurvivorStates [1..4,0..511] of TSurvivor; - // - TMChannel MChannel[5][4]; - - float AFC_dF_avg[5]; - float AFC_dF[5]; - float AFC_bit_osc[5]; - float AFC_bit_buf[5][1024]; - unsigned short AFC_cnt[5]; - - string raw_bits1[5]; - string raw_bits[5]; - UCHAR last_nrzi_bit[5]; - - float BPF_core[5][2048]; - float LPF_core[5][2048]; - - float src_INTR_buf[5][8192]; - float src_INTRI_buf[5][8192]; - float src_INTRQ_buf[5][8192]; - float src_LPF1I_buf[5][8192]; - float src_LPF1Q_buf[5][8192]; - - float src_BPF_buf[5][2048]; - float src_Loop_buf[5][8192]; - float prev_BPF_buf[5][4096]; - - float prev_LPF1I_buf[5][4096]; - float prev_LPF1Q_buf[5][4096]; - float prev_INTR_buf[5][16384]; - float prev_INTRI_buf[5][16384]; - float prev_INTRQ_buf[5][16384]; - - Byte emph_decoded; - Byte rx_decoded; - Byte errors; - - -} TDetector; - - - -typedef struct AGWUser_t -{ - void *socket; - string * data_in; - TStringList AGW_frame_buf; - boolean Monitor; - boolean Monitor_raw; - boolean reportFreqAndModem; // Can report modem and frequency to host - -} AGWUser; - -typedef struct TAX25Info_t -{ - longint stat_s_pkt; - longint stat_s_byte; - longint stat_r_pkt; - longint stat_r_byte; - longint stat_r_fc; - longint stat_fec_count; - time_t stat_begin_ses; - time_t stat_end_ses; - longint stat_l_r_byte; - longint stat_l_s_byte; - -} TAX25Info; - -typedef struct TAX25Port_t -{ - Byte hi_vs; - Byte vs; - Byte vr; - Byte PID; - TStringList in_data_buf; - TStringList frm_collector; - string frm_win[8]; - string out_data_buf; - word t1; - word t2; - word t3; - Byte i_lo; - Byte i_hi; - word n1; - word n2; - word IPOLL_cnt; - TStringList frame_buf; //áóôåð êàäðîâ íà ïåðåäà÷ó - TStringList I_frame_buf; - Byte status; - word clk_frack; - char corrcall[10]; - char mycall[10]; - UCHAR digi[56]; - UCHAR Path[80]; // Path in ax25 format - added to save building it each time - UCHAR ReversePath[80]; - int snd_ch; // Simplifies parameter passing - int port; - int pathLen; - void * socket; - char kind[16]; - TAX25Info info; -} TAX25Port; - - -#define LOGEMERGENCY 0 -#define LOGALERT 1 -#define LOGCRIT 2 -#define LOGERROR 3 -#define LOGWARNING 4 -#define LOGNOTICE 5 -#define LOGINFO 6 -#define LOGDEBUG 7 - -#define PTTRTS 1 -#define PTTDTR 2 -#define PTTCAT 4 -#define PTTCM108 8 -#define PTTHAMLIB 16 - -// Status flags - -#define STAT_NO_LINK 0 -#define STAT_LINK 1 -#define STAT_CHK_LINK 2 -#define STAT_WAIT_ANS 3 -#define STAT_TRY_LINK 4 -#define STAT_TRY_UNLINK 5 - - - // Ñmd,Resp,Poll,Final,Digipeater flags -#define SET_P 1 -#define SET_F 0 -#define SET_C 1 -#define SET_R 0 -#define SET_NO_RPT 0 -#define SET_RPT 1 - // Frame ID flags -#define I_FRM 0 -#define S_FRM 1 -#define U_FRM 2 -#define I_I 0 -#define S_RR 1 -#define S_RNR 5 -#define S_REJ 9 -#define S_SREJ 0x0D -#define U_SABM 47 -#define U_DISC 67 -#define U_DM 15 -#define U_UA 99 -#define U_FRMR 135 -#define U_UI 3 - // PID flags -#define PID_X25 0x01 // 00000001-CCIT X25 PLP -#define PID_SEGMENT 0x08 // 00001000-Segmentation fragment -#define PID_TEXNET 0xC3 // 11000011-TEXNET Datagram Protocol -#define PID_LQ 0xC4 // 11001000-Link Quality Protocol -#define PID_APPLETALK 0xCA // 11001010-Appletalk -#define PID_APPLEARP 0xCB // 11001011-Appletalk ARP -#define PID_IP 0xCC // 11001100-ARPA Internet Protocol -#define PID_ARP 0xCD // 11001101-ARPA Address Resolution Protocol -#define PID_NET_ROM 0xCF // 11001111-NET/ROM - - -// Sound interface buffer size - -#define SendSize 1024 // 100 mS for now -#define ReceiveSize 512 // try 100 mS for now -#define NumberofinBuffers 4 - -#define Now getTicks() - -// #defines from all modules (?? is this a good idaa ?? - -#define WIN_MAXIMIZED 0 -#define WIN_MINIMIZED 1 -#define MODEM_CAPTION 'SoundModem by UZ7HO' -#define MODEM_VERSION '1.06' -#define SND_IDLE 0 -#define SND_RX 1 -#define SND_TX 2 -#define BUF_EMPTY 0 -#define BUF_FULL 1 -#define DISP_MONO FALSE -#define DISP_RGB TRUE -#define MOD_IDLE 0 -#define MOD_RX 1 -#define MOD_TX 2 -#define MOD_WAIT 3 -#define TIMER_FREE 0 -#define TIMER_BUSY 1 -#define TIMER_OFF 2 -#define TIMER_EVENT_ON 3 -#define TIMER_EVENT_OFF 4 -#define DEBUG_TIMER 1 -#define DEBUG_WATERFALL 2 -#define DEBUG_DECODE 4 -#define DEBUG_SOUND 8 -#define IS_LAST TRUE -#define IS_NOT_LAST FALSE -#define modes_count 16 -#define SPEED_300 0 -#define SPEED_1200 1 -#define SPEED_600 2 -#define SPEED_2400 3 -#define SPEED_P1200 4 -#define SPEED_P600 5 -#define SPEED_P300 6 -#define SPEED_P2400 7 -#define SPEED_Q4800 8 -#define SPEED_Q3600 9 -#define SPEED_Q2400 10 -#define SPEED_MP400 11 -#define SPEED_DW2400 12 -#define SPEED_8P4800 13 -#define SPEED_AE2400 14 -#define SPEED_ARDOP 15 - -#define MODE_FSK 0 -#define MODE_BPSK 1 -#define MODE_QPSK 2 -#define MODE_MPSK 3 -#define MODE_8PSK 4 -#define MODE_PI4QPSK 5 -#define MODE_ARDOP 6 - -#define QPSK_SM 0 -#define QPSK_V26 1 - - -#define MODEM_8P4800_BPF 3200 -#define MODEM_8P4800_TXBPF 3400 -#define MODEM_8P4800_LPF 1000 -#define MODEM_8P4800_BPF_TAP 64 -#define MODEM_8P4800_LPF_TAP 8 - // -#define MODEM_MP400_BPF 775 -#define MODEM_MP400_TXBPF 850 -#define MODEM_MP400_LPF 70 -#define MODEM_MP400_BPF_TAP 256 -#define MODEM_MP400_LPF_TAP 128 - // -#define MODEM_DW2400_BPF 2400 -#define MODEM_DW2400_TXBPF 2500 -#define MODEM_DW2400_LPF 900 -#define MODEM_DW2400_BPF_TAP 256 //256 -#define MODEM_DW2400_LPF_TAP 32 //128 - // -#define MODEM_Q2400_BPF 2400 -#define MODEM_Q2400_TXBPF 2500 -#define MODEM_Q2400_LPF 900 -#define MODEM_Q2400_BPF_TAP 256 //256 -#define MODEM_Q2400_LPF_TAP 128 //128 - // -#define MODEM_Q3600_BPF 3600 -#define MODEM_Q3600_TXBPF 3750 -#define MODEM_Q3600_LPF 1350 -#define MODEM_Q3600_BPF_TAP 256 -#define MODEM_Q3600_LPF_TAP 128 - // -#define MODEM_Q4800_BPF 4800 -#define MODEM_Q4800_TXBPF 5000 -#define MODEM_Q4800_LPF 1800 -#define MODEM_Q4800_BPF_TAP 256 -#define MODEM_Q4800_LPF_TAP 128 - // -#define MODEM_P2400_BPF 4800 -#define MODEM_P2400_TXBPF 5000 -#define MODEM_P2400_LPF 1800 -#define MODEM_P2400_BPF_TAP 256 -#define MODEM_P2400_LPF_TAP 128 - // -#define MODEM_P1200_BPF 2400 -#define MODEM_P1200_TXBPF 2500 -#define MODEM_P1200_LPF 900 -#define MODEM_P1200_BPF_TAP 256 -#define MODEM_P1200_LPF_TAP 128 - // -#define MODEM_P600_BPF 1200 -#define MODEM_P600_TXBPF 1250 -#define MODEM_P600_LPF 400 -#define MODEM_P600_BPF_TAP 256 -#define MODEM_P600_LPF_TAP 128 - // -#define MODEM_P300_BPF 600 -#define MODEM_P300_TXBPF 625 -#define MODEM_P300_LPF 200 -#define MODEM_P300_BPF_TAP 256 -#define MODEM_P300_LPF_TAP 128 - // -#define MODEM_300_BPF 500 -#define MODEM_300_TXBPF 500 -#define MODEM_300_LPF 155 -#define MODEM_300_BPF_TAP 256 -#define MODEM_300_LPF_TAP 128 - // -#define MODEM_600_BPF 800 -#define MODEM_600_TXBPF 900 -#define MODEM_600_LPF 325 -#define MODEM_600_BPF_TAP 256 -#define MODEM_600_LPF_TAP 128 - // -#define MODEM_1200_BPF 1400 -#define MODEM_1200_TXBPF 1600 -#define MODEM_1200_LPF 650 -#define MODEM_1200_BPF_TAP 256 -#define MODEM_1200_LPF_TAP 128 - // -#define MODEM_2400_BPF 3200 -#define MODEM_2400_TXBPF 3200 -#define MODEM_2400_LPF 1400 -#define MODEM_2400_BPF_TAP 256 -#define MODEM_2400_LPF_TAP 128 - -#define TX_SILENCE 0 -#define TX_DELAY 1 -#define TX_TAIL 2 -#define TX_NO_DATA 3 -#define TX_FRAME 4 -#define TX_WAIT_BPF 5 - - -#define FRAME_WAIT 0 -#define FRAME_LOAD 1 -#define RX_BIT0 0 -#define RX_BIT1 128 -#define DCD_WAIT_SLOT 0 -#define DCD_WAIT_PERSIST 1 - -#define FX25_MODE_NONE 0 -#define FX25_MODE_RX 1 -#define FX25_MODE_TXRX 2 -#define FX25_TAG 0 -#define FX25_LOAD 1 - -#define IL2P_MODE_NONE 0 -#define IL2P_MODE_RX 1 // RX il2p + HDLC -#define IL2P_MODE_TXRX 2 -#define IL2P_MODE_ONLY 3 // RX only il2p, TX il2p - - -#define MODE_OUR 0 -#define MODE_OTHER 1 -#define MODE_RETRY 2 - -#define FRAME_FLAG 126 // 7e - -#define port_num 32 // ?? Max AGW sessions -#define PKT_ERR 17 // Minimum packet size, bytes -#define I_MAX 7 // Maximum number of packets - - - // externs for all modules - -#define ARDOPBufferSize 12000 * 100 - -extern short ARDOPTXBuffer[4][12000 * 100]; // Enough to hold whole frame of samples - -extern int ARDOPTXLen[4]; // Length of frame -extern int ARDOPTXPtr[4]; // Tx Pointer - -extern BOOL KISSServ; -extern int KISSPort; - -extern BOOL AGWServ; -extern int AGWPort; - -extern TStringList KISS_acked[]; -extern TStringList KISS_iacked[]; - -extern TStringList all_frame_buf[5]; - -extern unsigned short pkt_raw_min_len; -extern int stat_r_mem; - -extern UCHAR diddles; - -extern int stdtones; -extern int fullduplex; - -extern struct TQPSK_t qpsk_set[4]; - -extern int NonAX25[5]; - -extern short txtail[5]; -extern short txdelay[5]; - -extern short modem_def[5]; - -extern int emph_db[5]; -extern UCHAR emph_all[5]; - -extern UCHAR modem_mode[5]; - -extern UCHAR RCVR[5]; -extern int soundChannel[5]; -extern int modemtoSoundLR[4]; - -extern short rx_freq[5]; -extern short rx_shift[5]; -extern short rx_baudrate[5]; -extern short rcvr_offset[5]; - -extern int tx_hitoneraisedb[5]; -extern float tx_hitoneraise[5]; - - -extern UCHAR tx_status[5]; -extern float tx_freq[5]; -extern float tx_shift[5]; -extern unsigned short tx_baudrate[5]; - -extern unsigned short bpf[5]; -extern unsigned short lpf[5]; - -extern unsigned short txbpf[5]; - -extern unsigned short tx_BPF_tap[5]; -extern unsigned short tx_BPF_timer[5]; - -extern unsigned short BPF_tap[5]; -extern unsigned short LPF_tap[5]; - -extern float tx_BPF_core[5][32768]; -extern float LPF_core[5][2048]; - -extern UCHAR xData[256]; -extern UCHAR xEncoded[256]; -extern UCHAR xDecoded[256]; - -extern float PI125; -extern float PI375; -extern float PI625; -extern float PI875; -extern float PI5; -extern float PI25; -extern float PI75; - -extern int max_frame_collector[4]; -extern boolean KISS_opt[4]; - -#define MaxErrors 4 - -extern BOOL MinOnStart; - -//RS TReedSolomon; -// Form1 TForm1; -// WaveFormat TWaveFormatEx; - -extern int UDPServ; -extern long long udpServerSeqno; - -extern int Channels; -extern int BitsPerSample; -extern float TX_Samplerate; -extern float RX_Samplerate; -extern int RX_SR; -extern int TX_SR; -extern int RX_PPM; -extern int TX_PPM; -extern int tx_bufsize; -extern int rx_bufsize; -extern int tx_bufcount; -extern int rx_bufcount; -extern int fft_size; -extern int mouse_down[2]; -//UCHAR * RX_pBuf array[257]; -// RX_header array[1..256] of TWaveHdr; -// TX_pBuf array[1..4,1..256] of pointer; -//TX_header array[1..4,1..256] of TWaveHdr; -extern UCHAR calib_mode[5]; -extern UCHAR snd_status[5]; -extern UCHAR buf_status[5]; -extern UCHAR tx_buf_num1[5]; -extern UCHAR tx_buf_num[5]; -extern int speed[5]; -extern int panels[6]; - -extern int FFTSize; -#define fft_size FFTSize - -extern float fft_window_arr[2048]; -// fft_s,fft_d array[0..2047] of TComplex; -extern short fft_buf[5][4096]; -extern UCHAR fft_disp[5][4096]; -// bm array[1..4] of TBitMap; -// bm1,bm2,bm3 TBitMap; - -// WaveInHandle hWaveIn; -// WaveOutHandle array[1..4] of hWaveOut; -extern int RXBufferLength; - -// data1 PData16; - -extern int grid_time; -extern int fft_mult; -extern int fft_spd; -extern int grid_timer; -extern int stop_wf; -extern int raduga; -extern char snd_rx_device_name[32]; -extern char snd_tx_device_name[32]; -extern int snd_rx_device; -extern int snd_tx_device; -extern UCHAR mod_icon_status; -extern UCHAR last_mod_icon_status; -extern UCHAR icon_timer; -// TelIni TIniFile; -extern char cur_dir[]; -// TimerId1 cardinal; -// TimerId2 cardinal; -extern UCHAR TimerStat1; -extern UCHAR TimerStat2; -extern int stat_log; - -extern char PTTPort[80]; // Port for Hardware PTT - may be same as control port. -extern int PTTMode; -extern int PTTBAUD ; - -extern char PTTOnString[128]; -extern char PTTOffString[128]; - -extern UCHAR PTTOnCmd[64]; -extern UCHAR PTTOnCmdLen; - -extern UCHAR PTTOffCmd[64]; -extern UCHAR PTTOffCmdLen; - -extern int PTT_device; -extern int RX_device; -extern int TX_device; -extern int TX_rotate; -extern int UsingLeft; -extern int UsingRight; -extern int UsingBothChannels; -extern int pttGPIOPin; -extern int pttGPIOPinR; -extern BOOL pttGPIOInvert; -extern BOOL useGPIO; -extern BOOL gotGPIO; -extern int VID; -extern int PID; -extern char CM108Addr[80]; -extern int HamLibPort; -extern char HamLibHost[]; - -extern int SCO; -extern int DualPTT; -extern UCHAR DebugMode; -extern UCHAR TimerEvent; -extern int nr_monitor_lines; -extern int UTC_Tim; -extern int MainPriority; -// MainThreadHandle THandle; -extern UCHAR w_state; - -extern BOOL Firstwaterfall; -extern BOOL Secondwaterfall; - -extern int dcd_threshold; -extern int rxOffset; -extern int chanOffset[4]; - -extern boolean busy; -extern boolean dcd[5]; - -extern struct TKISSMode_t KISS; - -extern boolean dyn_frack[4] ; -extern Byte recovery[4]; -extern Byte users[4]; - -extern int resptime[4]; -extern int slottime[4]; -extern int persist[4]; -extern int fracks[4]; -extern int frack_time[4]; -extern int idletime[4]; -extern int redtime[4]; -extern int IPOLL[4]; -extern int maxframe[4]; -extern int TXFrmMode[4]; - -extern char MyDigiCall[4][512]; -extern char exclude_callsigns[4][512]; -extern char exclude_APRS_frm[4][512]; - -extern TStringList list_exclude_callsigns[4]; -extern TStringList list_exclude_APRS_frm[4]; -extern TStringList list_digi_callsigns[4]; - - -extern int SoundIsPlaying; -extern int Capturing; - -extern struct TDetector_t DET[nr_emph + 1][16]; - -extern char CaptureDevice[80]; -extern char PlaybackDevice[80]; - -extern TAX25Port AX25Port[4][port_num]; - -extern int fx25_mode[4]; -extern int il2p_mode[4]; - -extern int tx_fx25_size[4]; -extern int tx_fx25_size_cnt[4]; -extern int tx_fx25_mode[4]; - -extern int SatelliteMode; - -// Function prototypes - -void KISS_send_ack(UCHAR port, string * data); -void AGW_AX25_frame_analiz(int snd_ch, int RX, string * frame); -void FIR_filter(float * src, unsigned short buf_size, unsigned short tap, float * core, float * dest, float * prev); -void make_core_TXBPF(UCHAR snd_ch, float freq, float width); -void OpenPTTPort(); -void ClosePTTPort(); - -void RadioPTT(int snd_ch, BOOL PTTState); -void put_frame(int snd_ch, string * frame, char * code, int tx_stat, int excluded); -void CloseCOMPort(int fd); -void COMClearRTS(int fd); -void COMClearDTR(int fd); -unsigned int getTicks(); -char * ShortDateTime(); -void write_ax25_info(TAX25Port * AX25Sess); -void reverse_addr(Byte * path, Byte * revpath, int Len); -string * get_mycall(string * path); -TAX25Port * get_user_port_by_calls(int snd_ch, char * CallFrom, char * CallTo); -TAX25Port * get_free_port(int snd_ch); -void * in_list_incoming_mycall(Byte * path); -boolean add_incoming_mycalls(void * socket, char * src_call); -int get_addr(char * Calls, UCHAR * AXCalls); -void reverse_addr(Byte * path, Byte * revpath, int Len); -void set_link(TAX25Port * AX25Sess, UCHAR * axpath); -void rst_timer(TAX25Port * AX25Sess); -void set_unlink(TAX25Port * AX25Sess, Byte * path); -unsigned short get_fcs(UCHAR * Data, unsigned short len); -void KISSSendtoServer(void * sock, Byte * Msg, int Len); -int ConvFromAX25(unsigned char * incall, char * outcall); -BOOL ConvToAX25(char * callsign, unsigned char * ax25call); -void Debugprintf(const char * format, ...); - -double pila(double x); - -void AGW_Raw_monitor(int snd_ch, string * data); - -// Dephi emulation functions - -string * Strings(TStringList * Q, int Index); -void Clear(TStringList * Q); -int Count(TStringList * List); - -string * newString(); -string * copy(string * Source, int StartChar, int Count); -TStringList * newTStringList(); - -void freeString(string * Msg); - -void initString(string * S); -void initTStringList(TStringList* T); - -// Two delete() This is confusing!! -// Not really - one acts on String, other TStringList - -void Delete(TStringList * Q, int Index); -void mydelete(string * Source, int StartChar, int Count); - -void move(UCHAR * SourcePointer, UCHAR * DestinationPointer, int CopyCount); -void fmove(float * SourcePointer, float * DestinationPointer, int CopyCount); - -void setlength(string * Msg, int Count); // Set string length - -string * stringAdd(string * Msg, UCHAR * Chars, int Count); // Extend string - -void Assign(TStringList * to, TStringList * from); // Duplicate from to to - -string * duplicateString(string * in); - -// This looks for a string in a stringlist. Returns inhex if found, otherwise -1 - -int my_indexof(TStringList * l, string * s); - -boolean compareStrings(string * a, string * b); - -int Add(TStringList * Q, string * Entry); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/agwlib.h b/agwlib.h deleted file mode 100644 index 688f918..0000000 --- a/agwlib.h +++ /dev/null @@ -1,45 +0,0 @@ - -#ifndef AGWLIB_H -#define AGWLIB_H 1 - - -// Call at beginning to start it up. - -int agwlib_init (char *host, char *port, int (*init_func)(void)); - - - -// Send commands to TNC. - - -int agwlib_X_register_callsign (int chan, char *call_from); - -int agwlib_x_unregister_callsign (int chan, char *call_from); - -int agwlib_G_ask_port_information (void); - -int agwlib_C_connect (int chan, char *call_from, char *call_to); - -int agwlib_d_disconnect (int chan, char *call_from, char *call_to); - -int agwlib_D_send_connected_data (int chan, int pid, char *call_from, char *call_to, int data_len, char *data); - -int agwlib_Y_outstanding_frames_for_station (int chan, char *call_from, char *call_to); - - - -// The application must define these. - -void agw_cb_C_connection_received (int chan, char *call_from, char *call_to, int data_len, char *data); -void on_C_connection_received (int chan, char *call_from, char *call_to, int incoming, char *data); - -void agw_cb_d_disconnected (int chan, char *call_from, char *call_to, int data_len, char *data); - -void agw_cb_D_connected_data (int chan, char *call_from, char *call_to, int data_len, char *data); - -void agw_cb_G_port_information (int num_chan, char *chan_descriptions[]); - -void agw_cb_Y_outstanding_frames_for_station (int chan, char *call_from, char *call_to, int frame_count); - - -#endif \ No newline at end of file diff --git a/ais.h b/ais.h deleted file mode 100644 index 6b96288..0000000 --- a/ais.h +++ /dev/null @@ -1,8 +0,0 @@ - - -void ais_to_nmea (unsigned char *ais, int ais_len, char *nema, int nema_size); - -int ais_parse (char *sentence, int quiet, char *descr, int descr_size, char *mssi, int mssi_size, double *odlat, double *odlon, - float *ofknots, float *ofcourse, float *ofalt_m, char *symtab, char *symbol, char *comment, int comment_size); - -int ais_check_length (int type, int length); diff --git a/aprs_tt.h b/aprs_tt.h deleted file mode 100644 index 4d33f48..0000000 --- a/aprs_tt.h +++ /dev/null @@ -1,191 +0,0 @@ - -/* aprs_tt.h */ - -#ifndef APRS_TT_H -#define APRS_TT_H 1 - - - -/* - * For holding location format specifications from config file. - * Same thing is also useful for macro definitions. - * We have exactly the same situation of looking for a pattern - * match and extracting fixed size groups of digits. - */ - -struct ttloc_s { - enum { TTLOC_POINT, TTLOC_VECTOR, TTLOC_GRID, TTLOC_UTM, TTLOC_MGRS, TTLOC_USNG, TTLOC_MACRO, TTLOC_MHEAD, TTLOC_SATSQ, TTLOC_AMBIG } type; - - char pattern[20]; /* e.g. B998, B5bbbdddd, B2xxyy, Byyyxxx, BAxxxx */ - /* For macros, it should be all fixed digits, */ - /* and the letters x, y, z. e.g. 911, xxyyyz */ - - union { - - struct { - double lat; /* Specific locations. */ - double lon; - } point; - - struct { - double lat; /* For bearing/direction. */ - double lon; - double scale; /* conversion to meters */ - } vector; - - struct { - double lat0; /* yyy all zeros. */ - double lon0; /* xxx */ - double lat9; /* yyy all nines. */ - double lon9; /* xxx */ - } grid; - - struct { - double scale; - double x_offset; - double y_offset; - long lzone; /* UTM zone, should be 1-60 */ - char latband; /* Latitude band if specified, otherwise space or - */ - char hemi; /* UTM Hemisphere, should be 'N' or 'S'. */ - } utm; - - struct { - char zone[8]; /* Zone and square for USNG/MGRS */ - } mgrs; - - struct { - char prefix[24]; /* should be 10, 6, or 4 digits to be */ - /* prepended to the received sequence. */ - } mhead; - - struct { - char *definition; - } macro; - - }; -}; - - -/* Error codes for sending responses to user. */ - -#define TT_ERROR_OK 0 /* Success. */ -#define TT_ERROR_D_MSG 1 /* D was first char of field. Not implemented yet. */ -#define TT_ERROR_INTERNAL 2 /* Internal error. Shouldn't be here. */ -#define TT_ERROR_MACRO_NOMATCH 3 /* No definition for digit sequence. */ -#define TT_ERROR_BAD_CHECKSUM 4 /* Bad checksum on call. */ -#define TT_ERROR_INVALID_CALL 5 /* Invalid callsign. */ -#define TT_ERROR_INVALID_OBJNAME 6 /* Invalid object name. */ -#define TT_ERROR_INVALID_SYMBOL 7 /* Invalid symbol specification. */ -#define TT_ERROR_INVALID_LOC 8 /* Invalid location. */ -#define TT_ERROR_NO_CALL 9 /* No call or object name included. */ -#define TT_ERROR_INVALID_MHEAD 10 /* Invalid Maidenhead Locator. */ -#define TT_ERROR_INVALID_SATSQ 11 /* Satellite square must be 4 digits. */ -#define TT_ERROR_SUFFIX_NO_CALL 12 /* No known callsign for suffix. */ - -#define TT_ERROR_MAXP1 13 /* Number of items above. i.e. Last number plus 1. */ - - -#if CONFIG_C /* Is this being included from config.c? */ - -/* Must keep in sync with above !!! */ - -static const char *tt_msg_id[TT_ERROR_MAXP1] = { - "OK", - "D_MSG", - "INTERNAL", - "MACRO_NOMATCH", - "BAD_CHECKSUM", - "INVALID_CALL", - "INVALID_OBJNAME", - "INVALID_SYMBOL", - "INVALID_LOC", - "NO_CALL", - "INVALID_MHEAD", - "INVALID_SATSQ", - "SUFFIX_NO_CALL" -}; - -#endif - -/* - * Configuration options for APRStt. - */ - -#define TT_MAX_XMITS 10 - -#define TT_MTEXT_LEN 64 - - -struct tt_config_s { - - int gateway_enabled; /* Send DTMF sequences to APRStt gateway. */ - - int obj_recv_chan; /* Channel to listen for tones. */ - - int obj_xmit_chan; /* Channel to transmit object report. */ - /* -1 for none. This could happen if we */ - /* are only sending to application */ - /* and/or IGate. */ - - int obj_send_to_app; /* send to attached application(s). */ - - int obj_send_to_ig; /* send to IGate. */ - - char obj_xmit_via[AX25_MAX_REPEATERS * (AX25_MAX_ADDR_LEN+1)]; - /* e.g. empty or "WIDE2-1,WIDE1-1" */ - - int retain_time; /* Seconds to keep information about a user. */ - - int num_xmits; /* Number of times to transmit object report. */ - - int xmit_delay[TT_MAX_XMITS]; /* Delay between them. */ - /* e.g. 3 seconds before first transmission then */ - /* delays of 16, 32, seconds etc. in between repeats. */ - - struct ttloc_s *ttloc_ptr; /* Pointer to variable length array of above. */ - int ttloc_size; /* Number of elements allocated. */ - int ttloc_len; /* Number of elements actually used. */ - - double corral_lat; /* The "corral" for unknown locations. */ - double corral_lon; - double corral_offset; - int corral_ambiguity; - - char status[10][TT_MTEXT_LEN]; /* Up to 9 status messages. e.g. "/enroute" */ - /* Position 0 means none and can't be changed. */ - - struct { - char method[AX25_MAX_ADDR_LEN]; /* SPEECH or MORSE[-n] */ - char mtext[TT_MTEXT_LEN]; /* Message text. */ - } response[TT_ERROR_MAXP1]; - - char ttcmd[80]; /* Command to generate custom audible response. */ -}; - - - - -void aprs_tt_init (struct tt_config_s *p_config, int debug); - -void aprs_tt_button (int chan, char button); - - - - - -#define APRSTT_LOC_DESC_LEN 32 /* Need at least 26 */ - -#define APRSTT_DEFAULT_SYMTAB '\\' -#define APRSTT_DEFAULT_SYMBOL 'A' - - -void aprs_tt_dao_to_desc (char *dao, char *str); - -void aprs_tt_sequence (int chan, char *msg); - -int dw_run_cmd (char *cmd, int oneline, char *result, size_t resultsiz); - - -#endif - -/* end aprs_tt.h */ \ No newline at end of file diff --git a/audio_stats.h b/audio_stats.h deleted file mode 100644 index 4cf8ad0..0000000 --- a/audio_stats.h +++ /dev/null @@ -1,7 +0,0 @@ - - -/* audio_stats.h */ - - -extern void audio_stats (int adev, int nchan, int nsamp, int interval); - diff --git a/ax25_agw.c b/ax25_agw.c index 5432195..ec73b2b 100644 --- a/ax25_agw.c +++ b/ax25_agw.c @@ -515,13 +515,15 @@ void on_AGW_Gs_frame(AGWUser * AGW, struct AGWHeader * Frame, Byte * Data) { // QTSM with a data field is used by QtSM to set/read Modem Params - Byte info[44] = { 0, 255, 24, 3, 100, 15, 6, 0, 1, 0, 0, 0 }; //QTSM Signature + Byte info[48] = { 0, 255, 24, 3, 100, 15, 6, 0, 1, 0, 0, 0 }; //QTSM Signature int Len = 12; if (Frame->DataLength == 32) { // BPQ to QTSM private Format. + // First 4 Freq, 4 to 24 Modem, rest was spare. Use 27-31 for modem control flags (fx.25 il2p etc) + int Freq; Byte versionBytes[4] = VersionBytes; @@ -542,7 +544,7 @@ void on_AGW_Gs_frame(AGWUser * AGW, struct AGWHeader * Frame, Byte * Data) // New Modem Name. Need to convert to index unless numeric int n; - + if (strlen(&Data[4]) < 3) { n = atoi(&Data[4]); @@ -569,6 +571,13 @@ void on_AGW_Gs_frame(AGWUser * AGW, struct AGWHeader * Frame, Byte * Data) } } + if (Data[27] == 2) + { + fx25_mode[Frame->Port] = Data[28]; + il2p_mode[Frame->Port] = Data[29]; + il2p_crc[Frame->Port] = Data[30]; + } + // Return Freq and Modem memcpy(&info[12], &rx_freq[Frame->Port], 2); @@ -577,6 +586,22 @@ void on_AGW_Gs_frame(AGWUser * AGW, struct AGWHeader * Frame, Byte * Data) memcpy(&info[38], versionBytes, 4); Len = 44; + + if (Data[27]) + { + // BPQ understands fx25 and il2p fields + + AGW->reportFreqAndModem = 2; // Can report frequency Modem and flags + + + Len = 48; + + info[44] = 1; // Show includes Modem Flags + info[45] = fx25_mode[Frame->Port]; + info[46] = il2p_mode[Frame->Port]; + info[47] = il2p_crc[Frame->Port]; + } + AGW_send_to_app(AGW->socket, AGW_Gs_Frame(Frame->Port, info, Len)); return; } @@ -1337,6 +1362,9 @@ void AGW_Report_Modem_Change(int port) AGWUser * AGW; string * pkt; + if (soundChannel[port] == 0) // Not in use + return; + // I think we send to all AGW sockets for (i = 0; i < AGWConCount; i++) @@ -1345,16 +1373,27 @@ void AGW_Report_Modem_Change(int port) if (AGW->reportFreqAndModem) { - // QTSM 's' Message with a data field is used by QtSM to set/read Modem Params + // QTSM 'g' Message with a data field is used by QtSM to set/read Modem Params - Byte info[44] = { 0, 255, 24, 3, 100, 15, 6, 0, 1, 0, 0, 0 }; //QTSM Signature + Byte info[48] = { 0, 255, 24, 3, 100, 15, 6, 0, 1, 0, 0, 0 }; //QTSM Signature + int Len = 44; // Return Freq and Modem memcpy(&info[12], &rx_freq[port], 2); memcpy(&info[16], modes_name[speed[port]], 20); info[37] = speed[port]; // Index - AGW_send_to_app(AGW->socket, AGW_Gs_Frame(port, info, 44)); + + if (AGW->reportFreqAndModem == 2) + { + Len = 48; + + info[44] = 1; // Show includes Modem Flags + info[45] = fx25_mode[port]; + info[46] = il2p_mode[port]; + info[47] = il2p_crc[port]; + } + AGW_send_to_app(AGW->socket, AGW_Gs_Frame(port, info, Len)); } } } diff --git a/ax25_demod.c b/ax25_demod.c index 3e1b5bb..f1b0b36 100644 --- a/ax25_demod.c +++ b/ax25_demod.c @@ -142,6 +142,7 @@ short active_rx_freq[5] = { 1700, 1700,1700,1700,1700 }; int fx25_mode[4] = { 0, 0, 0, 0 }; int il2p_mode[4] = { 0, 0, 0, 0 }; +int il2p_crc[4] = { 0, 0, 0, 0 }; int pnt_change[5] = { 0 }; float src_buf[5][2048]; diff --git a/ax25_link.h b/ax25_link.h deleted file mode 100644 index 40fa401..0000000 --- a/ax25_link.h +++ /dev/null @@ -1,88 +0,0 @@ - -/* ax25_link.h */ - - -#ifndef AX25_LINK_H -#define AX25_LINK_H 1 - -#include "ax25_pad.h" // for AX25_MAX_INFO_LEN - -#include "dlq.h" // for dlq_item_t - -#include "config.h" // for struct misc_config_s - - - -// Limits and defaults for parameters. - - -#define AX25_N1_PACLEN_MIN 1 // Max bytes in Information part of frame. -#define AX25_N1_PACLEN_DEFAULT 256 // some v2.0 implementations have 128 -#define AX25_N1_PACLEN_MAX AX25_MAX_INFO_LEN // from ax25_pad.h - - -#define AX25_N2_RETRY_MIN 1 // Number of times to retry before giving up. -#define AX25_N2_RETRY_DEFAULT 10 -#define AX25_N2_RETRY_MAX 15 - - -#define AX25_T1V_FRACK_MIN 1 // Number of seconds to wait before retrying. -#define AX25_T1V_FRACK_DEFAULT 3 // KPC-3+ has 4. TM-D710A has 3. -#define AX25_T1V_FRACK_MAX 15 - - -#define AX25_K_MAXFRAME_BASIC_MIN 1 // Window size - number of I frames to send before waiting for ack. -#define AX25_K_MAXFRAME_BASIC_DEFAULT 4 -#define AX25_K_MAXFRAME_BASIC_MAX 7 - -#define AX25_K_MAXFRAME_EXTENDED_MIN 1 -#define AX25_K_MAXFRAME_EXTENDED_DEFAULT 32 -#define AX25_K_MAXFRAME_EXTENDED_MAX 63 // In theory 127 but I'm restricting as explained in SREJ handling. - - - -// Call once at startup time. - -void ax25_link_init (struct misc_config_s *pconfig); - - - -// IMPORTANT: - -// These functions must be called on a single thread, one at a time. -// The Data Link Queue (DLQ) is used to serialize events from multiple sources. - -// Maybe the dispatch switch should be moved to ax25_link.c so they can all -// be made static and they can't be called from the wrong place accidentally. - -void dl_connect_request (dlq_item_t *E); - -void dl_disconnect_request (dlq_item_t *E); - -void dl_data_request (dlq_item_t *E); - -void dl_register_callsign (dlq_item_t *E); - -void dl_unregister_callsign (dlq_item_t *E); - -void dl_outstanding_frames_request (dlq_item_t *E); - -void dl_client_cleanup (dlq_item_t *E); - - -void lm_data_indication (dlq_item_t *E); - -void lm_seize_confirm (dlq_item_t *E); - -void lm_channel_busy (dlq_item_t *E); - - -void dl_timer_expiry (void); - - -double ax25_link_get_next_timer_expiry (void); - - -#endif - -/* end ax25_link.h */ \ No newline at end of file diff --git a/ax25_mod-DESKTOP-MHE5LO8.c b/ax25_mod-DESKTOP-MHE5LO8.c deleted file mode 100644 index 4c803c2..0000000 --- a/ax25_mod-DESKTOP-MHE5LO8.c +++ /dev/null @@ -1,1810 +0,0 @@ -/* -Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO - -This file is part of QtSoundModem - -QtSoundModem 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 3 of the License, or -(at your option) any later version. - -QtSoundModem 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 QtSoundModem. If not, see http://www.gnu.org/licenses - -*/ - -// UZ7HO Soundmodem Port by John Wiseman G8BPQ - - -#include "UZ7HOStuff.h" - -// I assume this modulates (and sends?} frames - -int RSEncode(UCHAR * bytToRS, UCHAR * RSBytes, int DataLen, int RSLen); - -//unit ax25_mod; - -//interface - -//uses sysutils,classes,math - -extern int SampleNo; - -extern BOOL KISSServ; - -extern TStringList KISS_acked[]; -extern TStringList KISS_iacked[]; - -extern UCHAR modem_mode[]; - -#define sbc 175 - -extern single ch_offset[4]; -int Continuation[4] = { 0, 0, 0, 0 }; // Sending 2nd or more packet of burst - -#define COS45 0.70710676908493f - -#define TX_SILENCE 0 -#define TX_DELAY 1 -#define TX_TAIL 2 -#define TX_NO_DATA 3 -#define TX_FRAME 4 -#define TX_WAIT_BPF 5 - - -#define TX_BIT0 0 -#define TX_BIT1 1 -#define FRAME_EMPTY 0 -#define FRAME_FULL 1 -#define FRAME_NO_FRAME 2 -#define FRAME_NEW_FRAME 3 -#define BYTE_EMPTY 0 -#define BYTE_FULL 1 - - -UCHAR gray_8PSK[8] = {7,0,6,5,2,1,3,4}; // ?? was 1::8 - -UCHAR gray_PI4QPSK[4] = {3,1,5,7}; - - -float audio_buf[5][32768]; // [1..4,0..32767] -float tx_src_BPF_buf[5][32768]; -float tx_BPF_buf[5][32768]; -float tx_prev_BPF_buf[5][32768]; -float tx_BPF_core[5][32768]; - -long tx_delay_cnt[5] = {0}; // : array[1..4] of longword=(0,0,0,0}; -long tx_tail_cnt[5] = {0}; - -int tx_hitoneraisedb[5] = {0}; // : array[1..4] of integer=(0,0,0,0}; -float tx_hitoneraise[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_freq[5] = { 1000, 1000, 1000, 1000, 1000}; // : array[1..4] of single=(1000,1000,1000,1000}; -float tx_shift[5] = { 200, 200, 200, 200, 200}; // : array[1..4] of single=(200,200,200,200}; -float tx_bit_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_osc[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_bit_osc[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -unsigned short txbpf[5] = { 400, 400, 400, 400, 400}; // : array[1..4] of word=(400,400,400,400}; -unsigned short tx_BPF_tap[5] = { 256, 256, 256, 256, 256}; // : array[1..4] of word=(256,256,256,256}; -unsigned short tx_baudrate[5] = { 300, 300, 300, 300, 300 }; // : array[1..4] of word=(300,300,300,300}; -unsigned short tx_bitrate[5] = { 300, 300, 300, 300, 300 }; // : array[1..4] of word=(300,300,300,300}; -unsigned short tx_BPF_timer[5] = {0}; // : array[1..4] of word=(0,0,0,0}; -UCHAR tx_pol[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_last_pol[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_last_diddle[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_flag_cnt[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_frame_status[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_byte_status[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_status[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_bit_stuff_cnt[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_bit_cnt[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_last_bit[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_bit_stream[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; - -UCHAR tx_8PSK[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; -UCHAR tx_QPSK[5] = {0}; // : array[1..4] of byte=(0,0,0,0}; - -float tx_I_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_Q_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_QPSK_avg_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_avg_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_df_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_df_Q [5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_old_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_QPSK_old_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_avg_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_avg_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_df_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_df_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_old_I[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_8PSK_old_Q[5] = {0}; // : array[1..4] of single=(0,0,0,0}; - -float tx_osc1[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_osc2[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_osc3[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -float tx_osc4[5] = {0}; // : array[1..4] of single=(0,0,0,0}; -short tx_inv1[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_inv2[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_inv3[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_inv4[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_old_inv1[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_old_inv2[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_old_inv3[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -short tx_old_inv4[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -float tx_bit1_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_bit2_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_bit3_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -float tx_bit4_mod[5] = {1, 1, 1, 1, 1}; // : array[1..4] of single=(1,1,1,1}; -UINT tx_viterbi[5] = {0}; // : array[1..4] of word=(0,0,0,0}; -UCHAR tx_intv_tbl[5][4]; // : array[1..4,0..3] of byte; - -short tx_inv[5] = {1, 1, 1, 1, 1}; // : array[1..4] of shortint=(1,1,1,1}; -BOOL tx_change_phase[5] = {0}; // : array[1..4] of boolean=(FALSE,FALSE,FALSE,FALSE}; -BOOL tx_bs_bit[5] = {0}; // : array[1..4] of boolean=(FALSE,FALSE,FALSE,FALSE}; - -string * tx_data[5] = {0}; // : array[1..4] of string=('','','',''}; -int tx_data_len[5] = {0}; - -int tx_fx25_size[4] = { 0, 0, 0, 0 }; -int tx_fx25_size_cnt[4] = { 0, 0, 0, 0 }; -int tx_fx25_mode[4] = { 0, 0, 0, 0 }; - - -// uses sm_main,ax25,ax25_agw,ax25_demod,rsunit; - -UCHAR tx_nrzi(UCHAR snd_ch, UCHAR bit) -{ -// Debugprintf("Before NRZI %d", bit); - - if (bit == TX_BIT0) - { - // Zero so switch bit - - tx_last_bit[snd_ch] ^= 1; - } - return tx_last_bit[snd_ch]; -} - -BOOL tx_bit_stuffing(UCHAR snd_ch, UCHAR bit) -{ - // result = FALSE; - // if bit=TX_BIT1 then inc(tx_bit_stuff_cnt[snd_ch]}; - // if bit=TX_BIT0 then tx_bit_stuff_cnt[snd_ch] = 0; - // if tx_bit_stuff_cnt[snd_ch]=5 then begin tx_bit_stuff_cnt[snd_ch] = 0; result = TRUE; end; -//end; - - if (bit == TX_BIT1) - tx_bit_stuff_cnt[snd_ch]++; - - if (bit == TX_BIT0) - tx_bit_stuff_cnt[snd_ch] = 0; - - if (tx_bit_stuff_cnt[snd_ch] == 5) - { - tx_bit_stuff_cnt[snd_ch] = 0; - return TRUE; - } - - return FALSE; -} - - - - -void interleave(char *s, int len) -{ -// var - // data: string; - // i,k,len: word; - // nr_blocks: word; -//begin{ -// data = ''; - // len = length(s}; - // if len>0 then nr_blocks = ((len-1} div 16}+1 else nr_blocks = 1; - // for i = 1 to 16 do - // for k = 0 to nr_blocks-1 do - // if (i+k*16}<=len then data = data+s[i+k*16]; - // result = data; -//end; - - char data[1024]; - - UINT i,k; - UINT nr_blocks; - int n = 0; - - if (len > 0) - nr_blocks = ((len - 1) / 16) + 1; - else - nr_blocks = 1; - - for (i = 0; i < 16; i++) - { - for (k = 0; k < nr_blocks; k++) - { - if ((i + k * 16) <= len) - data[n++] = s[i + k * 16]; - } - } - - memcpy(s, data, len); -} - -//procedure get_new_frame(snd_ch: byte; var frame_stream: TStringList}; -//var -// header,line,temp: string; -// len,i,size: word; - // crc: word; -//begin - -void get_new_frame(UCHAR snd_ch, TStringList * frame_stream) -{ - UCHAR header[256]; - UCHAR line[1024]; - - int LineLen; - - string ** Items; - - string * myTemp; - - UCHAR temp[1024]; - - UINT len, i, size; - UINT crc; - - tx_bs_bit[snd_ch] = FALSE; - tx_bit_cnt[snd_ch] = 0; - tx_flag_cnt[snd_ch] = 0; - tx_bit_stuff_cnt[snd_ch] = 0; - tx_bit_stream[snd_ch] = FRAME_FLAG; - tx_frame_status[snd_ch] = FRAME_NEW_FRAME; - tx_byte_status[snd_ch] = BYTE_EMPTY; - - if (frame_stream->Count == 0) - { - tx_frame_status[snd_ch] = FRAME_NO_FRAME; - return; - } - - // We now pass control byte and ack bytes on front and pointer to socket on end if ackmode - - myTemp = Strings(frame_stream, 0); // get message - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[snd_ch], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - tx_data[snd_ch] = duplicateString(myTemp); // so can free original below - - Delete(frame_stream, 0); // This will invalidate temp - - AGW_AX25_frame_analiz(snd_ch, FALSE, tx_data[snd_ch]); - - put_frame(snd_ch, tx_data[snd_ch], "", TRUE, FALSE); - - if (tx_data[snd_ch]->Length == 0 || modem_mode[snd_ch] != MODE_MPSK) - return; - - // Reformat MPSK Data - - //Take data 8 bytes at a time and add 8 bytes of RS data - - LineLen = 0; - - while (tx_data[snd_ch]->Length > 0) - { - size = tx_data[snd_ch]->Length; - - if (size > 8) - size = 8; - - memcpy(temp, tx_data[snd_ch]->Data, size); - - // Delete the chars from tx_data - - mydelete(tx_data[snd_ch], 0, 8); - - memset(xData, 0, sizeof(xData)); - memset(xEncoded, 0, sizeof(xEncoded)); - - memcpy(xData, temp, size); - - InitBuffers(); - EncodeRS(xData, xEncoded); // This puts the 8 RS bytes in xEncoded - - memcpy(&line[LineLen], xData, size); - memcpy(&line[LineLen + size], xEncoded, MaxErrors * 2); - - LineLen += size + (MaxErrors * 2); - } - - - - - len = LineLen; - - interleave(line, LineLen); - scrambler(line, LineLen); - - header[0] = 0x7e; - header[1] = 0x7e; - header[2] = len >> 8; - header[3] = len; - - crc = get_fcs(header, 4); - - header[4] = crc >> 8; - header[5] = crc; - - memset(xData, 0, sizeof(xData)); - memset(xEncoded, 0, sizeof(xEncoded)); - memmove(xData, header, 6); - - - // RSEncode(xData, xEncoded, 6 + (MaxErrors * 2), MaxErrors * 2); - - InitBuffers(); - EncodeRS(xData, xEncoded); - - fx25_encode_rs(xData, xEncoded, 0, 8); - - - // We should now have RS Encoded Header in xEncoded; - - // I think we send encoded header then line - - tx_data[snd_ch]->Length = 0; - - stringAdd(tx_data[snd_ch], xData, 6); - stringAdd(tx_data[snd_ch], xEncoded, MaxErrors * 2); - stringAdd(tx_data[snd_ch], line, LineLen); - - // For testing, descramble and de-interleve - - scrambler(line, LineLen); // should look like interleaved - { - Byte unscrambled[1024]; - int count, len; - int origlen; - - len = LineLen; - count = (len + 15) / 16; - - int j1, j2, j3, i, j; - - j3 = 0; - - for (j1 = 0; j1 < 16; j1++) - { - // Each char in block - - for (j2 = 0; j2 < count; j2++) - { - // Blocks - - unscrambled[j2 * 16 + j1] = line[j3]; - j3++; - } - } - - // Now remove RS (will check later) - - i = 0; - j = 0; - - while (j < len) - { - Byte line1[256]; - int nErr, eras_pos = 0; - Byte rs_block[256]; - - memcpy(line1, &unscrambled[j], 16); - - memset(xEncoded, 0, sizeof(xEncoded)); - memset(xDecoded, 0, sizeof(xDecoded)); - - memcpy(xEncoded, &unscrambled[j], 16); - -// nErr = DecodeRS(xEncoded, xDecoded); - - memset(rs_block, 0, 255); - memcpy(rs_block, &unscrambled[j], 8); - memcpy(&rs_block[255 - 8], &unscrambled[j+8], 8); - - nErr = fx25_decode_rs(rs_block, &eras_pos, 0, 0, 8); - - -// line1 = ''; -// for j1 = MaxErrors * 2 to size - 1 do line1 = line1 + chr(xDecoded[j1]); - - - memcpy(&unscrambled[i], &unscrambled[j], 8); - i += 8; - j += 16; - } - - j3 = j3; - - } - -} - - - -int get_new_bit(Byte snd_ch, Byte bit) -{ - unsigned short len; - string * s; - - if (tx_frame_status[snd_ch] == FRAME_FULL) - { - if (tx_byte_status[snd_ch] == BYTE_EMPTY) - { - len = tx_data[snd_ch]->Length; - - if (len > 0) - { - s = tx_data[snd_ch]; - tx_bit_stream[snd_ch] = (s->Data[0]); - tx_frame_status[snd_ch] = FRAME_FULL; - tx_byte_status[snd_ch] = BYTE_FULL; - tx_bit_cnt[snd_ch] = 0; - mydelete(tx_data[snd_ch], 0, 1); - } - - else tx_frame_status[snd_ch] = FRAME_EMPTY; - } - - if (tx_byte_status[snd_ch] == BYTE_FULL) - bit = tx_bit_stream[snd_ch] & TX_BIT1; - - if (modem_mode[snd_ch] == MODE_MPSK) - { - tx_bit_cnt[snd_ch]++; - tx_bit_stream[snd_ch] = tx_bit_stream[snd_ch] >> 1; - if (tx_bit_cnt[snd_ch] >= 8) - tx_byte_status[snd_ch] = BYTE_EMPTY; - - } - else - { - if (tx_bs_bit[snd_ch]) - bit = TX_BIT0; - - tx_bs_bit[snd_ch] = tx_bit_stuffing(snd_ch, bit); - - if (!tx_bs_bit[snd_ch]) - { - tx_bit_cnt[snd_ch]++; - tx_bit_stream[snd_ch] >>= 1; - if (tx_bit_cnt[snd_ch] >= 8 && !tx_bs_bit[snd_ch]) - tx_byte_status[snd_ch] = BYTE_EMPTY; - } - } - } - - if (tx_frame_status[snd_ch] == FRAME_EMPTY) - get_new_frame(snd_ch, &all_frame_buf[snd_ch]); - - if ((tx_frame_status[snd_ch] == FRAME_NEW_FRAME) || (tx_frame_status[snd_ch] == FRAME_NO_FRAME)) - { - bit = tx_bit_stream[snd_ch] & TX_BIT1; - tx_flag_cnt[snd_ch]++; - tx_bit_stream[snd_ch] >>= 1; - - if (tx_flag_cnt[snd_ch] == 8) - { - switch (tx_frame_status[snd_ch]) - { - case FRAME_NEW_FRAME: - - tx_frame_status[snd_ch] = FRAME_FULL; - break; - - case FRAME_NO_FRAME: - - tx_tail_cnt[snd_ch] = 0; - tx_frame_status[snd_ch] = FRAME_EMPTY; - tx_status[snd_ch] = TX_TAIL; - - break; - } - } - } - return bit; -} - -////// FX.25 ////// - - -void bit_to_fx25(Byte * tx_byte, Byte * bit_cnt, Byte bit, string * data, int * data_cnt) -{ - *tx_byte = (*tx_byte >> 1) | (bit << 7); - (*bit_cnt)++; - - if (*bit_cnt == 8) - { - stringAdd(data, tx_byte, 1); - *bit_cnt = 0; - } - (*data_cnt)++; -} - -string * fill_fx25_data(int snd_ch, string * data) -{ -#define nr_tags 5 - - string * result; - - Byte rs_roots[nr_tags + 1] = { 16, 32, 64, 32, 16, 16 }; - word rs_payload[nr_tags + 1] = { 1912, 1784, 1528, 1024, 512, 256 }; // 239, 233, 191, 128, 64, 32 - - unsigned long long rs_tag[nr_tags + 1] = - { - 0xB74DB7DF8A532F3E, // 255 / 16 (239) - 0x6E260B1AC5835FAE, // 255 / 32 (223) - 0x3ADB0C13DEAE2836, // 255 / 64 (191) - 0xFF94DC634F1CFF4E, // 160 / 32 (128) - 0xC7DC0508F3D9B09E, // 80 / 16 (64) - 0x8F056EB4369660EE // 48 / 16 (32) - }; - -// 0x26FF60A600CC8FDE) 144; = 16; -// 0x1EB7B9CDBC09C00E) 96; 32; -// 0xDBF869BD2DBB1776) 64;= 32; -// 0xAB69DB6A543188D6) 192; = 64; -// 0x4A4ABEC4A724B796) 128; = 64; - - string * ax25_data = newString(); - - int i, ax25_size; - Byte a, bit, bit_cnt, bit_cnt1, bs, tx_byte; - Byte rs_id; - Byte rs_block[256], parity[256]; - - ax25_size = 0; - bs = 0; - tx_byte = 0; - bit_cnt = 0; - - // Load start flag - a = FRAME_FLAG; - - for (i = 0; i < 8; i++) - { - bit = a & 1; - a = a >> 1; - bit_to_fx25(&tx_byte, &bit_cnt, bit, ax25_data, &ax25_size); - } - - // Load body - for (i = 0; i < data->Length; i++) - { - bit_cnt1 = 0; - a = data->Data[i]; - do - { - if (bs == 5) - { - bit = TX_BIT0; - bs = 0; - } - else - { - bit = a & 1; - a = a >> 1; - bit_cnt1++; - - if (bit == TX_BIT1) - bs++; - else - bs = 0; - } - - bit_to_fx25(&tx_byte, &bit_cnt, bit, ax25_data, &ax25_size); - - } while (bit_cnt1 != 8 || bs == 5); - } - - // Load close flag - - a = FRAME_FLAG; - - for (i = 0; i < 8; i++) - { - bit = a & 1; - a = a >> 1; - bit_to_fx25(&tx_byte, &bit_cnt, bit, ax25_data, &ax25_size); - } - - a = FRAME_FLAG; - - // if too short or too long - - if (ax25_size < 168 || ax25_size > 1912) // < 21 or > 239 - { - // Send as normal ax25 packet - - if (bit_cnt > 0) - { - do - { - tx_byte = tx_byte >> 1; - bit_cnt++; - if (bit_cnt == 8) - stringAdd(ax25_data, &tx_byte, 1); - } while (bit_cnt < 8); - } - tx_fx25_size[snd_ch] = ax25_size; - return ax25_data; - } - - // Send as FX25 Message - - // find RS block size - - rs_id = 0; - - for (i = 0; i <= nr_tags; i++) - if (ax25_size <= rs_payload[i]) - rs_id = i; - - // Padding to block size - - while (ax25_size != rs_payload[rs_id]) - { - bit = a & 1; - a = (a >> 1) | (bit << 7); - bit_to_fx25(&tx_byte, &bit_cnt, bit, ax25_data, &ax25_size); - } - - memset(rs_block, 0, 255); - move(&ax25_data->Data[0], &rs_block[0], ax25_data->Length); - - fx25_encode_rs(rs_block, parity, 0, rs_roots[rs_id]); - - result = newString(); - - stringAdd(result, (Byte *)&rs_tag[rs_id], 8); - stringAdd(result, ax25_data->Data, ax25_data->Length); - stringAdd(result, parity, rs_roots[rs_id]); - - tx_fx25_size[snd_ch] = result->Length << 3; - - freeString(ax25_data); - return result; -} - -void fx25_get_new_frame(int snd_ch, TStringList * frame_stream) -{ - string * myTemp; - - tx_bs_bit[snd_ch] = 0; - tx_bit_cnt[snd_ch] = 0; - tx_flag_cnt[snd_ch] = 0; - tx_bit_stuff_cnt[snd_ch] = 0; - tx_fx25_size_cnt[snd_ch] = 0; - tx_fx25_size[snd_ch] = 1; - tx_frame_status[snd_ch] = FRAME_NEW_FRAME; - tx_byte_status[snd_ch] = BYTE_EMPTY; - if (frame_stream->Count == 0) - tx_frame_status[snd_ch] = FRAME_NO_FRAME; - else - { - // We now pass control byte and ack bytes on front and pointer to socket on end if ackmode - - myTemp = Strings(frame_stream, 0); // get message - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[snd_ch], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - AGW_AX25_frame_analiz(snd_ch, FALSE, myTemp); - put_frame(snd_ch, myTemp, "", TRUE, FALSE); - - tx_data[snd_ch] = fill_fx25_data(snd_ch, myTemp); - - Delete(frame_stream, 0); // This will invalidate temp - } -} - -int fx25_get_new_bit(int snd_ch, Byte bit) -{ - string *s; - - if (tx_frame_status[snd_ch] == FRAME_EMPTY) - { - fx25_get_new_frame(snd_ch, &all_frame_buf[snd_ch]); - if (tx_frame_status[snd_ch] == FRAME_NEW_FRAME) - tx_frame_status[snd_ch] = FRAME_FULL; - } - - if (tx_frame_status[snd_ch] == FRAME_FULL) - { - if (tx_byte_status[snd_ch] == BYTE_EMPTY) - { - if (tx_data[snd_ch]->Length) - { - s = tx_data[snd_ch]; - - tx_bit_stream[snd_ch] = s->Data[0]; - tx_frame_status[snd_ch] = FRAME_FULL; - tx_byte_status[snd_ch] = BYTE_FULL; - tx_bit_cnt[snd_ch] = 0; - mydelete(tx_data[snd_ch], 0, 1); - } - else - tx_frame_status[snd_ch] = FRAME_EMPTY; - } - if (tx_byte_status[snd_ch] == BYTE_FULL) - { - bit = tx_bit_stream[snd_ch] & TX_BIT1; - tx_bit_stream[snd_ch] = tx_bit_stream[snd_ch] >> 1; - tx_bit_cnt[snd_ch]++; - tx_fx25_size_cnt[snd_ch]++; - if (tx_bit_cnt[snd_ch] >= 8) - tx_byte_status[snd_ch] = BYTE_EMPTY; - if (tx_fx25_size_cnt[snd_ch] == tx_fx25_size[snd_ch]) - tx_frame_status[snd_ch] = FRAME_EMPTY; - } - } - - if (tx_frame_status[snd_ch] == FRAME_EMPTY) - { - fx25_get_new_frame(snd_ch, &all_frame_buf[snd_ch]); - - switch (tx_frame_status[snd_ch]) - { - case FRAME_NEW_FRAME: - tx_frame_status[snd_ch] = FRAME_FULL; - break; - - case FRAME_NO_FRAME: - tx_tail_cnt[snd_ch] = 0; - tx_frame_status[snd_ch] = FRAME_EMPTY; - tx_status[snd_ch] = TX_TAIL; - break; - } - } - return bit; -} - - -////////////////// - - -int get_new_bit_tail(UCHAR snd_ch, UCHAR bit) -{ - long _txtail = 0; - UCHAR _diddles; - - if (modem_mode[snd_ch] == MODE_FSK) - _diddles = diddles; - else - _diddles = 0; - - if (modem_mode[snd_ch] == MODE_FSK) - _txtail = txtail[snd_ch]; - - else if (modem_mode[snd_ch] == MODE_BPSK) - _txtail = txtail[snd_ch]; - - else if (modem_mode[snd_ch] == MODE_8PSK) - _txtail = txtail[snd_ch] * 3; - - else if (modem_mode[snd_ch] == MODE_QPSK || modem_mode[snd_ch] == MODE_PI4QPSK) - _txtail = txtail[snd_ch] << 1; - - else if (modem_mode[snd_ch] == MODE_MPSK) - _txtail = txtail[snd_ch] << 2; - - _txtail = (_txtail * tx_baudrate[snd_ch]) / 1000; - - if (qpsk_set[snd_ch].mode == QPSK_V26 || modem_mode[snd_ch] == MODE_8PSK) - _diddles = 2; - - switch (_diddles) - { - case 0: - - if (tx_tail_cnt[snd_ch] < _txtail) - { - bit = TX_BIT0; - tx_tail_cnt[snd_ch]++; - } - else - { - tx_status[snd_ch] = TX_WAIT_BPF; - } - - break; - - case 1: - - if (tx_tail_cnt[snd_ch] < _txtail) - { - if (tx_last_diddle[snd_ch] == TX_BIT0) - bit = TX_BIT1; - else - bit = TX_BIT0; - - tx_tail_cnt[snd_ch]++; - tx_last_diddle[snd_ch] = bit; - } - else - { - Debugprintf("End TXTAIL %d", SampleNo); - tx_status[snd_ch] = TX_WAIT_BPF; - } - - break; - - case 2: - - if (tx_tail_cnt[snd_ch] < _txtail) - { - bit = FRAME_FLAG >> (tx_tail_cnt[snd_ch] % 8) & 1; - tx_tail_cnt[snd_ch]++; - } - else - { - Debugprintf("End TXTAIL %d", SampleNo); - tx_status[snd_ch] = TX_WAIT_BPF; - } - break; - } - return bit; -} - -int get_new_bit_delay(UCHAR snd_ch, UCHAR bit) -{ - ULONG _txdelay = 0; - UCHAR _diddles; - - _diddles = 0; - - switch (modem_mode[snd_ch]) - { - case MODE_FSK: - - _diddles = diddles; - break; - - case MODE_PI4QPSK: - case MODE_8PSK: - - _diddles = 2; - break; - - case MODE_QPSK: - - if (qpsk_set[snd_ch].mode == QPSK_V26) - _diddles = 2; - break; - } - - if (modem_mode[snd_ch] == MODE_FSK) - _txdelay = txdelay[snd_ch]; - - else if (modem_mode[snd_ch] == MODE_BPSK) - _txdelay = txdelay[snd_ch]; - - else if (modem_mode[snd_ch] == MODE_8PSK) - _txdelay = txdelay[snd_ch] * 3; - - else if (modem_mode[snd_ch] == MODE_QPSK || modem_mode[snd_ch] == MODE_PI4QPSK) - _txdelay = txdelay[snd_ch] << 1; - - else if (modem_mode[snd_ch] == MODE_MPSK) - { - if (txdelay[snd_ch] < 400) - _txdelay = 400 << 2; //AFC delay - else - _txdelay = txdelay[snd_ch] << 2; - } - - _txdelay = (_txdelay * tx_baudrate[snd_ch]) / 1000; - - switch (_diddles) - { - case 0: - - if (tx_delay_cnt[snd_ch] < _txdelay) - { - bit = TX_BIT0; - tx_delay_cnt[snd_ch]++; - } - else - { - tx_status[snd_ch] = TX_FRAME; - } - - break; - - case 1: - - if (tx_delay_cnt[snd_ch] < _txdelay) - { - if (tx_last_diddle[snd_ch] == TX_BIT0) - bit = TX_BIT1; - else - bit = TX_BIT0; - - tx_delay_cnt[snd_ch]++; - tx_last_diddle[snd_ch] = bit; - } - else - { - tx_status[snd_ch] = TX_FRAME; - Debugprintf("End TXD %d", SampleNo); - } - break; - - case 2: - - // Send Flags - - if (tx_delay_cnt[snd_ch] < _txdelay) - { - bit = FRAME_FLAG >> ((8 - (_txdelay % 8) + tx_delay_cnt[snd_ch]) % 8) & 1; - tx_delay_cnt[snd_ch]++; - } - else - { - tx_status[snd_ch] = TX_FRAME; - Debugprintf("End TXD %d", SampleNo); - } - break; - } - return bit; -} - -// is this waiting for the filter to fill? -// No, flushing BPF - -void get_wait_bpf(UCHAR snd_ch) -{ - tx_BPF_timer[snd_ch]++; - - if (tx_BPF_timer[snd_ch] == tx_BPF_tap[snd_ch] ) - { - tx_status[snd_ch] = TX_NO_DATA; - tx_BPF_timer[snd_ch] = 0; - } -} - - -//procedure modulator(snd_ch: byte; var buf: array of single; buf_size: word}; -//{ -/* -function filter(x,k: single}: single; -begin - result = k*cos(x}; - if result>1 then result = 1; - if result<-1 then result = -1; -end; -} -*/ - -single filter(single x) -{ - if (x <= PI25) - return 1.0f; - - if (x >= PI75) - return -1.0f; - - return cosf(2.0f * x -PI5); -} - - -// make_samples return one sample of the waveform - -// But seems to be called only once per bit ?? - -// No, but needs to preserve bit between calls - -float make_samples(unsigned char snd_ch, unsigned char * bitptr) -{ - float pi2, x1, x; - Byte i,qbit,tribit,dibit; - float z1,z2,z3,z4; - unsigned short b, msb, lsb; - unsigned char bit = *bitptr; - - float amp = 0; - - pi2 = 2 * pi / TX_Samplerate; - x1 = pi * tx_baudrate[snd_ch] / TX_Samplerate; - - if (modem_mode[snd_ch] == MODE_FSK) - { - if (bit == TX_BIT0) - x = pi2*(tx_freq[snd_ch] + 0.5f * tx_shift[snd_ch]); - else - x = pi2*(tx_freq[snd_ch] - 0.5f * tx_shift[snd_ch]); - - amp = 1.0f; - - if (tx_baudrate[snd_ch] > 600) - { - if (tx_hitoneraisedb[snd_ch] < 0 && bit == TX_BIT0) - amp = tx_hitoneraise[snd_ch]; - - if (tx_hitoneraisedb[snd_ch] > 0 && bit == TX_BIT1) - amp = tx_hitoneraise[snd_ch]; - } - - tx_osc[snd_ch] = tx_osc[snd_ch] + x; - - if (tx_osc[snd_ch] > 2*pi) - tx_osc[snd_ch] = tx_osc[snd_ch] - 2*pi; - } - - else if (modem_mode[snd_ch] == MODE_BPSK) - { - if (tx_change_phase[snd_ch]) - tx_bit_mod[snd_ch] = tx_inv[snd_ch] * cos(tx_bit_osc[snd_ch]); - - x = pi2 * (tx_freq[snd_ch]); - - tx_osc[snd_ch] = tx_osc[snd_ch] + x; - - if (tx_osc[snd_ch] > 2 * pi) - tx_osc[snd_ch] = tx_osc[snd_ch] - 2 * pi; - } - - else if (modem_mode[snd_ch] == MODE_QPSK) - { - if (tx_QPSK_old_I[snd_ch] != tx_QPSK_I[snd_ch]) - - tx_I_mod[snd_ch] = tx_QPSK_avg_I[snd_ch] + tx_QPSK_df_I[snd_ch] * filter(tx_bit_osc[snd_ch]); - else - tx_I_mod[snd_ch] = tx_QPSK_I[snd_ch]; - - if (tx_QPSK_old_Q[snd_ch] != tx_QPSK_Q[snd_ch]) - tx_Q_mod[snd_ch] = tx_QPSK_avg_Q[snd_ch] + tx_QPSK_df_Q[snd_ch] * filter(tx_bit_osc[snd_ch]); - else - tx_Q_mod[snd_ch] = tx_QPSK_Q[snd_ch]; - - x = pi2 * (tx_freq[snd_ch]); - tx_osc[snd_ch] = tx_osc[snd_ch] + x; - if (tx_osc[snd_ch] > 2 * pi) - tx_osc[snd_ch] = tx_osc[snd_ch] - 2 * pi; - } - - else if (modem_mode[snd_ch] == MODE_8PSK || modem_mode[snd_ch] == MODE_PI4QPSK) - { - if (tx_8PSK_old_I[snd_ch] != tx_8PSK_I[snd_ch]) - tx_I_mod[snd_ch] = tx_8PSK_avg_I[snd_ch] + tx_8PSK_df_I[snd_ch] * filter(tx_bit_osc[snd_ch]); - else - tx_I_mod[snd_ch] = tx_8PSK_I[snd_ch]; - - if (tx_8PSK_old_Q[snd_ch] != tx_8PSK_Q[snd_ch]) - tx_Q_mod[snd_ch] = tx_8PSK_avg_Q[snd_ch] + tx_8PSK_df_Q[snd_ch] * filter(tx_bit_osc[snd_ch]); - else - tx_Q_mod[snd_ch] = tx_8PSK_Q[snd_ch]; - - x = pi2 * (tx_freq[snd_ch]); - tx_osc[snd_ch] = tx_osc[snd_ch] + x; - - if (tx_osc[snd_ch] > 2 * pi) - tx_osc[snd_ch] = tx_osc[snd_ch] - 2 * pi; - - } - - else if (modem_mode[snd_ch] == MODE_MPSK) - { - z1 = pi2 * (tx_freq[snd_ch] + ch_offset[0]); - z2 = pi2 * (tx_freq[snd_ch] + ch_offset[1]); - z3 = pi2 * (tx_freq[snd_ch] + ch_offset[2]); - z4 = pi2 * (tx_freq[snd_ch] + ch_offset[3]); - - tx_osc1[snd_ch] = tx_osc1[snd_ch] + z1; - tx_osc2[snd_ch] = tx_osc2[snd_ch] + z2; - tx_osc3[snd_ch] = tx_osc3[snd_ch] + z3; - tx_osc4[snd_ch] = tx_osc4[snd_ch] + z4; - - if (tx_osc1[snd_ch] > 2 * pi) - tx_osc1[snd_ch] = tx_osc1[snd_ch] - 2 * pi; - - if (tx_osc2[snd_ch] > 2 * pi) - tx_osc2[snd_ch] = tx_osc2[snd_ch] - 2 * pi; - - if (tx_osc3[snd_ch] > 2 * pi) - tx_osc3[snd_ch] = tx_osc3[snd_ch] - 2 * pi; - - if (tx_osc4[snd_ch] > 2 * pi) - tx_osc4[snd_ch] = tx_osc4[snd_ch] - 2 * pi; - - if (tx_old_inv1[snd_ch] != tx_inv1[snd_ch]) - tx_bit1_mod[snd_ch] = tx_inv1[snd_ch] * cos(tx_bit_osc[snd_ch]); - else - tx_bit1_mod[snd_ch] = -tx_inv1[snd_ch]; - - if (tx_old_inv2[snd_ch] != tx_inv2[snd_ch]) - tx_bit2_mod[snd_ch] = tx_inv2[snd_ch] * cos(tx_bit_osc[snd_ch]); - else - tx_bit2_mod[snd_ch] = -tx_inv2[snd_ch]; - - if (tx_old_inv3[snd_ch] != tx_inv3[snd_ch]) - tx_bit3_mod[snd_ch] = tx_inv3[snd_ch] * cos(tx_bit_osc[snd_ch]); - else - tx_bit3_mod[snd_ch] = -tx_inv3[snd_ch]; - - if (tx_old_inv4[snd_ch] != tx_inv4[snd_ch]) - tx_bit4_mod[snd_ch] = tx_inv4[snd_ch] * cos(tx_bit_osc[snd_ch]); - else - tx_bit4_mod[snd_ch] = -tx_inv4[snd_ch]; - } - - tx_bit_osc[snd_ch] = tx_bit_osc[snd_ch] + x1; - - if (tx_bit_osc[snd_ch] > pi) - { - // This seems to get the next bit, - // but why?? - end of samples for last bit - - tx_bit_osc[snd_ch] = tx_bit_osc[snd_ch] - pi; - - // FSK Mode - if (modem_mode[snd_ch] == MODE_FSK) - { - bit = 0; - - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - tx_status[snd_ch] = TX_DELAY; - } - - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - { - // il2p generates TXDELAY as part of the frame, so go straight to TX_FRAME - - if (tx_status[snd_ch] == TX_DELAY) - tx_status[snd_ch] = TX_FRAME; - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = il2p_get_new_bit(snd_ch, bit); - - - // No nrzi for il2p - - *bitptr = bit; - } - else - { - // ax25/fx25 - - if (tx_status[snd_ch] == TX_DELAY) - bit = get_new_bit_delay(snd_ch, bit); - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - { - if (tx_fx25_mode[snd_ch]) - bit = fx25_get_new_bit(snd_ch, bit); - else - bit = get_new_bit(snd_ch, bit); - } - - *bitptr = tx_nrzi(snd_ch, bit); - - } - } - - // BPSK Mode - if (modem_mode[snd_ch] == MODE_BPSK) - { - bit = 0; - - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - Debugprintf("Start TXD"); - tx_status[snd_ch] = TX_DELAY; - } - - - - // il2p generates TXDELAY as part of the frame, so go straight too TX_FRAME - - if (tx_status[snd_ch] == TX_DELAY) - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - tx_status[snd_ch] = TX_FRAME; - else - bit = get_new_bit_delay(snd_ch, bit); - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - { - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - bit = il2p_get_new_bit(snd_ch, bit); - else if (tx_fx25_mode[snd_ch]) - bit = fx25_get_new_bit(snd_ch, bit); - else - bit = get_new_bit(snd_ch, bit); - } - // ?? *bitptr = tx_nrzi(snd_ch, bit); - - if (bit == 0) - { - tx_inv[snd_ch] = -tx_inv[snd_ch]; - tx_change_phase[snd_ch] = TRUE; - } - else - tx_change_phase[snd_ch] = FALSE; - } - - // QPSK Mode - - else if (modem_mode[snd_ch] == MODE_QPSK) - { - dibit = 0; - for (i = 0; i < 2; i++) - { - bit = 0; - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - tx_status[snd_ch] = TX_DELAY; - } - - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - { - if (tx_status[snd_ch] == TX_DELAY) - tx_status[snd_ch] = TX_FRAME; // il2p generates TXDELAY as part of the frame, so go straight to TX_FRAME - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = il2p_get_new_bit(snd_ch, bit); - - // No nrzi for il2p - - dibit = (dibit << 1) | bit; - } - else - { - // ax25/fx25 - - if (tx_status[snd_ch] == TX_DELAY) - bit = get_new_bit_delay(snd_ch, bit); - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - if (tx_status[snd_ch] == TX_FRAME) - bit = get_new_bit(snd_ch, bit); - dibit = (dibit << 1) | tx_nrzi(snd_ch, bit); - - } - } - - - dibit = qpsk_set[snd_ch].tx[dibit & 3]; - tx_QPSK[snd_ch] = (tx_QPSK[snd_ch] + dibit) & 3; - tx_QPSK_old_I[snd_ch] = tx_QPSK_I[snd_ch]; - tx_QPSK_old_Q[snd_ch] = tx_QPSK_Q[snd_ch]; - - switch (tx_QPSK[snd_ch]) - { - case 0: - - tx_QPSK_I[snd_ch] = COS45; - tx_QPSK_Q[snd_ch] = COS45; - break; - - case 1: - - tx_QPSK_I[snd_ch] = -COS45; - tx_QPSK_Q[snd_ch] = COS45; - break; - - case 2: - - tx_QPSK_I[snd_ch] = -COS45; - tx_QPSK_Q[snd_ch] = -COS45; - break; - - case 3: - - tx_QPSK_I[snd_ch] = COS45; - tx_QPSK_Q[snd_ch] = -COS45; - break; - } - - tx_QPSK_avg_I[snd_ch] = 0.5f*(tx_QPSK_old_I[snd_ch] + tx_QPSK_I[snd_ch]); - tx_QPSK_df_I[snd_ch] = 0.5f*(tx_QPSK_old_I[snd_ch] - tx_QPSK_I[snd_ch]); - tx_QPSK_avg_Q[snd_ch] = 0.5f*(tx_QPSK_old_Q[snd_ch] + tx_QPSK_Q[snd_ch]); - tx_QPSK_df_Q[snd_ch] = 0.5f*(tx_QPSK_old_Q[snd_ch] - tx_QPSK_Q[snd_ch]); - } - - // PI/4 QPSK Mode - - if (modem_mode[snd_ch] == MODE_PI4QPSK) - { - dibit = 0; - - for (i = 0; i < 2; i++) - { - bit = 0; - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - Debugprintf("Start TXD"); - tx_status[snd_ch] = TX_DELAY; - } - - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - { - if (tx_status[snd_ch] == TX_DELAY) - tx_status[snd_ch] = TX_FRAME; // il2p generates TXDELAY as part of the frame, so go straight to TX_FRAME - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = il2p_get_new_bit(snd_ch, bit); - - // No nrzi for il2p - - dibit = (dibit << 1) | bit; - } - else - { - // ax25/fx25 - - if (tx_status[snd_ch] == TX_DELAY) - bit = get_new_bit_delay(snd_ch, bit); - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = get_new_bit(snd_ch, bit); - - *bitptr = tx_nrzi(snd_ch, bit); - - dibit = (dibit << 1) | *bitptr; - } - } - - // This returns 3,1,5 or 7 so we use the odd enties in the 8PSK table - - dibit = gray_PI4QPSK[dibit & 3]; - - tx_8PSK[snd_ch] = (tx_8PSK[snd_ch] + dibit) & 7; - tx_8PSK_old_I[snd_ch] = tx_8PSK_I[snd_ch]; - tx_8PSK_old_Q[snd_ch] = tx_8PSK_Q[snd_ch]; - - switch (tx_8PSK[snd_ch]) - { - case 0: - tx_8PSK_I[snd_ch] = 0; - tx_8PSK_Q[snd_ch] = 1; - break; - - case 1: - tx_8PSK_I[snd_ch] = COS45; - tx_8PSK_Q[snd_ch] = COS45; - break; - - case 2: - tx_8PSK_I[snd_ch] = 1; - tx_8PSK_Q[snd_ch] = 0; - break; - - case 3: - tx_8PSK_I[snd_ch] = COS45; - tx_8PSK_Q[snd_ch] = -COS45; - break; - - case 4: - tx_8PSK_I[snd_ch] = 0; - tx_8PSK_Q[snd_ch] = -1; - break; - - case 5: - tx_8PSK_I[snd_ch] = -COS45; - tx_8PSK_Q[snd_ch] = -COS45; - break; - - case 6: - tx_8PSK_I[snd_ch] = -1; - tx_8PSK_Q[snd_ch] = 0; - break; - - case 7: - tx_8PSK_I[snd_ch] = -COS45; - tx_8PSK_Q[snd_ch] = COS45; - break; - - } - - tx_8PSK_avg_I[snd_ch] = 0.5*(tx_8PSK_old_I[snd_ch] + tx_8PSK_I[snd_ch]); - tx_8PSK_df_I[snd_ch] = 0.5*(tx_8PSK_old_I[snd_ch] - tx_8PSK_I[snd_ch]); - tx_8PSK_avg_Q[snd_ch] = 0.5*(tx_8PSK_old_Q[snd_ch] + tx_8PSK_Q[snd_ch]); - tx_8PSK_df_Q[snd_ch] = 0.5*(tx_8PSK_old_Q[snd_ch] - tx_8PSK_Q[snd_ch]); - - } - - // 8PSK Mode - - if (modem_mode[snd_ch] == MODE_8PSK) - { - tribit = 0; - for (i = 0; i < 3; i++) - { - bit = 0; - - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - tx_status[snd_ch] = TX_DELAY; - } - - if (il2p_mode[snd_ch] >= IL2P_MODE_TXRX) - { - if (tx_status[snd_ch] == TX_DELAY) - tx_status[snd_ch] = TX_FRAME; // il2p generates TXDELAY as part of the frame, so go straight to TX_FRAME - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = il2p_get_new_bit(snd_ch, bit); - - // No nrzi for il2p - - tribit = (tribit << 1) | bit; - } - else - { - // ax25/fx25 - - if (tx_status[snd_ch] == TX_DELAY) - bit = get_new_bit_delay(snd_ch, bit); - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - if (tx_status[snd_ch] == TX_FRAME) - bit = get_new_bit(snd_ch, bit); - - tribit = (tribit << 1) | tx_nrzi(snd_ch, bit); - } - } - tribit = gray_8PSK[tribit & 7]; - - tx_8PSK[snd_ch] = (tx_8PSK[snd_ch] + tribit) & 7; - tx_8PSK_old_I[snd_ch] = tx_8PSK_I[snd_ch]; - tx_8PSK_old_Q[snd_ch] = tx_8PSK_Q[snd_ch]; - - switch (tx_8PSK[snd_ch]) - { - case 0: - - tx_8PSK_I[snd_ch] = 0; - tx_8PSK_Q[snd_ch] = 1; - break; - - case 1: - - tx_8PSK_I[snd_ch] = COS45; - tx_8PSK_Q[snd_ch] = COS45; - break; - - case 2: - - tx_8PSK_I[snd_ch] = 1; - tx_8PSK_Q[snd_ch] = 0; - break; - - case 3: - - tx_8PSK_I[snd_ch] = COS45; - tx_8PSK_Q[snd_ch] = -COS45; - break; - - case 4: - - tx_8PSK_I[snd_ch] = 0; - tx_8PSK_Q[snd_ch] = -1; - break; - - case 5: - - tx_8PSK_I[snd_ch] = -COS45; - tx_8PSK_Q[snd_ch] = -COS45; - break; - - case 6: - - tx_8PSK_I[snd_ch] = -1; - tx_8PSK_Q[snd_ch] = 0; - break; - - case 7: - - tx_8PSK_I[snd_ch] = -COS45; - tx_8PSK_Q[snd_ch] = COS45; - break; - - } - - tx_8PSK_avg_I[snd_ch] = 0.5f*(tx_8PSK_old_I[snd_ch] + tx_8PSK_I[snd_ch]); - tx_8PSK_df_I[snd_ch] = 0.5f*(tx_8PSK_old_I[snd_ch] - tx_8PSK_I[snd_ch]); - tx_8PSK_avg_Q[snd_ch] = 0.5f*(tx_8PSK_old_Q[snd_ch] + tx_8PSK_Q[snd_ch]); - tx_8PSK_df_Q[snd_ch] = 0.5f*(tx_8PSK_old_Q[snd_ch] - tx_8PSK_Q[snd_ch]); - } - - if (modem_mode[snd_ch] == MODE_MPSK) - { - qbit = 0; - - // get the bits for each of 4 carriers - - for (i = 1; i <= 4; i++) - { - bit = 0; - - if (tx_status[snd_ch] == TX_SILENCE) - { - tx_delay_cnt[snd_ch] = 0; - Debugprintf("Start TXD"); - tx_status[snd_ch] = TX_DELAY; - } - - if (tx_status[snd_ch] == TX_DELAY) - bit = get_new_bit_delay(snd_ch, bit); - - if (tx_status[snd_ch] == TX_TAIL) - bit = get_new_bit_tail(snd_ch, bit); - - if (tx_status[snd_ch] == TX_FRAME) - bit = get_new_bit(snd_ch, bit); - - qbit = (qbit << 1) | bit; - } - - tx_old_inv1[snd_ch] = tx_inv1[snd_ch]; - tx_old_inv2[snd_ch] = tx_inv2[snd_ch]; - tx_old_inv3[snd_ch] = tx_inv3[snd_ch]; - tx_old_inv4[snd_ch] = tx_inv4[snd_ch]; - - if ((qbit & 8) == 0) - tx_inv1[snd_ch] = -tx_inv1[snd_ch]; - if ((qbit & 4) == 0) - tx_inv2[snd_ch] = -tx_inv2[snd_ch]; - if ((qbit & 2) == 0) - tx_inv3[snd_ch] = -tx_inv3[snd_ch]; - if ((qbit & 1) == 0) - tx_inv4[snd_ch] = -tx_inv4[snd_ch]; - - } - } - - if (tx_status[snd_ch] == TX_WAIT_BPF) - get_wait_bpf(snd_ch); - - if (modem_mode[snd_ch] == MODE_FSK) - return amp * sinf(tx_osc[snd_ch]); - - if (modem_mode[snd_ch] == MODE_BPSK) - return sinf(tx_osc[snd_ch]) * tx_bit_mod[snd_ch]; - - if (modem_mode[snd_ch] == MODE_QPSK || modem_mode[snd_ch] == MODE_8PSK || modem_mode[snd_ch] == MODE_PI4QPSK) - return sin(tx_osc[snd_ch]) * tx_I_mod[snd_ch] + cos(tx_osc[snd_ch]) * tx_Q_mod[snd_ch]; - - if (modem_mode[snd_ch] == MODE_MPSK) - return 0.35*(sinf(tx_osc1[snd_ch])*tx_bit1_mod[snd_ch] + - sinf(tx_osc2[snd_ch])*tx_bit2_mod[snd_ch] + - sinf(tx_osc3[snd_ch])*tx_bit3_mod[snd_ch] + - sinf(tx_osc4[snd_ch])*tx_bit4_mod[snd_ch]); - - return 0.0f; -} - -float make_samples_calib(UCHAR snd_ch, UCHAR tones) -{ - float amp, pi2, x, x1; - - x1 = pi * tx_baudrate[snd_ch] / TX_Samplerate; - pi2 = 2 * pi / TX_Samplerate; - - switch (tones) - { - case 1: - - tx_last_bit[snd_ch] = 1; - break; - - case 2: - - tx_last_bit[snd_ch] = 0; - break; - - case 3: - - tx_bit_osc[snd_ch] = tx_bit_osc[snd_ch] + x1; - - if (tx_bit_osc[snd_ch] > pi) - { - tx_bit_osc[snd_ch] = tx_bit_osc[snd_ch] - pi; - tx_last_bit[snd_ch] = tx_last_bit[snd_ch] ^ 1; - } - break; - } - - amp = 1; - - if (tx_baudrate[snd_ch] > 600) - { - if (tx_hitoneraisedb[snd_ch] < 0 && tx_last_bit[snd_ch] == 0) - amp = tx_hitoneraise[snd_ch]; - - if (tx_hitoneraisedb[snd_ch] > 0 && tx_last_bit[snd_ch] == 1) - amp = tx_hitoneraise[snd_ch]; - } - - if (tx_last_bit[snd_ch] == 0) - x = pi2*(tx_freq[snd_ch] + 0.5f * tx_shift[snd_ch]); - else - x = pi2*(tx_freq[snd_ch] - 0.5f * tx_shift[snd_ch]); - - tx_osc[snd_ch] = tx_osc[snd_ch] + x; - - if (tx_osc[snd_ch] > 2*pi) - tx_osc[snd_ch] = tx_osc[snd_ch] - 2 * pi; - - return amp * sinf(tx_osc[snd_ch]); -} - -int amplitude = 22000; - -void modulator(UCHAR snd_ch, int buf_size) -{ - // We feed samples to samplesink instead of buffering them - - // I think this is the top of the TX hierarchy - - int i; - short Sample; - - if (calib_mode[snd_ch] > 0) - { - if (calib_mode[snd_ch] == 4) // CWID - { - if (tx_status[snd_ch] == TX_SILENCE) - { - SoundIsPlaying = TRUE; - Debugprintf("Start CWID Chan %d", snd_ch); - RadioPTT(snd_ch, 1); - - tx_status[snd_ch] = 6; - } - - if (ARDOPSendToCard(snd_ch, SendSize) == 1) - { - // End of TX - - tx_status[snd_ch] = TX_SILENCE; // Stop TX - Flush(); - RadioPTT(snd_ch, 0); - Debugprintf("End CWID"); - calib_mode[snd_ch] = 0; - } - return; - } - - - if (tx_status[snd_ch] == TX_SILENCE) - { - SoundIsPlaying = TRUE; - Debugprintf("Start Calib Chan %d", snd_ch); - RadioPTT(snd_ch, 1); - - tx_bit_osc[snd_ch] = 0; - tx_last_bit[snd_ch] = 0; - - // fill filter - - for (i = 0; i < tx_BPF_tap[snd_ch]; i++) - tx_prev_BPF_buf[snd_ch][buf_size + i] = make_samples_calib(snd_ch,calib_mode[snd_ch]); - } - tx_status[snd_ch] = TX_WAIT_BPF; - - for (i = 0; i < buf_size; i++) - tx_src_BPF_buf[snd_ch][i] = make_samples_calib(snd_ch, calib_mode[snd_ch]); - - FIR_filter(tx_src_BPF_buf[snd_ch],buf_size,tx_BPF_tap[snd_ch],tx_BPF_core[snd_ch],tx_BPF_buf[snd_ch],tx_prev_BPF_buf[snd_ch]); - - for (i = 0; i < buf_size; i++) - { - Sample = tx_BPF_buf[snd_ch][i] * amplitude; - SampleSink(modemtoSoundLR[snd_ch], Sample); - } - } - else - { - if (tx_status[snd_ch] == TX_SILENCE) - { - if (fx25_mode[snd_ch] == FX25_MODE_TXRX) - tx_fx25_mode[snd_ch] = 1; - else - tx_fx25_mode[snd_ch] = 0; - - tx_bit_osc[snd_ch] = 0; - tx_8PSK[snd_ch] = 0; - tx_QPSK[snd_ch] = 0; - tx_last_bit[snd_ch] = 0; - tx_inv1[snd_ch] = 1; - tx_inv2[snd_ch] = 1; - tx_inv3[snd_ch] = 1; - tx_inv4[snd_ch] = 1; - tx_8PSK_I[snd_ch] = 0; - tx_8PSK_Q[snd_ch] = 1; - tx_8PSK_old_I[snd_ch] = 0; - tx_8PSK_old_Q[snd_ch] = 1; - tx_QPSK_I[snd_ch] = COS45; - tx_QPSK_Q[snd_ch] = COS45; - tx_QPSK_old_I[snd_ch] = COS45; - tx_QPSK_old_Q[snd_ch] = COS45; - - for (i = 0; i < tx_BPF_tap[snd_ch]; i++) - tx_prev_BPF_buf[snd_ch][buf_size+i] = make_samples(snd_ch, &tx_pol[snd_ch]); - } - - for (i = 0; i < buf_size; i++) - tx_src_BPF_buf[snd_ch][i] = make_samples(snd_ch, &tx_pol[snd_ch]); - - FIR_filter(tx_src_BPF_buf[snd_ch], buf_size, tx_BPF_tap[snd_ch], tx_BPF_core[snd_ch], tx_BPF_buf[snd_ch], tx_prev_BPF_buf[snd_ch]); - - for (i = 0; i < buf_size; i++) - { - Sample = tx_BPF_buf[snd_ch][i] * 20000.0f; - SampleSink(modemtoSoundLR[snd_ch], Sample); - } - } -} - - diff --git a/ax25_pad2.h b/ax25_pad2.h deleted file mode 100644 index c6dc17a..0000000 --- a/ax25_pad2.h +++ /dev/null @@ -1,55 +0,0 @@ -/*------------------------------------------------------------------- - * - * Name: ax25_pad2.h - * - * Purpose: Header file for using ax25_pad2.c - * ax25_pad dealt only with UI frames. - * This adds a facility for the other types: U, s, I. - * - *------------------------------------------------------------------*/ - -#ifndef AX25_PAD2_H -#define AX25_PAD2_H 1 - -#include "ax25_pad.h" - - - - -#if AX25MEMDEBUG // to investigate a memory leak problem - - - -packet_t ax25_u_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int pf, int pid, unsigned char *pinfo, int info_len, char *src_file, int src_line); - -packet_t ax25_s_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int modulo, int nr, int pf, unsigned char *pinfo, int info_len, char *src_file, int src_line); - -packet_t ax25_i_frame_debug (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, int modulo, int nr, int ns, int pf, int pid, unsigned char *pinfo, int info_len, char *src_file, int src_line); - - -#define ax25_u_frame(a,n,c,f,p,q,i,l) ax25_u_frame_debug(a,n,c,f,p,q,i,l,__FILE__,__LINE__) - -#define ax25_s_frame(a,n,c,f,m,r,p,i,l) ax25_s_frame_debug(a,n,c,f,m,r,p,i,l,__FILE__,__LINE__) - -#define ax25_i_frame(a,n,c,m,r,s,p,q,i,l) ax25_i_frame_debug(a,n,c,m,r,s,p,q,i,l,__FILE__,__LINE__) - - -#else - -packet_t ax25_u_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int pf, int pid, unsigned char *pinfo, int info_len); - -packet_t ax25_s_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int modulo, int nr, int pf, unsigned char *pinfo, int info_len); - -packet_t ax25_i_frame (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, int modulo, int nr, int ns, int pf, int pid, unsigned char *pinfo, int info_len); - - -#endif - - - - -#endif /* AX25_PAD2_H */ - -/* end ax25_pad2.h */ - - diff --git a/beacon.h b/beacon.h deleted file mode 100644 index f7d2a56..0000000 --- a/beacon.h +++ /dev/null @@ -1,6 +0,0 @@ - -/* beacon.h */ - -void beacon_init (struct audio_s *pmodem, struct misc_config_s *pconfig, struct igate_config_s *pigate); - -void beacon_tracker_set_debug (int level); diff --git a/cdigipeater.h b/cdigipeater.h deleted file mode 100644 index 69a4b8c..0000000 --- a/cdigipeater.h +++ /dev/null @@ -1,62 +0,0 @@ - - -#ifndef CDIGIPEATER_H -#define CDIGIPEATER_H 1 - -#include "regex.h" - -#include "direwolf.h" /* for MAX_CHANS */ -#include "ax25_pad.h" /* for packet_t */ -#include "audio.h" /* for radio channel properties */ - - -/* - * Information required for Connected mode digipeating. - * - * The configuration file reader fills in this information - * and it is passed to cdigipeater_init at application start up time. - */ - - -struct cdigi_config_s { - -/* - * Rules for each of the [from_chan][to_chan] combinations. - */ - int enabled[MAX_CHANS][MAX_CHANS]; // Is it enabled for from/to pair? - - int has_alias[MAX_CHANS][MAX_CHANS]; // If there was no alias in the config file, - // the structure below will not be set up - // properly and an attempt to use it could - // result in a crash. (fixed v1.5) - // Not needed for [APRS] DIGIPEAT because - // the alias is mandatory there. - regex_t alias[MAX_CHANS][MAX_CHANS]; - - char *cfilter_str[MAX_CHANS][MAX_CHANS]; - // NULL or optional Packet Filter strings such as "t/m". -}; - -/* - * Call once at application start up time. - */ - -extern void cdigipeater_init (struct audio_s *p_audio_config, struct cdigi_config_s *p_cdigi_config); - -/* - * Call this for each packet received. - * Suitable packets will be queued for transmission. - */ - -extern void cdigipeater (int from_chan, packet_t pp); - - -/* Make statistics available. */ - -int cdigipeater_get_count (int from_chan, int to_chan); - - -#endif - -/* end cdigipeater.h */ - diff --git a/cm108.h b/cm108.h deleted file mode 100644 index 2def77a..0000000 --- a/cm108.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Dire Wolf cm108.h */ - -extern void cm108_find_ptt (char *output_audio_device, char *ptt_device, int ptt_device_size); - -extern int cm108_set_gpio_pin (char *name, int num, int state); \ No newline at end of file diff --git a/config.h b/config.h deleted file mode 100644 index 360ac49..0000000 --- a/config.h +++ /dev/null @@ -1,262 +0,0 @@ - -/*---------------------------------------------------------------------------- - * - * Name: config.h - * - * Purpose: - * - * Description: - * - *-----------------------------------------------------------------------------*/ - - -#ifndef CONFIG_H -#define CONFIG_H 1 - -#include "audio.h" /* for struct audio_s */ -#include "digipeater.h" /* for struct digi_config_s */ -#include "cdigipeater.h" /* for struct cdigi_config_s */ -#include "aprs_tt.h" /* for struct tt_config_s */ -#include "igate.h" /* for struct igate_config_s */ - -/* - * All the leftovers. - * This wasn't thought out. It just happened. - */ - -enum beacon_type_e { BEACON_IGNORE, BEACON_POSITION, BEACON_OBJECT, BEACON_TRACKER, BEACON_CUSTOM, BEACON_IGATE }; - -enum sendto_type_e { SENDTO_XMIT, SENDTO_IGATE, SENDTO_RECV }; - - -#define MAX_BEACONS 30 -#define MAX_KISS_TCP_PORTS (MAX_CHANS+1) - -struct misc_config_s { - - int agwpe_port; /* TCP Port number for the "AGW TCPIP Socket Interface" */ - - // Previously we allowed only a single TCP port for KISS. - // An increasing number of people want to run multiple radios. - // Unfortunately, most applications don't know how to deal with multi-radio TNCs. - // They ignore the channel on receive and always transmit to channel 0. - // Running multiple instances of direwolf is a work-around but this leads to - // more complex configuration and we lose the cross-channel digipeating capability. - // In release 1.7 we add a new feature to assign a single radio channel to a TCP port. - // e.g. - // KISSPORT 8001 # default, all channels. Radio channel = KISS channel. - // - // KISSPORT 7000 0 # Only radio channel 0 for receive. - // # Transmit to radio channel 0, ignoring KISS channel. - // - // KISSPORT 7001 1 # Only radio channel 1 for receive. KISS channel set to 0. - // # Transmit to radio channel 1, ignoring KISS channel. - - int kiss_port[MAX_KISS_TCP_PORTS]; /* TCP Port number for the "TCP KISS" protocol. */ - int kiss_chan[MAX_KISS_TCP_PORTS]; /* Radio Channel number for this port or -1 for all. */ - - int kiss_copy; /* Data from network KISS client is copied to all others. */ - int enable_kiss_pt; /* Enable pseudo terminal for KISS. */ - /* Want this to be off by default because it hangs */ - /* after a while if nothing is reading from other end. */ - - char kiss_serial_port[20]; - /* Serial port name for our end of the */ - /* virtual null modem for native Windows apps. */ - /* Version 1.5 add same capability for Linux. */ - - int kiss_serial_speed; /* Speed, in bps, for the KISS serial port. */ - /* If 0, just leave what was already there. */ - - int kiss_serial_poll; /* When using Bluetooth KISS, the /dev/rfcomm0 device */ - /* will appear and disappear as the remote application */ - /* opens and closes the virtual COM port. */ - /* When this is non-zero, we will check periodically to */ - /* see if the device has appeared and we will open it. */ - - char gpsnmea_port[20]; /* Serial port name for reading NMEA sentences from GPS. */ - /* e.g. COM22, /dev/ttyACM0 */ - - int gpsnmea_speed; /* Speed for above, baud, default 4800. */ - - char gpsd_host[20]; /* Host for gpsd server. */ - /* e.g. localhost, 192.168.1.2 */ - - int gpsd_port; /* Port number for gpsd server. */ - /* Default is 2947. */ - - - char waypoint_serial_port[20]; /* Serial port name for sending NMEA waypoint sentences */ - /* to a GPS map display or other mapping application. */ - /* e.g. COM22, /dev/ttyACM0 */ - /* Currently no option for setting non-standard speed. */ - /* This was done in 2014 and no one has complained yet. */ - - char waypoint_udp_hostname[80]; /* Destination host when using UDP. */ - - int waypoint_udp_portnum; /* UDP port. */ - - int waypoint_formats; /* Which sentence formats should be generated? */ - -#define WPL_FORMAT_NMEA_GENERIC 0x01 /* N $GPWPL */ -#define WPL_FORMAT_GARMIN 0x02 /* G $PGRMW */ -#define WPL_FORMAT_MAGELLAN 0x04 /* M $PMGNWPL */ -#define WPL_FORMAT_KENWOOD 0x08 /* K $PKWDWPL */ -#define WPL_FORMAT_AIS 0x10 /* A !AIVDM */ - - - int log_daily_names; /* True to generate new log file each day. */ - - char log_path[80]; /* Either directory or full file name depending on above. */ - - int dns_sd_enabled; /* DNS Service Discovery announcement enabled. */ - char dns_sd_name[64]; /* Name announced on dns-sd; defaults to "Dire Wolf on " */ - - int sb_configured; /* TRUE if SmartBeaconing is configured. */ - int sb_fast_speed; /* MPH */ - int sb_fast_rate; /* seconds */ - int sb_slow_speed; /* MPH */ - int sb_slow_rate; /* seconds */ - int sb_turn_time; /* seconds */ - int sb_turn_angle; /* degrees */ - int sb_turn_slope; /* degrees * MPH */ - -// AX.25 connected mode. - - int frack; /* Number of seconds to wait for ack to transmission. */ - - int retry; /* Number of times to retry before giving up. */ - - int paclen; /* Max number of bytes in information part of frame. */ - - int maxframe_basic; /* Max frames to send before ACK. mod 8 "Window" size. */ - - int maxframe_extended; /* Max frames to send before ACK. mod 128 "Window" size. */ - - int maxv22; /* Maximum number of unanswered SABME frames sent before */ - /* switching to SABM. This is to handle the case of an old */ - /* TNC which simply ignores SABME rather than replying with FRMR. */ - - char **v20_addrs; /* Stations known to understand only AX.25 v2.0 so we don't */ - /* waste time trying v2.2 first. */ - - int v20_count; /* Number of station addresses in array above. */ - - char **noxid_addrs; /* Stations known not to understand XID command so don't */ - /* waste time sending it and eventually giving up. */ - /* AX.25 for Linux is the one known case, so far, where */ - /* SABME is implemented but XID is not. */ - - int noxid_count; /* Number of station addresses in array above. */ - - -// Beacons. - - int num_beacons; /* Number of beacons defined. */ - - struct beacon_s { - - enum beacon_type_e btype; /* Position or object. */ - - int lineno; /* Line number from config file for later error messages. */ - - enum sendto_type_e sendto_type; - - /* SENDTO_XMIT - Usually beacons go to a radio transmitter. */ - /* chan, below is the channel number. */ - /* SENDTO_IGATE - Send to IGate, probably to announce my position */ - /* rather than relying on someone else to hear */ - /* me on the radio and report me. */ - /* SENDTO_RECV - Pretend this was heard on the specified */ - /* radio channel. Mostly for testing. It is a */ - /* convenient way to send packets to attached apps. */ - - int sendto_chan; /* Transmit or simulated receive channel for above. Should be 0 for IGate. */ - - int delay; /* Seconds to delay before first transmission. */ - - int slot; /* Seconds after hour for slotted time beacons. */ - /* If specified, it overrides any 'delay' value. */ - - int every; /* Time between transmissions, seconds. */ - /* Remains fixed for PBEACON and OBEACON. */ - /* Dynamically adjusted for TBEACON. */ - - time_t next; /* Unix time to transmit next one. */ - - char *source; /* NULL or explicit AX.25 source address to use */ - /* instead of the mycall value for the channel. */ - - char *dest; /* NULL or explicit AX.25 destination to use */ - /* instead of the software version such as APDW11. */ - - int compress; /* Use more compact form? */ - - char objname[10]; /* Object name. Any printable characters. */ - - char *via; /* Path, e.g. "WIDE1-1,WIDE2-1" or NULL. */ - - char *custom_info; /* Info part for handcrafted custom beacon. */ - /* Ignore the rest below if this is set. */ - - char *custom_infocmd; /* Command to generate info part. */ - /* Again, other options below are then ignored. */ - - int messaging; /* Set messaging attribute for position report. */ - /* i.e. Data Type Indicator of '=' rather than '!' */ - - double lat; /* Latitude and longitude. */ - double lon; - int ambiguity; /* Number of lower digits to trim from location. 0 (default), 1, 2, 3, 4. */ - float alt_m; /* Altitude in meters. */ - - char symtab; /* Symbol table: / or \ or overlay character. */ - char symbol; /* Symbol code. */ - - float power; /* For PHG. */ - float height; /* HAAT in feet */ - float gain; /* Original protocol spec was unclear. */ - /* Addendum 1.1 clarifies it is dBi not dBd. */ - - char dir[3]; /* 1 or 2 of N,E,W,S, or empty for omni. */ - - float freq; /* MHz. */ - float tone; /* Hz. */ - float offset; /* MHz. */ - - char *comment; /* Comment or NULL. */ - char *commentcmd; /* Command to append more to Comment or NULL. */ - - - } beacon[MAX_BEACONS]; - -}; - - -#define MIN_IP_PORT_NUMBER 1024 -#define MAX_IP_PORT_NUMBER 49151 - - -#define DEFAULT_AGWPE_PORT 8000 /* Like everyone else. */ -#define DEFAULT_KISS_PORT 8001 /* Above plus 1. */ - - -#define DEFAULT_NULLMODEM "COM3" /* should be equiv. to /dev/ttyS2 on Cygwin */ - - - - -extern void config_init (char *fname, struct audio_s *p_modem, - struct digi_config_s *digi_config, - struct cdigi_config_s *cdigi_config, - struct tt_config_s *p_tt_config, - struct igate_config_s *p_igate_config, - struct misc_config_s *misc_config); - - - -#endif /* CONFIG_H */ - -/* end config.h */ - - diff --git a/debug/QtSoundModem.ini b/debug/QtSoundModem.ini deleted file mode 100644 index 0aefa4a..0000000 --- a/debug/QtSoundModem.ini +++ /dev/null @@ -1,201 +0,0 @@ -[General] -geometry="@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0z\0\0\0\t\0\0\x4=\0\0\x2\xf9\0\0\0{\0\0\0(\0\0\x4<\0\0\x2\xf8\0\0\0\0\0\0\0\0\x5\0\0\0\0{\0\0\0(\0\0\x4<\0\0\x2\xf8)" -windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\0\0\0\x3\xc2\0\0\x2\xb9\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\0) -PSKWindow=@Rect(46 499 366 140) -FontFamily=Courier New -PointSize=12 -Weight=50 - -[AX25_A] -Retries=15 -HiToneRaise=0 -Maxframe=3 -FrackTime=5 -IdleTime=180 -SlotTime=100 -Persist=128 -RespTime=1500 -TXFrmMode=1 -FrameCollector=6 -ExcludeCallsigns= -ExcludeAPRSFrmType= -KISSOptimization=0 -DynamicFrack=0 -BitRecovery=0 -NonAX25Frm=0 -MEMRecovery=200 -IPOLL=80 -MyDigiCall= -FX25=1 -IL2P=2 -RSID_UI=0 -RSID_SABM=0 -RSID_SetModem=0 - -[Init] -SoundMode=0 -UDPClientPort=8888 -UDPServerPort=8884 -TXPort=8884 -UDPServer=0 -UDPHost=192.168.1.255 -TXSampleRate=12000 -RXSampleRate=12000 -SndRXDeviceName="CABLE-B OUTPUT (VB-AUDIO CABLE " -SndTXDeviceName=CABLE-B INPUT (VB-AUDIO CABLE B -SCO=0 -DualPTT=1 -TXRotate=0 -DispMode=1 -PTT= -PTTBAUD=19200 -PTTMode=1 -PTTOffString= -PTTOnString= -pttGPIOPin=17 -pttGPIOPinR=17 -CM108Addr=0xD8C:0x08 -HamLibPort=4532 -HamLibHost=127.0.0.1 -MinimizetoTray=1 -multiCore=1 -Wisdom=(fftw-3.3.5 fftwf_wisdom #x9e7d4dee #xdb14fed1 #x34bf76a4 #xeb6e8fdf\n (fftwf_codelet_n2fv_12_avx 0 #x10048 #x10048 #x0 #xb0767e46 #x8d41dd22 #x439264a0 #x18435a99)\n (fftwf_rdft_rank0_register 0 #x11048 #x11048 #x0 #xff75c762 #x3a0ee093 #x5b78d592 #x6b6be60e)\n (fftwf_codelet_t2fv_2_avx 0 #x11048 #x11048 #x0 #x34057a74 #x664db78f #xa9524ebc #x606afd88)\n (fftwf_dft_nop_register 0 #x11048 #x11048 #x0 #x4a593e24 #xb5f06ddf #xf11fe7f2 #xc010b545)\n (fftwf_dft_bluestein_register 0 #x11048 #x11048 #x0 #x5e17c068 #x1682c5d6 #x89dd79be #x9b951c0f)\n (fftwf_dft_vrank_geq1_register 0 #x10048 #x10048 #x0 #x2fce15e1 #x178d4f4d #x1e956a41 #xf3fd6b80)\n (fftwf_codelet_t1fuv_4_sse2 0 #x11048 #x11048 #x0 #x2fb84bc5 #x2792028e #x8ec66ed5 #x47b5f7dc)\n (fftwf_dft_buffered_register 0 #x11048 #x11048 #x0 #x4f8e87b4 #xec4f2fa0 #x79fe76a1 #xa16e32a5)\n (fftwf_dft_vrank_geq1_register 0 #x11048 #x11048 #x0 #x8a9c355b #xb6dbadad #xbac1daac #xa866ceb3)\n (fftwf_dft_r2hc_register 0 #x11048 #x11048 #x0 #x576d5db6 #xa6a15f8a #x875d87d5 #x7561a866)\n (fftwf_codelet_t1fv_6_avx 0 #x10048 #x10048 #x0 #xd9db29d8 #x3302fcf3 #x19ce6e5d #x869fc341)\n (fftwf_dft_vrank_geq1_register 0 #x11048 #x11048 #x0 #xf7abab03 #x5f0e79b1 #x1b8367ad #xe5028f2c)\n (fftwf_codelet_t1fv_12_avx 0 #x10048 #x10048 #x0 #x0b0d3933 #x08267d12 #x45613873 #xde496efe)\n)\n -WaterfallMin=0 -WaterfallMax=3300 - -[AX25_B] -Retries=15 -HiToneRaise=0 -Maxframe=3 -FrackTime=5 -IdleTime=180 -SlotTime=100 -Persist=128 -RespTime=1500 -TXFrmMode=1 -FrameCollector=6 -ExcludeCallsigns= -ExcludeAPRSFrmType= -KISSOptimization=0 -DynamicFrack=0 -BitRecovery=0 -NonAX25Frm=0 -MEMRecovery=200 -IPOLL=80 -MyDigiCall= -FX25=1 -IL2P=2 -RSID_UI=0 -RSID_SABM=0 -RSID_SetModem=0 - -[Modem] -NRRcvrPairs1=2 -NRRcvrPairs2=2 -NRRcvrPairs3=0 -NRRcvrPairs4=2 -RcvrShift1=50 -RcvrShift2=30 -RcvrShift3=30 -RcvrShift4=30 -ModemType1=4 -ModemType2=14 -ModemType3=0 -ModemType4=14 -soundChannel1=1 -soundChannel2=1 -soundChannel3=0 -soundChannel4=0 -DCDThreshold=40 -rxOffset=-100 -PreEmphasisAll1=0 -PreEmphasisAll2=0 -PreEmphasisAll3=0 -PreEmphasisAll4=0 -PreEmphasisDB1=0 -PreEmphasisDB2=0 -PreEmphasisDB3=0 -PreEmphasisDB4=0 -TxDelay1=250 -TxDelay2=250 -TxDelay3=250 -TxDelay4=250 -TxTail1=50 -TxTail2=50 -TxTail3=50 -TxTail4=50 -CWIDCall= -CWIDInterval=0 -CWIDLeft=0 -CWIDRight=0 -CWIDType=1 -RXFreq1=1700 -RXFreq2=1700 -RXFreq3=500 -RXFreq4=1700 -CWIDMark= -afterTraffic=false - -[AGWHost] -Server=1 -Port=8000 - -[KISS] -Server=0 -Port=8105 - -[AX25_C] -Retries=15 -HiToneRaise=0 -Maxframe=3 -FrackTime=5 -IdleTime=180 -SlotTime=100 -Persist=128 -RespTime=1500 -TXFrmMode=1 -FrameCollector=6 -ExcludeCallsigns= -ExcludeAPRSFrmType= -KISSOptimization=0 -DynamicFrack=0 -BitRecovery=0 -NonAX25Frm=0 -MEMRecovery=200 -IPOLL=80 -MyDigiCall= -FX25=1 -IL2P=0 -RSID_UI=0 -RSID_SABM=0 -RSID_SetModem=0 - -[Window] -Waterfall1=1 -Waterfall2=1 - -[AX25_D] -Retries=15 -HiToneRaise=0 -Maxframe=3 -FrackTime=5 -IdleTime=180 -SlotTime=100 -Persist=128 -RespTime=1500 -TXFrmMode=1 -FrameCollector=6 -ExcludeCallsigns= -ExcludeAPRSFrmType= -KISSOptimization=0 -DynamicFrack=0 -BitRecovery=0 -NonAX25Frm=0 -MEMRecovery=200 -IPOLL=80 -MyDigiCall= -FX25=1 -IL2P=0 -RSID_UI=0 -RSID_SABM=0 -RSID_SetModem=0 diff --git a/debug/moc_predefs-DESKTOP-MHE5LO8.h b/debug/moc_predefs-DESKTOP-MHE5LO8.h deleted file mode 100644 index 2c1557b..0000000 --- a/debug/moc_predefs-DESKTOP-MHE5LO8.h +++ /dev/null @@ -1,12 +0,0 @@ -#define _MSC_EXTENSIONS -#define _INTEGRAL_MAX_BITS 64 -#define _MSC_VER 1916 -#define _MSC_FULL_VER 191627050 -#define _MSC_BUILD 0 -#define _WIN32 -#define _M_IX86 600 -#define _M_IX86_FP 2 -#define _CPPRTTI -#define _DEBUG -#define _MT -#define _DLL diff --git a/debug/moc_predefs.h b/debug/moc_predefs.h index 8247e15..b857b2e 100644 --- a/debug/moc_predefs.h +++ b/debug/moc_predefs.h @@ -1,7 +1,7 @@ #define _MSC_EXTENSIONS #define _INTEGRAL_MAX_BITS 64 #define _MSC_VER 1916 -#define _MSC_FULL_VER 191627043 +#define _MSC_FULL_VER 191627045 #define _MSC_BUILD 0 #define _WIN32 #define _M_IX86 600 diff --git a/decode_aprs.h b/decode_aprs.h deleted file mode 100644 index f25d1e9..0000000 --- a/decode_aprs.h +++ /dev/null @@ -1,150 +0,0 @@ - -/* decode_aprs.h */ - - -#ifndef DECODE_APRS_H - -#define DECODE_APRS_H 1 - - - -#ifndef G_UNKNOWN -#include "latlong.h" -#endif - -#ifndef AX25_MAX_ADDR_LEN -#include "ax25_pad.h" -#endif - -#ifndef APRSTT_LOC_DESC_LEN -#include "aprs_tt.h" -#endif - -typedef struct decode_aprs_s { - - int g_quiet; /* Suppress error messages when decoding. */ - - char g_src[AX25_MAX_ADDR_LEN]; - - char g_dest[AX25_MAX_ADDR_LEN]; - - char g_data_type_desc[100]; /* APRS data type description. Telemetry descriptions get pretty long. */ - - char g_symbol_table; /* The Symbol Table Identifier character selects one */ - /* of the two Symbol Tables, or it may be used as */ - /* single-character (alpha or numeric) overlay, as follows: */ - - /* / Primary Symbol Table (mostly stations) */ - - /* \ Alternate Symbol Table (mostly Objects) */ - - /* 0-9 Numeric overlay. Symbol from Alternate Symbol */ - /* Table (uncompressed lat/long data format) */ - - /* a-j Numeric overlay. Symbol from Alternate */ - /* Symbol Table (compressed lat/long data */ - /* format only). i.e. a-j maps to 0-9 */ - - /* A-Z Alpha overlay. Symbol from Alternate Symbol Table */ - - - char g_symbol_code; /* Where the Symbol Table Identifier is 0-9 or A-Z (or a-j */ - /* with compressed position data only), the symbol comes from */ - /* the Alternate Symbol Table, and is overlaid with the */ - /* identifier (as a single digit or a capital letter). */ - - char g_aprstt_loc[APRSTT_LOC_DESC_LEN]; /* APRStt location from !DAO! */ - - double g_lat, g_lon; /* Location, degrees. Negative for South or West. */ - /* Set to G_UNKNOWN if missing or error. */ - - char g_maidenhead[12]; /* 4 or 6 (or 8?) character maidenhead locator. */ - - char g_name[12]; /* Object or item name. Max. 9 characters. */ - - char g_addressee[12]; /* Addressee for a "message." Max. 9 characters. */ - /* Also for Directed Station Query which is a */ - /* special case of message. */ - - enum message_subtype_e { message_subtype_invalid = 0, - message_subtype_message, - message_subtype_ack, - message_subtype_rej, - message_subtype_telem_parm, - message_subtype_telem_unit, - message_subtype_telem_eqns, - message_subtype_telem_bits, - message_subtype_directed_query - } g_message_subtype; /* Various cases of the overloaded "message." */ - - char g_message_number[12]; /* Message number. Should be 1 - 5 alphanumeric characters if used. */ - /* Addendum 1.1 has new format {mm} or {mm}aa with only two */ - /* characters for message number and an ack riding piggyback. */ - - float g_speed_mph; /* Speed in MPH. */ - /* The APRS transmission uses knots so watch out for */ - /* conversions when sending and receiving APRS packets. */ - - float g_course; /* 0 = North, 90 = East, etc. */ - - int g_power; /* Transmitter power in watts. */ - - int g_height; /* Antenna height above average terrain, feet. */ - - int g_gain; /* Antenna gain in dB. */ - - char g_directivity[12]; /* Direction of max signal strength */ - - float g_range; /* Precomputed radio range in miles. */ - - float g_altitude_ft; /* Feet above median sea level. */ - /* I used feet here because the APRS specification */ - /* has units of feet for alititude. Meters would be */ - /* more natural to the other 96% of the world. */ - - char g_mfr[80]; /* Manufacturer or application. */ - - char g_mic_e_status[32]; /* MIC-E message. */ - - double g_freq; /* Frequency, MHz */ - - float g_tone; /* CTCSS tone, Hz, one fractional digit */ - - int g_dcs; /* Digital coded squelch, print as 3 octal digits. */ - - int g_offset; /* Transmit offset, kHz */ - - - char g_query_type[12]; /* General Query: APRS, IGATE, WX, ... */ - /* Addressee is NOT set. */ - - /* Directed Station Query: exactly 5 characters. */ - /* APRSD, APRST, PING?, ... */ - /* Addressee is set. */ - - double g_footprint_lat; /* A general query may contain a foot print. */ - double g_footprint_lon; /* Set all to G_UNKNOWN if not used. */ - float g_footprint_radius; /* Radius in miles. */ - - char g_query_callsign[12]; /* Directed query may contain callsign. */ - /* e.g. tell me all objects from that callsign. */ - - - char g_weather[500]; /* Weather. Can get quite long. Rethink max size. */ - - char g_telemetry[256]; /* Telemetry data. Rethink max size. */ - - char g_comment[256]; /* Comment. */ - -} decode_aprs_t; - - - - - -extern void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_src); - -extern void decode_aprs_print (decode_aprs_t *A); - - -#endif diff --git a/dedupe.h b/dedupe.h deleted file mode 100644 index 9c0613c..0000000 --- a/dedupe.h +++ /dev/null @@ -1,10 +0,0 @@ - - -void dedupe_init (int ttl); - -void dedupe_remember (packet_t pp, int chan); - -int dedupe_check (packet_t pp, int chan); - - -/* end dedupe.h */ diff --git a/demod.h b/demod.h deleted file mode 100644 index 3233b9b..0000000 --- a/demod.h +++ /dev/null @@ -1,17 +0,0 @@ - - -/* demod.h */ - -#include "audio.h" /* for struct audio_s */ -#include "ax25_pad.h" /* for alevel_t */ - - -int demod_init (struct audio_s *pa); - -int demod_get_sample (int a); - -void demod_process_sample (int chan, int subchan, int sam); - -void demod_print_agc (int chan, int subchan); - -alevel_t demod_get_audio_level (int chan, int subchan); \ No newline at end of file diff --git a/demod_afsk.h b/demod_afsk.h deleted file mode 100644 index e44a44e..0000000 --- a/demod_afsk.h +++ /dev/null @@ -1,8 +0,0 @@ - -/* demod_afsk.h */ - - -void demod_afsk_init (int samples_per_sec, int baud, int mark_freq, - int space_freq, char profile, struct demodulator_state_s *D); - -void demod_afsk_process_sample (int chan, int subchan, int sam, struct demodulator_state_s *D); diff --git a/demod_psk.h b/demod_psk.h deleted file mode 100644 index 134b199..0000000 --- a/demod_psk.h +++ /dev/null @@ -1,7 +0,0 @@ - -/* demod_psk.h */ - - -void demod_psk_init (enum modem_t modem_type, enum v26_e v26_alt, int samples_per_sec, int bps, char profile, struct demodulator_state_s *D); - -void demod_psk_process_sample (int chan, int subchan, int sam, struct demodulator_state_s *D); diff --git a/devicesDialog.ui b/devicesDialog.ui index bf2bd9b..b090d6b 100644 --- a/devicesDialog.ui +++ b/devicesDialog.ui @@ -151,7 +151,7 @@ 20 304 - 251 + 231 17 @@ -582,6 +582,19 @@ to + + + + 260 + 304 + 161 + 17 + + + + Dark Theme + + diff --git a/digipeater.h b/digipeater.h deleted file mode 100644 index 5c84976..0000000 --- a/digipeater.h +++ /dev/null @@ -1,78 +0,0 @@ - -#ifndef DIGIPEATER_H -#define DIGIPEATER_H 1 - -#include "regex.h" - -#include "direwolf.h" /* for MAX_CHANS */ -#include "ax25_pad.h" /* for packet_t */ -#include "audio.h" /* for radio channel properties */ - - -/* - * Information required for digipeating. - * - * The configuration file reader fills in this information - * and it is passed to digipeater_init at application start up time. - */ - - -struct digi_config_s { - - - int dedupe_time; /* Don't digipeat duplicate packets */ - /* within this number of seconds. */ - -#define DEFAULT_DEDUPE 30 - -/* - * Rules for each of the [from_chan][to_chan] combinations. - */ - - regex_t alias[MAX_CHANS][MAX_CHANS]; - - regex_t wide[MAX_CHANS][MAX_CHANS]; - - int enabled[MAX_CHANS][MAX_CHANS]; - - enum preempt_e { PREEMPT_OFF, PREEMPT_DROP, PREEMPT_MARK, PREEMPT_TRACE } preempt[MAX_CHANS][MAX_CHANS]; - - // ATGP is an ugly hack for the specific need of ATGP which needs more that 8 digipeaters. - // DO NOT put this in the User Guide. On a need to know basis. - - char atgp[MAX_CHANS][MAX_CHANS][AX25_MAX_ADDR_LEN]; - - char *filter_str[MAX_CHANS+1][MAX_CHANS+1]; - // NULL or optional Packet Filter strings such as "t/m". - // Notice the size of arrays is one larger than normal. - // That extra position is for the IGate. - - int regen[MAX_CHANS][MAX_CHANS]; // Regenerate packet. - // Sort of like digipeating but passed along unchanged. -}; - -/* - * Call once at application start up time. - */ - -extern void digipeater_init (struct audio_s *p_audio_config, struct digi_config_s *p_digi_config); - -/* - * Call this for each packet received. - * Suitable packets will be queued for transmission. - */ - -extern void digipeater (int from_chan, packet_t pp); - -void digi_regen (int from_chan, packet_t pp); - - -/* Make statistics available. */ - -int digipeater_get_count (int from_chan, int to_chan); - - -#endif - -/* end digipeater.h */ - diff --git a/dlq.h b/dlq.h deleted file mode 100644 index 8771636..0000000 --- a/dlq.h +++ /dev/null @@ -1,148 +0,0 @@ - -/*------------------------------------------------------------------ - * - * Module: dlq.h - * - *---------------------------------------------------------------*/ - -#ifndef DLQ_H -#define DLQ_H 1 - -#include "ax25_pad.h" -#include "audio.h" - - -/* A transmit or receive data block for connected mode. */ - -typedef struct cdata_s { - int magic; /* For integrity checking. */ - -#define TXDATA_MAGIC 0x09110911 - - struct cdata_s *next; /* Pointer to next when part of a list. */ - - int pid; /* Protocol id. */ - - int size; /* Number of bytes allocated. */ - - int len; /* Number of bytes actually used. */ - - char data[]; /* Variable length data. */ - -} cdata_t; - - - -/* Types of things that can be in queue. */ - -typedef enum dlq_type_e {DLQ_REC_FRAME, DLQ_CONNECT_REQUEST, DLQ_DISCONNECT_REQUEST, DLQ_XMIT_DATA_REQUEST, DLQ_REGISTER_CALLSIGN, DLQ_UNREGISTER_CALLSIGN, DLQ_OUTSTANDING_FRAMES_REQUEST, DLQ_CHANNEL_BUSY, DLQ_SEIZE_CONFIRM, DLQ_CLIENT_CLEANUP} dlq_type_t; - - -/* A queue item. */ - -// TODO: call this event rather than item. -// TODO: should add fences. - -typedef struct dlq_item_s { - - struct dlq_item_s *nextp; /* Next item in queue. */ - - dlq_type_t type; /* Type of item. */ - /* See enum definition above. */ - - int chan; /* Radio channel of origin. */ - -// I'm not worried about amount of memory used but this might be a -// little clearer if a union was used for the different event types. - -// Used for received frame. - - int subchan; /* Winning "subchannel" when using multiple */ - /* decoders on one channel. */ - /* Special case, -1 means DTMF decoder. */ - /* Maybe we should have a different type in this case? */ - - int slice; /* Winning slicer. */ - - packet_t pp; /* Pointer to frame structure. */ - - alevel_t alevel; /* Audio level. */ - - int is_fx25; /* Was it from FX.25? */ - - retry_t retries; /* Effort expended to get a valid CRC. */ - /* Bits changed for regular AX.25. */ - /* Number of bytes fixed for FX.25. */ - - char spectrum[MAX_SUBCHANS*MAX_SLICERS+1]; /* "Spectrum" display for multi-decoders. */ - -// Used by requests from a client application, connect, etc. - - char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN]; - - int num_addr; /* Range 2 .. 10. */ - - int client; - - -// Used only by client request to transmit connected data. - - cdata_t *txdata; - -// Used for channel activity change. -// It is useful to know when the channel is busy either for carrier detect -// or when we are transmitting. - - int activity; /* OCTYPE_PTT for my transmission start/end. */ - /* OCTYPE_DCD if we hear someone else. */ - - int status; /* 1 for active or 0 for quiet. */ - -} dlq_item_t; - - - -void dlq_init (void); - - - -void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, int is_fx25, retry_t retries, char *spectrum); - -void dlq_connect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client, int pid); - -void dlq_disconnect_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client); - -void dlq_outstanding_frames_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client); - -void dlq_xmit_data_request (char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, int chan, int client, int pid, char *xdata_ptr, int xdata_len); - -void dlq_register_callsign (char addr[AX25_MAX_ADDR_LEN], int chan, int client); - -void dlq_unregister_callsign (char addr[AX25_MAX_ADDR_LEN], int chan, int client); - -void dlq_channel_busy (int chan, int activity, int status); - -void dlq_seize_confirm (int chan); - -void dlq_client_cleanup (int client); - - - -int dlq_wait_while_empty (double timeout_val); - -struct dlq_item_s *dlq_remove (void); - -void dlq_delete (struct dlq_item_s *pitem); - - - -cdata_t *cdata_new (int pid, char *data, int len); - -void cdata_delete (cdata_t *txdata); - -void cdata_check_leak (void); - - -#endif - -/* end dlq.h */ diff --git a/dns_sd_common.h b/dns_sd_common.h deleted file mode 100644 index f104bf8..0000000 --- a/dns_sd_common.h +++ /dev/null @@ -1,7 +0,0 @@ - -#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD) - -char *dns_sd_default_service_name(void); - -#endif - diff --git a/dns_sd_dw.h b/dns_sd_dw.h deleted file mode 100644 index 79f4b86..0000000 --- a/dns_sd_dw.h +++ /dev/null @@ -1,10 +0,0 @@ - -#if (USE_AVAHI_CLIENT|USE_MACOS_DNSSD) - -#include "config.h" - -#define DNS_SD_SERVICE "_kiss-tnc._tcp" - -void dns_sd_announce (struct misc_config_s *mc); - -#endif // USE_AVAHI_CLIENT diff --git a/dtime_now.h b/dtime_now.h deleted file mode 100644 index 411534b..0000000 --- a/dtime_now.h +++ /dev/null @@ -1,18 +0,0 @@ - - -extern double dtime_realtime (void); - -extern double dtime_monotonic (void); - - -void timestamp_now (char *result, int result_size, int show_ms); - -void timestamp_user_format (char *result, int result_size, char *user_format); - -void timestamp_filename (char *result, int result_size); - - -// FIXME: remove temp workaround. -// Needs many scattered updates. - -#define dtime_now dtime_realtime diff --git a/dtmf.h b/dtmf.h deleted file mode 100644 index c1b52b9..0000000 --- a/dtmf.h +++ /dev/null @@ -1,14 +0,0 @@ -/* dtmf.h */ - - -#include "audio.h" - -void dtmf_init (struct audio_s *p_audio_config, int amp); - -char dtmf_sample (int c, float input); - -int dtmf_send (int chan, char *str, int speed, int txdelay, int txtail); - - -/* end dtmf.h */ - diff --git a/dw9600.c b/dw9600.c index 8307342..407feb1 100644 --- a/dw9600.c +++ b/dw9600.c @@ -25,6 +25,7 @@ typedef struct TStringList_T extern int fx25_mode[4]; extern int il2p_mode[4]; +extern int il2p_crc[4]; extern short rx_baudrate[5]; #define FX25_MODE_NONE 0 diff --git a/dwgps.h b/dwgps.h deleted file mode 100644 index 78f821f..0000000 --- a/dwgps.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* dwgps.h */ - -#ifndef DWGPS_H -#define DWGPS_H 1 - - -#include -#include "config.h" /* for struct misc_config_s */ - - -/* - * Values for fix, equivalent to values from libgps. - * -2 = not initialized. - * -1 = error communicating with GPS receiver. - * 0 = nothing heard yet. - * 1 = had signal but lost it. - * 2 = 2D. - * 3 = 3D. - * - * Undefined float & double values are set to G_UNKNOWN. - * - */ - -enum dwfix_e { DWFIX_NOT_INIT= -2, DWFIX_ERROR= -1, DWFIX_NOT_SEEN=0, DWFIX_NO_FIX=1, DWFIX_2D=2, DWFIX_3D=3 }; - -typedef enum dwfix_e dwfix_t; - -typedef struct dwgps_info_s { - time_t timestamp; /* When last updated. System time. */ - dwfix_t fix; /* Quality of position fix. */ - double dlat; /* Latitude. Valid if fix >= 2. */ - double dlon; /* Longitude. Valid if fix >= 2. */ - float speed_knots; /* libgps uses meters/sec but we use GPS usual knots. */ - float track; /* What is difference between track and course? */ - float altitude; /* meters above mean sea level. Valid if fix == 3. */ -} dwgps_info_t; - - - - - -void dwgps_init (struct misc_config_s *pconfig, int debug); - -void dwgps_clear (dwgps_info_t *gpsinfo); - -dwfix_t dwgps_read (dwgps_info_t *gpsinfo); - -void dwgps_print (char *msg, dwgps_info_t *gpsinfo); - -void dwgps_term (void); - -void dwgps_set_data (dwgps_info_t *gpsinfo); - - -#endif /* DWGPS_H 1 */ - -/* end dwgps.h */ - - - diff --git a/dwgpsd.h b/dwgpsd.h deleted file mode 100644 index 4c0e0fd..0000000 --- a/dwgpsd.h +++ /dev/null @@ -1,22 +0,0 @@ - -/* dwgpsd.h - For communicating with daemon */ - - - -#ifndef DWGPSD_H -#define DWGPSD_H 1 - -#include "config.h" - - -int dwgpsd_init (struct misc_config_s *pconfig, int debug); - -void dwgpsd_term (void); - -#endif - - -/* end dwgpsd.h */ - - - diff --git a/dwgpsnmea.h b/dwgpsnmea.h deleted file mode 100644 index ffe5a12..0000000 --- a/dwgpsnmea.h +++ /dev/null @@ -1,32 +0,0 @@ - -/* dwgpsnmea.h - For reading NMEA sentences over serial port */ - - - -#ifndef DWGPSNMEA_H -#define DWGPSNMEA_H 1 - -#include "dwgps.h" /* for dwfix_t */ -#include "config.h" -#include "serial_port.h" /* for MYFDTYPE */ - - -int dwgpsnmea_init (struct misc_config_s *pconfig, int debug); - -MYFDTYPE dwgpsnmea_get_fd(char *wp_port_name, int speed); - -void dwgpsnmea_term (void); - - -dwfix_t dwgpsnmea_gprmc (char *sentence, int quiet, double *odlat, double *odlon, float *oknots, float *ocourse); - -dwfix_t dwgpsnmea_gpgga (char *sentence, int quiet, double *odlat, double *odlon, float *oalt, int *onsat); - - -#endif - - -/* end dwgpsnmea.h */ - - - diff --git a/dwsock.h b/dwsock.h deleted file mode 100644 index 986f6a2..0000000 --- a/dwsock.h +++ /dev/null @@ -1,21 +0,0 @@ - -/* dwsock.h - Socket helper functions. */ - -#ifndef DWSOCK_H -#define DWSOCK_H 1 - -#define DWSOCK_IPADDR_LEN 48 // Size of string to hold IPv4 or IPv6 address. - // I think 40 would be adequate but we'll make - // it a little larger just to be safe. - // Use INET6_ADDRSTRLEN (from netinet/in.h) instead? - -int dwsock_init (void); - -int dwsock_connect (char *hostname, char *port, char *description, int allow_ipv6, int debug, char ipaddr_str[DWSOCK_IPADDR_LEN]); - /* ipaddr_str needs to be at least SOCK_IPADDR_LEN bytes */ - -char *dwsock_ia_to_text (int Family, void * pAddr, char * pStringBuf, size_t StringBufSize); - -void dwsock_close (int fd); - -#endif \ No newline at end of file diff --git a/encode_aprs.h b/encode_aprs.h deleted file mode 100644 index dc7b8bd..0000000 --- a/encode_aprs.h +++ /dev/null @@ -1,17 +0,0 @@ - -int encode_position (int messaging, int compressed, double lat, double lon, int ambiguity, int alt_ft, - char symtab, char symbol, - int power, int height, int gain, char *dir, - int course, int speed_knots, - float freq, float tone, float offset, - char *comment, - char *presult, size_t result_size); - -int encode_object (char *name, int compressed, time_t thyme, double lat, double lon, int ambiguity, - char symtab, char symbol, - int power, int height, int gain, char *dir, - int course, int speed_knots, - float freq, float tone, float offset, char *comment, - char *presult, size_t result_size); - -int encode_message (char *addressee, char *text, char *id, char *presult, size_t result_size); diff --git a/fcs_calc.h b/fcs_calc.h deleted file mode 100644 index 2e2b0ef..0000000 --- a/fcs_calc.h +++ /dev/null @@ -1,11 +0,0 @@ - -/* fcs_calc.h */ - - -unsigned short fcs_calc (unsigned char *data, int len); - -unsigned short crc16 (unsigned char *data, int len, unsigned short seed); - -/* end fcs_calc.h */ - - diff --git a/fsk_filters.h b/fsk_filters.h deleted file mode 100644 index 81c4e9a..0000000 --- a/fsk_filters.h +++ /dev/null @@ -1,7 +0,0 @@ -/* 1200 bits/sec with Audio sample rate = 11025 */ -/* Mark freq = 1200, Space freq = 2200 */ - -static const signed short m_sin_table[9] = { 0 , 7347 , 11257 , 9899 , 3909 , -3909 , -9899 , -11257 , -7347 }; -static const signed short m_cos_table[9] = { 11431 , 8756 , 1984 , -5715 , -10741 , -10741 , -5715 , 1984 , 8756 }; -static const signed short s_sin_table[9] = { 0 , 10950 , 6281 , -7347 , -10496 , 1327 , 11257 , 5130 , -8314 }; -static const signed short s_cos_table[9] = { 11431 , 3278 , -9550 , -8756 , 4527 , 11353 , 1984 , -10215 , -7844 }; diff --git a/fsk_gen_filter.h b/fsk_gen_filter.h deleted file mode 100644 index e7e8fa6..0000000 --- a/fsk_gen_filter.h +++ /dev/null @@ -1,15 +0,0 @@ - - -#ifndef FSK_GEN_FILTER_H -#define FSK_GEN_FILTER_H 1 - -#include "audio.h" -#include "fsk_demod_state.h" - -void fsk_gen_filter (int samples_per_sec, - int baud, - int mark_freq, int space_freq, - char profile, - struct demodulator_state_s *D); - -#endif \ No newline at end of file diff --git a/gen_tone.h b/gen_tone.h deleted file mode 100644 index bbe23b5..0000000 --- a/gen_tone.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * gen_tone.h - */ - - -int gen_tone_init (struct audio_s *pp, int amp, int gen_packets); - - -//int gen_tone_open (int nchan, int sample_rate, int bit_rate, int f1, int f2, int amp, char *fname); - -//int gen_tone_open_fd (int nchan, int sample_rate, int bit_rate, int f1, int f2, int amp, int fd) ; - -//int gen_tone_close (void); - -void tone_gen_put_bit (int chan, int dat); - -void gen_tone_put_sample (int chan, int a, int sam); \ No newline at end of file diff --git a/grm_sym.h b/grm_sym.h deleted file mode 100644 index 7a15041..0000000 --- a/grm_sym.h +++ /dev/null @@ -1,501 +0,0 @@ - -/* - * grm_sym.h - * - * Symbol codes for use in $PGRMWPL sentence. - * - * Copied from - * Garmin Device Interface Specification - * May 19, 2006 - * Drawing Number: 001-00063-00 Rev. C - */ - - -typedef unsigned short symbol_type_t; - -enum symbol_type_e -{ -/*--------------------------------------------------------------- -Marine symbols ----------------------------------------------------------------*/ -sym_anchor = 0, /* white anchor symbol */ -sym_bell = 1, /* white bell symbol */ -sym_diamond_grn = 2, /* green diamond symbol */ -sym_diamond_red = 3, /* red diamond symbol */ -sym_dive1 = 4, /* diver down flag 1 */ -sym_dive2 = 5, /* diver down flag 2 */ -sym_dollar = 6, /* white dollar symbol */ -sym_fish = 7, /* white fish symbol */ -sym_fuel = 8, /* white fuel symbol */ -sym_horn = 9, /* white horn symbol */ -sym_house = 10, /* white house symbol */ -sym_knife = 11, /* white knife & fork symbol */ -sym_light = 12, /* white light symbol */ -sym_mug = 13, /* white mug symbol */ -sym_skull = 14, /* white skull and crossbones symbol*/ -sym_square_grn = 15, /* green square symbol */ -sym_square_red = 16, /* red square symbol */ -sym_wbuoy = 17, /* white buoy waypoint symbol */ -sym_wpt_dot = 18, /* waypoint dot */ -sym_wreck = 19, /* white wreck symbol */ -sym_null = 20, /* null symbol (transparent) */ -sym_mob = 21, /* man overboard symbol */ -sym_buoy_ambr = 22, /* amber map buoy symbol */ -sym_buoy_blck = 23, /* black map buoy symbol */ -sym_buoy_blue = 24, /* blue map buoy symbol */ -sym_buoy_grn = 25, /* green map buoy symbol */ -sym_buoy_grn_red = 26, /* green/red map buoy symbol */ -sym_buoy_grn_wht = 27, /* green/white map buoy symbol */ -sym_buoy_orng = 28, /* orange map buoy symbol */ -sym_buoy_red = 29, /* red map buoy symbol */ -sym_buoy_red_grn = 30, /* red/green map buoy symbol */ -sym_buoy_red_wht = 31, /* red/white map buoy symbol */ -sym_buoy_violet = 32, /* violet map buoy symbol */ -sym_buoy_wht = 33, /* white map buoy symbol */ -sym_buoy_wht_grn = 34, /* white/green map buoy symbol */ -sym_buoy_wht_red = 35, /* white/red map buoy symbol */ -sym_dot = 36, /* white dot symbol */ -sym_rbcn = 37, /* radio beacon symbol */ -sym_boat_ramp = 150, /* boat ramp symbol */ -sym_camp = 151, /* campground symbol */ -sym_restrooms = 152, /* restrooms symbol */ -sym_showers = 153, /* shower symbol */ -sym_drinking_wtr = 154, /* drinking water symbol */ -sym_phone = 155, /* telephone symbol */ -sym_1st_aid = 156, /* first aid symbol */ -sym_info = 157, /* information symbol */ -sym_parking = 158, /* parking symbol */ -sym_park = 159, /* park symbol */ -sym_picnic = 160, /* picnic symbol */ -sym_scenic = 161, /* scenic area symbol */ -sym_skiing = 162, /* skiing symbol */ -sym_swimming = 163, /* swimming symbol */ -sym_dam = 164, /* dam symbol */ -sym_controlled = 165, /* controlled area symbol */ -sym_danger = 166, /* danger symbol */ -sym_restricted = 167, /* restricted area symbol */ -sym_null_2 = 168, /* null symbol */ -sym_ball = 169, /* ball symbol */ -sym_car = 170, /* car symbol */ -sym_deer = 171, /* deer symbol */ -sym_shpng_cart = 172, /* shopping cart symbol */ -sym_lodging = 173, /* lodging symbol */ -sym_mine = 174, /* mine symbol */ -sym_trail_head = 175, /* trail head symbol */ -sym_truck_stop = 176, /* truck stop symbol */ -sym_user_exit = 177, /* user exit symbol */ -sym_flag = 178, /* flag symbol */ -sym_circle_x = 179, /* circle with x in the center */ -sym_open_24hr = 180, /* open 24 hours symbol */ -sym_fhs_facility = 181, /* U Fishing Hot Spots(tm) Facility */ -sym_bot_cond = 182, /* Bottom Conditions */ -sym_tide_pred_stn = 183, /* Tide/Current Prediction Station */ -sym_anchor_prohib = 184, /* U anchor prohibited symbol */ -sym_beacon = 185, /* U beacon symbol */ -sym_coast_guard = 186, /* U coast guard symbol */ -sym_reef = 187, /* U reef symbol */ -sym_weedbed = 188, /* U weedbed symbol */ -sym_dropoff = 189, /* U dropoff symbol */ -sym_dock = 190, /* U dock symbol */ -sym_marina = 191, /* U marina symbol */ -sym_bait_tackle = 192, /* U bait and tackle symbol */ -sym_stump = 193, /* U stump symbol */ -/*--------------------------------------------------------------- -User customizable symbols -The values from sym_begin_custom to sym_end_custom inclusive are -reserved for the identification of user customizable symbols. ----------------------------------------------------------------*/ -sym_begin_custom = 7680, /* first user customizable symbol */ -sym_end_custom = 8191, /* last user customizable symbol */ -/*--------------------------------------------------------------- -Land symbols ----------------------------------------------------------------*/ -sym_is_hwy = 8192, /* interstate hwy symbol */ -sym_us_hwy = 8193, /* us hwy symbol */ -sym_st_hwy = 8194, /* state hwy symbol */ -sym_mi_mrkr = 8195, /* mile marker symbol */ -sym_trcbck = 8196, /* TracBack (feet) symbol */ -sym_golf = 8197, /* golf symbol */ -sym_sml_cty = 8198, /* small city symbol */ -sym_med_cty = 8199, /* medium city symbol */ -sym_lrg_cty = 8200, /* large city symbol */ -sym_freeway = 8201, /* intl freeway hwy symbol */ -sym_ntl_hwy = 8202, /* intl national hwy symbol */ -sym_cap_cty = 8203, /* capitol city symbol (star) */ -sym_amuse_pk = 8204, /* amusement park symbol */ -sym_bowling = 8205, /* bowling symbol */ -sym_car_rental = 8206, /* car rental symbol */ -sym_car_repair = 8207, /* car repair symbol */ -sym_fastfood = 8208, /* fast food symbol */ -sym_fitness = 8209, /* fitness symbol */ -sym_movie = 8210, /* movie symbol */ -sym_museum = 8211, /* museum symbol */ -sym_pharmacy = 8212, /* pharmacy symbol */ -sym_pizza = 8213, /* pizza symbol */ -sym_post_ofc = 8214, /* post office symbol */ -sym_rv_park = 8215, /* RV park symbol */ -sym_school = 8216, /* school symbol */ -sym_stadium = 8217, /* stadium symbol */ -sym_store = 8218, /* dept. store symbol */ -sym_zoo = 8219, /* zoo symbol */ -sym_gas_plus = 8220, /* convenience store symbol */ -sym_faces = 8221, /* live theater symbol */ -sym_ramp_int = 8222, /* ramp intersection symbol */ -sym_st_int = 8223, /* street intersection symbol */ -sym_weigh_sttn = 8226, /* inspection/weigh station symbol */ -sym_toll_booth = 8227, /* toll booth symbol */ -sym_elev_pt = 8228, /* elevation point symbol */ -sym_ex_no_srvc = 8229, /* exit without services symbol */ -sym_geo_place_mm = 8230, /* Geographic place name, man-made */ -sym_geo_place_wtr = 8231, /* Geographic place name, water */ -sym_geo_place_lnd = 8232, /* Geographic place name, land */ -sym_bridge = 8233, /* bridge symbol */ -sym_building = 8234, /* building symbol */ -sym_cemetery = 8235, /* cemetery symbol */ -sym_church = 8236, /* church symbol */ -sym_civil = 8237, /* civil location symbol */ -sym_crossing = 8238, /* crossing symbol */ -sym_hist_town = 8239, /* historical town symbol */ -sym_levee = 8240, /* levee symbol */ -sym_military = 8241, /* military location symbol */ -sym_oil_field = 8242, /* oil field symbol */ -sym_tunnel = 8243, /* tunnel symbol */ -sym_beach = 8244, /* beach symbol */ -sym_forest = 8245, /* forest symbol */ -sym_summit = 8246, /* summit symbol */ -sym_lrg_ramp_int = 8247, /* large ramp intersection symbol */ -sym_lrg_ex_no_srvc = 8248, /* large exit without services smbl */ -sym_badge = 8249, /* police/official badge symbol */ -sym_cards = 8250, /* gambling/casino symbol */ -sym_snowski = 8251, /* snow skiing symbol */ -sym_iceskate = 8252, /* ice skating symbol */ -sym_wrecker = 8253, /* tow truck (wrecker) symbol */ -sym_border = 8254, /* border crossing (port of entry) */ -sym_geocache = 8255, /* geocache location */ -sym_geocache_fnd = 8256, /* found geocache */ -sym_cntct_smiley = 8257, /* Rino contact symbol, "smiley" */ -sym_cntct_ball_cap = 8258, /* Rino contact symbol, "ball cap" */ -sym_cntct_big_ears = 8259, /* Rino contact symbol, "big ear" */ -sym_cntct_spike = 8260, /* Rino contact symbol, "spike" */ -sym_cntct_goatee = 8261, /* Rino contact symbol, "goatee" */ -sym_cntct_afro = 8262, /* Rino contact symbol, "afro" */ -sym_cntct_dreads = 8263, /* Rino contact symbol, "dreads" */ -sym_cntct_female1 = 8264, /* Rino contact symbol, "female 1" */ -sym_cntct_female2 = 8265, /* Rino contact symbol, "female 2" */ -sym_cntct_female3 = 8266, /* Rino contact symbol, "female 3" */ -sym_cntct_ranger = 8267, /* Rino contact symbol, "ranger" */ -sym_cntct_kung_fu = 8268, /* Rino contact symbol, "kung fu" */ -sym_cntct_sumo = 8269, /* Rino contact symbol, "sumo" */ -sym_cntct_pirate = 8270, /* Rino contact symbol, "pirate" */ -sym_cntct_biker = 8271, /* Rino contact symbol, "biker" */ -sym_cntct_alien = 8272, /* Rino contact symbol, "alien" */ -sym_cntct_bug = 8273, /* Rino contact symbol, "bug" */ -sym_cntct_cat = 8274, /* Rino contact symbol, "cat" */ -sym_cntct_dog = 8275, /* Rino contact symbol, "dog" */ -sym_cntct_pig = 8276, /* Rino contact symbol, "pig" */ -sym_hydrant = 8282, /* water hydrant symbol */ -sym_flag_blue = 8284, /* blue flag symbol */ -sym_flag_green = 8285, /* green flag symbol */ -sym_flag_red = 8286, /* red flag symbol */ -sym_pin_blue = 8287, /* blue pin symbol */ -sym_pin_green = 8288, /* green pin symbol */ -sym_pin_red = 8289, /* red pin symbol */ -sym_block_blue = 8290, /* blue block symbol */ -sym_block_green = 8291, /* green block symbol */ -sym_block_red = 8292, /* red block symbol */ -sym_bike_trail = 8293, /* bike trail symbol */ -sym_circle_red = 8294, /* red circle symbol */ -sym_circle_green = 8295, /* green circle symbol */ -sym_circle_blue = 8296, /* blue circle symbol */ -sym_diamond_blue = 8299, /* blue diamond symbol */ -sym_oval_red = 8300, /* red oval symbol */ -sym_oval_green = 8301, /* green oval symbol */ -sym_oval_blue = 8302, /* blue oval symbol */ -sym_rect_red = 8303, /* red rectangle symbol */ -sym_rect_green = 8304, /* green rectangle symbol */ -sym_rect_blue = 8305, /* blue rectangle symbol */ -sym_square_blue = 8308, /* blue square symbol */ -sym_letter_a_red = 8309, /* red letter 'A' symbol */ -sym_letter_b_red = 8310, /* red letter 'B' symbol */ -sym_letter_c_red = 8311, /* red letter 'C' symbol */ -sym_letter_d_red = 8312, /* red letter 'D' symbol */ -sym_letter_a_green = 8313, /* green letter 'A' symbol */ -sym_letter_c_green = 8314, /* green letter 'C' symbol */ -sym_letter_b_green = 8315, /* green letter 'B' symbol */ -sym_letter_d_green = 8316, /* green letter 'D' symbol */ -sym_letter_a_blue = 8317, /* blue letter 'A' symbol */ -sym_letter_b_blue = 8318, /* blue letter 'B' symbol */ -sym_letter_c_blue = 8319, /* blue letter 'C' symbol */ -sym_letter_d_blue = 8320, /* blue letter 'D' symbol */ -sym_number_0_red = 8321, /* red number '0' symbol */ -sym_number_1_red = 8322, /* red number '1' symbol */ -sym_number_2_red = 8323, /* red number '2' symbol */ -sym_number_3_red = 8324, /* red number '3' symbol */ -sym_number_4_red = 8325, /* red number '4' symbol */ -sym_number_5_red = 8326, /* red number '5' symbol */ -sym_number_6_red = 8327, /* red number '6' symbol */ -sym_number_7_red = 8328, /* red number '7' symbol */ -sym_number_8_red = 8329, /* red number '8' symbol */ -sym_number_9_red = 8330, /* red number '9' symbol */ -sym_number_0_green = 8331, /* green number '0' symbol */ -sym_number_1_green = 8332, /* green number '1' symbol */ -sym_number_2_green = 8333, /* green number '2' symbol */ -sym_number_3_green = 8334, /* green number '3' symbol */ -sym_number_4_green = 8335, /* green number '4' symbol */ -sym_number_5_green = 8336, /* green number '5' symbol */ -sym_number_6_green = 8337, /* green number '6' symbol */ -sym_number_7_green = 8338, /* green number '7' symbol */ -sym_number_8_green = 8339, /* green number '8' symbol */ -sym_number_9_green = 8340, /* green number '9' symbol */ -sym_number_0_blue = 8341, /* blue number '0' symbol */ -sym_number_1_blue = 8342, /* blue number '1' symbol */ -sym_number_2_blue = 8343, /* blue number '2' symbol */ -sym_number_3_blue = 8344, /* blue number '3' symbol */ -sym_number_4_blue = 8345, /* blue number '4' symbol */ -sym_number_5_blue = 8346, /* blue number '5' symbol */ -sym_number_6_blue = 8347, /* blue number '6' symbol */ -sym_number_7_blue = 8348, /* blue number '7' symbol */ -sym_number_8_blue = 8349, /* blue number '8' symbol */ -sym_number_9_blue = 8350, /* blue number '9' symbol */ -sym_triangle_blue = 8351, /* blue triangle symbol */ -sym_triangle_green = 8352, /* green triangle symbol */ -sym_triangle_red = 8353, /* red triangle symbol */ -sym_food_asian = 8359, /* asian food symbol */ -sym_food_deli = 8360, /* deli symbol */ -sym_food_italian = 8361, /* italian food symbol */ -sym_food_seafood = 8362, /* seafood symbol */ -sym_food_steak = 8363, /* steak symbol */ -/*--------------------------------------------------------------- -Aviation symbols ----------------------------------------------------------------*/ -sym_airport = 16384, /* airport symbol */ -sym_int = 16385, /* intersection symbol */ -sym_ndb = 16386, /* non-directional beacon symbol */ -sym_vor = 16387, /* VHF omni-range symbol */ -sym_heliport = 16388, /* heliport symbol */ -sym_private = 16389, /* private field symbol */ -sym_soft_fld = 16390, /* soft field symbol */ -sym_tall_tower = 16391, /* tall tower symbol */ -sym_short_tower = 16392, /* short tower symbol */ -sym_glider = 16393, /* glider symbol */ -sym_ultralight = 16394, /* ultralight symbol */ -sym_parachute = 16395, /* parachute symbol */ -sym_vortac = 16396, /* VOR/TACAN symbol */ -sym_vordme = 16397, /* VOR-DME symbol */ -sym_faf = 16398, /* first approach fix */ -sym_lom = 16399, /* localizer outer marker */ -sym_map = 16400, /* missed approach point */ -sym_tacan = 16401, /* TACAN symbol */ -sym_seaplane = 16402, /* Seaplane Base */ -}; - - - -/* - * Mapping from APRS symbols to Garmin. - */ - -// TODO: NEEDS MORE WORK!!! - - -#define SYMTAB_SIZE 95 - -#define sym_default sym_diamond_grn - - -static const symbol_type_t grm_primary_symtab[SYMTAB_SIZE] = { - - sym_default, // 00 --no-symbol-- - sym_cntct_ranger, // ! 01 Police, Sheriff - sym_default, // " 02 reserved (was rain) - sym_rbcn, // # 03 DIGI (white center) - sym_phone, // $ 04 PHONE - sym_rbcn, // % 05 DX CLUSTER - sym_rbcn, // & 06 HF GATEway - sym_glider, // ' 07 Small AIRCRAFT - sym_rbcn, // ( 08 Mobile Satellite Station - sym_default, // ) 09 Wheelchair (handicapped) - sym_car, // * 10 SnowMobile - sym_1st_aid, // + 11 Red Cross - sym_cntct_ball_cap, // , 12 Boy Scouts - sym_house, // - 13 House QTH (VHF) - sym_default, // . 14 X - sym_default, // / 15 Red Dot - sym_default, // 0 16 # circle (obsolete) - sym_default, // 1 17 TBD - sym_default, // 2 18 TBD - sym_default, // 3 19 TBD - sym_default, // 4 20 TBD - sym_default, // 5 21 TBD - sym_default, // 6 22 TBD - sym_default, // 7 23 TBD - sym_default, // 8 24 TBD - sym_default, // 9 25 TBD - sym_default, // : 26 FIRE - sym_camp, // ; 27 Campground (Portable ops) - sym_cntct_biker, // < 28 Motorcycle - sym_default, // = 29 RAILROAD ENGINE - sym_car, // > 30 CAR - sym_default, // ? 31 SERVER for Files - sym_default, // @ 32 HC FUTURE predict (dot) - sym_1st_aid, // A 33 Aid Station - sym_rbcn, // B 34 BBS or PBBS - sym_boat_ramp, // C 35 Canoe - sym_default, // D 36 - sym_default, // E 37 EYEBALL (Eye catcher!) - sym_default, // F 38 Farm Vehicle (tractor) - sym_default, // G 39 Grid Square (6 digit) - sym_lodging, // H 40 HOTEL (blue bed symbol) - sym_rbcn, // I 41 TcpIp on air network stn - sym_default, // J 42 - sym_school, // K 43 School - sym_default, // L 44 PC user - sym_default, // M 45 MacAPRS - sym_default, // N 46 NTS Station - sym_parachute, // O 47 BALLOON - sym_cntct_ranger, // P 48 Police - sym_default, // Q 49 TBD - sym_rv_park, // R 50 REC. VEHICLE - sym_glider, // S 51 SHUTTLE - sym_default, // T 52 SSTV - sym_car, // U 53 BUS - sym_cntct_biker, // V 54 ATV - sym_default, // W 55 National WX Service Site - sym_default, // X 56 HELO - sym_default, // Y 57 YACHT (sail) - sym_default, // Z 58 WinAPRS - sym_cntct_smiley, // [ 59 Human/Person (HT) - sym_triangle_green, // \ 60 TRIANGLE(DF station) - sym_default, // ] 61 MAIL/PostOffice(was PBBS) - sym_glider, // ^ 62 LARGE AIRCRAFT - sym_default, // _ 63 WEATHER Station (blue) - sym_rbcn, // ` 64 Dish Antenna - sym_1st_aid, // a 65 AMBULANCE - sym_cntct_biker, // b 66 BIKE - sym_default, // c 67 Incident Command Post - sym_hydrant, // d 68 Fire dept - sym_deer, // e 69 HORSE (equestrian) - sym_hydrant, // f 70 FIRE TRUCK - sym_glider, // g 71 Glider - sym_1st_aid, // h 72 HOSPITAL - sym_default, // i 73 IOTA (islands on the air) - sym_car, // j 74 JEEP - sym_car, // k 75 TRUCK - sym_default, // l 76 Laptop - sym_rbcn, // m 77 Mic-E Repeater - sym_default, // n 78 Node (black bulls-eye) - sym_default, // o 79 EOC - sym_cntct_dog, // p 80 ROVER (puppy, or dog) - sym_default, // q 81 GRID SQ shown above 128 m - sym_rbcn, // r 82 Repeater - sym_default, // s 83 SHIP (pwr boat) - sym_truck_stop, // t 84 TRUCK STOP - sym_truck_stop, // u 85 TRUCK (18 wheeler) - sym_car, // v 86 VAN - sym_drinking_wtr, // w 87 WATER station - sym_default, // x 88 xAPRS (Unix) - sym_tall_tower, // y 89 YAGI @ QTH - sym_default, // z 90 TBD - sym_default, // { 91 - sym_default, // | 92 TNC Stream Switch - sym_default, // } 93 - sym_default }; // ~ 94 TNC Stream Switch - -static const symbol_type_t grm_alternate_symtab[SYMTAB_SIZE] = { - - sym_default, // 00 --no-symbol-- - sym_default, // ! 01 EMERGENCY (!) - sym_default, // " 02 reserved - sym_default, // # 03 OVERLAY DIGI (green star) - sym_default, // $ 04 Bank or ATM (green box) - sym_default, // % 05 Power Plant with overlay - sym_rbcn, // & 06 I=Igte IGate R=RX T=1hopTX 2=2hopTX - sym_default, // ' 07 Crash (& now Incident sites) - sym_default, // ( 08 CLOUDY (other clouds w ovrly) - sym_hydrant, // ) 09 Firenet MEO, MODIS Earth Obs. - sym_default, // * 10 SNOW (& future ovrly codes) - sym_default, // + 11 Church - sym_cntct_female1, // , 12 Girl Scouts - sym_house, // - 13 House (H=HF) (O = Op Present) - sym_default, // . 14 Ambiguous (Big Question mark) - sym_default, // / 15 Waypoint Destination - sym_default, // 0 16 CIRCLE (E/I/W=IRLP/Echolink/WIRES) - sym_default, // 1 17 - sym_default, // 2 18 - sym_default, // 3 19 - sym_default, // 4 20 - sym_default, // 5 21 - sym_default, // 6 22 - sym_default, // 7 23 - sym_default, // 8 24 802.11 or other network node - sym_default, // 9 25 Gas Station (blue pump) - sym_default, // : 26 Hail (& future ovrly codes) - sym_park, // ; 27 Park/Picnic area - sym_default, // < 28 ADVISORY (one WX flag) - sym_rbcn, // = 29 APRStt Touchtone (DTMF users) - sym_car, // > 30 OVERLAID CAR - sym_default, // ? 31 INFO Kiosk (Blue box with ?) - sym_default, // @ 32 HURRICANE/Trop-Storm - sym_default, // A 33 overlayBOX DTMF & RFID & XO - sym_default, // B 34 Blwng Snow (& future codes) - sym_coast_guard, // C 35 Coast Guard - sym_default, // D 36 Drizzle (proposed APRStt) - sym_default, // E 37 Smoke (& other vis codes) - sym_default, // F 38 Freezng rain (&future codes) - sym_default, // G 39 Snow Shwr (& future ovrlys) - sym_default, // H 40 Haze (& Overlay Hazards) - sym_default, // I 41 Rain Shower - sym_default, // J 42 Lightning (& future ovrlys) - sym_rbcn, // K 43 Kenwood HT (W) - sym_light, // L 44 Lighthouse - sym_default, // M 45 MARS (A=Army,N=Navy,F=AF) - sym_default, // N 46 Navigation Buoy - sym_default, // O 47 Rocket - sym_default, // P 48 Parking - sym_default, // Q 49 QUAKE - sym_default, // R 50 Restaurant - sym_rbcn, // S 51 Satellite/Pacsat - sym_default, // T 52 Thunderstorm - sym_default, // U 53 SUNNY - sym_default, // V 54 VORTAC Nav Aid - sym_default, // W 55 # NWS site (NWS options) - sym_pharmacy, // X 56 Pharmacy Rx (Apothicary) - sym_rbcn, // Y 57 Radios and devices - sym_default, // Z 58 - sym_default, // [ 59 W.Cloud (& humans w Ovrly) - sym_default, // \ 60 New overlayable GPS symbol - sym_default, // ] 61 - sym_glider, // ^ 62 # Aircraft (shows heading) - sym_default, // _ 63 # WX site (green digi) - sym_default, // ` 64 Rain (all types w ovrly) - sym_default, // a 65 ARRL, ARES, WinLINK - sym_default, // b 66 Blwng Dst/Snd (& others) - sym_default, // c 67 CD triangle RACES/SATERN/etc - sym_default, // d 68 DX spot by callsign - sym_default, // e 69 Sleet (& future ovrly codes) - sym_default, // f 70 Funnel Cloud - sym_default, // g 71 Gale Flags - sym_default, // h 72 Store. or HAMFST Hh=HAM store - sym_default, // i 73 BOX or points of Interest - sym_default, // j 74 WorkZone (Steam Shovel) - sym_car, // k 75 Special Vehicle SUV,ATV,4x4 - sym_default, // l 76 Areas (box,circles,etc) - sym_default, // m 77 Value Sign (3 digit display) - sym_default, // n 78 OVERLAY TRIANGLE - sym_default, // o 79 small circle - sym_default, // p 80 Prtly Cldy (& future ovrlys) - sym_default, // q 81 - sym_restrooms, // r 82 Restrooms - sym_default, // s 83 OVERLAY SHIP/boat (top view) - sym_default, // t 84 Tornado - sym_car, // u 85 OVERLAID TRUCK - sym_car, // v 86 OVERLAID Van - sym_default, // w 87 Flooding - sym_wreck, // x 88 Wreck or Obstruction ->X<- - sym_default, // y 89 Skywarn - sym_default, // z 90 OVERLAID Shelter - sym_default, // { 91 Fog (& future ovrly codes) - sym_default, // | 92 TNC Stream Switch - sym_default, // } 93 - sym_default }; // ~ 94 TNC Stream Switch - diff --git a/hdlc_send.h b/hdlc_send.h deleted file mode 100644 index 4f8a105..0000000 --- a/hdlc_send.h +++ /dev/null @@ -1,17 +0,0 @@ - -/* hdlc_send.h */ - -// In version 1.7 an extra layer of abstraction was added here. -// Rather than calling hdlc_send_frame, we now use another function -// which sends AX.25, FX.25, or IL2P depending on - -#include "ax25_pad.h" -#include "audio.h" - -int layer2_send_frame (int chan, packet_t pp, int bad_fcs, struct audio_s *audio_config_p); - -int layer2_preamble_postamble (int chan, int flags, int finish, struct audio_s *audio_config_p); - -/* end hdlc_send.h */ - - diff --git a/igate.h b/igate.h deleted file mode 100644 index 8203ac7..0000000 --- a/igate.h +++ /dev/null @@ -1,128 +0,0 @@ - -/*---------------------------------------------------------------------------- - * - * Name: igate.h - * - * Purpose: Interface to the Internet Gateway functions. - * - *-----------------------------------------------------------------------------*/ - - -#ifndef IGATE_H -#define IGATE_H 1 - - -#include "ax25_pad.h" -#include "digipeater.h" -#include "audio.h" - - -#define DEFAULT_IGATE_PORT 14580 - - - -struct igate_config_s { - -/* - * For logging into the IGate server. - */ - char t2_server_name[40]; /* Tier 2 IGate server name. */ - - int t2_server_port; /* Typically 14580. */ - - char t2_login[AX25_MAX_ADDR_LEN];/* e.g. WA9XYZ-15 */ - /* Note that the ssid could be any two alphanumeric */ - /* characters not just 1 thru 15. */ - /* Could be same or different than the radio call(s). */ - /* Not sure what the consequences would be. */ - - char t2_passcode[8]; /* Max. 5 digits. Could be "-1". */ - - char *t2_filter; /* Optional filter for IS -> RF direction. */ - /* This is the "server side" filter. */ - /* A better name would be subscription or something */ - /* like that because we can only ask for more. */ - -/* - * For transmitting. - */ - int tx_chan; /* Radio channel for transmitting. */ - /* 0=first, etc. -1 for none. */ - /* Presently IGate can transmit on only a single channel. */ - /* A future version might generalize this. */ - /* Each transmit channel would have its own client side filtering. */ - - char tx_via[80]; /* VIA path for transmitting third party packets. */ - /* Usual text representation. */ - /* Must start with "," if not empty so it can */ - /* simply be inserted after the destination address. */ - - int max_digi_hops; /* Maximum number of digipeater hops possible for via path. */ - /* Derived from the SSID when last character of address is a digit. */ - /* e.g. "WIDE1-1,WIDE5-2" would be 3. */ - /* This is useful to know so we can determine how many */ - /* stations we might be able to reach. */ - - int tx_limit_1; /* Max. packets to transmit in 1 minute. */ - - int tx_limit_5; /* Max. packets to transmit in 5 minutes. */ - - int igmsp; /* Number of message sender position reports to allow. */ - /* Common practice is to default to 1. */ - /* We allow additional flexibility of 0 to disable feature */ - /* or a small number to allow more. */ - -/* - * Receiver to IS data options. - */ - int rx2ig_dedupe_time; /* seconds. 0 to disable. */ - -/* - * Special SATgate mode to delay packets heard directly. - */ - int satgate_delay; /* seconds. 0 to disable. */ -}; - - -#define IGATE_TX_LIMIT_1_DEFAULT 6 -#define IGATE_TX_LIMIT_1_MAX 20 - -#define IGATE_TX_LIMIT_5_DEFAULT 20 -#define IGATE_TX_LIMIT_5_MAX 80 - -#define IGATE_RX2IG_DEDUPE_TIME 0 /* Issue 85. 0 means disable dupe checking in RF>IS direction. */ - /* See comments in rx_to_ig_remember & rx_to_ig_allow. */ - /* Currently there is no configuration setting to change this. */ - -#define DEFAULT_SATGATE_DELAY 10 -#define MIN_SATGATE_DELAY 5 -#define MAX_SATGATE_DELAY 30 - - -/* Call this once at startup */ - -void igate_init (struct audio_s *p_audio_config, struct igate_config_s *p_igate_config, struct digi_config_s *p_digi_config, int debug_level); - -/* Call this with each packet received from the radio. */ - -void igate_send_rec_packet (int chan, packet_t recv_pp); - -/* This when digipeater transmits. Set bydigi to 1 . */ - -void ig_to_tx_remember (packet_t pp, int chan, int bydigi); - - - -/* Get statistics for IGATE status beacon. */ - -int igate_get_msg_cnt (void); - -int igate_get_pkt_cnt (void); - -int igate_get_upl_cnt (void); - -int igate_get_dnl_cnt (void); - - - -#endif diff --git a/il2p.c b/il2p.c index e51264c..6a284f2 100644 --- a/il2p.c +++ b/il2p.c @@ -42,11 +42,44 @@ along with QtSoundModem. If not, see http://www.gnu.org/licenses // IP2P receive code (il2p_rec_bit) is called from the bit receiving code in ax25_demod.c, so includes parallel decoders - - - #include "UZ7HOStuff.h" +#include // for uint64_t + + // Oct 2023 Nino has added an optional crc + +// Hamming(7,4) Encoding Table +// Enter this table with the 4-bit value to be encoded. +// Returns 7-bit encoded value, with high bit zero'd. + +uint8_t Hamming74EncodeTable[16] = { 0x0, 0x71, 0x62, 0x13, 0x54, 0x25, 0x36, 0x47, 0x38, 0x49, 0x5a, 0x2b, 0x6c, 0x1d, 0xe, 0x7f }; + +// Hamming(7,4) Decoding Table +// Enter this table with 7-bit encoded value, high bit masked. +// Returns 4-bit decoded value. + +uint16_t Hamming74DecodeTable[128] = { \ + 0x0, 0x0, 0x0, 0x3, 0x0, 0x5, 0xe, 0x7, \ + 0x0, 0x9, 0xe, 0xb, 0xe, 0xd, 0xe, 0xe, \ + 0x0, 0x3, 0x3, 0x3, 0x4, 0xd, 0x6, 0x3, \ + 0x8, 0xd, 0xa, 0x3, 0xd, 0xd, 0xe, 0xd, \ + 0x0, 0x5, 0x2, 0xb, 0x5, 0x5, 0x6, 0x5, \ + 0x8, 0xb, 0xb, 0xb, 0xc, 0x5, 0xe, 0xb, \ + 0x8, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x6, \ + 0x8, 0x8, 0x8, 0xb, 0x8, 0xd, 0x6, 0xf, \ + 0x0, 0x9, 0x2, 0x7, 0x4, 0x7, 0x7, 0x7, \ + 0x9, 0x9, 0xa, 0x9, 0xc, 0x9, 0xe, 0x7, \ + 0x4, 0x1, 0xa, 0x3, 0x4, 0x4, 0x4, 0x7, \ + 0xa, 0x9, 0xa, 0xa, 0x4, 0xd, 0xa, 0xf, \ + 0x2, 0x1, 0x2, 0x2, 0xc, 0x5, 0x2, 0x7, \ + 0xc, 0x9, 0x2, 0xb, 0xc, 0xc, 0xc, 0xf, \ + 0x1, 0x1, 0x2, 0x1, 0x4, 0x1, 0x6, 0xf, \ + 0x8, 0x1, 0xa, 0xf, 0xc, 0xf, 0xf, 0xf }; + + + + + void Debugprintf(const char * format, ...); int SMUpdatePhaseConstellation(int chan, float * Phases, float * Mags, int intPSKPhase, int Count); @@ -109,7 +142,6 @@ int MaxMagIndex = 0; #ifndef FX25_H #define FX25_H -#include // for uint64_t extern unsigned int pskStates[4]; @@ -343,6 +375,7 @@ struct packet_s { unsigned char frame_data[AX25_MAX_PACKET_LEN + 1]; /* Raw frame contents, without the CRC. */ + unsigned char crc[4]; // received crc int magic2; /* Will get stomped on if above overflows. */ }; @@ -1015,6 +1048,39 @@ void multi_modem_process_rec_packet(int snd_ch, int subchan, int slice, packet_t sprintf(Mode, "IL2P %d", centreFreq); + // check crc if enabled + + if (il2p_crc[snd_ch]) + { + unsigned short CRCMSG; + unsigned short CRCCALC; + uint8_t crc[4]; + + // check crc if enabled + + // The four encoded CRC bytes are arranged : + // | CRC3 | CRC2 | CRC1 | CRC0 | but we store as received, so F->crc[0] is CRC3 + // CRC3 encoded from high nibble of 16 - bit CRC value (from crc2) + // CRC0 encoded from low nibble of 16 - bit CRC value (from crc1) + + crc[0] = Hamming74DecodeTable[(pp->crc[0] & 0x7f)]; + crc[1] = Hamming74DecodeTable[(pp->crc[1] & 0x7f)]; + crc[2] = Hamming74DecodeTable[(pp->crc[2] & 0x7f)]; + crc[3] = Hamming74DecodeTable[(pp->crc[3] & 0x7f)]; + + CRCMSG = crc[0] << 12 | crc[1] << 8 | crc[2] << 4 | crc[3]; + + CRCCALC = get_fcs(pp->frame_data, pp->frame_len); + + if (CRCCALC != CRCMSG) + { + Debugprintf("CRC Error Decoder %d Received %x Sent %x", subchan, CRCCALC, CRCMSG); + // freeString(data); + // ax25_delete(pp); + // return; + } + } + stringAdd(data, pp->frame_data, pp->frame_len + 2); // QTSM assumes a CRC ax25_delete(pp); @@ -3151,6 +3217,13 @@ int il2p_type_1_header(packet_t pp, int max_fec, unsigned char *hdr) ax25_get_addr_no_ssid(pp, AX25_SOURCE, src_addr); int src_ssid = ax25_get_ssid(pp, AX25_SOURCE); + if ((pp->frame_data[6] & 0x80) == (pp->frame_data[13] & 0x80)) + { + // Both C bits are the same (ax.25 v1) so can't be sent as type 1 as will be changed + + return -1; + } + unsigned char *a = (unsigned char *)dst_addr; for (int i = 0; *a != '\0'; i++, a++) { if (*a < ' ' || *a > '_') { @@ -3919,7 +3992,7 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) //assert(slice >= 0 && slice < MAX_SLICERS); F = il2p_context[chan][subchan][slice] = (struct il2p_context_s *)malloc(sizeof(struct il2p_context_s)); //assert(F != NULL); - memset(F, 0, sizeof(struct il2p_context_s)); +memset(F, 0, sizeof(struct il2p_context_s)); } // Accumulate most recent 24 bits received. Most recent is LSB. @@ -3942,7 +4015,7 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) nPhases[chan][subchan][slice] = 0; // Determine Centre Freq - + centreFreq[chan] = GuessCentreFreq(chan); } else if (__builtin_popcount((~F->acc & 0x00ffffff) ^ IL2P_SYNC_WORD) <= 1) { @@ -3956,7 +4029,7 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) centreFreq[chan] = GuessCentreFreq(chan); nPhases[chan][subchan][slice] = 0; } - + break; case IL2P_HEADER: // Gathering the header. @@ -3990,7 +4063,7 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) F->eplen = il2p_payload_compute(&plprop, len, max_fec); if (il2p_get_debug() >= 1) - { + { Debugprintf("Header type %d, max fec = %d", hdr_type, max_fec); Debugprintf("Need to collect %d encoded bytes for %d byte payload.", F->eplen, len); Debugprintf("%d small blocks of %d and %d large blocks of %d. %d parity symbols per block", @@ -4008,9 +4081,21 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) F->pc = 0; F->state = IL2P_PAYLOAD; } - else if (F->eplen == 0) { // No payload. + else if (F->eplen == 0) + { + // No payload. + F->pc = 0; - F->state = IL2P_DECODE; + + if (il2p_crc[chan]) + { + // enter collect crc state + + F->crccount = 0; + F->state = IL2P_CRC; + } + else + F->state = IL2P_DECODE; } else { // Error. @@ -4039,16 +4124,47 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) else { F->spayload[F->pc++] = (~F->acc) & 0xff; } - if (F->pc == F->eplen) { + if (F->pc == F->eplen) + { + // got frame. See if need crc - // TODO?: for symmetry it seems like we should clarify the payload before combining. + if (il2p_crc[chan]) + { + // enter collect crc state - F->state = IL2P_DECODE; + F->crccount = 0; + F->state = IL2P_CRC; + } + else + F->state = IL2P_DECODE; } } break; + case IL2P_CRC: + + F->bc++; + if (F->bc == 8) + { + // full byte has been collected. + F->bc = 0; + if (!F->polarity) + F->crc[F->crccount++] = F->acc & 0xff; + else + F->crc[F->crccount++] = (~F->acc) & 0xff; + + if (F->crccount == 4) + { + // have all crc bytes. enter DECODE + + F->state = IL2P_DECODE; + } + } + + break; + case IL2P_DECODE: + // We get here after a good header and any payload has been collected. // Processing is delayed by one bit but I think it makes the logic cleaner. // During unit testing be sure to send an extra bit to flush it out at the end. @@ -4077,6 +4193,18 @@ void il2p_rec_bit(int chan, int subchan, int slice, int dbit) // TODO: Could we put last 3 arguments in packet object rather than passing around separately? + // if using crc pass received crc to packet object + + if (il2p_crc[chan]) + { + //copy crc bytes to packet object + + pp->crc[0] = F->crc[0]; + pp->crc[1] = F->crc[1]; + pp->crc[2] = F->crc[2]; + pp->crc[3] = F->crc[3]; + } + multi_modem_process_rec_packet(chan, subchan, slice, pp, alevel, retries, is_fx25, slice, centreFreq[chan]); } } // end block for local variables. @@ -4269,13 +4397,19 @@ static void send_bit(int chan, int b, int polarity); * *--------------------------------------------------------------*/ + string * il2p_send_frame(int chan, packet_t pp, int max_fec, int polarity) { - unsigned char encoded[IL2P_MAX_PACKET_SIZE]; + unsigned char encoded[IL2P_MAX_PACKET_SIZE] = ""; string * packet = newString(); int preamblecount; unsigned char preamble[1024]; + // The data includes the 2 byte crc but length doesn't + + uint8_t crc1 = pp->frame_data[pp->frame_len]; // Low 8 bits + uint8_t crc2 = pp->frame_data[pp->frame_len + 1]; // High 8 bits + encoded[0] = (IL2P_SYNC_WORD >> 16) & 0xff; encoded[1] = (IL2P_SYNC_WORD >> 8) & 0xff; encoded[2] = (IL2P_SYNC_WORD) & 0xff; @@ -4289,6 +4423,24 @@ string * il2p_send_frame(int chan, packet_t pp, int max_fec, int polarity) elen += IL2P_SYNC_WORD_SIZE; + // if we are using crc add it now. elen should point to end of data + // crc should be at pp->frame_data[pp->frame_len] + + if (il2p_crc[chan]) + { + // The four encoded CRC bytes are arranged : + // | CRC3 | CRC2 | CRC1 | CRC0 | + + // CRC3 encoded from high nibble of 16 - bit CRC value (from crc2) + // CRC0 encoded from low nibble of 16 - bit CRC value (from crc1) + + encoded[elen++] = Hamming74EncodeTable[crc2 >> 4]; + encoded[elen++] = Hamming74EncodeTable[crc2 & 0xf]; + encoded[elen++] = Hamming74EncodeTable[crc1 >> 4]; + encoded[elen++] = Hamming74EncodeTable[crc1 &0xf]; + } + + number_of_bits_sent[chan] = 0; if (il2p_get_debug() >= 1) { @@ -4366,7 +4518,7 @@ string * fill_il2p_data(int snd_ch, string * data) // Call il2p_send_frame to build the bit stream pp->frame_len = data->Length - 2; // Included CRC - memcpy(pp->frame_data, data->Data, data->Length); + memcpy(pp->frame_data, data->Data, data->Length); // Copy the crc in case we are going to send it result = il2p_send_frame(snd_ch, pp, 1, 0); diff --git a/il2p.c.bak b/il2p.c.bak deleted file mode 100644 index 2c81201..0000000 --- a/il2p.c.bak +++ /dev/null @@ -1,4502 +0,0 @@ -/* -Copyright (C) 2019-2020 Andrei Kopanchuk UZ7HO - -This file is part of QtSoundModem - -QtSoundModem 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 3 of the License, or -(at your option) any later version. - -QtSoundModem 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 QtSoundModem. If not, see http://www.gnu.org/licenses - -*/ - -// UZ7HO Soundmodem Port by John Wiseman G8BPQ - -// IL2P code. Based on Direwolf code, under the following copyright - -// -// Copyright (C) 2021 John Langner, WB2OSZ -// -// This program 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. -// -// This program 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 this program. If not, see . -// - - -// IP2P receive code (il2p_rec_bit) is called from the bit receiving code in ax25_demod.c, so includes parallel decoders - - - - -#include "UZ7HOStuff.h" - -void Debugprintf(const char * format, ...); - -#define MAX_ADEVS 3 - -#define MAX_RADIO_CHANS ((MAX_ADEVS) * 2) - -#define MAX_CHANS MAX_RADIO_CHANS // TODO: Replace all former with latter to avoid confusion with following. - -#define MAX_TOTAL_CHANS 16 // v1.7 allows additional virtual channels which are connected - // to something other than radio modems. - // Total maximum channels is based on the 4 bit KISS field. - // Someone with very unusual requirements could increase this and - // use only the AGW network protocol. - - -#define MAX_SUBCHANS 9 - -#define MAX_SLICERS 9 - -#define max(x, y) ((x) > (y) ? (x) : (y)) -#define min(x, y) ((x) < (y) ? (x) : (y)) - -/* For option to try fixing frames with bad CRC. */ - -typedef enum retry_e { - RETRY_NONE = 0, - RETRY_INVERT_SINGLE = 1, - RETRY_INVERT_DOUBLE = 2, - RETRY_INVERT_TRIPLE = 3, - RETRY_INVERT_TWO_SEP = 4, - RETRY_MAX = 5 -} retry_t; - -typedef struct alevel_s { - int rec; - int mark; - int space; - //float ms_ratio; // TODO: take out after temporary investigation. -} alevel_t; - - -alevel_t demod_get_audio_level(int chan, int subchan); -void tone_gen_put_bit(int chan, int dat); - -int ax25memdebug = 1; - -// Code to try to determine centre freq - -float MagOut[4096]; -float MaxMagOut = 0; -int MaxMagIndex = 0; - -// FFT Bin Size is 12000 / FFTSize - -#ifndef FX25_H -#define FX25_H - -#include // for uint64_t - - -/* Reed-Solomon codec control block */ -struct rs { - unsigned int mm; /* Bits per symbol */ - unsigned int nn; /* Symbols per block (= (1<mm) -#define NN (rs->nn) -#define ALPHA_TO (rs->alpha_to) -#define INDEX_OF (rs->index_of) -#define GENPOLY (rs->genpoly) -#define NROOTS (rs->nroots) -#define FCR (rs->fcr) -#define PRIM (rs->prim) -#define IPRIM (rs->iprim) -#define A0 (NN) - -int __builtin_popcountll(unsigned long long int i) -{ - return 0; -} - -int __builtin_popcount(unsigned int n) -{ - unsigned int count = 0; - while (n) - { - count += n & 1; - n >>= 1; - } - return count; -} - -static inline int modnn(struct rs *rs, int x) { - while (x >= rs->nn) { - x -= rs->nn; - x = (x >> rs->mm) + (x & rs->nn); - } - return x; -} - -#define MODNN(x) modnn(rs,x) - - -#define ENCODE_RS encode_rs_char -#define DECODE_RS decode_rs_char -#define INIT_RS init_rs_char -#define FREE_RS free_rs_char - -#define DTYPE unsigned char - -void ENCODE_RS(struct rs *rs, DTYPE *data, DTYPE *bb); - -int DECODE_RS(struct rs *rs, DTYPE *data, int *eras_pos, int no_eras); - -struct rs *INIT_RS(unsigned int symsize, unsigned int gfpoly, - unsigned int fcr, unsigned int prim, unsigned int nroots); - -void FREE_RS(struct rs *rs); - - - -// These 3 are the external interface. -// Maybe these should be in a different file, separated from the internal stuff. - -void fx25_init(int debug_level); -int fx25_send_frame(int chan, unsigned char *fbuf, int flen, int fx_mode); -void fx25_rec_bit(int chan, int subchan, int slice, int dbit); -int fx25_rec_busy(int chan); - - -// Other functions in fx25_init.c. - -struct rs *fx25_get_rs(int ctag_num); -uint64_t fx25_get_ctag_value(int ctag_num); -int fx25_get_k_data_radio(int ctag_num); -int fx25_get_k_data_rs(int ctag_num); -int fx25_get_nroots(int ctag_num); -int fx25_get_debug(void); -int fx25_tag_find_match(uint64_t t); -int fx25_pick_mode(int fx_mode, int dlen); - -void fx_hex_dump(unsigned char *x, int len); - -/*------------------------------------------------------------------- - * - * Name: ax25_pad.h - * - * Purpose: Header file for using ax25_pad.c - * - *------------------------------------------------------------------*/ - -#ifndef AX25_PAD_H -#define AX25_PAD_H 1 - - -#define AX25_MAX_REPEATERS 8 -#define AX25_MIN_ADDRS 2 /* Destination & Source. */ -#define AX25_MAX_ADDRS 10 /* Destination, Source, 8 digipeaters. */ - -#define AX25_DESTINATION 0 /* Address positions in frame. */ -#define AX25_SOURCE 1 -#define AX25_REPEATER_1 2 -#define AX25_REPEATER_2 3 -#define AX25_REPEATER_3 4 -#define AX25_REPEATER_4 5 -#define AX25_REPEATER_5 6 -#define AX25_REPEATER_6 7 -#define AX25_REPEATER_7 8 -#define AX25_REPEATER_8 9 - -#define AX25_MAX_ADDR_LEN 12 /* In theory, you would expect the maximum length */ - /* to be 6 letters, dash, 2 digits, and nul for a */ - /* total of 10. However, object labels can be 10 */ - /* characters so throw in a couple extra bytes */ - /* to be safe. */ - -#define AX25_MIN_INFO_LEN 0 /* Previously 1 when considering only APRS. */ - -#define AX25_MAX_INFO_LEN 2048 /* Maximum size for APRS. */ - /* AX.25 starts out with 256 as the default max */ - /* length but the end stations can negotiate */ - /* something different. */ - /* version 0.8: Change from 256 to 2028 to */ - /* handle the larger paclen for Linux AX25. */ - - /* These don't include the 2 bytes for the */ - /* HDLC frame FCS. */ - -/* - * Previously, for APRS only. - * #define AX25_MIN_PACKET_LEN ( 2 * 7 + 2 + AX25_MIN_INFO_LEN) - * #define AX25_MAX_PACKET_LEN ( AX25_MAX_ADDRS * 7 + 2 + AX25_MAX_INFO_LEN) - */ - - /* The more general case. */ - /* An AX.25 frame can have a control byte and no protocol. */ - -#define AX25_MIN_PACKET_LEN ( 2 * 7 + 1 ) - -#define AX25_MAX_PACKET_LEN ( AX25_MAX_ADDRS * 7 + 2 + 3 + AX25_MAX_INFO_LEN) - - -/* - * packet_t is a pointer to a packet object. - * - * The actual implementation is not visible outside ax25_pad.c. - */ - -#define AX25_UI_FRAME 3 /* Control field value. */ - -#define AX25_PID_NO_LAYER_3 0xf0 /* protocol ID used for APRS */ -#define AX25_PID_SEGMENTATION_FRAGMENT 0x08 -#define AX25_PID_ESCAPE_CHARACTER 0xff - -struct packet_s { - - int magic1; /* for error checking. */ - - int seq; /* unique sequence number for debugging. */ - - double release_time; /* Time stamp in format returned by dtime_now(). */ - /* When to release from the SATgate mode delay queue. */ - -#define MAGIC 0x41583235 - - struct packet_s *nextp; /* Pointer to next in queue. */ - - int num_addr; /* Number of addresses in frame. */ - /* Range of AX25_MIN_ADDRS .. AX25_MAX_ADDRS for AX.25. */ - /* It will be 0 if it doesn't look like AX.25. */ - /* -1 is used temporarily at allocation to mean */ - /* not determined yet. */ - - - - /* - * The 7th octet of each address contains: - * - * Bits: H R R SSID 0 - * - * H for digipeaters set to 0 initially. - * Changed to 1 when position has been used. - * - * for source & destination it is called - * command/response. Normally both 1 for APRS. - * They should be opposites for connected mode. - * - * R R Reserved. Normally set to 1 1. - * - * SSID Substation ID. Range of 0 - 15. - * - * 0 Usually 0 but 1 for last address. - */ - - -#define SSID_H_MASK 0x80 -#define SSID_H_SHIFT 7 - -#define SSID_RR_MASK 0x60 -#define SSID_RR_SHIFT 5 - -#define SSID_SSID_MASK 0x1e -#define SSID_SSID_SHIFT 1 - -#define SSID_LAST_MASK 0x01 - - - int frame_len; /* Frame length without CRC. */ - - int modulo; /* I & S frames have sequence numbers of either 3 bits (modulo 8) */ - /* or 7 bits (modulo 128). This is conveyed by either 1 or 2 */ - /* control bytes. Unfortunately, we can't determine this by looking */ - /* at an isolated frame. We need to know about the context. If we */ - /* are part of the conversation, we would know. But if we are */ - /* just listening to others, this would be more difficult to determine. */ - - /* For U frames: set to 0 - not applicable */ - /* For I & S frames: 8 or 128 if known. 0 if unknown. */ - - unsigned char frame_data[AX25_MAX_PACKET_LEN + 1]; - /* Raw frame contents, without the CRC. */ - - - int magic2; /* Will get stomped on if above overflows. */ -}; - - - -typedef struct packet_s *packet_t; - -typedef enum cmdres_e { cr_00 = 2, cr_cmd = 1, cr_res = 0, cr_11 = 3 } cmdres_t; - - -extern packet_t ax25_new(void); - - -#ifdef AX25_PAD_C /* Keep this hidden - implementation could change. */ - - -/* - * APRS always has one control octet of 0x03 but the more - * general AX.25 case is one or two control bytes depending on - * whether "modulo 128 operation" is in effect. - */ - - //#define DEBUGX 1 - -static inline int ax25_get_control_offset(packet_t this_p) -{ - return (this_p->num_addr * 7); -} - -static inline int ax25_get_num_control(packet_t this_p) -{ - int c; - - c = this_p->frame_data[ax25_get_control_offset(this_p)]; - - if ((c & 0x01) == 0) { /* I xxxx xxx0 */ -#if DEBUGX - Debugprintf("ax25_get_num_control, %02x is I frame, returns %d\n", c, (this_p->modulo == 128) ? 2 : 1); -#endif - return ((this_p->modulo == 128) ? 2 : 1); - } - - if ((c & 0x03) == 1) { /* S xxxx xx01 */ -#if DEBUGX - Debugprintf("ax25_get_num_control, %02x is S frame, returns %d\n", c, (this_p->modulo == 128) ? 2 : 1); -#endif - return ((this_p->modulo == 128) ? 2 : 1); - } - -#if DEBUGX - Debugprintf("ax25_get_num_control, %02x is U frame, always returns 1.\n", c); -#endif - - return (1); /* U xxxx xx11 */ -} - - - -/* - * APRS always has one protocol octet of 0xF0 meaning no level 3 - * protocol but the more general case is 0, 1 or 2 protocol ID octets. - */ - -static inline int ax25_get_pid_offset(packet_t this_p) -{ - return (ax25_get_control_offset(this_p) + ax25_get_num_control(this_p)); -} - -static int ax25_get_num_pid(packet_t this_p) -{ - int c; - int pid; - - c = this_p->frame_data[ax25_get_control_offset(this_p)]; - - if ((c & 0x01) == 0 || /* I xxxx xxx0 */ - c == 0x03 || c == 0x13) { /* UI 000x 0011 */ - - pid = this_p->frame_data[ax25_get_pid_offset(this_p)]; -#if DEBUGX - Debugprintf("ax25_get_num_pid, %02x is I or UI frame, pid = %02x, returns %d\n", c, pid, (pid == AX25_PID_ESCAPE_CHARACTER) ? 2 : 1); -#endif - if (pid == AX25_PID_ESCAPE_CHARACTER) { - return (2); /* pid 1111 1111 means another follows. */ - } - return (1); - } -#if DEBUGX - Debugprintf("ax25_get_num_pid, %02x is neither I nor UI frame, returns 0\n", c); -#endif - return (0); -} - - -/* - * AX.25 has info field for 5 frame types depending on the control field. - * - * xxxx xxx0 I - * 000x 0011 UI (which includes APRS) - * 101x 1111 XID - * 111x 0011 TEST - * 100x 0111 FRMR - * - * APRS always has an Information field with at least one octet for the Data Type Indicator. - */ - -static inline int ax25_get_info_offset(packet_t this_p) -{ - int offset = ax25_get_control_offset(this_p) + ax25_get_num_control(this_p) + ax25_get_num_pid(this_p); -#if DEBUGX - Debugprintf("ax25_get_info_offset, returns %d\n", offset); -#endif - return (offset); -} - -static inline int ax25_get_num_info(packet_t this_p) -{ - int len; - - /* assuming AX.25 frame. */ - - len = this_p->frame_len - this_p->num_addr * 7 - ax25_get_num_control(this_p) - ax25_get_num_pid(this_p); - if (len < 0) { - len = 0; /* print error? */ - } - - return (len); -} - -#endif - - -typedef enum ax25_modulo_e { modulo_unknown = 0, modulo_8 = 8, modulo_128 = 128 } ax25_modulo_t; - -typedef enum ax25_frame_type_e { - - frame_type_I = 0, // Information - - frame_type_S_RR, // Receive Ready - System Ready To Receive - frame_type_S_RNR, // Receive Not Ready - TNC Buffer Full - frame_type_S_REJ, // Reject Frame - Out of Sequence or Duplicate - frame_type_S_SREJ, // Selective Reject - Request single frame repeat - - frame_type_U_SABME, // Set Async Balanced Mode, Extended - frame_type_U_SABM, // Set Async Balanced Mode - frame_type_U_DISC, // Disconnect - frame_type_U_DM, // Disconnect Mode - frame_type_U_UA, // Unnumbered Acknowledge - frame_type_U_FRMR, // Frame Reject - frame_type_U_UI, // Unnumbered Information - frame_type_U_XID, // Exchange Identification - frame_type_U_TEST, // Test - frame_type_U, // other Unnumbered, not used by AX.25. - - frame_not_AX25 // Could not get control byte from frame. - // This must be last because value plus 1 is - // for the size of an array. - -} ax25_frame_type_t; - - -/* - * Originally this was a single number. - * Let's try something new in version 1.2. - * Also collect AGC values from the mark and space filters. - */ - -#ifndef AXTEST -// TODO: remove this? -#define AX25MEMDEBUG 1 -#endif - - - -extern packet_t ax25_from_text(char *monitor, int strict); - -extern packet_t ax25_from_frame(unsigned char *data, int len, alevel_t alevel); - -extern packet_t ax25_dup(packet_t copy_from); - -extern void ax25_delete(packet_t pp); - - - -extern int ax25_parse_addr(int position, char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard); -extern int ax25_check_addresses(packet_t pp); - -extern packet_t ax25_unwrap_third_party(packet_t from_pp); - -extern void ax25_set_addr(packet_t pp, int, char *); -extern void ax25_insert_addr(packet_t this_p, int n, char *ad); -extern void ax25_remove_addr(packet_t this_p, int n); - -extern int ax25_get_num_addr(packet_t pp); -extern int ax25_get_num_repeaters(packet_t this_p); - -extern void ax25_get_addr_with_ssid(packet_t pp, int n, char *station); -extern void ax25_get_addr_no_ssid(packet_t pp, int n, char *station); - -extern int ax25_get_ssid(packet_t pp, int n); -extern void ax25_set_ssid(packet_t this_p, int n, int ssid); - -extern int ax25_get_h(packet_t pp, int n); - -extern void ax25_set_h(packet_t pp, int n); - -extern int ax25_get_heard(packet_t this_p); - -extern int ax25_get_first_not_repeated(packet_t pp); - -extern int ax25_get_rr(packet_t this_p, int n); - -extern int ax25_get_info(packet_t pp, unsigned char **paddr); -extern void ax25_set_info(packet_t pp, unsigned char *info_ptr, int info_len); -extern int ax25_cut_at_crlf(packet_t this_p); - -extern void ax25_set_nextp(packet_t this_p, packet_t next_p); - -extern int ax25_get_dti(packet_t this_p); - -extern packet_t ax25_get_nextp(packet_t this_p); - -extern void ax25_set_release_time(packet_t this_p, double release_time); -extern double ax25_get_release_time(packet_t this_p); - -extern void ax25_set_modulo(packet_t this_p, int modulo); -extern int ax25_get_modulo(packet_t this_p); - -extern void ax25_format_addrs(packet_t pp, char *); -extern void ax25_format_via_path(packet_t this_p, char *result, size_t result_size); - -extern int ax25_pack(packet_t pp, unsigned char result[AX25_MAX_PACKET_LEN]); - -extern ax25_frame_type_t ax25_frame_type(packet_t this_p, cmdres_t *cr, char *desc, int *pf, int *nr, int *ns); - -extern void ax25_hex_dump(packet_t this_p); - -extern int ax25_is_aprs(packet_t pp); -extern int ax25_is_null_frame(packet_t this_p); - -extern int ax25_get_control(packet_t this_p); -extern int ax25_get_c2(packet_t this_p); - -extern int ax25_get_pid(packet_t this_p); - -extern int ax25_get_frame_len(packet_t this_p); -extern unsigned char *ax25_get_frame_data_ptr(packet_t this_p); - -extern unsigned short ax25_dedupe_crc(packet_t pp); - -extern unsigned short ax25_m_m_crc(packet_t pp); - -extern void ax25_safe_print(char *, int, int ascii_only); - -#define AX25_ALEVEL_TO_TEXT_SIZE 40 // overkill but safe. -extern int ax25_alevel_to_text(alevel_t alevel, char text[AX25_ALEVEL_TO_TEXT_SIZE]); - - -#endif /* AX25_PAD_H */ - -/* end ax25_pad.h */ - - - - -#define CTAG_MIN 0x01 -#define CTAG_MAX 0x0B - -// Maximum sizes of "data" and "check" parts. - -#define FX25_MAX_DATA 239 // i.e. RS(255,239) -#define FX25_MAX_CHECK 64 // e.g. RS(255, 191) -#define FX25_BLOCK_SIZE 255 // Block size always 255 for 8 bit symbols. - -#endif // FX25_H - -#ifndef IL2P_H -#define IL2P_H 1 - - -#define IL2P_PREAMBLE 0x55 - -#define IL2P_SYNC_WORD 0xF15E48 - -#define IL2P_SYNC_WORD_SIZE 3 -#define IL2P_HEADER_SIZE 13 // Does not include 2 parity. -#define IL2P_HEADER_PARITY 2 - -#define IL2P_MAX_PAYLOAD_SIZE 1023 -#define IL2P_MAX_PAYLOAD_BLOCKS 5 -#define IL2P_MAX_PARITY_SYMBOLS 16 // For payload only. -#define IL2P_MAX_ENCODED_PAYLOAD_SIZE (IL2P_MAX_PAYLOAD_SIZE + IL2P_MAX_PAYLOAD_BLOCKS * IL2P_MAX_PARITY_SYMBOLS) - -#define IL2P_MAX_PACKET_SIZE (IL2P_SYNC_WORD_SIZE + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY + IL2P_MAX_ENCODED_PAYLOAD_SIZE) - - -float GuessCentreFreq(int i) -{ - float Freq = 0; - float Start; - float End; - int n; - float Max = 0; - int Index = 0; - - Start = (rx_freq[i] - RCVR[i] * rcvr_offset[i]) / BinSize; - End = (rx_freq[i] + RCVR[i] * rcvr_offset[i]) / BinSize; - - for (n = Start; n <= End; n++) - { - if (MagOut[n] > Max) - { - Max = MagOut[n]; - Index = n; - } - } - - Freq = Index * BinSize; - - return Freq; -} - -/*------------------------------------------------------------------------------ - * - * Name: ax25_new - * - * Purpose: Allocate memory for a new packet object. - * - * Returns: Identifier for a new packet object. - * In the current implementation this happens to be a pointer. - * - *------------------------------------------------------------------------------*/ - -int last_seq_num = 0; -int new_count = 0; -int delete_count = 0; - -packet_t ax25_new(void) -{ - struct packet_s *this_p; - - -#if DEBUG - text_color_set(DW_COLOR_DEBUG); - Debugprintf("ax25_new(): before alloc, new=%d, delete=%d\n", new_count, delete_count); -#endif - - last_seq_num++; - new_count++; - - /* - * check for memory leak. - */ - - // version 1.4 push up the threshold. We could have considerably more with connected mode. - - //if (new_count > delete_count + 100) { - if (new_count > delete_count + 256) { - - Debugprintf("Report to WB2OSZ - Memory leak for packet objects. new=%d, delete=%d\n", new_count, delete_count); -#if AX25MEMDEBUG -#endif - } - - this_p = calloc(sizeof(struct packet_s), (size_t)1); - - if (this_p == NULL) { - Debugprintf("ERROR - can't allocate memory in ax25_new.\n"); - } - -// assert(this_p != NULL); - - this_p->magic1 = MAGIC; - this_p->seq = last_seq_num; - this_p->magic2 = MAGIC; - this_p->num_addr = (-1); - - return (this_p); -} - -/*------------------------------------------------------------------------------ - * - * Name: ax25_delete - * - * Purpose: Destroy a packet object, freeing up memory it was using. - * - *------------------------------------------------------------------------------*/ - -void ax25_delete(packet_t this_p) -{ - if (this_p == NULL) { - Debugprintf("ERROR - NULL pointer passed to ax25_delete.\n"); - return; - } - - delete_count++; - -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - this_p->magic1 = 0; - this_p->magic1 = 0; - - free(this_p); -} - - - - - -/*------------------------------------------------------------------------------ - * - * Name: ax25_s_frame - * - * Purpose: Construct an S frame. - * - * Input: addrs - Array of addresses. - * - * num_addr - Number of addresses, range 2 .. 10. - * - * cr - cr_cmd command frame, cr_res for a response frame. - * - * ftype - One of: - * frame_type_S_RR, // Receive Ready - System Ready To Receive - * frame_type_S_RNR, // Receive Not Ready - TNC Buffer Full - * frame_type_S_REJ, // Reject Frame - Out of Sequence or Duplicate - * frame_type_S_SREJ, // Selective Reject - Request single frame repeat - * - * modulo - 8 or 128. Determines if we have 1 or 2 control bytes. - * - * nr - N(R) field --- describe. - * - * pf - Poll/Final flag. - * - * pinfo - Pointer to data for Info field. Allowed only for SREJ. - * - * info_len - Length for Info field. - * - * - * Returns: Pointer to new packet object. - * - *------------------------------------------------------------------------------*/ - - -packet_t ax25_s_frame(char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int modulo, int nr, int pf, unsigned char *pinfo, int info_len) -{ - packet_t this_p; - unsigned char *p; - int ctrl = 0; - - this_p = ax25_new(); - - if (this_p == NULL) return (NULL); - - if (!set_addrs(this_p, addrs, num_addr, cr)) { - Debugprintf("Internal error in %s: Could not set addresses for S frame.\n", __func__); - ax25_delete(this_p); - return (NULL); - } - - if (modulo != 8 && modulo != 128) { - Debugprintf("Internal error in %s: Invalid modulo %d for S frame.\n", __func__, modulo); - modulo = 8; - } - this_p->modulo = modulo; - - if (nr < 0 || nr >= modulo) { - Debugprintf("Internal error in %s: Invalid N(R) %d for S frame.\n", __func__, nr); - nr &= (modulo - 1); - } - - // Erratum: The AX.25 spec is not clear about whether SREJ should be command, response, or both. - // The underlying X.25 spec clearly says it is response only. Let's go with that. - - if (ftype == frame_type_S_SREJ && cr != cr_res) { - Debugprintf("Internal error in %s: SREJ must be response.\n", __func__); - } - - switch (ftype) { - - case frame_type_S_RR: ctrl = 0x01; break; - case frame_type_S_RNR: ctrl = 0x05; break; - case frame_type_S_REJ: ctrl = 0x09; break; - case frame_type_S_SREJ: ctrl = 0x0d; break; - - default: - Debugprintf("Internal error in %s: Invalid ftype %d for S frame.\n", __func__, ftype); - ax25_delete(this_p); - return (NULL); - break; - } - - p = this_p->frame_data + this_p->frame_len; - - if (modulo == 8) { - if (pf) ctrl |= 0x10; - ctrl |= nr << 5; - *p++ = ctrl; - this_p->frame_len++; - } - else { - *p++ = ctrl; - this_p->frame_len++; - - ctrl = pf & 1; - ctrl |= nr << 1; - *p++ = ctrl; - this_p->frame_len++; - } - - if (ftype == frame_type_S_SREJ) { - if (pinfo != NULL && info_len > 0) { - if (info_len > AX25_MAX_INFO_LEN) { - Debugprintf("Internal error in %s: SREJ frame, Invalid information field length %d.\n", __func__, info_len); - info_len = AX25_MAX_INFO_LEN; - } - memcpy(p, pinfo, info_len); - p += info_len; - this_p->frame_len += info_len; - } - } - else { - if (pinfo != NULL || info_len != 0) { - Debugprintf("Internal error in %s: Info part not allowed for RR, RNR, REJ frame.\n", __func__); - } - } - *p = '\0'; - - - return (this_p); - -} /* end ax25_s_frame */ - - - - - -/*------------------------------------------------------------------------------ - * - * Name: ax25_i_frame - * - * Purpose: Construct an I frame. - * - * Input: addrs - Array of addresses. - * - * num_addr - Number of addresses, range 2 .. 10. - * - * cr - cr_cmd command frame, cr_res for a response frame. - * - * modulo - 8 or 128. - * - * nr - N(R) field --- describe. - * - * ns - N(S) field --- describe. - * - * pf - Poll/Final flag. - * - * pid - Protocol ID. - * Normally 0xf0 meaning no level 3. - * Could be other values for NET/ROM, etc. - * - * pinfo - Pointer to data for Info field. - * - * info_len - Length for Info field. - * - * - * Returns: Pointer to new packet object. - * - *------------------------------------------------------------------------------*/ - -packet_t ax25_i_frame(char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, int modulo, int nr, int ns, int pf, int pid, unsigned char *pinfo, int info_len) -{ - packet_t this_p; - unsigned char *p; - int ctrl = 0; - - this_p = ax25_new(); - - if (this_p == NULL) return (NULL); - - if (!set_addrs(this_p, addrs, num_addr, cr)) { - Debugprintf("Internal error in %s: Could not set addresses for I frame.\n", __func__); - ax25_delete(this_p); - return (NULL); - } - - if (modulo != 8 && modulo != 128) { - Debugprintf("Internal error in %s: Invalid modulo %d for I frame.\n", __func__, modulo); - modulo = 8; - } - this_p->modulo = modulo; - - if (nr < 0 || nr >= modulo) { - Debugprintf("Internal error in %s: Invalid N(R) %d for I frame.\n", __func__, nr); - nr &= (modulo - 1); - } - - if (ns < 0 || ns >= modulo) { - Debugprintf("Internal error in %s: Invalid N(S) %d for I frame.\n", __func__, ns); - ns &= (modulo - 1); - } - - p = this_p->frame_data + this_p->frame_len; - - if (modulo == 8) { - ctrl = (nr << 5) | (ns << 1); - if (pf) ctrl |= 0x10; - *p++ = ctrl; - this_p->frame_len++; - } - else { - ctrl = ns << 1; - *p++ = ctrl; - this_p->frame_len++; - - ctrl = nr << 1; - if (pf) ctrl |= 0x01; - *p++ = ctrl; - this_p->frame_len++; - } - - // Definitely don't want pid value of 0 (not in valid list) - // or 0xff (which means more bytes follow). - - if (pid < 0 || pid == 0 || pid == 0xff) { - Debugprintf("Warning: Client application provided invalid PID value, 0x%02x, for I frame.\n", pid); - pid = AX25_PID_NO_LAYER_3; - } - *p++ = pid; - this_p->frame_len++; - - if (pinfo != NULL && info_len > 0) { - if (info_len > AX25_MAX_INFO_LEN) { - Debugprintf("Internal error in %s: I frame, Invalid information field length %d.\n", __func__, info_len); - info_len = AX25_MAX_INFO_LEN; - } - memcpy(p, pinfo, info_len); - p += info_len; - this_p->frame_len += info_len; - } - - *p = '\0'; - - - return (this_p); - -} /* end ax25_i_frame */ - - - - - -extern TStringList detect_list[5]; -extern TStringList detect_list_c[5]; - -void multi_modem_process_rec_packet(int snd_ch, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, int is_fx25, int emph, int centreFreq) -{ - // Convert to QtSM internal format - - struct TDetector_t * pDET = &DET[emph][subchan]; - string * data = newString(); - char Mode[16] = "IL2P"; - - sprintf(Mode, "IL2P %d", centreFreq); - - stringAdd(data, pp->frame_data, pp->frame_len + 2); // QTSM assumes a CRC - - ax25_delete(pp); - - if (retries) - { - pDET->rx_decoded = decodedFEC; - pDET->emph_decoded = decodedFEC; - pDET->errors = retries; - } - else - { - pDET->rx_decoded = decodedNormal; - pDET->emph_decoded = decodedNormal; - pDET->errors = 0; - } - - if (detect_list[snd_ch].Count > 0 && - my_indexof(&detect_list[snd_ch], data) >= 0) - { - // Already have a copy of this frame - - freeString(data); - Debugprintf("Discarding copy rcvr %d emph %d", subchan, 0); - return; - } - - string * xx = newString(); - memset(xx->Data, 0, 16); - - Add(&detect_list_c[snd_ch], xx); - Add(&detect_list[snd_ch], data); - -// if (retries) -// sprintf(Mode, "IP2P-%d", retries); - - stringAdd(xx, Mode, strlen(Mode)); - return; - -} - - - - -alevel_t demod_get_audio_level(int chan, int subchan) -{ - alevel_t alevel; - alevel.rec = 0; - alevel.mark = 0; - alevel.space = 0; - return (alevel); -} - -void ax25_hex_dump(packet_t this_p) -{} - - -/*------------------------------------------------------------------------------ - * - * Name: ax25_from_frame - * - * Purpose: Split apart an HDLC frame to components. - * - * Inputs: fbuf - Pointer to beginning of frame. - * - * flen - Length excluding the two FCS bytes. - * - * alevel - Audio level of received signal. - * Maximum range 0 - 100. - * -1 might be used when not applicable. - * - * Returns: Pointer to new packet object or NULL if error. - * - * Outputs: Use the "get" functions to retrieve information in different ways. - * - *------------------------------------------------------------------------------*/ - - -packet_t ax25_from_frame(unsigned char *fbuf, int flen, alevel_t alevel) -{ - packet_t this_p; - - - /* - * First make sure we have an acceptable length: - * - * We are not concerned with the FCS (CRC) because someone else checked it. - * - * Is is possible to have zero length for info? - * - * In the original version, assuming APRS, the answer was no. - * We always had at least 3 octets after the address part: - * control, protocol, and first byte of info part for data type. - * - * In later versions, this restriction was relaxed so other - * variations of AX.25 could be used. Now the minimum length - * is 7+7 for addresses plus 1 for control. - * - */ - - - if (flen < AX25_MIN_PACKET_LEN || flen > AX25_MAX_PACKET_LEN) - { - Debugprintf("Frame length %d not in allowable range of %d to %d.", flen, AX25_MIN_PACKET_LEN, AX25_MAX_PACKET_LEN); - return (NULL); - } - - this_p = ax25_new(); - - /* Copy the whole thing intact. */ - - memcpy(this_p->frame_data, fbuf, flen); - this_p->frame_data[flen] = 0; - this_p->frame_len = flen; - - /* Find number of addresses. */ - - this_p->num_addr = (-1); - (void)ax25_get_num_addr(this_p); - - return (this_p); -} - - - -/*------------------------------------------------------------------------------ - * - * Name: ax25_get_num_addr - * - * Purpose: Return number of addresses in current packet. - * - * Assumption: ax25_from_text or ax25_from_frame was called first. - * - * Returns: Number of addresses in the current packet. - * Should be in the range of 2 .. AX25_MAX_ADDRS. - * - * Version 0.9: Could be zero for a non AX.25 frame in KISS mode. - * - *------------------------------------------------------------------------------*/ - -int ax25_get_num_addr(packet_t this_p) -{ - //unsigned char *pf; - int a; - int addr_bytes; - - -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - /* Use cached value if already set. */ - - if (this_p->num_addr >= 0) { - return (this_p->num_addr); - } - - /* Otherwise, determine the number ofaddresses. */ - - this_p->num_addr = 0; /* Number of addresses extracted. */ - - addr_bytes = 0; - for (a = 0; a < this_p->frame_len && addr_bytes == 0; a++) { - if (this_p->frame_data[a] & SSID_LAST_MASK) { - addr_bytes = a + 1; - } - } - - if (addr_bytes % 7 == 0) { - int addrs = addr_bytes / 7; - if (addrs >= AX25_MIN_ADDRS && addrs <= AX25_MAX_ADDRS) { - this_p->num_addr = addrs; - } - } - - return (this_p->num_addr); -} - - - -void ax25_get_addr_with_ssid(packet_t pp, int n, char *station) -{} - -/*------------------------------------------------------------------------------ - * - * Name: ax25_get_addr_no_ssid - * - * Purpose: Return specified address WITHOUT any SSID. - * - * Inputs: n - Index of address. Use the symbols - * AX25_DESTINATION, AX25_SOURCE, AX25_REPEATER1, etc. - * - * Outputs: station - String representation of the station, WITHOUT the SSID. - * e.g. "WB2OSZ" - * Usually variables will be AX25_MAX_ADDR_LEN bytes - * but 7 would be adequate. - * - * Bugs: No bounds checking is performed. Be careful. - * - * Assumption: ax25_from_text or ax25_from_frame was called first. - * - * Returns: Character string in usual human readable format, - * - * - *------------------------------------------------------------------------------*/ - -void ax25_get_addr_no_ssid(packet_t this_p, int n, char *station) -{ - int i; - - //assert(this_p->magic1 == MAGIC); - //assert(this_p->magic2 == MAGIC); - - - if (n < 0) { - Debugprintf("Internal error detected in ax25_get_addr_no_ssid, %s, line %d.\n", __FILE__, __LINE__); - Debugprintf("Address index, %d, is less than zero.\n", n); - strcpy(station, "??????"); - return; - } - - if (n >= this_p->num_addr) { - Debugprintf("Internal error detected in ax25_get_no_with_ssid, %s, line %d.\n", __FILE__, __LINE__); - Debugprintf("Address index, %d, is too large for number of addresses, %d.\n", n, this_p->num_addr); - strcpy(station, "??????"); - return; - } - - // At one time this would stop at the first space, on the assumption we would have only trailing spaces. - // Then there was a forum discussion where someone encountered the address " WIDE2" with a leading space. - // In that case, we would have returned a zero length string here. - // Now we return exactly what is in the address field and trim trailing spaces. - // This will provide better information for troubleshooting. - - for (i = 0; i < 6; i++) { - station[i] = (this_p->frame_data[n * 7 + i] >> 1) & 0x7f; - } - station[6] = '\0'; - - for (i = 5; i >= 0; i--) { - if (station[i] == ' ') - station[i] = '\0'; - else - break; - } - - if (strlen(station) == 0) { - Debugprintf("Station address, in position %d, is empty! This is not a valid AX.25 frame.\n", n); - } - -} /* end ax25_get_addr_no_ssid */ - - -/*------------------------------------------------------------------------------ - * - * Name: ax25_get_ssid - * - * Purpose: Return SSID of specified address in current packet. - * - * Inputs: n - Index of address. Use the symbols - * AX25_DESTINATION, AX25_SOURCE, AX25_REPEATER1, etc. - * - * Assumption: ax25_from_text or ax25_from_frame was called first. - * - * Returns: Substation id, as integer 0 .. 15. - * - *------------------------------------------------------------------------------*/ - -int ax25_get_ssid(packet_t this_p, int n) -{ - -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - if (n >= 0 && n < this_p->num_addr) { - return ((this_p->frame_data[n * 7 + 6] & SSID_SSID_MASK) >> SSID_SSID_SHIFT); - } - else { - Debugprintf("Internal error: ax25_get_ssid(%d), num_addr=%d\n", n, this_p->num_addr); - return (0); - } -} - - - -static inline int ax25_get_pid_offset(packet_t this_p) -{ - return (ax25_get_control_offset(this_p) + ax25_get_num_control(this_p)); -} - -static int ax25_get_num_pid(packet_t this_p) -{ - int c; - int pid; - - c = this_p->frame_data[ax25_get_control_offset(this_p)]; - - if ((c & 0x01) == 0 || /* I xxxx xxx0 */ - c == 0x03 || c == 0x13) { /* UI 000x 0011 */ - - pid = this_p->frame_data[ax25_get_pid_offset(this_p)]; - if (pid == AX25_PID_ESCAPE_CHARACTER) { - return (2); /* pid 1111 1111 means another follows. */ - } - return (1); - } - return (0); -} - - -inline int ax25_get_control_offset(packet_t this_p) -{ - return (this_p->num_addr * 7); -} - -inline int ax25_get_num_control(packet_t this_p) -{ - int c; - - c = this_p->frame_data[ax25_get_control_offset(this_p)]; - - if ((c & 0x01) == 0) { /* I xxxx xxx0 */ - return ((this_p->modulo == 128) ? 2 : 1); - } - - if ((c & 0x03) == 1) { /* S xxxx xx01 */ - return ((this_p->modulo == 128) ? 2 : 1); - } - - return (1); /* U xxxx xx11 */ -} - - - - -int ax25_get_info_offset(packet_t this_p) -{ - int offset = ax25_get_control_offset(this_p) + ax25_get_num_control(this_p) + ax25_get_num_pid(this_p); - return (offset); -} - -int ax25_get_num_info(packet_t this_p) -{ - int len; - - /* assuming AX.25 frame. */ - - len = this_p->frame_len - this_p->num_addr * 7 - ax25_get_num_control(this_p) - ax25_get_num_pid(this_p); - if (len < 0) { - len = 0; /* print error? */ - } - - return (len); -} - - - - - - /*------------------------------------------------------------------------------ - * - * Name: ax25_get_info - * - * Purpose: Obtain Information part of current packet. - * - * Inputs: this_p - Packet object pointer. - * - * Outputs: paddr - Starting address of information part is returned here. - * - * Assumption: ax25_from_text or ax25_from_frame was called first. - * - * Returns: Number of octets in the Information part. - * Should be in the range of AX25_MIN_INFO_LEN .. AX25_MAX_INFO_LEN. - * - *------------------------------------------------------------------------------*/ - -int ax25_get_info(packet_t this_p, unsigned char **paddr) -{ - unsigned char *info_ptr; - int info_len; - - - //assert(this_p->magic1 == MAGIC); - //assert(this_p->magic2 == MAGIC); - - if (this_p->num_addr >= 2) { - - /* AX.25 */ - - info_ptr = this_p->frame_data + ax25_get_info_offset(this_p); - info_len = ax25_get_num_info(this_p); - } - else { - - /* Not AX.25. Treat Whole packet as info. */ - - info_ptr = this_p->frame_data; - info_len = this_p->frame_len; - } - - /* Add nul character in case caller treats as printable string. */ - -// assert(info_len >= 0); - - info_ptr[info_len] = '\0'; - - *paddr = info_ptr; - return (info_len); - -} /* end ax25_get_info */ - - - - -void ax25_set_info(packet_t this_p, unsigned char *new_info_ptr, int new_info_len) -{ - unsigned char *old_info_ptr; - int old_info_len = ax25_get_info(this_p, &old_info_ptr); - this_p->frame_len -= old_info_len; - - if (new_info_len < 0) new_info_len = 0; - if (new_info_len > AX25_MAX_INFO_LEN) new_info_len = AX25_MAX_INFO_LEN; - memcpy(old_info_ptr, new_info_ptr, new_info_len); - this_p->frame_len += new_info_len; -} - -int ax25_get_pid(packet_t this_p) -{ -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - // TODO: handle 2 control byte case. - // TODO: sanity check: is it I or UI frame? - - if (this_p->frame_len == 0) return(-1); - - if (this_p->num_addr >= 2) { - return (this_p->frame_data[ax25_get_pid_offset(this_p)]); - } - return (-1); -} - - -int ax25_get_frame_len(packet_t this_p) -{ -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - -// assert(this_p->frame_len >= 0 && this_p->frame_len <= AX25_MAX_PACKET_LEN); - - return (this_p->frame_len); - -} /* end ax25_get_frame_len */ - - -unsigned char *ax25_get_frame_data_ptr(packet_t this_p) -{ -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - return (this_p->frame_data); - -} /* end ax25_get_frame_data_ptr */ - - -int ax25_get_modulo(packet_t this_p) -{ - return 7; -} - - -/*------------------------------------------------------------------ - * - * Function: ax25_get_control - ax25_get_c2 - * - * Purpose: Get Control field from packet. - * - * Inputs: this_p - pointer to packet object. - * - * Returns: APRS uses AX25_UI_FRAME. - * This could also be used in other situations. - * - *------------------------------------------------------------------*/ - - -int ax25_get_control(packet_t this_p) -{ -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - if (this_p->frame_len == 0) return(-1); - - if (this_p->num_addr >= 2) { - return (this_p->frame_data[ax25_get_control_offset(this_p)]); - } - return (-1); -} - - -/*------------------------------------------------------------------ -* -* Function: ax25_frame_type -* -* Purpose : Extract the type of frame. -* This is derived from the control byte(s) but -* is an enumerated type for easier handling. -* -* Inputs : this_p - pointer to packet object. -* -* Outputs : desc - Text description such as "I frame" or -*"U frame SABME". -* Supply 56 bytes to be safe. -* -* cr - Command or response ? -* -* pf - P / F - Poll / Final or -1 if not applicable -* -* nr - N(R) - receive sequence or -1 if not applicable. -* -* ns - N(S) - send sequence or -1 if not applicable. -* -* Returns: Frame type from enum ax25_frame_type_e. -* -*------------------------------------------------------------------*/ - -// TODO: need someway to ensure caller allocated enough space. -// Should pass in as parameter. - -#define DESC_SIZ 56 - - -ax25_frame_type_t ax25_frame_type(packet_t this_p, cmdres_t *cr, char *desc, int *pf, int *nr, int *ns) -{ - int c; // U frames are always one control byte. - int c2 = 0; // I & S frames can have second Control byte. - -// assert(this_p->magic1 == MAGIC); -// assert(this_p->magic2 == MAGIC); - - - strcpy(desc, "????"); - *cr = cr_11; - *pf = -1; - *nr = -1; - *ns = -1; - - c = ax25_get_control(this_p); - if (c < 0) { - strcpy(desc, "Not AX.25"); - return (frame_not_AX25); - } - - /* - * TERRIBLE HACK :-( for display purposes. - * - * I and S frames can have 1 or 2 control bytes but there is - * no good way to determine this without dipping into the data - * link state machine. Can we guess? - * - * S frames have no protocol id or information so if there is one - * more byte beyond the control field, we could assume there are - * two control bytes. - * - * For I frames, the protocol id will usually be 0xf0. If we find - * that as the first byte of the information field, it is probably - * the pid and not part of the information. Ditto for segments 0x08. - * Not fool proof but good enough for troubleshooting text out. - * - * If we have a link to the peer station, this will be set properly - * before it needs to be used for other reasons. - * - * Setting one of the RR bits (find reference!) is sounding better and better. - * It's in common usage so I should lobby to get that in the official protocol spec. - */ - - // Dont support mod 128 -/* - if (this_p->modulo == 0 && (c & 3) == 1 && ax25_get_c2(this_p) != -1) { - this_p->modulo = modulo_128; - } - else if (this_p->modulo == 0 && (c & 1) == 0 && this_p->frame_data[ax25_get_info_offset(this_p)] == 0xF0) { - this_p->modulo = modulo_128; - } - else if (this_p->modulo == 0 && (c & 1) == 0 && this_p->frame_data[ax25_get_info_offset(this_p)] == 0x08) { // same for segments - this_p->modulo = modulo_128; - } - - - if (this_p->modulo == modulo_128) { - c2 = ax25_get_c2(this_p); - } -*/ - - int dst_c = this_p->frame_data[AX25_DESTINATION * 7 + 6] & SSID_H_MASK; - int src_c = this_p->frame_data[AX25_SOURCE * 7 + 6] & SSID_H_MASK; - - char cr_text[8]; - char pf_text[8]; - - if (dst_c) { - if (src_c) { *cr = cr_11; strcpy(cr_text, "cc=11"); strcpy(pf_text, "p/f"); } - else { *cr = cr_cmd; strcpy(cr_text, "cmd"); strcpy(pf_text, "p"); } - } - else { - if (src_c) { *cr = cr_res; strcpy(cr_text, "res"); strcpy(pf_text, "f"); } - else { *cr = cr_00; strcpy(cr_text, "cc=00"); strcpy(pf_text, "p/f"); } - } - - if ((c & 1) == 0) { - - // Information rrr p sss 0 or sssssss 0 rrrrrrr p - - if (this_p->modulo == modulo_128) { - *ns = (c >> 1) & 0x7f; - *pf = c2 & 1; - *nr = (c2 >> 1) & 0x7f; - } - else { - *ns = (c >> 1) & 7; - *pf = (c >> 4) & 1; - *nr = (c >> 5) & 7; - } - - //snprintf (desc, DESC_SIZ, "I %s, n(s)=%d, n(r)=%d, %s=%d", cr_text, *ns, *nr, pf_text, *pf); - sprintf(desc, "I %s, n(s)=%d, n(r)=%d, %s=%d, pid=0x%02x", cr_text, *ns, *nr, pf_text, *pf, ax25_get_pid(this_p)); - return (frame_type_I); - } - else if ((c & 2) == 0) { - - // Supervisory rrr p/f ss 0 1 or 0000 ss 0 1 rrrrrrr p/f - - if (this_p->modulo == modulo_128) { - *pf = c2 & 1; - *nr = (c2 >> 1) & 0x7f; - } - else { - *pf = (c >> 4) & 1; - *nr = (c >> 5) & 7; - } - - - switch ((c >> 2) & 3) { - case 0: sprintf(desc, "RR %s, n(r)=%d, %s=%d", cr_text, *nr, pf_text, *pf); return (frame_type_S_RR); break; - case 1: sprintf(desc, "RNR %s, n(r)=%d, %s=%d", cr_text, *nr, pf_text, *pf); return (frame_type_S_RNR); break; - case 2: sprintf(desc, "REJ %s, n(r)=%d, %s=%d", cr_text, *nr, pf_text, *pf); return (frame_type_S_REJ); break; - case 3: sprintf(desc, "SREJ %s, n(r)=%d, %s=%d", cr_text, *nr, pf_text, *pf); return (frame_type_S_SREJ); break; - } - } - else { - - // Unnumbered mmm p/f mm 1 1 - - *pf = (c >> 4) & 1; - - switch (c & 0xef) { - - case 0x6f: sprintf(desc, "SABME %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_SABME); break; - case 0x2f: sprintf(desc, "SABM %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_SABM); break; - case 0x43: sprintf(desc, "DISC %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_DISC); break; - case 0x0f: sprintf(desc, "DM %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_DM); break; - case 0x63: sprintf(desc, "UA %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_UA); break; - case 0x87: sprintf(desc, "FRMR %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_FRMR); break; - case 0x03: sprintf(desc, "UI %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_UI); break; - case 0xaf: sprintf(desc, "XID %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_XID); break; - case 0xe3: sprintf(desc, "TEST %s, %s=%d", cr_text, pf_text, *pf); return (frame_type_U_TEST); break; - default: sprintf(desc, "U other???"); return (frame_type_U); break; - } - } - - // Should be unreachable but compiler doesn't realize that. - // Here only to suppress "warning: control reaches end of non-void function" - - return (frame_not_AX25); - -} /* end ax25_frame_type */ - - - -packet_t ax25_u_frame(char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr, ax25_frame_type_t ftype, int pf, int pid, unsigned char *pinfo, int info_len) -{ - packet_t this_p; - unsigned char *p; - int ctrl = 0; - unsigned int t = 999; // 1 = must be cmd, 0 = must be response, 2 = can be either. - int i = 0; // Is Info part allowed? - - this_p = ax25_new(); - - if (this_p == NULL) return (NULL); - - this_p->modulo = 0; - - if (!set_addrs(this_p, addrs, num_addr, cr)) { - Debugprintf("Internal error in %s: Could not set addresses for U frame.\n", __func__); - ax25_delete(this_p); - return (NULL); - } - - switch (ftype) { - // 1 = cmd only, 0 = res only, 2 = either - case frame_type_U_SABME: ctrl = 0x6f; t = 1; break; - case frame_type_U_SABM: ctrl = 0x2f; t = 1; break; - case frame_type_U_DISC: ctrl = 0x43; t = 1; break; - case frame_type_U_DM: ctrl = 0x0f; t = 0; break; - case frame_type_U_UA: ctrl = 0x63; t = 0; break; - case frame_type_U_FRMR: ctrl = 0x87; t = 0; i = 1; break; - case frame_type_U_UI: ctrl = 0x03; t = 2; i = 1; break; - case frame_type_U_XID: ctrl = 0xaf; t = 2; i = 1; break; - case frame_type_U_TEST: ctrl = 0xe3; t = 2; i = 1; break; - - default: - Debugprintf("Internal error in %s: Invalid ftype %d for U frame.\n", __func__, ftype); - ax25_delete(this_p); - return (NULL); - break; - } - if (pf) ctrl |= 0x10; - - if (t != 2) { - if (cr != t) { - Debugprintf("Internal error in %s: U frame, cr is %d but must be %d. ftype=%d\n", __func__, cr, t, ftype); - } - } - - p = this_p->frame_data + this_p->frame_len; - *p++ = ctrl; - this_p->frame_len++; - - if (ftype == frame_type_U_UI) { - - // Definitely don't want pid value of 0 (not in valid list) - // or 0xff (which means more bytes follow). - - if (pid < 0 || pid == 0 || pid == 0xff) { - Debugprintf("Internal error in %s: U frame, Invalid pid value 0x%02x.\n", __func__, pid); - pid = AX25_PID_NO_LAYER_3; - } - *p++ = pid; - this_p->frame_len++; - } - - if (i) { - if (pinfo != NULL && info_len > 0) { - if (info_len > AX25_MAX_INFO_LEN) { - - Debugprintf("Internal error in %s: U frame, Invalid information field length %d.\n", __func__, info_len); - info_len = AX25_MAX_INFO_LEN; - } - memcpy(p, pinfo, info_len); - p += info_len; - this_p->frame_len += info_len; - } - } - else { - if (pinfo != NULL && info_len > 0) { - Debugprintf("Internal error in %s: Info part not allowed for U frame type.\n", __func__); - } - } - *p = '\0'; - - //assert(p == this_p->frame_data + this_p->frame_len); - //assert(this_p->magic1 == MAGIC); - //assert(this_p->magic2 == MAGIC); - -#if PAD2TEST - ax25_frame_type_t check_ftype; - cmdres_t check_cr; - char check_desc[80]; - int check_pf; - int check_nr; - int check_ns; - - check_ftype = ax25_frame_type(this_p, &check_cr, check_desc, &check_pf, &check_nr, &check_ns); - - text_color_set(DW_COLOR_DEBUG); - Debugprintf("check: ftype=%d, desc=\"%s\", pf=%d\n", check_ftype, check_desc, check_pf); - - assert(check_cr == cr); - assert(check_ftype == ftype); - assert(check_pf == pf); - assert(check_nr == -1); - assert(check_ns == -1); - -#endif - - return (this_p); - -} /* end ax25_u_frame */ - - - - - - -static const char *position_name[1 + AX25_MAX_ADDRS] = { - "", "Destination ", "Source ", - "Digi1 ", "Digi2 ", "Digi3 ", "Digi4 ", - "Digi5 ", "Digi6 ", "Digi7 ", "Digi8 " }; - -int ax25_parse_addr(int position, char *in_addr, int strict, char *out_addr, int *out_ssid, int *out_heard) -{ - char *p; - char sstr[8]; /* Should be 1 or 2 digits for SSID. */ - int i, j, k; - int maxlen; - - *out_addr = '\0'; - *out_ssid = 0; - *out_heard = 0; - - // Debugprintf ("ax25_parse_addr in: position=%d, '%s', strict=%d\n", position, in_addr, strict); - - if (position < -1) position = -1; - if (position > AX25_REPEATER_8) position = AX25_REPEATER_8; - position++; /* Adjust for position_name above. */ - - if (strlen(in_addr) == 0) { - Debugprintf("%sAddress \"%s\" is empty.\n", position_name[position], in_addr); - return 0; - } - - if (strict && strlen(in_addr) >= 2 && strncmp(in_addr, "qA", 2) == 0) { - - Debugprintf("%sAddress \"%s\" is a \"q-construct\" used for communicating with\n", position_name[position], in_addr); - Debugprintf("APRS Internet Servers. It should never appear when going over the radio.\n"); - } - - // Debugprintf ("ax25_parse_addr in: %s\n", in_addr); - - maxlen = strict ? 6 : (AX25_MAX_ADDR_LEN - 1); - p = in_addr; - i = 0; - for (p = in_addr; *p != '\0' && *p != '-' && *p != '*'; p++) { - if (i >= maxlen) { - Debugprintf("%sAddress is too long. \"%s\" has more than %d characters.\n", position_name[position], in_addr, maxlen); - return 0; - } - if (!isalnum(*p)) { - Debugprintf("%sAddress, \"%s\" contains character other than letter or digit in character position %d.\n", position_name[position], in_addr, (int)(long)(p - in_addr) + 1); - return 0; - } - - out_addr[i++] = *p; - out_addr[i] = '\0'; - -#if DECAMAIN // Hack when running in decode_aprs utility. - // Exempt the "qA..." case because it was already mentioned. - - if (strict && islower(*p) && strncmp(in_addr, "qA", 2) != 0) { - text_color_set(DW_COLOR_ERROR); - Debugprintf("%sAddress has lower case letters. \"%s\" must be all upper case.\n", position_name[position], in_addr); - } -#else - if (strict && islower(*p)) { - Debugprintf("%sAddress has lower case letters. \"%s\" must be all upper case.\n", position_name[position], in_addr); - return 0; - } -#endif - } - - j = 0; - sstr[j] = '\0'; - if (*p == '-') { - for (p++; isalnum(*p); p++) { - if (j >= 2) { - Debugprintf("%sSSID is too long. SSID part of \"%s\" has more than 2 characters.\n", position_name[position], in_addr); - return 0; - } - sstr[j++] = *p; - sstr[j] = '\0'; - if (strict && !isdigit(*p)) { - Debugprintf("%sSSID must be digits. \"%s\" has letters in SSID.\n", position_name[position], in_addr); - return 0; - } - } - k = atoi(sstr); - if (k < 0 || k > 15) { - Debugprintf("%sSSID out of range. SSID of \"%s\" not in range of 0 to 15.\n", position_name[position], in_addr); - return 0; - } - *out_ssid = k; - } - - if (*p == '*') { - *out_heard = 1; - p++; - if (strict == 2) { - Debugprintf("\"*\" is not allowed at end of address \"%s\" here.\n", in_addr); - return 0; - } - } - - if (*p != '\0') { - Debugprintf("Invalid character \"%c\" found in %saddress \"%s\".\n", *p, position_name[position], in_addr); - return 0; - } - - // Debugprintf ("ax25_parse_addr out: '%s' %d %d\n", out_addr, *out_ssid, *out_heard); - - return (1); - -} /* end ax25_parse_addr */ - - - -int set_addrs(packet_t pp, char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN], int num_addr, cmdres_t cr) -{ - int n; - - //assert(pp->frame_len == 0); - //assert(cr == cr_cmd || cr == cr_res); - - if (num_addr < AX25_MIN_ADDRS || num_addr > AX25_MAX_ADDRS) { - Debugprintf("INTERNAL ERROR: %s %s %d, num_addr = %d\n", __FILE__, __func__, __LINE__, num_addr); - return (0); - } - - for (n = 0; n < num_addr; n++) { - - unsigned char *pa = pp->frame_data + n * 7; - int ok; - int strict = 1; - char oaddr[AX25_MAX_ADDR_LEN]; - int ssid; - int heard; - int j; - - ok = ax25_parse_addr(n, addrs[n], strict, oaddr, &ssid, &heard); - - if (!ok) return (0); - - // Fill in address. - - memset(pa, ' ' << 1, 6); - for (j = 0; oaddr[j]; j++) { - pa[j] = oaddr[j] << 1; - } - pa += 6; - - // Fill in SSID. - - *pa = 0x60 | ((ssid & 0xf) << 1); - - // Command / response flag. - - switch (n) { - case AX25_DESTINATION: - if (cr == cr_cmd) *pa |= 0x80; - break; - case AX25_SOURCE: - if (cr == cr_res) *pa |= 0x80; - break; - default: - break; - } - - // Is this the end of address field? - - if (n == num_addr - 1) { - *pa |= 1; - } - - pp->frame_len += 7; - } - - pp->num_addr = num_addr; - return (1); - -} /* end set_addrs */ - - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_init.c -// -/////////////////////////////////////////////////////////////////////////////// - - -// Init must be called at start of application. - -extern void il2p_init(int debug); - -extern struct rs *il2p_find_rs(int nparity); // Internal later? - -extern void il2p_encode_rs(unsigned char *tx_data, int data_size, int num_parity, unsigned char *parity_out); - -extern int il2p_decode_rs(unsigned char *rec_block, int data_size, int num_parity, unsigned char *out); - -extern int il2p_get_debug(void); -extern void il2p_set_debug(int debug); - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_rec.c -// -/////////////////////////////////////////////////////////////////////////////// - -// Receives a bit stream from demodulator. - -extern void il2p_rec_bit(int chan, int subchan, int slice, int dbit); - - - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_send.c -// -/////////////////////////////////////////////////////////////////////////////// - - -// Send bit stream to modulator. - -string * il2p_send_frame(int chan, packet_t pp, int max_fec, int polarity); - - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_codec.c -// -/////////////////////////////////////////////////////////////////////////////// - - -extern int il2p_encode_frame(packet_t pp, int max_fec, unsigned char *iout); - -packet_t il2p_decode_frame(unsigned char *irec); - -packet_t il2p_decode_header_payload(unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected); - - - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_header.c -// -/////////////////////////////////////////////////////////////////////////////// - - -extern int il2p_type_1_header(packet_t pp, int max_fec, unsigned char *hdr); - -extern packet_t il2p_decode_header_type_1(unsigned char *hdr, int num_sym_changed); - - -extern int il2p_type_0_header(packet_t pp, int max_fec, unsigned char *hdr); - -extern int il2p_clarify_header(unsigned char *rec_hdr, unsigned char *corrected_descrambled_hdr); - - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_scramble.c -// -/////////////////////////////////////////////////////////////////////////////// - -extern void il2p_scramble_block(unsigned char *in, unsigned char *out, int len); - -extern void il2p_descramble_block(unsigned char *in, unsigned char *out, int len); - - -/////////////////////////////////////////////////////////////////////////////// -// -// il2p_payload.c -// -/////////////////////////////////////////////////////////////////////////////// - - -typedef struct { - int payload_byte_count; // Total size, 0 thru 1023 - int payload_block_count; - int small_block_size; - int large_block_size; - int large_block_count; - int small_block_count; - int parity_symbols_per_block; // 2, 4, 6, 8, 16 -} il2p_payload_properties_t; - -extern int il2p_payload_compute(il2p_payload_properties_t *p, int payload_size, int max_fec); - -extern int il2p_encode_payload(unsigned char *payload, int payload_size, int max_fec, unsigned char *enc); - -extern int il2p_decode_payload(unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected); - -extern int il2p_get_header_attributes(unsigned char *hdr, int *hdr_type, int *max_fec); - -#endif - - - -// Interesting related stuff: -// https://www.kernel.org/doc/html/v4.15/core-api/librs.html -// https://berthub.eu/articles/posts/reed-solomon-for-programmers/ - - -#define MAX_NROOTS 16 - -#define NTAB 5 - -static struct { - int symsize; // Symbol size, bits (1-8). Always 8 for this application. - int genpoly; // Field generator polynomial coefficients. - int fcs; // First root of RS code generator polynomial, index form. - // FX.25 uses 1 but IL2P uses 0. - int prim; // Primitive element to generate polynomial roots. - int nroots; // RS code generator polynomial degree (number of roots). - // Same as number of check bytes added. - struct rs *rs; // Pointer to RS codec control block. Filled in at init time. -} Tab[NTAB] = { - {8, 0x11d, 0, 1, 2, NULL }, // 2 parity - {8, 0x11d, 0, 1, 4, NULL }, // 4 parity - {8, 0x11d, 0, 1, 6, NULL }, // 6 parity - {8, 0x11d, 0, 1, 8, NULL }, // 8 parity - {8, 0x11d, 0, 1, 16, NULL }, // 16 parity -}; - - - -static int g_il2p_debug = 0; - - -/*------------------------------------------------------------- - * - * Name: il2p_init - * - * Purpose: This must be called at application start up time. - * It sets up tables for the Reed-Solomon functions. - * - * Inputs: debug - Enable debug output. - * - *--------------------------------------------------------------*/ - -void il2p_init(int il2p_debug) -{ - g_il2p_debug = il2p_debug; - - for (int i = 0; i < NTAB; i++) { - //assert(Tab[i].nroots <= MAX_NROOTS); - Tab[i].rs = INIT_RS(Tab[i].symsize, Tab[i].genpoly, Tab[i].fcs, Tab[i].prim, Tab[i].nroots); - if (Tab[i].rs == NULL) { - Debugprintf("IL2P internal error: init_rs_char failed!\n"); - exit(0); - } - } - -} // end il2p_init - - -int il2p_get_debug(void) -{ - return (g_il2p_debug); -} -void il2p_set_debug(int debug) -{ - g_il2p_debug = debug; -} - - -// Find RS codec control block for specified number of parity symbols. - -struct rs *il2p_find_rs(int nparity) -{ - for (int n = 0; n < NTAB; n++) { - if (Tab[n].nroots == nparity) { - return (Tab[n].rs); - } - } - Debugprintf("IL2P INTERNAL ERROR: il2p_find_rs: control block not found for nparity = %d.\n", nparity); - return (Tab[0].rs); -} - - -/*------------------------------------------------------------- - * - * Name: void il2p_encode_rs - * - * Purpose: Add parity symbols to a block of data. - * - * Inputs: tx_data Header or other data to transmit. - * data_size Number of data bytes in above. - * num_parity Number of parity symbols to add. - * Maximum of IL2P_MAX_PARITY_SYMBOLS. - * - * Outputs: parity_out Specified number of parity symbols - * - * Restriction: data_size + num_parity <= 255 which is the RS block size. - * The caller must ensure this. - * - *--------------------------------------------------------------*/ - -void il2p_encode_rs(unsigned char *tx_data, int data_size, int num_parity, unsigned char *parity_out) -{ - //assert(data_size >= 1); - //assert(num_parity == 2 || num_parity == 4 || num_parity == 6 || num_parity == 8 || num_parity == 16); - //assert(data_size + num_parity <= 255); - - unsigned char rs_block[FX25_BLOCK_SIZE]; - memset(rs_block, 0, sizeof(rs_block)); - memcpy(rs_block + sizeof(rs_block) - data_size - num_parity, tx_data, data_size); - ENCODE_RS(il2p_find_rs(num_parity), rs_block, parity_out); -} - -/*------------------------------------------------------------- - * - * Name: void il2p_decode_rs - * - * Purpose: Check and attempt to fix block with FEC. - * - * Inputs: rec_block Received block composed of data and parity. - * Total size is sum of following two parameters. - * data_size Number of data bytes in above. - * num_parity Number of parity symbols (bytes) in above. - * - * Outputs: out Original with possible corrections applied. - * data_size bytes. - * - * Returns: -1 for unrecoverable. - * >= 0 for success. Number of symbols corrected. - * - *--------------------------------------------------------------*/ - -int il2p_decode_rs(unsigned char *rec_block, int data_size, int num_parity, unsigned char *out) -{ - - // Use zero padding in front if data size is too small. - - int n = data_size + num_parity; // total size in. - - unsigned char rs_block[FX25_BLOCK_SIZE]; - - // We could probably do this more efficiently by skipping the - // processing of the bytes known to be zero. Good enough for now. - - memset(rs_block, 0, sizeof(rs_block) - n); - memcpy(rs_block + sizeof(rs_block) - n, rec_block, n); - - if (il2p_get_debug() >= 3) { - Debugprintf("============================== il2p_decode_rs ==============================\n"); - Debugprintf("%d filler zeros, %d data, %d parity\n", (int)(sizeof(rs_block) - n), data_size, num_parity); - fx_hex_dump(rs_block, sizeof(rs_block)); - } - - int derrlocs[FX25_MAX_CHECK]; // Half would probably be OK. - - int derrors = DECODE_RS(il2p_find_rs(num_parity), rs_block, derrlocs, 0); - memcpy(out, rs_block + sizeof(rs_block) - n, data_size); - - if (il2p_get_debug() >= 3) { - if (derrors == 0) { - Debugprintf("No errors reported for RS block.\n"); - } - else if (derrors > 0) { - Debugprintf("%d errors fixed in positions:\n", derrors); - for (int j = 0; j < derrors; j++) { - Debugprintf(" %3d (0x%02x)\n", derrlocs[j], derrlocs[j]); - } - fx_hex_dump(rs_block, sizeof(rs_block)); - } - } - - // It is possible to have a situation where too many errors are - // present but the algorithm could get a good code block by "fixing" - // one of the padding bytes that should be 0. - - for (int i = 0; i < derrors; i++) { - if (derrlocs[i] < sizeof(rs_block) - n) { - if (il2p_get_debug() >= 3) { - Debugprintf("RS DECODE ERROR! Padding position %d should be 0 but it was set to %02x.\n", derrlocs[i], rs_block[derrlocs[i]]); - } - derrors = -1; - break; - } - } - - if (il2p_get_debug() >= 3) { - Debugprintf("============================== il2p_decode_rs returns %d ==============================\n", derrors); - } - return (derrors); -} - -// end il2p_init.c - - - - - - - - - - - - - -void ENCODE_RS(struct rs * rs, DTYPE * data, DTYPE * bb) -{ - - int i, j; - DTYPE feedback; - - memset(bb, 0, NROOTS * sizeof(DTYPE)); // clear out the FEC data area - - for (i = 0; i < NN - NROOTS; i++) { - feedback = INDEX_OF[data[i] ^ bb[0]]; - if (feedback != A0) { /* feedback term is non-zero */ - for (j = 1; j < NROOTS; j++) - bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS - j])]; - } - /* Shift */ - memmove(&bb[0], &bb[1], sizeof(DTYPE)*(NROOTS - 1)); - if (feedback != A0) - bb[NROOTS - 1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; - else - bb[NROOTS - 1] = 0; - } -} - - - - -int DECODE_RS(struct rs * rs, DTYPE * data, int *eras_pos, int no_eras) { - - int deg_lambda, el, deg_omega; - int i, j, r, k; - DTYPE u, q, tmp, num1, num2, den, discr_r; - // DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly and syndrome poly */ - // DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; - // DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; - DTYPE lambda[FX25_MAX_CHECK + 1], s[FX25_MAX_CHECK]; /* Err+Eras Locator poly and syndrome poly */ - DTYPE b[FX25_MAX_CHECK + 1], t[FX25_MAX_CHECK + 1], omega[FX25_MAX_CHECK + 1]; - DTYPE root[FX25_MAX_CHECK], reg[FX25_MAX_CHECK + 1], loc[FX25_MAX_CHECK]; - int syn_error, count; - - /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ - for (i = 0; i < NROOTS; i++) - s[i] = data[0]; - - for (j = 1; j < NN; j++) { - for (i = 0; i < NROOTS; i++) { - if (s[i] == 0) { - s[i] = data[j]; - } - else { - s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR + i)*PRIM)]; - } - } - } - - /* Convert syndromes to index form, checking for nonzero condition */ - syn_error = 0; - for (i = 0; i < NROOTS; i++) { - syn_error |= s[i]; - s[i] = INDEX_OF[s[i]]; - } - - // fprintf(stderr,"syn_error = %4x\n",syn_error); - if (!syn_error) { - /* if syndrome is zero, data[] is a codeword and there are no - * errors to correct. So return data[] unmodified - */ - count = 0; - goto finish; - } - memset(&lambda[1], 0, NROOTS * sizeof(lambda[0])); - lambda[0] = 1; - - if (no_eras > 0) { - /* Init lambda to be the erasure locator polynomial */ - lambda[1] = ALPHA_TO[MODNN(PRIM*(NN - 1 - eras_pos[0]))]; - for (i = 1; i < no_eras; i++) { - u = MODNN(PRIM*(NN - 1 - eras_pos[i])); - for (j = i + 1; j > 0; j--) { - tmp = INDEX_OF[lambda[j - 1]]; - if (tmp != A0) - lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; - } - } - -#if DEBUG >= 1 - /* Test code that verifies the erasure locator polynomial just constructed - Needed only for decoder debugging. */ - - /* find roots of the erasure location polynomial */ - for (i = 1; i <= no_eras; i++) - reg[i] = INDEX_OF[lambda[i]]; - - count = 0; - for (i = 1, k = IPRIM - 1; i <= NN; i++, k = MODNN(k + IPRIM)) { - q = 1; - for (j = 1; j <= no_eras; j++) - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - if (q != 0) - continue; - /* store root and error location number indices */ - root[count] = i; - loc[count] = k; - count++; - } - if (count != no_eras) { - fprintf(stderr, "count = %d no_eras = %d\n lambda(x) is WRONG\n", count, no_eras); - count = -1; - goto finish; - } -#if DEBUG >= 2 - fprintf(stderr, "\n Erasure positions as determined by roots of Eras Loc Poly:\n"); - for (i = 0; i < count; i++) - fprintf(stderr, "%d ", loc[i]); - fprintf(stderr, "\n"); -#endif -#endif - } - for (i = 0; i < NROOTS + 1; i++) - b[i] = INDEX_OF[lambda[i]]; - - /* - * Begin Berlekamp-Massey algorithm to determine error+erasure - * locator polynomial - */ - r = no_eras; - el = no_eras; - while (++r <= NROOTS) { /* r is the step number */ - /* Compute discrepancy at the r-th step in poly-form */ - discr_r = 0; - for (i = 0; i < r; i++) { - if ((lambda[i] != 0) && (s[r - i - 1] != A0)) { - discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r - i - 1])]; - } - } - discr_r = INDEX_OF[discr_r]; /* Index form */ - if (discr_r == A0) { - /* 2 lines below: B(x) <-- x*B(x) */ - memmove(&b[1], b, NROOTS * sizeof(b[0])); - b[0] = A0; - } - else { - /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ - t[0] = lambda[0]; - for (i = 0; i < NROOTS; i++) { - if (b[i] != A0) - t[i + 1] = lambda[i + 1] ^ ALPHA_TO[MODNN(discr_r + b[i])]; - else - t[i + 1] = lambda[i + 1]; - } - if (2 * el <= r + no_eras - 1) { - el = r + no_eras - el; - /* - * 2 lines below: B(x) <-- inv(discr_r) * - * lambda(x) - */ - for (i = 0; i <= NROOTS; i++) - b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN); - } - else { - /* 2 lines below: B(x) <-- x*B(x) */ - memmove(&b[1], b, NROOTS * sizeof(b[0])); - b[0] = A0; - } - memcpy(lambda, t, (NROOTS + 1) * sizeof(t[0])); - } - } - - /* Convert lambda to index form and compute deg(lambda(x)) */ - deg_lambda = 0; - for (i = 0; i < NROOTS + 1; i++) { - lambda[i] = INDEX_OF[lambda[i]]; - if (lambda[i] != A0) - deg_lambda = i; - } - /* Find roots of the error+erasure locator polynomial by Chien search */ - memcpy(®[1], &lambda[1], NROOTS * sizeof(reg[0])); - count = 0; /* Number of roots of lambda(x) */ - for (i = 1, k = IPRIM - 1; i <= NN; i++, k = MODNN(k + IPRIM)) { - q = 1; /* lambda[0] is always 0 */ - for (j = deg_lambda; j > 0; j--) { - if (reg[j] != A0) { - reg[j] = MODNN(reg[j] + j); - q ^= ALPHA_TO[reg[j]]; - } - } - if (q != 0) - continue; /* Not a root */ - /* store root (index-form) and error location number */ -#if DEBUG>=2 - fprintf(stderr, "count %d root %d loc %d\n", count, i, k); -#endif - root[count] = i; - loc[count] = k; - /* If we've already found max possible roots, - * abort the search to save time - */ - if (++count == deg_lambda) - break; - } - if (deg_lambda != count) { - /* - * deg(lambda) unequal to number of roots => uncorrectable - * error detected - */ - count = -1; - goto finish; - } - /* - * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo - * x**NROOTS). in index form. Also find deg(omega). - */ - deg_omega = 0; - for (i = 0; i < NROOTS; i++) { - tmp = 0; - j = (deg_lambda < i) ? deg_lambda : i; - for (; j >= 0; j--) { - if ((s[i - j] != A0) && (lambda[j] != A0)) - tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; - } - if (tmp != 0) - deg_omega = i; - omega[i] = INDEX_OF[tmp]; - } - omega[NROOTS] = A0; - - /* - * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = - * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form - */ - for (j = count - 1; j >= 0; j--) { - num1 = 0; - for (i = deg_omega; i >= 0; i--) { - if (omega[i] != A0) - num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; - } - num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; - den = 0; - - /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ - for (i = min(deg_lambda, NROOTS - 1) & ~1; i >= 0; i -= 2) { - if (lambda[i + 1] != A0) - den ^= ALPHA_TO[MODNN(lambda[i + 1] + i * root[j])]; - } - if (den == 0) { -#if DEBUG >= 1 - fprintf(stderr, "\n ERROR: denominator = 0\n"); -#endif - count = -1; - goto finish; - } - /* Apply error to data */ - if (num1 != 0) { - data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; - } - } -finish: - if (eras_pos != NULL) { - for (i = 0; i < count; i++) - eras_pos[i] = loc[i]; - } - return count; -} - - - - -struct rs *INIT_RS(unsigned int symsize, unsigned int gfpoly, unsigned fcr, unsigned prim, - unsigned int nroots) { - struct rs *rs; - int i, j, sr, root, iprim; - - if (symsize > 8 * sizeof(DTYPE)) - return NULL; /* Need version with ints rather than chars */ - - if (fcr >= (1 << symsize)) - return NULL; - if (prim == 0 || prim >= (1 << symsize)) - return NULL; - if (nroots >= (1 << symsize)) - return NULL; /* Can't have more roots than symbol values! */ - - rs = (struct rs *)calloc(1, sizeof(struct rs)); - if (rs == NULL) { - Debugprintf("FATAL ERROR: Out of memory.\n"); - exit(0); - } - rs->mm = symsize; - rs->nn = (1 << symsize) - 1; - - rs->alpha_to = (DTYPE *)calloc((rs->nn + 1), sizeof(DTYPE)); - if (rs->alpha_to == NULL) { - Debugprintf("FATAL ERROR: Out of memory.\n"); - exit(0); - } - rs->index_of = (DTYPE *)calloc((rs->nn + 1), sizeof(DTYPE)); - if (rs->index_of == NULL) { - Debugprintf("FATAL ERROR: Out of memory.\n"); - exit(0); - } - - /* Generate Galois field lookup tables */ - rs->index_of[0] = A0; /* log(zero) = -inf */ - rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ - sr = 1; - for (i = 0; i < rs->nn; i++) { - rs->index_of[sr] = i; - rs->alpha_to[i] = sr; - sr <<= 1; - if (sr & (1 << symsize)) - sr ^= gfpoly; - sr &= rs->nn; - } - if (sr != 1) { - /* field generator polynomial is not primitive! */ - free(rs->alpha_to); - free(rs->index_of); - free(rs); - return NULL; - } - - /* Form RS code generator polynomial from its roots */ - rs->genpoly = (DTYPE *)calloc((nroots + 1), sizeof(DTYPE)); - if (rs->genpoly == NULL) { - Debugprintf("FATAL ERROR: Out of memory.\n"); - exit(0); - } - rs->fcr = fcr; - rs->prim = prim; - rs->nroots = nroots; - - /* Find prim-th root of 1, used in decoding */ - for (iprim = 1; (iprim % prim) != 0; iprim += rs->nn) - ; - rs->iprim = iprim / prim; - - rs->genpoly[0] = 1; - for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { - rs->genpoly[i + 1] = 1; - - /* Multiply rs->genpoly[] by @**(root + x) */ - for (j = i; j > 0; j--) { - if (rs->genpoly[j] != 0) - rs->genpoly[j] = rs->genpoly[j - 1] ^ rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; - else - rs->genpoly[j] = rs->genpoly[j - 1]; - } - /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; - } - /* convert rs->genpoly[] to index form for quicker encoding */ - for (i = 0; i <= nroots; i++) { - rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; - } - - // diagnostic prints -#if 0 - printf("Alpha To:\n\r"); - for (i = 0; i < sizeof(DTYPE)*(rs->nn + 1); i++) - printf("0x%2x,", rs->alpha_to[i]); - printf("\n\r"); - - printf("Index Of:\n\r"); - for (i = 0; i < sizeof(DTYPE)*(rs->nn + 1); i++) - printf("0x%2x,", rs->index_of[i]); - printf("\n\r"); - - printf("GenPoly:\n\r"); - for (i = 0; i <= nroots; i++) - printf("0x%2x,", rs->genpoly[i]); - printf("\n\r"); -#endif - return rs; -} - - -// TEMPORARY!!! -// FIXME: We already have multiple copies of this. -// Consolidate them into one somewhere. - -void fx_hex_dump(unsigned char *p, int len) -{ - int n, i, offset; - - offset = 0; - while (len > 0) { - n = len < 16 ? len : 16; - Debugprintf(" %03x: ", offset); - for (i = 0; i < n; i++) { - Debugprintf(" %02x", p[i]); - } - for (i = n; i < 16; i++) { - Debugprintf(" "); - } - Debugprintf(" "); - for (i = 0; i < n; i++) { - Debugprintf("%c", isprint(p[i]) ? p[i] : '.'); - } - Debugprintf("\n"); - p += 16; - offset += 16; - len -= 16; - } -} - - -/*------------------------------------------------------------- - * - * File: il2p_codec.c - * - * Purpose: Convert IL2P encoded format from and to direwolf internal packet format. - * - *--------------------------------------------------------------*/ - - - /*------------------------------------------------------------- - * - * Name: il2p_encode_frame - * - * Purpose: Convert AX.25 frame to IL2P encoding. - * - * Inputs: chan - Audio channel number, 0 = first. - * - * pp - Packet object pointer. - * - * max_fec - 1 to send maximum FEC size rather than automatic. - * - * Outputs: iout - Encoded result, excluding the 3 byte sync word. - * Caller should provide IL2P_MAX_PACKET_SIZE bytes. - * - * Returns: Number of bytes for transmission. - * -1 is returned for failure. - * - * Description: Encode into IL2P format. - * - * Errors: If something goes wrong, return -1. - * - * Most likely reason is that the frame is too large. - * IL2P has a max payload size of 1023 bytes. - * For a type 1 header, this is the maximum AX.25 Information part size. - * For a type 0 header, this is the entire AX.25 frame. - * - *--------------------------------------------------------------*/ - -int il2p_encode_frame(packet_t pp, int max_fec, unsigned char *iout) -{ - - // Can a type 1 header be used? - - unsigned char hdr[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY]; - int e; - int out_len = 0; - - e = il2p_type_1_header(pp, max_fec, hdr); - if (e >= 0) { - il2p_scramble_block(hdr, iout, IL2P_HEADER_SIZE); - il2p_encode_rs(iout, IL2P_HEADER_SIZE, IL2P_HEADER_PARITY, iout + IL2P_HEADER_SIZE); - out_len = IL2P_HEADER_SIZE + IL2P_HEADER_PARITY; - - if (e == 0) { - // Success. No info part. - return (out_len); - } - - // Payload is AX.25 info part. - unsigned char *pinfo; - int info_len; - info_len = ax25_get_info(pp, &pinfo); - - int k = il2p_encode_payload(pinfo, info_len, max_fec, iout + out_len); - if (k > 0) { - out_len += k; - // Success. Info part was <= 1023 bytes. - return (out_len); - } - - // Something went wrong with the payload encoding. - return (-1); - } - else if (e == -1) { - - // Could not use type 1 header for some reason. - // e.g. More than 2 addresses, extended (mod 128) sequence numbers, etc. - - e = il2p_type_0_header(pp, max_fec, hdr); - if (e > 0) { - - il2p_scramble_block(hdr, iout, IL2P_HEADER_SIZE); - il2p_encode_rs(iout, IL2P_HEADER_SIZE, IL2P_HEADER_PARITY, iout + IL2P_HEADER_SIZE); - out_len = IL2P_HEADER_SIZE + IL2P_HEADER_PARITY; - - // Payload is entire AX.25 frame. - - unsigned char *frame_data_ptr = ax25_get_frame_data_ptr(pp); - int frame_len = ax25_get_frame_len(pp); - int k = il2p_encode_payload(frame_data_ptr, frame_len, max_fec, iout + out_len); - if (k > 0) { - out_len += k; - // Success. Entire AX.25 frame <= 1023 bytes. - return (out_len); - } - // Something went wrong with the payload encoding. - return (-1); - } - else if (e == 0) { - // Impossible condition. Type 0 header must have payload. - return (-1); - } - else { - // AX.25 frame is too large. - return (-1); - } - } - - // AX.25 Information part is too large. - return (-1); -} - - - -/*------------------------------------------------------------- - * - * Name: il2p_decode_frame - * - * Purpose: Convert IL2P encoding to AX.25 frame. - * This is only used during testing, with a whole encoded frame. - * During reception, the header would have FEC and descrambling - * applied first so we would know how much to collect for the payload. - * - * Inputs: irec - Received IL2P frame excluding the 3 byte sync word. - * - * Future Out: Number of symbols corrected. - * - * Returns: Packet pointer or NULL for error. - * - *--------------------------------------------------------------*/ - -packet_t il2p_decode_frame(unsigned char *irec) -{ - unsigned char uhdr[IL2P_HEADER_SIZE]; // After FEC and descrambling. - int e = il2p_clarify_header(irec, uhdr); - - // TODO?: for symmetry we might want to clarify the payload before combining. - - return (il2p_decode_header_payload(uhdr, irec + IL2P_HEADER_SIZE + IL2P_HEADER_PARITY, &e)); -} - - -/*------------------------------------------------------------- - * - * Name: il2p_decode_header_payload - * - * Purpose: Convert IL2P encoding to AX.25 frame - * - * Inputs: uhdr - Received header after FEC and descrambling. - * epayload - Encoded payload. - * - * In/Out: symbols_corrected - Symbols (bytes) corrected in the header. - * Should be 0 or 1 because it has 2 parity symbols. - * Here we add number of corrections for the payload. - * - * Returns: Packet pointer or NULL for error. - * - *--------------------------------------------------------------*/ - -packet_t il2p_decode_header_payload(unsigned char* uhdr, unsigned char *epayload, int *symbols_corrected) -{ - int hdr_type; - int max_fec; - int payload_len = il2p_get_header_attributes(uhdr, &hdr_type, &max_fec); - - packet_t pp = NULL; - - if (hdr_type == 1) { - - // Header type 1. Any payload is the AX.25 Information part. - - pp = il2p_decode_header_type_1(uhdr, *symbols_corrected); - if (pp == NULL) { - // Failed for some reason. - return (NULL); - } - - if (payload_len > 0) { - // This is the AX.25 Information part. - - unsigned char extracted[IL2P_MAX_PAYLOAD_SIZE]; - int e = il2p_decode_payload(epayload, payload_len, max_fec, extracted, symbols_corrected); - - // It would be possible to have a good header but too many errors in the payload. - - if (e <= 0) { - ax25_delete(pp); - pp = NULL; - return (pp); - } - - if (e != payload_len) { - Debugprintf("IL2P Internal Error: %s(): hdr_type=%d, max_fec=%d, payload_len=%d, e=%d.\n", __func__, hdr_type, max_fec, payload_len, e); - } - - ax25_set_info(pp, extracted, payload_len); - } - return (pp); - } - else { - - // Header type 0. The payload is the entire AX.25 frame. - - unsigned char extracted[IL2P_MAX_PAYLOAD_SIZE]; - int e = il2p_decode_payload(epayload, payload_len, max_fec, extracted, symbols_corrected); - - if (e <= 0) { // Payload was not received correctly. - return (NULL); - } - - if (e != payload_len) { - Debugprintf("IL2P Internal Error: %s(): hdr_type=%d, e=%d, payload_len=%d\n", __func__, hdr_type, e, payload_len); - return (NULL); - } - - alevel_t alevel; - memset(&alevel, 0, sizeof(alevel)); - //alevel = demod_get_audio_level (chan, subchan); // What TODO? We don't know channel here. - // I think alevel gets filled in somewhere later making - // this redundant. - - pp = ax25_from_frame(extracted, payload_len, alevel); - return (pp); - } - -} // end il2p_decode_header_payload - -// end il2p_codec.c - - - -/*-------------------------------------------------------------------------------- - * - * File: il2p_header.c - * - * Purpose: Functions to deal with the IL2P header. - * - * Reference: http://tarpn.net/t/il2p/il2p-specification0-4.pdf - * - *--------------------------------------------------------------------------------*/ - - - - // Convert ASCII to/from DEC SIXBIT as defined here: - // https://en.wikipedia.org/wiki/Six-bit_character_code#DEC_six-bit_code - -static inline int ascii_to_sixbit(int a) -{ - if (a >= ' ' && a <= '_') return (a - ' '); - return (31); // '?' for any invalid. -} - -static inline int sixbit_to_ascii(int s) -{ - return (s + ' '); -} - -// Functions for setting the various header fields. -// It is assumed that it was zeroed first so only the '1' bits are set. - -static void set_field(unsigned char *hdr, int bit_num, int lsb_index, int width, int value) -{ - while (width > 0 && value != 0) { - //assert(lsb_index >= 0 && lsb_index <= 11); - if (value & 1) { - hdr[lsb_index] |= 1 << bit_num; - } - value >>= 1; - lsb_index--; - width--; - } - //assert(value == 0); -} - -#define SET_UI(hdr,val) set_field(hdr, 6, 0, 1, val) - -#define SET_PID(hdr,val) set_field(hdr, 6, 4, 4, val) - -#define SET_CONTROL(hdr,val) set_field(hdr, 6, 11, 7, val) - - -#define SET_FEC_LEVEL(hdr,val) set_field(hdr, 7, 0, 1, val) - -#define SET_HDR_TYPE(hdr,val) set_field(hdr, 7, 1, 1, val) - -#define SET_PAYLOAD_BYTE_COUNT(hdr,val) set_field(hdr, 7, 11, 10, val) - - -// Extracting the fields. - -static int get_field(unsigned char *hdr, int bit_num, int lsb_index, int width) -{ - int result = 0; - lsb_index -= width - 1; - while (width > 0) { - result <<= 1; - //assert(lsb_index >= 0 && lsb_index <= 11); - if (hdr[lsb_index] & (1 << bit_num)) { - result |= 1; - } - lsb_index++; - width--; - } - return (result); -} - -#define GET_UI(hdr) get_field(hdr, 6, 0, 1) - -#define GET_PID(hdr) get_field(hdr, 6, 4, 4) - -#define GET_CONTROL(hdr) get_field(hdr, 6, 11, 7) - - -#define GET_FEC_LEVEL(hdr) get_field(hdr, 7, 0, 1) - -#define GET_HDR_TYPE(hdr) get_field(hdr, 7, 1, 1) - -#define GET_PAYLOAD_BYTE_COUNT(hdr) get_field(hdr, 7, 11, 10) - - - -// AX.25 'I' and 'UI' frames have a protocol ID which determines how the -// information part should be interpreted. -// Here we squeeze the most common cases down to 4 bits. -// Return -1 if translation is not possible. Fall back to type 0 header in this case. - -static int encode_pid(packet_t pp) -{ - int pid = ax25_get_pid(pp); - - if ((pid & 0x30) == 0x20) return (0x2); // AX.25 Layer 3 - if ((pid & 0x30) == 0x10) return (0x2); // AX.25 Layer 3 - if (pid == 0x01) return (0x3); // ISO 8208 / CCIT X.25 PLP - if (pid == 0x06) return (0x4); // Compressed TCP/IP - if (pid == 0x07) return (0x5); // Uncompressed TCP/IP - if (pid == 0x08) return (0x6); // Segmentation fragmen - if (pid == 0xcc) return (0xb); // ARPA Internet Protocol - if (pid == 0xcd) return (0xc); // ARPA Address Resolution - if (pid == 0xce) return (0xd); // FlexNet - if (pid == 0xcf) return (0xe); // TheNET - if (pid == 0xf0) return (0xf); // No L3 - return (-1); -} - -// Convert IL2P 4 bit PID to AX.25 8 bit PID. - - -static int decode_pid(int pid) -{ - static const unsigned char axpid[16] = { - 0xf0, // Should not happen. 0 is for 'S' frames. - 0xf0, // Should not happen. 1 is for 'U' frames (but not UI). - 0x20, // AX.25 Layer 3 - 0x01, // ISO 8208 / CCIT X.25 PLP - 0x06, // Compressed TCP/IP - 0x07, // Uncompressed TCP/IP - 0x08, // Segmentation fragment - 0xf0, // Future - 0xf0, // Future - 0xf0, // Future - 0xf0, // Future - 0xcc, // ARPA Internet Protocol - 0xcd, // ARPA Address Resolution - 0xce, // FlexNet - 0xcf, // TheNET - 0xf0 }; // No L3 - - //assert(pid >= 0 && pid <= 15); - return (axpid[pid]); -} - - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_type_1_header - * - * Purpose: Attempt to create type 1 header from packet object. - * - * Inputs: pp - Packet object. - * - * max_fec - 1 to use maximum FEC symbols , 0 for automatic. - * - * Outputs: hdr - IL2P header with no scrambling or parity symbols. - * Must be large enough to hold IL2P_HEADER_SIZE unsigned bytes. - * - * Returns: Number of bytes for information part or -1 for failure. - * In case of failure, fall back to type 0 transparent encapsulation. - * - * Description: Type 1 Headers do not support AX.25 repeater callsign addressing, - * Modulo-128 extended mode window sequence numbers, nor any callsign - * characters that cannot translate to DEC SIXBIT. - * If these cases are encountered during IL2P packet encoding, - * the encoder switches to Type 0 Transparent Encapsulation. - * SABME can't be handled by type 1. - * - *--------------------------------------------------------------------------------*/ - -int il2p_type_1_header(packet_t pp, int max_fec, unsigned char *hdr) -{ - memset(hdr, 0, IL2P_HEADER_SIZE); - - if (ax25_get_num_addr(pp) != 2) { - // Only two addresses are allowed for type 1 header. - return (-1); - } - - // Check does not apply for 'U' frames but put in one place rather than two. - - if (ax25_get_modulo(pp) == 128) return(-1); - - // Destination and source addresses go into low bits 0-5 for bytes 0-11. - - char dst_addr[AX25_MAX_ADDR_LEN]; - char src_addr[AX25_MAX_ADDR_LEN]; - - ax25_get_addr_no_ssid(pp, AX25_DESTINATION, dst_addr); - int dst_ssid = ax25_get_ssid(pp, AX25_DESTINATION); - - ax25_get_addr_no_ssid(pp, AX25_SOURCE, src_addr); - int src_ssid = ax25_get_ssid(pp, AX25_SOURCE); - - unsigned char *a = (unsigned char *)dst_addr; - for (int i = 0; *a != '\0'; i++, a++) { - if (*a < ' ' || *a > '_') { - // Shouldn't happen but follow the rule. - return (-1); - } - hdr[i] = ascii_to_sixbit(*a); - } - - a = (unsigned char *)src_addr; - for (int i = 6; *a != '\0'; i++, a++) { - if (*a < ' ' || *a > '_') { - // Shouldn't happen but follow the rule. - return (-1); - } - hdr[i] = ascii_to_sixbit(*a); - } - - // Byte 12 has DEST SSID in upper nybble and SRC SSID in lower nybble and - hdr[12] = (dst_ssid << 4) | src_ssid; - - ax25_frame_type_t frame_type; - cmdres_t cr; // command or response. - char description[64]; - int pf; // Poll/Final. - int nr, ns; // Sequence numbers. - - frame_type = ax25_frame_type(pp, &cr, description, &pf, &nr, &ns); - - //Debugprintf ("%s(): %s-%d>%s-%d: %s\n", __func__, src_addr, src_ssid, dst_addr, dst_ssid, description); - - switch (frame_type) { - - case frame_type_S_RR: // Receive Ready - System Ready To Receive - case frame_type_S_RNR: // Receive Not Ready - TNC Buffer Full - case frame_type_S_REJ: // Reject Frame - Out of Sequence or Duplicate - case frame_type_S_SREJ: // Selective Reject - Request single frame repeat - - // S frames (RR, RNR, REJ, SREJ), mod 8, have control N(R) P/F S S 0 1 - // These are mapped into P/F N(R) C S S - // Bit 6 is not mentioned in documentation but it is used for P/F for the other frame types. - // C is copied from the C bit in the destination addr. - // C from source is not used here. Reception assumes it is the opposite. - // PID is set to 0, meaning none, for S frames. - - SET_UI(hdr, 0); - SET_PID(hdr, 0); - SET_CONTROL(hdr, (pf << 6) | (nr << 3) | (((cr == cr_cmd) | (cr == cr_11)) << 2)); - - // This gets OR'ed into the above. - switch (frame_type) { - case frame_type_S_RR: SET_CONTROL(hdr, 0); break; - case frame_type_S_RNR: SET_CONTROL(hdr, 1); break; - case frame_type_S_REJ: SET_CONTROL(hdr, 2); break; - case frame_type_S_SREJ: SET_CONTROL(hdr, 3); break; - default: break; - } - - break; - - case frame_type_U_SABM: // Set Async Balanced Mode - case frame_type_U_DISC: // Disconnect - case frame_type_U_DM: // Disconnect Mode - case frame_type_U_UA: // Unnumbered Acknowledge - case frame_type_U_FRMR: // Frame Reject - case frame_type_U_UI: // Unnumbered Information - case frame_type_U_XID: // Exchange Identification - case frame_type_U_TEST: // Test - - // The encoding allows only 3 bits for frame type and SABME got left out. - // Control format: P/F opcode[3] C n/a n/a - // The grayed out n/a bits are observed as 00 in the example. - // The header UI field must also be set for UI frames. - // PID is set to 1 for all U frames other than UI. - - if (frame_type == frame_type_U_UI) { - SET_UI(hdr, 1); // I guess this is how we distinguish 'I' and 'UI' - // on the receiving end. - int pid = encode_pid(pp); - if (pid < 0) return (-1); - SET_PID(hdr, pid); - } - else { - SET_PID(hdr, 1); // 1 for 'U' other than 'UI'. - } - - // Each of the destination and source addresses has a "C" bit. - // They should normally have the opposite setting. - // IL2P has only a single bit to represent 4 possbilities. - // - // dst src il2p meaning - // --- --- ---- ------- - // 0 0 0 Not valid (earlier protocol version) - // 1 0 1 Command (v2) - // 0 1 0 Response (v2) - // 1 1 1 Not valid (earlier protocol version) - // - // APRS does not mention how to set these bits and all 4 combinations - // are seen in the wild. Apparently these are ignored on receive and no - // one cares. Here we copy from the C bit in the destination address. - // It should be noted that the case of both C bits being the same can't - // be represented so the il2p encode/decode bit not produce exactly the - // same bits. We see this in the second example in the protocol spec. - // The original UI frame has both C bits of 0 so it is received as a response. - - SET_CONTROL(hdr, (pf << 6) | (((cr == cr_cmd) | (cr == cr_11)) << 2)); - - // This gets OR'ed into the above. - switch (frame_type) { - case frame_type_U_SABM: SET_CONTROL(hdr, 0 << 3); break; - case frame_type_U_DISC: SET_CONTROL(hdr, 1 << 3); break; - case frame_type_U_DM: SET_CONTROL(hdr, 2 << 3); break; - case frame_type_U_UA: SET_CONTROL(hdr, 3 << 3); break; - case frame_type_U_FRMR: SET_CONTROL(hdr, 4 << 3); break; - case frame_type_U_UI: SET_CONTROL(hdr, 5 << 3); break; - case frame_type_U_XID: SET_CONTROL(hdr, 6 << 3); break; - case frame_type_U_TEST: SET_CONTROL(hdr, 7 << 3); break; - default: break; - } - break; - - case frame_type_I: // Information - - // I frames (mod 8 only) - // encoded control: P/F N(R) N(S) - - SET_UI(hdr, 0); - - int pid2 = encode_pid(pp); - if (pid2 < 0) return (-1); - SET_PID(hdr, pid2); - - SET_CONTROL(hdr, (pf << 6) | (nr << 3) | ns); - break; - - case frame_type_U_SABME: // Set Async Balanced Mode, Extended - case frame_type_U: // other Unnumbered, not used by AX.25. - case frame_not_AX25: // Could not get control byte from frame. - default: - - // Fall back to the header type 0 for these. - return (-1); - } - - // Common for all header type 1. - - // Bit 7 has [FEC Level:1], [HDR Type:1], [Payload byte Count:10] - - SET_FEC_LEVEL(hdr, max_fec); - SET_HDR_TYPE(hdr, 1); - - unsigned char *pinfo; - int info_len; - - info_len = ax25_get_info(pp, &pinfo); - if (info_len < 0 || info_len > IL2P_MAX_PAYLOAD_SIZE) { - return (-2); - } - - SET_PAYLOAD_BYTE_COUNT(hdr, info_len); - return (info_len); -} - - -// This should create a packet from the IL2P header. -// The information part will not be filled in. - -static void trim(char *stuff) -{ - char *p = stuff + strlen(stuff) - 1; - while (strlen(stuff) > 0 && (*p == ' ')) { - *p = '\0'; - p--; - } -} - - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_decode_header_type_1 - * - * Purpose: Attempt to convert type 1 header to a packet object. - * - * Inputs: hdr - IL2P header with no scrambling or parity symbols. - * - * num_sym_changed - Number of symbols changed by FEC in the header. - * Should be 0 or 1. - * - * Returns: Packet Object or NULL for failure. - * - * Description: A later step will process the payload for the information part. - * - *--------------------------------------------------------------------------------*/ - -packet_t il2p_decode_header_type_1(unsigned char *hdr, int num_sym_changed) -{ - - if (GET_HDR_TYPE(hdr) != 1) { - Debugprintf("IL2P Internal error. Should not be here: %s, when header type is 0.\n", __func__); - return (NULL); - } - - // First get the addresses including SSID. - - char addrs[AX25_MAX_ADDRS][AX25_MAX_ADDR_LEN]; - int num_addr = 2; - memset(addrs, 0, 2 * AX25_MAX_ADDR_LEN); - - // The IL2P header uses 2 parity symbols which means a single corrupted symbol (byte) - // can always be corrected. - // However, I have seen cases, where the error rate is very high, where the RS decoder - // thinks it found a valid code block by changing one symbol but it was the wrong one. - // The result is trash. This shows up as address fields like 'R&G4"A' and 'TEW\ !'. - // I added a sanity check here to catch characters other than upper case letters and digits. - // The frame should be rejected in this case. The question is whether to discard it - // silently or print a message so the user can see that something strange is happening? - // My current thinking is that it should be silently ignored if the header has been - // modified (correctee or more likely, made worse in this cases). - // If no changes were made, something weird is happening. We should mention it for - // troubleshooting rather than sweeping it under the rug. - - // The same thing has been observed with the payload, under very high error conditions, - // and max_fec==0. Here I don't see a good solution. AX.25 information can contain - // "binary" data so I'm not sure what sort of sanity check could be added. - // This was not observed with max_fec==1. If we make that the default, same as Nino TNC, - // it would be extremely extremely unlikely unless someone explicitly selects weaker FEC. - - // TODO: We could do something similar for header type 0. - // The address fields should be all binary zero values. - // Someone overly ambitious might check the addresses found in the first payload block. - - for (int i = 0; i <= 5; i++) { - addrs[AX25_DESTINATION][i] = sixbit_to_ascii(hdr[i] & 0x3f); - } - trim(addrs[AX25_DESTINATION]); - for (int i = 0; i < strlen(addrs[AX25_DESTINATION]); i++) { - if (!isupper(addrs[AX25_DESTINATION][i]) && !isdigit(addrs[AX25_DESTINATION][i])) { - if (num_sym_changed == 0) { - // This can pop up sporadically when receiving random noise. - // Would be better to show only when debug is enabled but variable not available here. - // TODO: For now we will just suppress it. - //text_color_set(DW_COLOR_ERROR); - //Debugprintf ("IL2P: Invalid character '%c' in destination address '%s'\n", addrs[AX25_DESTINATION][i], addrs[AX25_DESTINATION]); - } - return (NULL); - } - } - sprintf(addrs[AX25_DESTINATION] + strlen(addrs[AX25_DESTINATION]), "-%d", (hdr[12] >> 4) & 0xf); - - for (int i = 0; i <= 5; i++) { - addrs[AX25_SOURCE][i] = sixbit_to_ascii(hdr[i + 6] & 0x3f); - } - trim(addrs[AX25_SOURCE]); - for (int i = 0; i < strlen(addrs[AX25_SOURCE]); i++) { - if (!isupper(addrs[AX25_SOURCE][i]) && !isdigit(addrs[AX25_SOURCE][i])) { - if (num_sym_changed == 0) { - // This can pop up sporadically when receiving random noise. - // Would be better to show only when debug is enabled but variable not available here. - // TODO: For now we will just suppress it. - //text_color_set(DW_COLOR_ERROR); - //Debugprintf ("IL2P: Invalid character '%c' in source address '%s'\n", addrs[AX25_SOURCE][i], addrs[AX25_SOURCE]); - } - return (NULL); - } - } - sprintf(addrs[AX25_SOURCE] + strlen(addrs[AX25_SOURCE]), "-%d", hdr[12] & 0xf); - - // The PID field gives us the general type. - // 0 = 'S' frame. - // 1 = 'U' frame other than UI. - // others are either 'UI' or 'I' depending on the UI field. - - int pid = GET_PID(hdr); - int ui = GET_UI(hdr); - - if (pid == 0) { - - // 'S' frame. - // The control field contains: P/F N(R) C S S - - int control = GET_CONTROL(hdr); - cmdres_t cr = (control & 0x04) ? cr_cmd : cr_res; - ax25_frame_type_t ftype; - switch (control & 0x03) { - case 0: ftype = frame_type_S_RR; break; - case 1: ftype = frame_type_S_RNR; break; - case 2: ftype = frame_type_S_REJ; break; - default: ftype = frame_type_S_SREJ; break; - } - int modulo = 8; - int nr = (control >> 3) & 0x07; - int pf = (control >> 6) & 0x01; - unsigned char *pinfo = NULL; // Any info for SREJ will be added later. - int info_len = 0; - return (ax25_s_frame(addrs, num_addr, cr, ftype, modulo, nr, pf, pinfo, info_len)); - } - else if (pid == 1) { - - // 'U' frame other than 'UI'. - // The control field contains: P/F OPCODE{3) C x x - - int control = GET_CONTROL(hdr); - cmdres_t cr = (control & 0x04) ? cr_cmd : cr_res; - int axpid = 0; // unused for U other than UI. - ax25_frame_type_t ftype; - switch ((control >> 3) & 0x7) { - case 0: ftype = frame_type_U_SABM; break; - case 1: ftype = frame_type_U_DISC; break; - case 2: ftype = frame_type_U_DM; break; - case 3: ftype = frame_type_U_UA; break; - case 4: ftype = frame_type_U_FRMR; break; - case 5: ftype = frame_type_U_UI; axpid = 0xf0; break; // Should not happen with IL2P pid == 1. - case 6: ftype = frame_type_U_XID; break; - default: ftype = frame_type_U_TEST; break; - } - int pf = (control >> 6) & 0x01; - unsigned char *pinfo = NULL; // Any info for UI, XID, TEST will be added later. - int info_len = 0; - return (ax25_u_frame(addrs, num_addr, cr, ftype, pf, axpid, pinfo, info_len)); - } - else if (ui) { - - // 'UI' frame. - // The control field contains: P/F OPCODE{3) C x x - - int control = GET_CONTROL(hdr); - cmdres_t cr = (control & 0x04) ? cr_cmd : cr_res; - ax25_frame_type_t ftype = frame_type_U_UI; - int pf = (control >> 6) & 0x01; - int axpid = decode_pid(GET_PID(hdr)); - unsigned char *pinfo = NULL; // Any info for UI, XID, TEST will be added later. - int info_len = 0; - return (ax25_u_frame(addrs, num_addr, cr, ftype, pf, axpid, pinfo, info_len)); - } - else { - - // 'I' frame. - // The control field contains: P/F N(R) N(S) - - int control = GET_CONTROL(hdr); - cmdres_t cr = cr_cmd; // Always command. - int pf = (control >> 6) & 0x01; - int nr = (control >> 3) & 0x7; - int ns = control & 0x7; - int modulo = 8; - int axpid = decode_pid(GET_PID(hdr)); - unsigned char *pinfo = NULL; // Any info for UI, XID, TEST will be added later. - int info_len = 0; - return (ax25_i_frame(addrs, num_addr, cr, modulo, nr, ns, pf, axpid, pinfo, info_len)); - } - return (NULL); // unreachable but avoid warning. - -} // end - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_type_0_header - * - * Purpose: Attempt to create type 0 header from packet object. - * - * Inputs: pp - Packet object. - * - * max_fec - 1 to use maximum FEC symbols, 0 for automatic. - * - * Outputs: hdr - IL2P header with no scrambling or parity symbols. - * Must be large enough to hold IL2P_HEADER_SIZE unsigned bytes. - * - * Returns: Number of bytes for information part or -1 for failure. - * In case of failure, fall back to type 0 transparent encapsulation. - * - * Description: The type 0 header is used when it is not one of the restricted cases - * covered by the type 1 header. - * The AX.25 frame is put in the payload. - * This will cover: more than one address, mod 128 sequences, etc. - * - *--------------------------------------------------------------------------------*/ - -int il2p_type_0_header(packet_t pp, int max_fec, unsigned char *hdr) -{ - memset(hdr, 0, IL2P_HEADER_SIZE); - - // Bit 7 has [FEC Level:1], [HDR Type:1], [Payload byte Count:10] - - SET_FEC_LEVEL(hdr, max_fec); - SET_HDR_TYPE(hdr, 0); - - int frame_len = ax25_get_frame_len(pp); - - if (frame_len < 14 || frame_len > IL2P_MAX_PAYLOAD_SIZE) { - return (-2); - } - - SET_PAYLOAD_BYTE_COUNT(hdr, frame_len); - return (frame_len); -} - - -/*********************************************************************************** - * - * Name: il2p_get_header_attributes - * - * Purpose: Extract a few attributes from an IL2p header. - * - * Inputs: hdr - IL2P header structure. - * - * Outputs: hdr_type - 0 or 1. - * - * max_fec - 0 for automatic or 1 for fixed maximum size. - * - * Returns: Payload byte count. (actual payload size, not the larger encoded format) - * - ***********************************************************************************/ - - -int il2p_get_header_attributes(unsigned char *hdr, int *hdr_type, int *max_fec) -{ - *hdr_type = GET_HDR_TYPE(hdr); - *max_fec = GET_FEC_LEVEL(hdr); - return(GET_PAYLOAD_BYTE_COUNT(hdr)); -} - - -/*********************************************************************************** - * - * Name: il2p_clarify_header - * - * Purpose: Convert received header to usable form. - * This involves RS FEC then descrambling. - * - * Inputs: rec_hdr - Header as received over the radio. - * - * Outputs: corrected_descrambled_hdr - After RS FEC and unscrambling. - * - * Returns: Number of symbols that were corrected: - * 0 = No errors - * 1 = Single symbol corrected. - * <0 = Unable to obtain good header. - * - ***********************************************************************************/ - -int il2p_clarify_header(unsigned char *rec_hdr, unsigned char *corrected_descrambled_hdr) -{ - unsigned char corrected[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY]; - - int e = il2p_decode_rs(rec_hdr, IL2P_HEADER_SIZE, IL2P_HEADER_PARITY, corrected); - - il2p_descramble_block(corrected, corrected_descrambled_hdr, IL2P_HEADER_SIZE); - - return (e); -} - -// end il2p_header.c - - -/*-------------------------------------------------------------------------------- - * - * File: il2p_payload.c - * - * Purpose: Functions dealing with the payload. - * - *--------------------------------------------------------------------------------*/ - - - /*-------------------------------------------------------------------------------- - * - * Function: il2p_payload_compute - * - * Purpose: Compute number and sizes of data blocks based on total size. - * - * Inputs: payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE) - * max_fec true for 16 parity symbols, false for automatic. - * - * Outputs: *p Payload block sizes and counts. - * Number of parity symbols per block. - * - * Returns: Number of bytes in the encoded format. - * Could be 0 for no payload blocks. - * -1 for error (i.e. invalid unencoded size: <0 or >1023) - * - *--------------------------------------------------------------------------------*/ - -int il2p_payload_compute(il2p_payload_properties_t *p, int payload_size, int max_fec) -{ - memset(p, 0, sizeof(il2p_payload_properties_t)); - - if (payload_size < 0 || payload_size > IL2P_MAX_PAYLOAD_SIZE) { - return (-1); - } - if (payload_size == 0) { - return (0); - } - - if (max_fec) { - p->payload_byte_count = payload_size; - p->payload_block_count = (p->payload_byte_count + 238) / 239; - p->small_block_size = p->payload_byte_count / p->payload_block_count; - p->large_block_size = p->small_block_size + 1; - p->large_block_count = p->payload_byte_count - (p->payload_block_count * p->small_block_size); - p->small_block_count = p->payload_block_count - p->large_block_count; - p->parity_symbols_per_block = 16; - } - else { - p->payload_byte_count = payload_size; - p->payload_block_count = (p->payload_byte_count + 246) / 247; - p->small_block_size = p->payload_byte_count / p->payload_block_count; - p->large_block_size = p->small_block_size + 1; - p->large_block_count = p->payload_byte_count - (p->payload_block_count * p->small_block_size); - p->small_block_count = p->payload_block_count - p->large_block_count; - //p->parity_symbols_per_block = (p->small_block_size / 32) + 2; // Looks like error in documentation - - // It would work if the number of parity symbols was based on large block size. - - if (p->small_block_size <= 61) p->parity_symbols_per_block = 2; - else if (p->small_block_size <= 123) p->parity_symbols_per_block = 4; - else if (p->small_block_size <= 185) p->parity_symbols_per_block = 6; - else if (p->small_block_size <= 247) p->parity_symbols_per_block = 8; - else { - // Should not happen. But just in case... - Debugprintf("IL2P parity symbol per payload block error. small_block_size = %d\n", p->small_block_size); - return (-1); - } - } - - // Return the total size for the encoded format. - - return (p->small_block_count * (p->small_block_size + p->parity_symbols_per_block) + - p->large_block_count * (p->large_block_size + p->parity_symbols_per_block)); - -} // end il2p_payload_compute - - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_encode_payload - * - * Purpose: Split payload into multiple blocks such that each set - * of data and parity symbols fit into a 255 byte RS block. - * - * Inputs: *payload Array of bytes. - * payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE) - * max_fec true for 16 parity symbols, false for automatic. - * - * Outputs: *enc Encoded payload for transmission. - * Up to IL2P_MAX_ENCODED_SIZE bytes. - * - * Returns: -1 for error (i.e. invalid size) - * 0 for no blocks. (i.e. size zero) - * Number of bytes generated. Maximum IL2P_MAX_ENCODED_SIZE. - * - * Note: I interpreted the protocol spec as saying the LFSR state is retained - * between data blocks. During interoperability testing, I found that - * was not the case. It is reset for each data block. - * - *--------------------------------------------------------------------------------*/ - - -int il2p_encode_payload(unsigned char *payload, int payload_size, int max_fec, unsigned char *enc) -{ - if (payload_size > IL2P_MAX_PAYLOAD_SIZE) return (-1); - if (payload_size == 0) return (0); - - // Determine number of blocks and sizes. - - il2p_payload_properties_t ipp; - int e; - e = il2p_payload_compute(&ipp, payload_size, max_fec); - if (e <= 0) { - return (e); - } - - unsigned char *pin = payload; - unsigned char *pout = enc; - int encoded_length = 0; - unsigned char scram[256]; - unsigned char parity[IL2P_MAX_PARITY_SYMBOLS]; - - // First the large blocks. - - for (int b = 0; b < ipp.large_block_count; b++) { - - il2p_scramble_block(pin, scram, ipp.large_block_size); - memcpy(pout, scram, ipp.large_block_size); - pin += ipp.large_block_size; - pout += ipp.large_block_size; - encoded_length += ipp.large_block_size; - il2p_encode_rs(scram, ipp.large_block_size, ipp.parity_symbols_per_block, parity); - memcpy(pout, parity, ipp.parity_symbols_per_block); - pout += ipp.parity_symbols_per_block; - encoded_length += ipp.parity_symbols_per_block; - } - - // Then the small blocks. - - for (int b = 0; b < ipp.small_block_count; b++) { - - il2p_scramble_block(pin, scram, ipp.small_block_size); - memcpy(pout, scram, ipp.small_block_size); - pin += ipp.small_block_size; - pout += ipp.small_block_size; - encoded_length += ipp.small_block_size; - il2p_encode_rs(scram, ipp.small_block_size, ipp.parity_symbols_per_block, parity); - memcpy(pout, parity, ipp.parity_symbols_per_block); - pout += ipp.parity_symbols_per_block; - encoded_length += ipp.parity_symbols_per_block; - } - - return (encoded_length); - -} // end il2p_encode_payload - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_decode_payload - * - * Purpose: Extract original data from encoded payload. - * - * Inputs: received Array of bytes. Size is unknown but in practice it - * must not exceed IL2P_MAX_ENCODED_SIZE. - * payload_size 0 to 1023. (IL2P_MAX_PAYLOAD_SIZE) - * Expected result size based on header. - * max_fec true for 16 parity symbols, false for automatic. - * - * Outputs: payload_out Recovered payload. - * - * In/Out: symbols_corrected Number of symbols corrected. - * - * - * Returns: Number of bytes extracted. Should be same as payload_size going in. - * -3 for unexpected internal inconsistency. - * -2 for unable to recover from signal corruption. - * -1 for invalid size. - * 0 for no blocks. (i.e. size zero) - * - * Description: Each block is scrambled separately but the LSFR state is carried - * from the first payload block to the next. - * - *--------------------------------------------------------------------------------*/ - -int il2p_decode_payload(unsigned char *received, int payload_size, int max_fec, unsigned char *payload_out, int *symbols_corrected) -{ - // Determine number of blocks and sizes. - - il2p_payload_properties_t ipp; - int e; - e = il2p_payload_compute(&ipp, payload_size, max_fec); - if (e <= 0) { - return (e); - } - - unsigned char *pin = received; - unsigned char *pout = payload_out; - int decoded_length = 0; - int failed = 0; - - // First the large blocks. - - for (int b = 0; b < ipp.large_block_count; b++) { - unsigned char corrected_block[255]; - int e = il2p_decode_rs(pin, ipp.large_block_size, ipp.parity_symbols_per_block, corrected_block); - - // Debugprintf ("%s:%d: large block decode_rs returned status = %d\n", __FILE__, __LINE__, e); - - if (e < 0) failed = 1; - *symbols_corrected += e; - - il2p_descramble_block(corrected_block, pout, ipp.large_block_size); - - if (il2p_get_debug() >= 2) { - - Debugprintf("Descrambled large payload block, %d bytes:\n", ipp.large_block_size); - fx_hex_dump(pout, ipp.large_block_size); - } - - pin += ipp.large_block_size + ipp.parity_symbols_per_block; - pout += ipp.large_block_size; - decoded_length += ipp.large_block_size; - } - - // Then the small blocks. - - for (int b = 0; b < ipp.small_block_count; b++) { - unsigned char corrected_block[255]; - int e = il2p_decode_rs(pin, ipp.small_block_size, ipp.parity_symbols_per_block, corrected_block); - - // Debugprintf ("%s:%d: small block decode_rs returned status = %d\n", __FILE__, __LINE__, e); - - if (e < 0) failed = 1; - *symbols_corrected += e; - - il2p_descramble_block(corrected_block, pout, ipp.small_block_size); - - if (il2p_get_debug() >= 2) { - - Debugprintf("Descrambled small payload block, %d bytes:\n", ipp.small_block_size); - fx_hex_dump(pout, ipp.small_block_size); - } - - pin += ipp.small_block_size + ipp.parity_symbols_per_block; - pout += ipp.small_block_size; - decoded_length += ipp.small_block_size; - } - - if (failed) { - //Debugprintf ("%s:%d: failed = %0x\n", __FILE__, __LINE__, failed); - return (-2); - } - - if (decoded_length != payload_size) { - Debugprintf("IL2P Internal error: decoded_length = %d, payload_size = %d\n", decoded_length, payload_size); - return (-3); - } - - return (decoded_length); - -} // end il2p_decode_payload - -// end il2p_payload.c - - - -struct il2p_context_s { - - enum { IL2P_SEARCHING = 0, IL2P_HEADER, IL2P_PAYLOAD, IL2P_DECODE } state; - - unsigned int acc; // Accumulate most recent 24 bits for sync word matching. - // Lower 8 bits are also used for accumulating bytes for - // the header and payload. - - int bc; // Bit counter so we know when a complete byte has been accumulated. - - int polarity; // 1 if opposite of expected polarity. - - unsigned char shdr[IL2P_HEADER_SIZE + IL2P_HEADER_PARITY]; - // Scrambled header as received over the radio. Includes parity. - int hc; // Number if bytes placed in above. - - unsigned char uhdr[IL2P_HEADER_SIZE]; // Header after FEC and unscrambling. - - int eplen; // Encoded payload length. This is not the nuumber from - // from the header but rather the number of encoded bytes to gather. - - unsigned char spayload[IL2P_MAX_ENCODED_PAYLOAD_SIZE]; - // Scrambled and encoded payload as received over the radio. - int pc; // Number of bytes placed in above. - - int corrected; // Number of symbols corrected by RS FEC. -}; - -static struct il2p_context_s *il2p_context[MAX_CHANS][MAX_SUBCHANS][MAX_SLICERS]; - - - -/*********************************************************************************** - * - * Name: il2p_rec_bit - * - * Purpose: Extract FX.25 packets from a stream of bits. - * - * Inputs: chan - Channel number. - * - * subchan - This allows multiple demodulators per channel. - * - * slice - Allows multiple slicers per demodulator (subchannel). - * - * dbit - One bit from the received data stream. - * - * Description: This is called once for each received bit. - * For each valid packet, process_rec_frame() is called for further processing. - * It can gather multiple candidates from different parallel demodulators - * ("subchannels") and slicers, then decide which one is the best. - * - ***********************************************************************************/ - -int centreFreq[4] = { 0, 0, 0, 0 }; - -void il2p_rec_bit(int chan, int subchan, int slice, int dbit) -{ - // Allocate context blocks only as needed. - - if (dbit) - dbit = 1; - - struct il2p_context_s *F = il2p_context[chan][subchan][slice]; - if (F == NULL) { - //assert(chan >= 0 && chan < MAX_CHANS); - //assert(subchan >= 0 && subchan < MAX_SUBCHANS); - //assert(slice >= 0 && slice < MAX_SLICERS); - F = il2p_context[chan][subchan][slice] = (struct il2p_context_s *)malloc(sizeof(struct il2p_context_s)); - //assert(F != NULL); - memset(F, 0, sizeof(struct il2p_context_s)); - } - - // Accumulate most recent 24 bits received. Most recent is LSB. - - F->acc = ((F->acc << 1) | (dbit & 1)) & 0x00ffffff; - - // State machine to look for sync word then gather appropriate number of header and payload bytes. - - switch (F->state) { - - case IL2P_SEARCHING: // Searching for the sync word. - - if (__builtin_popcount(F->acc ^ IL2P_SYNC_WORD) <= 1) { // allow single bit mismatch - //text_color_set (DW_COLOR_INFO); - //Debugprintf ("IL2P header has normal polarity\n"); - F->polarity = 0; - F->state = IL2P_HEADER; - F->bc = 0; - F->hc = 0; - - // Determine Centre Freq - - centreFreq[chan] = GuessCentreFreq(chan); - } - else if (__builtin_popcount((~F->acc & 0x00ffffff) ^ IL2P_SYNC_WORD) <= 1) { - // FIXME - this pops up occasionally with random noise. Find better way to convey information. - // This also happens for each slicer - to noisy. - //Debugprintf ("IL2P header has reverse polarity\n"); - F->polarity = 1; - F->state = IL2P_HEADER; - F->bc = 0; - F->hc = 0; - centreFreq[chan] = GuessCentreFreq(chan); - } - - break; - - case IL2P_HEADER: // Gathering the header. - - F->bc++; - if (F->bc == 8) { // full byte has been collected. - F->bc = 0; - if (!F->polarity) { - F->shdr[F->hc++] = F->acc & 0xff; - } - else { - F->shdr[F->hc++] = (~F->acc) & 0xff; - } - if (F->hc == IL2P_HEADER_SIZE + IL2P_HEADER_PARITY) { // Have all of header - - //if (il2p_get_debug() >= 1) - //{ - // Debugprintf("IL2P header as received [%d.%d.%d]:\n", chan, subchan, slice); - // fx_hex_dump(F->shdr, IL2P_HEADER_SIZE + IL2P_HEADER_PARITY); - //} - - // Fix any errors and descramble. - F->corrected = il2p_clarify_header(F->shdr, F->uhdr); - - if (F->corrected >= 0) { // Good header. - // How much payload is expected? - il2p_payload_properties_t plprop; - int hdr_type, max_fec; - int len = il2p_get_header_attributes(F->uhdr, &hdr_type, &max_fec); - - F->eplen = il2p_payload_compute(&plprop, len, max_fec); - - if (il2p_get_debug() >= 1) - { - Debugprintf("Header type %d, max fec = %d", hdr_type, max_fec); - Debugprintf("Need to collect %d encoded bytes for %d byte payload.", F->eplen, len); - Debugprintf("%d small blocks of %d and %d large blocks of %d. %d parity symbols per block", - plprop.small_block_count, plprop.small_block_size, - plprop.large_block_count, plprop.large_block_size, plprop.parity_symbols_per_block); - } - - if (F->eplen >= 1) { // Need to gather payload. - F->pc = 0; - F->state = IL2P_PAYLOAD; - } - else if (F->eplen == 0) { // No payload. - F->pc = 0; - F->state = IL2P_DECODE; - } - else { // Error. - - if (il2p_get_debug() >= 1) { - Debugprintf("IL2P header INVALID.\n"); - } - - F->state = IL2P_SEARCHING; - } - } // good header after FEC. - else { - F->state = IL2P_SEARCHING; // Header failed FEC check. - } - } // entire header has been collected. - } // full byte collected. - break; - - case IL2P_PAYLOAD: // Gathering the payload, if any. - - F->bc++; - if (F->bc == 8) { // full byte has been collected. - F->bc = 0; - if (!F->polarity) { - F->spayload[F->pc++] = F->acc & 0xff; - } - else { - F->spayload[F->pc++] = (~F->acc) & 0xff; - } - if (F->pc == F->eplen) { - - // TODO?: for symmetry it seems like we should clarify the payload before combining. - - F->state = IL2P_DECODE; - } - } - break; - - case IL2P_DECODE: - // We get here after a good header and any payload has been collected. - // Processing is delayed by one bit but I think it makes the logic cleaner. - // During unit testing be sure to send an extra bit to flush it out at the end. - - // in uhdr[IL2P_HEADER_SIZE]; // Header after FEC and descrambling. - - // TODO?: for symmetry, we might decode the payload here and later build the frame. - - { - packet_t pp = il2p_decode_header_payload(F->uhdr, F->spayload, &(F->corrected)); - - if (il2p_get_debug() >= 1) - { - if (pp == NULL) - { - // Most likely too many FEC errors. - Debugprintf("FAILED to construct frame in %s.\n", __func__); - } - } - - if (pp != NULL) { - alevel_t alevel = demod_get_audio_level(chan, subchan); - retry_t retries = F->corrected; - int is_fx25 = 1; // FIXME: distinguish fx.25 and IL2P. - // Currently this just means that a FEC mode was used. - - // TODO: Could we put last 3 arguments in packet object rather than passing around separately? - - multi_modem_process_rec_packet(chan, subchan, slice, pp, alevel, retries, is_fx25, slice, centreFreq[chan]); - } - } // end block for local variables. - - if (il2p_get_debug() >= 1) { - - Debugprintf("-----"); - } - - F->state = IL2P_SEARCHING; - break; - - } // end of switch - -} // end il2p_rec_bit - - - - - - - -// Scramble bits for il2p transmit. - -// Note that there is a delay of 5 until the first bit comes out. -// So we need to need to ignore the first 5 out and stick in -// an extra 5 filler bits to flush at the end. - -#define INIT_TX_LSFR 0x00f - -static inline int scramble_bit(int in, int *state) -{ - int out = ((*state >> 4) ^ *state) & 1; - *state = ((((in ^ *state) & 1) << 9) | (*state ^ ((*state & 1) << 4))) >> 1; - return (out); -} - - -// Undo data scrambling for il2p receive. - -#define INIT_RX_LSFR 0x1f0 - -static inline int descramble_bit(int in, int *state) -{ - int out = (in ^ *state) & 1; - *state = ((*state >> 1) | ((in & 1) << 8)) ^ ((in & 1) << 3); - return (out); -} - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_scramble_block - * - * Purpose: Scramble a block before adding RS parity. - * - * Inputs: in Array of bytes. - * len Number of bytes both in and out. - * - * Outputs: out Array of bytes. - * - *--------------------------------------------------------------------------------*/ - -void il2p_scramble_block(unsigned char *in, unsigned char *out, int len) -{ - int tx_lfsr_state = INIT_TX_LSFR; - - memset(out, 0, len); - - int skipping = 1; // Discard the first 5 out. - int ob = 0; // Index to output byte. - int om = 0x80; // Output bit mask; - for (int ib = 0; ib < len; ib++) { - for (int im = 0x80; im != 0; im >>= 1) { - int s = scramble_bit((in[ib] & im) != 0, &tx_lfsr_state); - if (ib == 0 && im == 0x04) skipping = 0; - if (!skipping) { - if (s) { - out[ob] |= om; - } - om >>= 1; - if (om == 0) { - om = 0x80; - ob++; - } - } - } - } - // Flush it. - - // This is a relic from when I thought the state would need to - // be passed along for the next block. - // Preserve the LSFR state from before flushing. - // This might be needed as the initial state for later payload blocks. - int x = tx_lfsr_state; - for (int n = 0; n < 5; n++) { - int s = scramble_bit(0, &x); - if (s) { - out[ob] |= om; - } - om >>= 1; - if (om == 0) { - om = 0x80; - ob++; - } - } - -} // end il2p_scramble_block - - - -/*-------------------------------------------------------------------------------- - * - * Function: il2p_descramble_block - * - * Purpose: Descramble a block after removing RS parity. - * - * Inputs: in Array of bytes. - * len Number of bytes both in and out. - * - * Outputs: out Array of bytes. - * - *--------------------------------------------------------------------------------*/ - -void il2p_descramble_block(unsigned char *in, unsigned char *out, int len) -{ - int rx_lfsr_state = INIT_RX_LSFR; - - memset(out, 0, len); - - for (int b = 0; b < len; b++) { - for (int m = 0x80; m != 0; m >>= 1) { - int d = descramble_bit((in[b] & m) != 0, &rx_lfsr_state); - if (d) { - out[b] |= m; - } - } - } -} - -// end il2p_scramble.c - - - - -static int number_of_bits_sent[MAX_CHANS]; // Count number of bits sent by "il2p_send_frame" - -static void send_bytes(int chan, unsigned char *b, int count, int polarity); -static void send_bit(int chan, int b, int polarity); - - - -/*------------------------------------------------------------- - * - * Name: il2p_send_frame - * - * Purpose: Convert frames to a stream of bits in IL2P format. - * - * Inputs: chan - Audio channel number, 0 = first. - * - * pp - Pointer to packet object. - * - * max_fec - 1 to force 16 parity symbols for each payload block. - * 0 for automatic depending on block size. - * - * polarity - 0 for normal. 1 to invert signal. - * 2 special case for testing - introduce some errors to test FEC. - * - * Outputs: Bits are shipped out by calling tone_gen_put_bit(). - * - * Returns: Number of bits sent including - * - Preamble (01010101...) - * - 3 byte Sync Word. - * - 15 bytes for Header. - * - Optional payload. - * The required time can be calculated by dividing this - * number by the transmit rate of bits/sec. - * -1 is returned for failure. - * - * Description: Generate an IL2P encoded frame. - * - * Assumptions: It is assumed that the tone_gen module has been - * properly initialized so that bits sent with - * tone_gen_put_bit() are processed correctly. - * - * Errors: Return -1 for error. Probably frame too large. - * - * Note: Inconsistency here. ax25 version has just a byte array - * and length going in. Here we need the full packet object. - * - *--------------------------------------------------------------*/ - -string * il2p_send_frame(int chan, packet_t pp, int max_fec, int polarity) -{ - unsigned char encoded[IL2P_MAX_PACKET_SIZE]; - string * packet = newString(); - int preamblecount; - unsigned char preamble[1024]; - - - encoded[0] = (IL2P_SYNC_WORD >> 16) & 0xff; - encoded[1] = (IL2P_SYNC_WORD >> 8) & 0xff; - encoded[2] = (IL2P_SYNC_WORD) & 0xff; - - int elen = il2p_encode_frame(pp, max_fec, encoded + IL2P_SYNC_WORD_SIZE); - if (elen <= 0) { - Debugprintf("IL2P: Unable to encode frame into IL2P.\n"); - return (packet); - } - - elen += IL2P_SYNC_WORD_SIZE; - - number_of_bits_sent[chan] = 0; - - if (il2p_get_debug() >= 1) { - Debugprintf("IL2P frame, max_fec = %d, %d encoded bytes total", max_fec, elen); -// fx_hex_dump(encoded, elen); - } - - // Send bits to modulator. - - // Try using preaamble for txdelay - - preamblecount = (txdelay[chan] * tx_baudrate[chan]) / 8000; // 8 for bits, 1000 for mS - - if (preamblecount > 1024) - preamblecount = 1024; - - memset(preamble, IL2P_PREAMBLE, preamblecount); - - stringAdd(packet, preamble, preamblecount); - stringAdd(packet, encoded, elen); - - tx_fx25_size[chan] = packet->Length * 8; - - return packet; -} - - - -// TX Code. Builds whole packet then sends a bit at a time - -#define TX_SILENCE 0 -#define TX_DELAY 1 -#define TX_TAIL 2 -#define TX_NO_DATA 3 -#define TX_FRAME 4 -#define TX_WAIT_BPF 5 - - -#define TX_BIT0 0 -#define TX_BIT1 1 -#define FRAME_EMPTY 0 -#define FRAME_FULL 1 -#define FRAME_NO_FRAME 2 -#define FRAME_NEW_FRAME 3 -#define BYTE_EMPTY 0 -#define BYTE_FULL 1 - -extern UCHAR tx_frame_status[5]; -extern UCHAR tx_byte_status[5]; -extern string * tx_data[5]; -extern int tx_data_len[5]; -extern UCHAR tx_bit_stream[5]; -extern UCHAR tx_bit_cnt[5]; -extern long tx_tail_cnt[5]; -extern BOOL tx_bs_bit[5]; - -string * fill_il2p_data(int snd_ch, string * data) -{ - string * result; - packet_t pp = ax25_new(); - - - // Call il2p_send_frame to build the bit stream - - pp->frame_len = data->Length - 2; // Included CRC - memcpy(pp->frame_data, data->Data, data->Length); - - result = il2p_send_frame(snd_ch, pp, 1, 0); - - return result; -} - - - -void il2p_get_new_frame(int snd_ch, TStringList * frame_stream) -{ - string * myTemp; - - tx_bs_bit[snd_ch] = 0; - tx_bit_cnt[snd_ch] = 0; - tx_fx25_size_cnt[snd_ch] = 0; - tx_fx25_size[snd_ch] = 1; - tx_frame_status[snd_ch] = FRAME_NEW_FRAME; - tx_byte_status[snd_ch] = BYTE_EMPTY; - - if (frame_stream->Count == 0) - tx_frame_status[snd_ch] = FRAME_NO_FRAME; - else - { - // We now pass control byte and ack bytes on front and pointer to socket on end if ackmode - - myTemp = Strings(frame_stream, 0); // get message - - if ((myTemp->Data[0] & 0x0f) == 12) // ACKMODE - { - // Save copy then copy data up 3 bytes - - Add(&KISS_acked[snd_ch], duplicateString(myTemp)); - - mydelete(myTemp, 0, 3); - myTemp->Length -= sizeof(void *); - } - else - { - // Just remove control - - mydelete(myTemp, 0, 1); - } - - AGW_AX25_frame_analiz(snd_ch, FALSE, myTemp); - put_frame(snd_ch, myTemp, "", TRUE, FALSE); - - tx_data[snd_ch] = fill_il2p_data(snd_ch, myTemp); - - Delete(frame_stream, 0); // This will invalidate temp - } -} - - - -// Original code - -/* -static void send_bytes(int chan, unsigned char *b, int count, int polarity) -{ - for (int j = 0; j < count; j++) { - unsigned int x = b[j]; - for (int k = 0; k < 8; k++) { - send_bit(chan, (x & 0x80) != 0, polarity); - x <<= 1; - } - } -} - -// NRZI would be applied for AX.25 but IL2P does not use it. -// However we do have an option to invert the signal. -// The direwolf receive implementation will automatically compensate -// for either polarity but other implementations might not. - -static void send_bit(int chan, int b, int polarity) -{ - tone_gen_put_bit(chan, (b ^ polarity) & 1); - number_of_bits_sent[chan]++; -} -*/ - - - - -int il2p_get_new_bit(int snd_ch, Byte bit) -{ - string *s; - - if (tx_frame_status[snd_ch] == FRAME_EMPTY) - { - il2p_get_new_frame(snd_ch, &all_frame_buf[snd_ch]); - if (tx_frame_status[snd_ch] == FRAME_NEW_FRAME) - tx_frame_status[snd_ch] = FRAME_FULL; - } - - if (tx_frame_status[snd_ch] == FRAME_FULL) - { - if (tx_byte_status[snd_ch] == BYTE_EMPTY) - { - if (tx_data[snd_ch]->Length) - { - s = tx_data[snd_ch]; - - tx_bit_stream[snd_ch] = s->Data[0]; - tx_frame_status[snd_ch] = FRAME_FULL; - tx_byte_status[snd_ch] = BYTE_FULL; - tx_bit_cnt[snd_ch] = 0; - mydelete(tx_data[snd_ch], 0, 1); - } - else - tx_frame_status[snd_ch] = FRAME_EMPTY; - } - if (tx_byte_status[snd_ch] == BYTE_FULL) - { - // il2p sends high order bit first - - bit = tx_bit_stream[snd_ch] >> 7; // top bit to bottom - - tx_bit_stream[snd_ch] = tx_bit_stream[snd_ch] << 1; - tx_bit_cnt[snd_ch]++; - tx_fx25_size_cnt[snd_ch]++; - if (tx_bit_cnt[snd_ch] >= 8) - tx_byte_status[snd_ch] = BYTE_EMPTY; - if (tx_fx25_size_cnt[snd_ch] == tx_fx25_size[snd_ch]) - tx_frame_status[snd_ch] = FRAME_EMPTY; - } - } - - if (tx_frame_status[snd_ch] == FRAME_EMPTY) - { - il2p_get_new_frame(snd_ch, &all_frame_buf[snd_ch]); - - switch (tx_frame_status[snd_ch]) - { - case FRAME_NEW_FRAME: - tx_frame_status[snd_ch] = FRAME_FULL; - break; - - case FRAME_NO_FRAME: - tx_tail_cnt[snd_ch] = 0; - tx_frame_status[snd_ch] = FRAME_EMPTY; - tx_status[snd_ch] = TX_TAIL; - break; - } - } - return bit; -} - - - diff --git a/kiss.h b/kiss.h deleted file mode 100644 index 1dc40da..0000000 --- a/kiss.h +++ /dev/null @@ -1,24 +0,0 @@ - -/* - * Name: kiss.h - * - * This is for the pseudo terminal KISS interface. - */ - - -#include "ax25_pad.h" /* for packet_t */ - -#include "config.h" - -#include "kiss_frame.h" // for struct kissport_status_s - - -void kisspt_init (struct misc_config_s *misc_config); - -void kisspt_send_rec_packet (int chan, int kiss_cmd, unsigned char *fbuf, int flen, - struct kissport_status_s *notused1, int notused2); - -void kisspt_set_debug (int n); - - -/* end kiss.h */ diff --git a/kiss_frame.h b/kiss_frame.h deleted file mode 100644 index 941f5c0..0000000 --- a/kiss_frame.h +++ /dev/null @@ -1,126 +0,0 @@ - -/* kiss_frame.h */ - -#ifndef KISS_FRAME_H -#define KISS_FRAME_H - - -#include "audio.h" /* for struct audio_s */ - - -/* - * The first byte of a KISS frame has: - * channel in upper nybble. - * command in lower nybble. - */ - -#define KISS_CMD_DATA_FRAME 0 -#define KISS_CMD_TXDELAY 1 -#define KISS_CMD_PERSISTENCE 2 -#define KISS_CMD_SLOTTIME 3 -#define KISS_CMD_TXTAIL 4 -#define KISS_CMD_FULLDUPLEX 5 -#define KISS_CMD_SET_HARDWARE 6 -#define XKISS_CMD_DATA 12 // Not supported. http://he.fi/pub/oh7lzb/bpq/multi-kiss.pdf -#define XKISS_CMD_POLL 14 // Not supported. -#define KISS_CMD_END_KISS 15 - - - -/* - * Special characters used by SLIP protocol. - */ - -#define FEND 0xC0 -#define FESC 0xDB -#define TFEND 0xDC -#define TFESC 0xDD - - - -enum kiss_state_e { - KS_SEARCHING = 0, /* Looking for FEND to start KISS frame. */ - /* Must be 0 so we can simply zero whole structure to initialize. */ - KS_COLLECTING}; /* In process of collecting KISS frame. */ - - -#define MAX_KISS_LEN 2048 /* Spec calls for at least 1024. */ - /* Might want to make it longer to accommodate */ - /* maximum packet length. */ - -#define MAX_NOISE_LEN 100 - -typedef struct kiss_frame_s { - - enum kiss_state_e state; - - unsigned char kiss_msg[MAX_KISS_LEN]; - /* Leading FEND is optional. */ - /* Contains escapes and ending FEND. */ - int kiss_len; - - unsigned char noise[MAX_NOISE_LEN]; - int noise_len; - -} kiss_frame_t; - - -// This is used only for TCPKISS but it put in kissnet.h, -// there would be a circular dependency between the two header files. -// Each KISS TCP port has its own status block. - -struct kissport_status_s { - - struct kissport_status_s *pnext; // To next in list. - - volatile int arg2; // temp for passing second arg into - // kissnet_listen_thread - - int tcp_port; // default 8001 - - int chan; // Radio channel for this tcp port. - // -1 for all. - - // The default is a limit of 3 client applications at the same time. - // You can increase the limit by changing the line below. - // A larger number consumes more resources so don't go crazy by making it larger than needed. - // TODO: Should this be moved to direwolf.h so max number of audio devices - // client apps are in the same place? - -#define MAX_NET_CLIENTS 3 - - int client_sock[MAX_NET_CLIENTS]; - /* File descriptor for socket for */ - /* communication with client application. */ - /* Set to -1 if not connected. */ - /* (Don't use SOCKET type because it is unsigned.) */ - - kiss_frame_t kf[MAX_NET_CLIENTS]; - /* Accumulated KISS frame and state of decoder. */ -}; - - - -#ifndef KISSUTIL -void kiss_frame_init (struct audio_s *pa); -#endif - -int kiss_encapsulate (unsigned char *in, int ilen, unsigned char *out); - -int kiss_unwrap (unsigned char *in, int ilen, unsigned char *out); - -void kiss_rec_byte (kiss_frame_t *kf, unsigned char ch, int debug, struct kissport_status_s *kps, int client, - void (*sendfun)(int chan, int kiss_cmd, unsigned char *fbuf, int flen, struct kissport_status_s *onlykps, int onlyclient)); - -typedef enum fromto_e { FROM_CLIENT=0, TO_CLIENT=1 } fromto_t; - -void kiss_process_msg (unsigned char *kiss_msg, int kiss_len, int debug, struct kissport_status_s *kps, int client, - void (*sendfun)(int chan, int kiss_cmd, unsigned char *fbuf, int flen, struct kissport_status_s *onlykps, int onlyclient)); - -void kiss_debug_print (fromto_t fromto, char *special, unsigned char *pmsg, int msg_len); - - -#endif // KISS_FRAME_H - - -/* end kiss_frame.h */ diff --git a/kiss_mode.c b/kiss_mode.c index 5adba5d..72688a7 100644 --- a/kiss_mode.c +++ b/kiss_mode.c @@ -245,7 +245,6 @@ void ProcessKISSFrame(void * socket, UCHAR * Msg, int Len) Add(&KISS.buffer[Chan], TXMSG); } - return; case KISS_DATA: diff --git a/kissnet.h b/kissnet.h deleted file mode 100644 index 469e4e6..0000000 --- a/kissnet.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Name: kissnet.h - */ - -#ifndef KISSNET_H -#define KISSNET_H - -#include "ax25_pad.h" /* for packet_t */ - -#include "config.h" - -#include "kiss_frame.h" - - - -void kissnet_init (struct misc_config_s *misc_config); - -void kissnet_send_rec_packet (int chan, int kiss_cmd, unsigned char *fbuf, int flen, - struct kissport_status_s *onlykps, int onlyclient); - -void kiss_net_set_debug (int n); - -void kissnet_copy (unsigned char *kiss_msg, int kiss_len, int chan, int cmd, struct kissport_status_s *from_kps, int from_client); - - -#endif // KISSNET_H - -/* end kissnet.h */ diff --git a/kissserial.h b/kissserial.h deleted file mode 100644 index 44fb3c3..0000000 --- a/kissserial.h +++ /dev/null @@ -1,23 +0,0 @@ - -/* - * Name: kissserial.h - */ - - -#include "ax25_pad.h" /* for packet_t */ - -#include "config.h" - -#include "kiss_frame.h" - - -void kissserial_init (struct misc_config_s *misc_config); - -void kissserial_send_rec_packet (int chan, int kiss_cmd, unsigned char *fbuf, int flen, - struct kissport_status_s *notused1, int notused2); - - -void kissserial_set_debug (int n); - - -/* end kissserial.h */ diff --git a/latlong.h b/latlong.h deleted file mode 100644 index ae98fe6..0000000 --- a/latlong.h +++ /dev/null @@ -1,24 +0,0 @@ - -/* latlong.h */ - - -/* Use this value for unknown latitude/longitude or other values. */ - -#define G_UNKNOWN (-999999) - - -void latitude_to_str (double dlat, int ambiguity, char *slat); -void longitude_to_str (double dlong, int ambiguity, char *slong); - -void latitude_to_comp_str (double dlat, char *clat); -void longitude_to_comp_str (double dlon, char *clon); - -void latitude_to_nmea (double dlat, char *slat, char *hemi); -void longitude_to_nmea (double dlong, char *slong, char *hemi); - -double latitude_from_nmea (char *pstr, char *phemi); -double longitude_from_nmea (char *pstr, char *phemi); - -double ll_distance_km (double lat1, double lon1, double lat2, double lon2); - -int ll_from_grid_square (char *maidenhead, double *dlat, double *dlon); \ No newline at end of file diff --git a/log.h b/log.h deleted file mode 100644 index 3afb6b1..0000000 --- a/log.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* log.h */ - - -#include "hdlc_rec2.h" // for retry_t - -#include "decode_aprs.h" // for decode_aprs_t - -#include "ax25_pad.h" - - - -void log_init (int daily_names, char *path); - -void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries); - -void log_rr_bits (decode_aprs_t *A, packet_t pp); - -void log_term (void); \ No newline at end of file diff --git a/main.cpp b/main.cpp index 402e849..43ea7cd 100644 --- a/main.cpp +++ b/main.cpp @@ -53,6 +53,8 @@ int main(int argc, char *argv[]) qDebug() << Title; + + if (nonGUIMode) a = new QCoreApplication(argc, argv); else @@ -60,6 +62,7 @@ int main(int argc, char *argv[]) getSettings(); + t = new workerThread; if (nonGUIMode == 0) @@ -85,4 +88,3 @@ int main(int argc, char *argv[]) } - diff --git a/mgn_icon.h b/mgn_icon.h deleted file mode 100644 index c870bc0..0000000 --- a/mgn_icon.h +++ /dev/null @@ -1,276 +0,0 @@ - - -/* - * MGN_icon.h - * - * Waypoint icon codes for use in the $PMGNWPL sentence. - * - * Derived from Data Transmission Protocol For Magellan Products - version 2.11, March 2003 - * - * http://www.gpsinformation.org/mag-proto-2-11.pdf - * - * - * That's 13 years ago. There should be something newer available but I can't find it. - * - * The is based on the newer models at the time. Earlier models had shorter incompatible icon lists. - */ - - - -#define MGN_crossed_square "a" -#define MGN_box "b" -#define MGN_house "c" -#define MGN_aerial "d" -#define MGN_airport "e" -#define MGN_amusement_park "f" -#define MGN_ATM "g" -#define MGN_auto_repair "h" -#define MGN_boating "I" -#define MGN_camping "j" -#define MGN_exit_ramp "k" -#define MGN_first_aid "l" -#define MGN_nav_aid "m" -#define MGN_buoy "n" -#define MGN_fuel "o" -#define MGN_garden "p" -#define MGN_golf "q" -#define MGN_hotel "r" -#define MGN_hunting_fishing "s" -#define MGN_large_city "t" -#define MGN_lighthouse "u" -#define MGN_major_city "v" -#define MGN_marina "w" -#define MGN_medium_city "x" -#define MGN_museum "y" -#define MGN_obstruction "z" -#define MGN_park "aa" -#define MGN_resort "ab" -#define MGN_restaurant "ac" -#define MGN_rock "ad" -#define MGN_scuba "ae" -#define MGN_RV_service "af" -#define MGN_shooting "ag" -#define MGN_sight_seeing "ah" -#define MGN_small_city "ai" -#define MGN_sounding "aj" -#define MGN_sports_arena "ak" -#define MGN_tourist_info "al" -#define MGN_truck_service "am" -#define MGN_winery "an" -#define MGN_wreck "ao" -#define MGN_zoo "ap" - - -/* - * Mapping from APRS symbols to Magellan. - * - * This is a bit of a challenge because there - * are no icons for moving objects. - * We can use airport for flying things but - * what about wheeled transportation devices? - */ - -// TODO: NEEDS MORE WORK!!! - - -#define MGN_default MGN_crossed_square - -#define SYMTAB_SIZE 95 - -static const char mgn_primary_symtab[SYMTAB_SIZE][3] = { - - MGN_default, // 00 --no-symbol-- - MGN_default, // ! 01 Police, Sheriff - MGN_default, // " 02 reserved (was rain) - MGN_aerial, // # 03 DIGI (white center) - MGN_default, // $ 04 PHONE - MGN_aerial, // % 05 DX CLUSTER - MGN_aerial, // & 06 HF GATEway - MGN_airport, // ' 07 Small AIRCRAFT - MGN_aerial, // ( 08 Mobile Satellite Station - MGN_default, // ) 09 Wheelchair (handicapped) - MGN_default, // * 10 SnowMobile - MGN_default, // + 11 Red Cross - MGN_default, // , 12 Boy Scouts - MGN_house, // - 13 House QTH (VHF) - MGN_default, // . 14 X - MGN_default, // / 15 Red Dot - MGN_default, // 0 16 # circle (obsolete) - MGN_default, // 1 17 TBD - MGN_default, // 2 18 TBD - MGN_default, // 3 19 TBD - MGN_default, // 4 20 TBD - MGN_default, // 5 21 TBD - MGN_default, // 6 22 TBD - MGN_default, // 7 23 TBD - MGN_default, // 8 24 TBD - MGN_default, // 9 25 TBD - MGN_default, // : 26 FIRE - MGN_camping, // ; 27 Campground (Portable ops) - MGN_default, // < 28 Motorcycle - MGN_default, // = 29 RAILROAD ENGINE - MGN_default, // > 30 CAR - MGN_default, // ? 31 SERVER for Files - MGN_default, // @ 32 HC FUTURE predict (dot) - MGN_first_aid, // A 33 Aid Station - MGN_aerial, // B 34 BBS or PBBS - MGN_boating, // C 35 Canoe - MGN_default, // D 36 - MGN_default, // E 37 EYEBALL (Eye catcher!) - MGN_default, // F 38 Farm Vehicle (tractor) - MGN_default, // G 39 Grid Square (6 digit) - MGN_hotel, // H 40 HOTEL (blue bed symbol) - MGN_aerial, // I 41 TcpIp on air network stn - MGN_default, // J 42 - MGN_default, // K 43 School - MGN_default, // L 44 PC user - MGN_default, // M 45 MacAPRS - MGN_aerial, // N 46 NTS Station - MGN_airport, // O 47 BALLOON - MGN_default, // P 48 Police - MGN_default, // Q 49 TBD - MGN_RV_service, // R 50 REC. VEHICLE - MGN_airport, // S 51 SHUTTLE - MGN_default, // T 52 SSTV - MGN_default, // U 53 BUS - MGN_default, // V 54 ATV - MGN_default, // W 55 National WX Service Site - MGN_default, // X 56 HELO - MGN_boating, // Y 57 YACHT (sail) - MGN_default, // Z 58 WinAPRS - MGN_default, // [ 59 Human/Person (HT) - MGN_default, // \ 60 TRIANGLE(DF station) - MGN_default, // ] 61 MAIL/PostOffice(was PBBS) - MGN_airport, // ^ 62 LARGE AIRCRAFT - MGN_default, // _ 63 WEATHER Station (blue) - MGN_aerial, // ` 64 Dish Antenna - MGN_default, // a 65 AMBULANCE - MGN_default, // b 66 BIKE - MGN_default, // c 67 Incident Command Post - MGN_default, // d 68 Fire dept - MGN_zoo, // e 69 HORSE (equestrian) - MGN_default, // f 70 FIRE TRUCK - MGN_airport, // g 71 Glider - MGN_default, // h 72 HOSPITAL - MGN_default, // i 73 IOTA (islands on the air) - MGN_default, // j 74 JEEP - MGN_default, // k 75 TRUCK - MGN_default, // l 76 Laptop - MGN_aerial, // m 77 Mic-E Repeater - MGN_default, // n 78 Node (black bulls-eye) - MGN_default, // o 79 EOC - MGN_zoo, // p 80 ROVER (puppy, or dog) - MGN_default, // q 81 GRID SQ shown above 128 m - MGN_aerial, // r 82 Repeater - MGN_default, // s 83 SHIP (pwr boat) - MGN_default, // t 84 TRUCK STOP - MGN_default, // u 85 TRUCK (18 wheeler) - MGN_default, // v 86 VAN - MGN_default, // w 87 WATER station - MGN_aerial, // x 88 xAPRS (Unix) - MGN_aerial, // y 89 YAGI @ QTH - MGN_default, // z 90 TBD - MGN_default, // { 91 - MGN_default, // | 92 TNC Stream Switch - MGN_default, // } 93 - MGN_default }; // ~ 94 TNC Stream Switch - - -static const char mgn_alternate_symtab[SYMTAB_SIZE][3] = { - - MGN_default, // 00 --no-symbol-- - MGN_default, // ! 01 EMERGENCY (!) - MGN_default, // " 02 reserved - MGN_aerial, // # 03 OVERLAY DIGI (green star) - MGN_ATM, // $ 04 Bank or ATM (green box) - MGN_default, // % 05 Power Plant with overlay - MGN_aerial, // & 06 I=Igte IGate R=RX T=1hopTX 2=2hopTX - MGN_default, // ' 07 Crash (& now Incident sites) - MGN_default, // ( 08 CLOUDY (other clouds w ovrly) - MGN_aerial, // ) 09 Firenet MEO, MODIS Earth Obs. - MGN_default, // * 10 SNOW (& future ovrly codes) - MGN_default, // + 11 Church - MGN_default, // , 12 Girl Scouts - MGN_house, // - 13 House (H=HF) (O = Op Present) - MGN_default, // . 14 Ambiguous (Big Question mark) - MGN_default, // / 15 Waypoint Destination - MGN_default, // 0 16 CIRCLE (E/I/W=IRLP/Echolink/WIRES) - MGN_default, // 1 17 - MGN_default, // 2 18 - MGN_default, // 3 19 - MGN_default, // 4 20 - MGN_default, // 5 21 - MGN_default, // 6 22 - MGN_default, // 7 23 - MGN_aerial, // 8 24 802.11 or other network node - MGN_fuel, // 9 25 Gas Station (blue pump) - MGN_default, // : 26 Hail (& future ovrly codes) - MGN_park, // ; 27 Park/Picnic area - MGN_default, // < 28 ADVISORY (one WX flag) - MGN_default, // = 29 APRStt Touchtone (DTMF users) - MGN_default, // > 30 OVERLAID CAR - MGN_tourist_info, // ? 31 INFO Kiosk (Blue box with ?) - MGN_default, // @ 32 HURRICANE/Trop-Storm - MGN_box, // A 33 overlayBOX DTMF & RFID & XO - MGN_default, // B 34 Blwng Snow (& future codes) - MGN_boating, // C 35 Coast Guard - MGN_default, // D 36 Drizzle (proposed APRStt) - MGN_default, // E 37 Smoke (& other vis codes) - MGN_default, // F 38 Freezng rain (&future codes) - MGN_default, // G 39 Snow Shwr (& future ovrlys) - MGN_default, // H 40 Haze (& Overlay Hazards) - MGN_default, // I 41 Rain Shower - MGN_default, // J 42 Lightning (& future ovrlys) - MGN_default, // K 43 Kenwood HT (W) - MGN_lighthouse, // L 44 Lighthouse - MGN_default, // M 45 MARS (A=Army,N=Navy,F=AF) - MGN_buoy, // N 46 Navigation Buoy - MGN_airport, // O 47 Rocket - MGN_default, // P 48 Parking - MGN_default, // Q 49 QUAKE - MGN_restaurant, // R 50 Restaurant - MGN_aerial, // S 51 Satellite/Pacsat - MGN_default, // T 52 Thunderstorm - MGN_default, // U 53 SUNNY - MGN_nav_aid, // V 54 VORTAC Nav Aid - MGN_default, // W 55 # NWS site (NWS options) - MGN_default, // X 56 Pharmacy Rx (Apothicary) - MGN_aerial, // Y 57 Radios and devices - MGN_default, // Z 58 - MGN_default, // [ 59 W.Cloud (& humans w Ovrly) - MGN_default, // \ 60 New overlayable GPS symbol - MGN_default, // ] 61 - MGN_airport, // ^ 62 # Aircraft (shows heading) - MGN_default, // _ 63 # WX site (green digi) - MGN_default, // ` 64 Rain (all types w ovrly) - MGN_aerial, // a 65 ARRL, ARES, WinLINK - MGN_default, // b 66 Blwng Dst/Snd (& others) - MGN_default, // c 67 CD triangle RACES/SATERN/etc - MGN_default, // d 68 DX spot by callsign - MGN_default, // e 69 Sleet (& future ovrly codes) - MGN_default, // f 70 Funnel Cloud - MGN_default, // g 71 Gale Flags - MGN_default, // h 72 Store. or HAMFST Hh=HAM store - MGN_box, // i 73 BOX or points of Interest - MGN_default, // j 74 WorkZone (Steam Shovel) - MGN_default, // k 75 Special Vehicle SUV,ATV,4x4 - MGN_default, // l 76 Areas (box,circles,etc) - MGN_default, // m 77 Value Sign (3 digit display) - MGN_default, // n 78 OVERLAY TRIANGLE - MGN_default, // o 79 small circle - MGN_default, // p 80 Prtly Cldy (& future ovrlys) - MGN_default, // q 81 - MGN_default, // r 82 Restrooms - MGN_default, // s 83 OVERLAY SHIP/boat (top view) - MGN_default, // t 84 Tornado - MGN_default, // u 85 OVERLAID TRUCK - MGN_default, // v 86 OVERLAID Van - MGN_default, // w 87 Flooding - MGN_wreck, // x 88 Wreck or Obstruction ->X<- - MGN_default, // y 89 Skywarn - MGN_default, // z 90 OVERLAID Shelter - MGN_default, // { 91 Fog (& future ovrly codes) - MGN_default, // | 92 TNC Stream Switch - MGN_default, // } 93 - MGN_default }; // ~ 94 TNC Stream Switch - diff --git a/mheard.h b/mheard.h deleted file mode 100644 index f8466ba..0000000 --- a/mheard.h +++ /dev/null @@ -1,20 +0,0 @@ - - -/* mheard.h */ - -#include "decode_aprs.h" // for decode_aprs_t - - -void mheard_init (int debug); - -void mheard_save_rf (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries); - -void mheard_save_is (char *ptext); - -int mheard_count (int max_hops, int time_limit); - -int mheard_was_recently_nearby (char *role, char *callsign, int time_limit, int max_hops, double dlat, double dlon, double km); - -void mheard_set_msp (char *callsign, int num); - -int mheard_get_msp (char *callsign); \ No newline at end of file diff --git a/morse.h b/morse.h deleted file mode 100644 index e34dd7b..0000000 --- a/morse.h +++ /dev/null @@ -1,8 +0,0 @@ -/* morse.h */ - -int morse_init (struct audio_s *audio_config_p, int amp) ; - -int morse_send (int chan, char *str, int wpm, int txdelay, int txtail); - -#define MORSE_DEFAULT_WPM 10 - diff --git a/multi_modem.h b/multi_modem.h deleted file mode 100644 index de3061e..0000000 --- a/multi_modem.h +++ /dev/null @@ -1,24 +0,0 @@ -/* multi_modem.h */ - -#ifndef MULTI_MODEM_H -#define MULTI_MODEM 1 - -/* Needed for typedef retry_t. */ -#include "hdlc_rec2.h" - -/* Needed for struct audio_s */ -#include "audio.h" - - -void multi_modem_init (struct audio_s *pmodem); - -void multi_modem_process_sample (int c, int audio_sample); - -int multi_modem_get_dc_average (int chan); - -// Deprecated. Replace with ...packet -void multi_modem_process_rec_frame (int chan, int subchan, int slice, unsigned char *fbuf, int flen, alevel_t alevel, retry_t retries, int is_fx25); - -void multi_modem_process_rec_packet (int chan, int subchan, int slice, packet_t pp, alevel_t alevel, retry_t retries, int is_fx25); - -#endif diff --git a/pfilter.h b/pfilter.h deleted file mode 100644 index d54e056..0000000 --- a/pfilter.h +++ /dev/null @@ -1,13 +0,0 @@ - -/* pfilter.h */ - - -#include "igate.h" // for igate_config_s - - - -void pfilter_init (struct igate_config_s *p_igate_config, int debug_level); - -int pfilter (int from_chan, int to_chan, char *filter, packet_t pp, int is_aprs); - -int is_telem_metadata (char *infop); \ No newline at end of file diff --git a/ptt.h b/ptt.h deleted file mode 100644 index 6e75253..0000000 --- a/ptt.h +++ /dev/null @@ -1,26 +0,0 @@ - - -#ifndef PTT_H -#define PTT_H 1 - - -#include "audio.h" /* for struct audio_s and definitions for octype values */ - - -void ptt_set_debug(int debug); - -void ptt_init (struct audio_s *p_modem); - -void ptt_set (int octype, int chan, int ptt); - -void ptt_term (void); - -int get_input (int it, int chan); - -#endif - - -/* end ptt.h */ - - - diff --git a/recv.h b/recv.h deleted file mode 100644 index 3201991..0000000 --- a/recv.h +++ /dev/null @@ -1,6 +0,0 @@ - -/* recv.h */ - -void recv_init (struct audio_s *pa); - -void recv_process (void); \ No newline at end of file diff --git a/redecode.h b/redecode.h deleted file mode 100644 index ffd9a95..0000000 --- a/redecode.h +++ /dev/null @@ -1,15 +0,0 @@ - - -#ifndef REDECODE_H -#define REDECODE_H 1 - -#include "rrbb.h" - - -extern void redecode_init (struct audio_s *p_audio_config); - - -#endif - -/* end redecode.h */ - diff --git a/release/moc_predefs-DESKTOP-MHE5LO8.h b/release/moc_predefs.h similarity index 95% rename from release/moc_predefs-DESKTOP-MHE5LO8.h rename to release/moc_predefs.h index 4c9c0c7..54e9037 100644 --- a/release/moc_predefs-DESKTOP-MHE5LO8.h +++ b/release/moc_predefs.h @@ -1,11 +1,11 @@ -#define _MSC_EXTENSIONS -#define _INTEGRAL_MAX_BITS 64 -#define _MSC_VER 1916 -#define _MSC_FULL_VER 191627043 -#define _MSC_BUILD 0 -#define _WIN32 -#define _M_IX86 600 -#define _M_IX86_FP 2 -#define _CPPRTTI -#define _MT -#define _DLL +#define _MSC_EXTENSIONS +#define _INTEGRAL_MAX_BITS 64 +#define _MSC_VER 1916 +#define _MSC_FULL_VER 191627043 +#define _MSC_BUILD 0 +#define _WIN32 +#define _M_IX86 600 +#define _M_IX86_FP 2 +#define _CPPRTTI +#define _MT +#define _DLL diff --git a/rpack.h b/rpack.h deleted file mode 100644 index d972a54..0000000 --- a/rpack.h +++ /dev/null @@ -1,94 +0,0 @@ - -/*------------------------------------------------------------------ - * - * File: rpack.h - * - * Purpose: Definition of Garmin Rino message format. - * - * References: http://www.radio-active.net.au/web3/APRS/Resources/RINO - * - * http://www.radio-active.net.au/web3/APRS/Resources/RINO/OnAir - * - *---------------------------------------------------------------*/ - - -#ifndef RPACK_H -#define RPACK_H 1 - - -#define RPACK_FRAME_LEN 168 - - -#ifdef RPACK_C /* Expose private details */ - - - -// Transmission order is LSB first. - -struct __attribute__((__packed__)) rpack_s { - - int lat; // Latitude. - // Signed integer. Scaled by 2**30/90. - - int lon; // Longitude. Same encoding. - - char unknown1; // Unproven theory: altitude. - char unknown2; - - unsigned name0:6; // 10 character name. - unsigned name1:6; // Bit packing is implementation dependent. - unsigned name2:6; // Should rewrite to be more portable. - unsigned name3:6; - unsigned name4:6; - unsigned name5:6; - unsigned name6:6; - unsigned name7:6; - unsigned name8:6; - unsigned name9:6; - - unsigned symbol:5; - - unsigned unknown3:7; - - -// unsigned crc:16; // Safe bet this is CRC for error checking. - - unsigned char crc1; - unsigned char crc2; - - char dummy[3]; // Total size should be 24 bytes if no gaps. - -}; - -#else /* Show only public interface. */ - - -struct rpack_s { - char stuff[24]; -}; - - -#endif - - - -void rpack_set_bit (struct rpack_s *rp, int position, int value); - -int rpack_is_valid (struct rpack_s *rp); - -int rpack_get_bit (struct rpack_s *rp, int position); - -double rpack_get_lat (struct rpack_s *rp); - -double rpack_get_lon (struct rpack_s *rp); - -int rpack_get_symbol (struct rpack_s *rp); - -void rpack_get_name (struct rpack_s *rp, char *str); - - - -#endif - -/* end rpack.h */ - diff --git a/rrbb.h b/rrbb.h deleted file mode 100644 index 4b28372..0000000 --- a/rrbb.h +++ /dev/null @@ -1,92 +0,0 @@ - -#ifndef RRBB_H - -#define RRBB_H - - -#define FASTER13 1 // Don't pack 8 samples per byte. - - -//typedef short slice_t; - - -/* - * Maximum size (in bytes) of an AX.25 frame including the 2 octet FCS. - */ - -#define MAX_FRAME_LEN ((AX25_MAX_PACKET_LEN) + 2) - -/* - * Maximum number of bits in AX.25 frame excluding the flags. - * Adequate for extreme case of bit stuffing after every 5 bits - * which could never happen. - */ - -#define MAX_NUM_BITS (MAX_FRAME_LEN * 8 * 6 / 5) - -typedef struct rrbb_s { - int magic1; - struct rrbb_s* nextp; /* Next pointer to maintain a queue. */ - - int chan; /* Radio channel from which it was received. */ - int subchan; /* Which modem when more than one per channel. */ - int slice; /* Which slicer. */ - - alevel_t alevel; /* Received audio level at time of frame capture. */ - unsigned int len; /* Current number of samples in array. */ - - int is_scrambled; /* Is data scrambled G3RUH / K9NG style? */ - int descram_state; /* Descrambler state before first data bit of frame. */ - int prev_descram; /* Previous descrambled bit. */ - - unsigned char fdata[MAX_NUM_BITS]; - - int magic2; -} *rrbb_t; - - - -rrbb_t rrbb_new (int chan, int subchan, int slice, int is_scrambled, int descram_state, int prev_descram); - -void rrbb_clear (rrbb_t b, int is_scrambled, int descram_state, int prev_descram); - - -static inline /*__attribute__((always_inline))*/ void rrbb_append_bit (rrbb_t b, const unsigned char val) -{ - if (b->len >= MAX_NUM_BITS) { - return; /* Silently discard if full. */ - } - b->fdata[b->len] = val; - b->len++; -} - -static inline /*__attribute__((always_inline))*/ unsigned char rrbb_get_bit (const rrbb_t b, const int ind) -{ - return (b->fdata[ind]); -} - - -void rrbb_chop8 (rrbb_t b); - -int rrbb_get_len (rrbb_t b); - -//void rrbb_flip_bit (rrbb_t b, unsigned int ind); - -void rrbb_delete (rrbb_t b); - -void rrbb_set_nextp (rrbb_t b, rrbb_t np); -rrbb_t rrbb_get_nextp (rrbb_t b); - -int rrbb_get_chan (rrbb_t b); -int rrbb_get_subchan (rrbb_t b); -int rrbb_get_slice (rrbb_t b); - -void rrbb_set_audio_level (rrbb_t b, alevel_t alevel); -alevel_t rrbb_get_audio_level (rrbb_t b); - -int rrbb_get_is_scrambled (rrbb_t b); -int rrbb_get_descram_state (rrbb_t b); -int rrbb_get_prev_descram (rrbb_t b); - - -#endif diff --git a/serial_port.h b/serial_port.h deleted file mode 100644 index 8a65a0b..0000000 --- a/serial_port.h +++ /dev/null @@ -1,32 +0,0 @@ -/* serial_port.h */ - - -#ifndef SERIAL_PORT_H -#define SERIAL_PORT_H 1 - - -#if __WIN32__ - -#include - -typedef HANDLE MYFDTYPE; -#define MYFDERROR INVALID_HANDLE_VALUE - -#else - -typedef int MYFDTYPE; -#define MYFDERROR (-1) - -#endif - - -extern MYFDTYPE serial_port_open (char *devicename, int baud); - -extern int serial_port_write (MYFDTYPE fd, char *str, int len); - -extern int serial_port_get1 (MYFDTYPE fd); - -extern void serial_port_close (MYFDTYPE fd); - - -#endif \ No newline at end of file diff --git a/server.h b/server.h deleted file mode 100644 index 4cc2ea0..0000000 --- a/server.h +++ /dev/null @@ -1,32 +0,0 @@ - -/* - * Name: server.h - */ - - -#include "ax25_pad.h" /* for packet_t */ - -#include "config.h" - - -void server_set_debug (int n); - -void server_init (struct audio_s *audio_config_p, struct misc_config_s *misc_config); - -void server_send_rec_packet (int chan, packet_t pp, unsigned char *fbuf, int flen); - -void server_send_monitored (int chan, packet_t pp, int own_xmit); - -int server_callsign_registered_by_client (char *callsign); - - -void server_link_established (int chan, int client, char *remote_call, char *own_call, int incoming); - -void server_link_terminated (int chan, int client, char *remote_call, char *own_call, int timeout); - -void server_rec_conn_data (int chan, int client, char *remote_call, char *own_call, int pid, char *data_ptr, int data_len); - -void server_outstanding_frames_reply (int chan, int client, char *own_call, char *remote_call, int count); - - -/* end server.h */ diff --git a/sm_main.c b/sm_main.c index 57bf549..d2c6cfd 100644 --- a/sm_main.c +++ b/sm_main.c @@ -27,7 +27,6 @@ void make_core_BPF(UCHAR snd_ch, short freq, short width); void make_core_TXBPF(UCHAR snd_ch, float freq, float width); void make_core_INTR(UCHAR snd_ch); void make_core_LPF(UCHAR snd_ch, short width); -void wf_pointer(int snd_ch); void dw9600ProcessSample(int snd_ch, short Sample); void init_RUH48(int snd_ch); void init_RUH96(int snd_ch); @@ -65,11 +64,8 @@ int TXPort = 8884; BOOL Firstwaterfall = 1; BOOL Secondwaterfall = 1; - int multiCore = FALSE; - - BOOL MinOnStart = 0; //RS TReedSolomon; // Form1 TForm1; @@ -728,7 +724,7 @@ void init_speed(int snd_ch) form1.show_freq_a; form1.show_freq_b; */ - wf_pointer(snd_ch); + NeedWaterfallHeaders = TRUE; CheckPSKWindows(); } @@ -863,6 +859,8 @@ void runModemthread(void * param) // I think this processes a buffer of samples +int Toggle = 0; + void BufferFull(short * Samples, int nSamples) // These are Stereo Samples { word i, i1, j; @@ -1064,6 +1062,8 @@ void BufferFull(short * Samples, int nSamples) // These are Stereo Samples // Collect samples for both channels if needed + Toggle++; + Needed = FFTSize - fftCount; if (Needed <= rx_bufsize) @@ -1076,7 +1076,8 @@ void BufferFull(short * Samples, int nSamples) // These are Stereo Samples data1 += 2; } - doWaterfall(FirstWaterfallChan); + if ((Toggle & 1) || (UsingBothChannels == 0)) + doWaterfall(FirstWaterfallChan); if (data2) { @@ -1085,9 +1086,13 @@ void BufferFull(short * Samples, int nSamples) // These are Stereo Samples *ptr2++ = *data2; data2 += 2; } - doWaterfall(1); + if (((Toggle & 1) == 0)) + doWaterfall(1); } + if (Firstwaterfall || Secondwaterfall) + displayWaterfall(); + remainingSamples = rx_bufsize - Needed; fftCount = 0; diff --git a/symbols.h b/symbols.h deleted file mode 100644 index 5ed91ad..0000000 --- a/symbols.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* symbols.h */ - -void symbols_init (void); - -void symbols_list (void); - -void symbols_from_dest_or_src (char dti, char *src, char *dest, char *symtab, char *symbol); - -int symbols_into_dest (char symtab, char symbol, char *dest); - -void symbols_get_description (char symtab, char symbol, char *description, size_t desc_size); - -int symbols_code_from_description (char overlay, char *description, char *symtab, char *symbol); - -void symbols_to_tones (char symtab, char symbol, char *tones, size_t tonessize); - - -/* end symbols.h */ diff --git a/telemetry.h b/telemetry.h deleted file mode 100644 index 4ef9b62..0000000 --- a/telemetry.h +++ /dev/null @@ -1,15 +0,0 @@ - - -/* telemetry.h */ - -void telemetry_data_original (char *station, char *info, int quiet, char *output, size_t outputsize, char *comment, size_t commentsize); - -void telemetry_data_base91 (char *station, char *cdata, char *output, size_t outputsize); - -void telemetry_name_message (char *station, char *msg); - -void telemetry_unit_label_message (char *station, char *msg); - -void telemetry_coefficents_message (char *station, char *msg, int quiet); - -void telemetry_bit_sense_message (char *station, char *msg, int quiet); diff --git a/tq.h b/tq.h deleted file mode 100644 index 37599d5..0000000 --- a/tq.h +++ /dev/null @@ -1,41 +0,0 @@ - -/*------------------------------------------------------------------ - * - * Module: tq.h - * - * Purpose: Transmit queue - hold packets for transmission until the channel is clear. - * - *---------------------------------------------------------------*/ - -#ifndef TQ_H -#define TQ_H 1 - -#include "ax25_pad.h" -#include "audio.h" - -#define TQ_NUM_PRIO 2 /* Number of priorities. */ - -#define TQ_PRIO_0_HI 0 -#define TQ_PRIO_1_LO 1 - - - -void tq_init (struct audio_s *audio_config_p); - -void tq_append (int chan, int prio, packet_t pp); - -void lm_data_request (int chan, int prio, packet_t pp); - -void lm_seize_request (int chan); - -void tq_wait_while_empty (int chan); - -packet_t tq_remove (int chan, int prio); - -packet_t tq_peek (int chan, int prio); - -int tq_count (int chan, int prio, char *source, char *dest, int bytes); - -#endif - -/* end tq.h */ diff --git a/tt_text.h b/tt_text.h deleted file mode 100644 index 7cab3b8..0000000 --- a/tt_text.h +++ /dev/null @@ -1,38 +0,0 @@ - -/* tt_text.h */ - - -/* Encode normal human readable to DTMF representation. */ - -int tt_text_to_multipress (const char *text, int quiet, char *buttons); - -int tt_text_to_two_key (const char *text, int quiet, char *buttons); - -int tt_text_to_call10 (const char *text, int quiet, char *buttons); - -int tt_text_to_mhead (const char *text, int quiet, char *buttons, size_t buttonsiz); - -int tt_text_to_satsq (const char *text, int quiet, char *buttons, size_t buttonsiz); - -int tt_text_to_ascii2d (const char *text, int quiet, char *buttons); - - -/* Decode DTMF to normal human readable form. */ - -int tt_multipress_to_text (const char *buttons, int quiet, char *text); - -int tt_two_key_to_text (const char *buttons, int quiet, char *text); - -int tt_call10_to_text (const char *buttons, int quiet, char *text); - -int tt_call5_suffix_to_text (const char *buttons, int quiet, char *text); - -int tt_mhead_to_text (const char *buttons, int quiet, char *text, size_t textsiz); - -int tt_satsq_to_text (const char *buttons, int quiet, char *text); - -int tt_ascii2d_to_text (const char *buttons, int quiet, char *text); - - - -/* end tt_text.h */ \ No newline at end of file diff --git a/tt_user.h b/tt_user.h deleted file mode 100644 index 4ff2ec8..0000000 --- a/tt_user.h +++ /dev/null @@ -1,15 +0,0 @@ - -/* tt_user.h */ - - -#include "audio.h" - -void tt_user_init (struct audio_s *p_audio_config, struct tt_config_s *p); - -int tt_user_heard (char *callsign, int ssid, char overlay, char symbol, char *loc_text, double latitude, - double longitude, int ambiguity, char *freq, char *ctcss, char *comment, char mic_e, char *dao); - -int tt_3char_suffix_search (char *suffix, char *callsign); - -void tt_user_background (void); -void tt_user_dump (void); \ No newline at end of file diff --git a/tune.h b/tune.h deleted file mode 100644 index 8d1c8b6..0000000 --- a/tune.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/version.h b/version.h deleted file mode 100644 index a09490c..0000000 --- a/version.h +++ /dev/null @@ -1,21 +0,0 @@ - -/* Dire Wolf version 1.6 */ - -// Put in destination field to identify the equipment used. - -#define APP_TOCALL "APDW" // Assigned by WB4APR in tocalls.txt - -// This now comes from compile command line options. - -//#define MAJOR_VERSION 1 -//#define MINOR_VERSION 6 -//#define EXTRA_VERSION "Beta Test" - - -// For user-defined data format. -// APRS protocol spec Chapter 18 and http://www.aprs.org/aprs11/expfmts.txt - -#define USER_DEF_USER_ID 'D' // user id D for direwolf - -#define USER_DEF_TYPE_AIS 'A' // data type A for AIS NMEA sentence -#define USER_DEF_TYPE_EAS 'E' // data type E for EAS broadcasts diff --git a/waypoint.h b/waypoint.h deleted file mode 100644 index 3ba6f1c..0000000 --- a/waypoint.h +++ /dev/null @@ -1,24 +0,0 @@ - -/* - * Name: waypoint.h - */ - - -#include "ax25_pad.h" /* for packet_t */ - -#include "config.h" /* for struct misc_config_s */ - - -void waypoint_init (struct misc_config_s *misc_config); - -void waypoint_set_debug (int n); - -void waypoint_send_sentence (char *wname_in, double dlat, double dlong, char symtab, char symbol, - float alt, float course, float speed, char *comment_in); - -void waypoint_send_ais (char *sentence); - -void waypoint_term (); - - -/* end waypoint.h */ diff --git a/xid.h b/xid.h deleted file mode 100644 index a221b73..0000000 --- a/xid.h +++ /dev/null @@ -1,32 +0,0 @@ - - -/* xid.h */ - - -#include "ax25_pad.h" // for enum ax25_modulo_e - - -struct xid_param_s { - - int full_duplex; - - // Order is important because negotiation keeps the lower value of - // REJ (srej_none), SREJ (default without negotiation), Multi-SREJ (if both agree). - - enum srej_e { srej_none=0, srej_single=1, srej_multi=2, srej_not_specified=3 } srej; - - enum ax25_modulo_e modulo; - - int i_field_length_rx; /* In bytes. XID has it in bits. */ - - int window_size_rx; - - int ack_timer; /* "T1" in mSec. */ - - int retries; /* "N1" */ -}; - - -int xid_parse (unsigned char *info, int info_len, struct xid_param_s *result, char *desc, int desc_size); - -int xid_encode (struct xid_param_s *param, unsigned char *info, cmdres_t cr); \ No newline at end of file diff --git a/xmit.h b/xmit.h deleted file mode 100644 index 248037d..0000000 --- a/xmit.h +++ /dev/null @@ -1,27 +0,0 @@ - - -#ifndef XMIT_H -#define XMIT_H 1 - -#include "audio.h" /* for struct audio_s */ - - -extern void xmit_init (struct audio_s *p_modem, int debug_xmit_packet); - -extern void xmit_set_txdelay (int channel, int value); - -extern void xmit_set_persist (int channel, int value); - -extern void xmit_set_slottime (int channel, int value); - -extern void xmit_set_txtail (int channel, int value); - -extern void xmit_set_fulldup (int channel, int value); - - -extern int xmit_speak_it (char *script, int c, char *msg); - -#endif - -/* end xmit.h */ - From d071d9c22c7854f390b00eaaf7f03ae6705f40a2 Mon Sep 17 00:00:00 2001 From: Dave Hibberd Date: Sun, 17 Dec 2023 14:08:17 +0000 Subject: [PATCH 3/3] Release --- debian/changelog | 6 ++++++ debian/dirs | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 debian/dirs diff --git a/debian/changelog b/debian/changelog index 187ce8d..aeb9bb9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +qtsoundmodem (0.0.0.71-1) unstable; urgency=medium + + * New Upstream Release + + -- Dave Hibberd Sun, 17 Dec 2023 14:07:52 +0000 + qtsoundmodem (0.0.0.68-1) unstable; urgency=medium * New Upstream diff --git a/debian/dirs b/debian/dirs deleted file mode 100644 index e6ca2b7..0000000 --- a/debian/dirs +++ /dev/null @@ -1 +0,0 @@ -opt/oarc/QtSoundModem