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
+
+
+
+
+
+
+
+
+ 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 */
-