From 26243c024775a14aa2311f24c5b74b168207c57d Mon Sep 17 00:00:00 2001 From: m0vse Date: Mon, 25 May 2020 20:29:49 +0100 Subject: [PATCH 01/19] Update RemoteCommand to disable/enable network modes --- MMDVMHost.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 40f954c..d344409 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1997,22 +1997,32 @@ void CMMDVMHost::remoteControl() case RCD_ENABLE_DSTAR: if (m_dstar != NULL && m_dstarEnabled==false) processEnableCommand(m_dstarEnabled, true); + if (m_dstarNetwork != NULL) + m_dstarNetwork->enable(true); break; case RCD_ENABLE_DMR: if (m_dmr != NULL && m_dmrEnabled==false) processEnableCommand(m_dmrEnabled, true); + if (m_dmrNetwork != NULL) + m_dmrNetwork->enable(true); break; case RCD_ENABLE_YSF: if (m_ysf != NULL && m_ysfEnabled==false) processEnableCommand(m_ysfEnabled, true); + if (m_ysfNetwork != NULL) + m_ysfNetwork->enable(true); break; case RCD_ENABLE_P25: if (m_p25 != NULL && m_p25Enabled==false) processEnableCommand(m_p25Enabled, true); + if (m_p25Network != NULL) + m_p25Network->enable(true); break; case RCD_ENABLE_NXDN: if (m_nxdn != NULL && m_nxdnEnabled==false) processEnableCommand(m_nxdnEnabled, true); + if (m_nxdnNetwork != NULL) + m_nxdnNetwork->enable(true); break; case RCD_ENABLE_FM: if (m_fmEnabled==false) @@ -2021,22 +2031,32 @@ void CMMDVMHost::remoteControl() case RCD_DISABLE_DSTAR: if (m_dstar != NULL && m_dstarEnabled==true) processEnableCommand(m_dstarEnabled, false); + if (m_dstarNetwork != NULL) + m_dstarNetwork->enable(false); break; case RCD_DISABLE_DMR: if (m_dmr != NULL && m_dmrEnabled==true) processEnableCommand(m_dmrEnabled, false); + if (m_dmrNetwork != NULL) + m_dmrNetwork->enable(false); break; case RCD_DISABLE_YSF: if (m_ysf != NULL && m_ysfEnabled==true) processEnableCommand(m_ysfEnabled, false); + if (m_ysfNetwork != NULL) + m_ysfNetwork->enable(false); break; case RCD_DISABLE_P25: if (m_p25 != NULL && m_p25Enabled==true) processEnableCommand(m_p25Enabled, false); + if (m_p25Network != NULL) + m_p25Network->enable(false); break; case RCD_DISABLE_NXDN: if (m_nxdn != NULL && m_nxdnEnabled==true) processEnableCommand(m_nxdnEnabled, false); + if (m_nxdnNetwork != NULL) + m_nxdnNetwork->enable(false); break; case RCD_DISABLE_FM: if (m_fmEnabled == true) From 45eafe3672025b7285fd6b4adec95835f6af29e2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 27 May 2020 11:38:46 +0100 Subject: [PATCH 02/19] Start adding the Kenwood protocol as an option. --- MMDVM.ini | 1 + MMDVMHost.h | 2 +- MMDVMHost.vcxproj | 4 + MMDVMHost.vcxproj.filters | 12 + Makefile | 9 +- Makefile.Pi | 9 +- Makefile.Pi.Adafruit | 9 +- Makefile.Pi.HD44780 | 9 +- Makefile.Pi.OLED | 9 +- Makefile.Pi.PCF8574 | 9 +- Makefile.Solaris | 9 +- NXDNIcomNetwork.cpp | 169 +++++++ NXDNIcomNetwork.h | 59 +++ NXDNKenwoodNetwork.cpp | 924 ++++++++++++++++++++++++++++++++++++++ NXDNKenwoodNetwork.h | 86 ++++ NXDNNetwork.cpp | 150 +------ NXDNNetwork.h | 31 +- 17 files changed, 1303 insertions(+), 198 deletions(-) create mode 100644 NXDNIcomNetwork.cpp create mode 100644 NXDNIcomNetwork.h create mode 100644 NXDNKenwoodNetwork.cpp create mode 100644 NXDNKenwoodNetwork.h diff --git a/MMDVM.ini b/MMDVM.ini index 12f2b73..9b02e83 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -215,6 +215,7 @@ Debug=0 [NXDN Network] Enable=1 +Protocol=Icom LocalAddress=127.0.0.1 LocalPort=14021 GatewayAddress=127.0.0.1 diff --git a/MMDVMHost.h b/MMDVMHost.h index 17d6786..6b1e078 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -66,7 +66,7 @@ private: CDMRNetwork* m_dmrNetwork; CYSFNetwork* m_ysfNetwork; CP25Network* m_p25Network; - CNXDNNetwork* m_nxdnNetwork; + INXDNNetwork* m_nxdnNetwork; CPOCSAGNetwork* m_pocsagNetwork; CDisplay* m_display; CUMP* m_ump; diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 812c7a4..44b50f2 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -203,6 +203,8 @@ + + @@ -297,6 +299,8 @@ + + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index fb8a362..01fcd3f 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -299,6 +299,12 @@ Header Files + + Header Files + + + Header Files + @@ -562,5 +568,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index efdaba6..33cc689 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o \ - NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o \ - POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o \ - TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o \ + NXDNKenwoodNetwork.oNXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ + P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o \ + YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi b/Makefile.Pi index 640c07f..d9c1acd 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -10,10 +10,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ - NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o \ - UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ + NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ + P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ + YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 24c2907..a9c0b35 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -11,10 +11,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ - NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ + NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ + P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ + YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index c2faad2..a0127af 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -10,10 +10,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ - NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ + NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ + P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ + YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index d2db40c..5629489 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -10,10 +10,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ - NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ + NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ + P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ + YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 4c5d3a3..cd6b67f 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -11,10 +11,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ - NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o \ - NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ + NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ + P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ + SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ + YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Solaris b/Makefile.Solaris index c50d41e..4d46985 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -10,10 +10,11 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \ - NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ - NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \ - QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \ - UMP.o UserDB.o UserDBebtry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o \ + NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o \ + P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o \ + StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBebtry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o \ + YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/NXDNIcomNetwork.cpp b/NXDNIcomNetwork.cpp new file mode 100644 index 0000000..2f3767b --- /dev/null +++ b/NXDNIcomNetwork.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2009-2014,2016,2018-2020 by Jonathan Naylor G4KLX + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "NXDNIcomNetwork.h" +#include "NXDNDefines.h" +#include "Defines.h" +#include "Utils.h" +#include "Log.h" + +#include +#include +#include + +const unsigned int BUFFER_LENGTH = 200U; + +CNXDNIcomNetwork::CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) : +m_socket(localAddress, localPort), +m_address(), +m_port(gatewayPort), +m_debug(debug), +m_enabled(false), +m_buffer(1000U, "NXDN Network") +{ + assert(gatewayPort > 0U); + assert(!gatewayAddress.empty()); + + m_address = CUDPSocket::lookup(gatewayAddress); +} + +CNXDNIcomNetwork::~CNXDNIcomNetwork() +{ +} + +bool CNXDNIcomNetwork::open() +{ + LogMessage("Opening NXDN network connection"); + + if (m_address.s_addr == INADDR_NONE) + return false; + + return m_socket.open(); +} + +bool CNXDNIcomNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type) +{ + assert(data != NULL); + + unsigned char buffer[110U]; + ::memset(buffer, 0x00U, 110U); + + buffer[0U] = 'I'; + buffer[1U] = 'C'; + buffer[2U] = 'O'; + buffer[3U] = 'M'; + buffer[4U] = 0x01U; + buffer[5U] = 0x01U; + buffer[6U] = 0x08U; + buffer[7U] = 0xE0U; + + switch (type) { + case NNMT_VOICE_HEADER: + case NNMT_VOICE_TRAILER: + buffer[37U] = 0x23U; + buffer[38U] = 0x1CU; + buffer[39U] = 0x21U; + break; + case NNMT_VOICE_BODY: + buffer[37U] = 0x23U; + buffer[38U] = 0x10U; + buffer[39U] = 0x21U; + break; + case NNMT_DATA_HEADER: + case NNMT_DATA_BODY: + case NNMT_DATA_TRAILER: + buffer[37U] = 0x23U; + buffer[38U] = 0x02U; + buffer[39U] = 0x18U; + break; + default: + return false; + } + + ::memcpy(buffer + 40U, data, 33U); + + if (m_debug) + CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U); + + return m_socket.write(buffer, 102U, m_address, m_port); +} + +void CNXDNIcomNetwork::clock(unsigned int ms) +{ + unsigned char buffer[BUFFER_LENGTH]; + + in_addr address; + unsigned int port; + int length = m_socket.read(buffer, BUFFER_LENGTH, address, port); + if (length <= 0) + return; + + // Check if the data is for us + if (m_address.s_addr != address.s_addr || port != m_port) { + LogMessage("NXDN packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port); + return; + } + + // Invalid packet type? + if (::memcmp(buffer, "ICOM", 4U) != 0) + return; + + if (length != 102) + return; + + if (!m_enabled) + return; + + if (m_debug) + CUtils::dump(1U, "NXDN Network Data Received", buffer, length); + + m_buffer.addData(buffer + 40U, 33U); +} + +bool CNXDNIcomNetwork::read(unsigned char* data) +{ + assert(data != NULL); + + if (m_buffer.isEmpty()) + return false; + + m_buffer.getData(data, 33U); + + return true; +} + +void CNXDNIcomNetwork::reset() +{ +} + +void CNXDNIcomNetwork::close() +{ + m_socket.close(); + + LogMessage("Closing NXDN network connection"); +} + +void CNXDNIcomNetwork::enable(bool enabled) +{ + if (enabled && !m_enabled) + reset(); + else if (!enabled && m_enabled) + m_buffer.clear(); + + m_enabled = enabled; +} diff --git a/NXDNIcomNetwork.h b/NXDNIcomNetwork.h new file mode 100644 index 0000000..05fb023 --- /dev/null +++ b/NXDNIcomNetwork.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef NXDNIcomNetwork_H +#define NXDNIcomNetwork_H + +#include "NXDNNetwork.h" +#include "NXDNDefines.h" +#include "RingBuffer.h" +#include "UDPSocket.h" +#include "Timer.h" + +#include +#include + +class CNXDNIcomNetwork : public INXDNNetwork { +public: + CNXDNIcomNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug); + virtual ~CNXDNIcomNetwork(); + + virtual bool open(); + + virtual void enable(bool enabled); + + virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type); + + virtual bool read(unsigned char* data); + + virtual void reset(); + + virtual void close(); + + virtual void clock(unsigned int ms); + +private: + CUDPSocket m_socket; + in_addr m_address; + unsigned int m_port; + bool m_debug; + bool m_enabled; + CRingBuffer m_buffer; +}; + +#endif diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp new file mode 100644 index 0000000..c5a4a20 --- /dev/null +++ b/NXDNKenwoodNetwork.cpp @@ -0,0 +1,924 @@ +/* + * Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "KenwoodNetwork.h" +#include "NXDNCRC.h" +#include "Utils.h" +#include "Log.h" + +#include +#include +#include +#include + +const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; + +#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +const unsigned int BUFFER_LENGTH = 200U; + +CKenwoodNetwork::CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug) : +m_rtpSocket(localPort + 0U), +m_rtcpSocket(localPort + 1U), +m_address(), +m_rtcpPort(rptPort + 1U), +m_rtpPort(rptPort + 0U), +m_headerSeen(false), +m_seen1(false), +m_seen2(false), +m_seen3(false), +m_seen4(false), +m_sacch(NULL), +m_sessionId(1U), +m_seqNo(0U), +m_ssrc(0U), +m_debug(debug), +m_startSecs(0U), +m_startUSecs(0U), +m_rtcpTimer(1000U, 0U, 200U), +m_hangTimer(1000U, 5U), +m_hangType(0U), +m_hangSrc(0U), +m_hangDst(0U) +{ + assert(localPort > 0U); + assert(!rptAddress.empty()); + assert(rptPort > 0U); + + m_sacch = new unsigned char[10U]; + + m_address = CUDPSocket::lookup(rptAddress); +} + +CKenwoodNetwork::~CKenwoodNetwork() +{ + delete[] m_sacch; +} + +bool CKenwoodNetwork::open() +{ + LogMessage("Opening Kenwood connection"); + + if (m_address.s_addr == INADDR_NONE) + return false; + + if (!m_rtcpSocket.open()) + return false; + + if (!m_rtpSocket.open()) { + m_rtcpSocket.close(); + return false; + } + + m_ssrc = m_rtpSocket.getLocalAddress(); + + return true; +} + +bool CKenwoodNetwork::write(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + + switch (data[0U]) { + case 0x81U: // Voice header or trailer + case 0x83U: + return processIcomVoiceHeader(data); + case 0xACU: // Voice data + case 0xAEU: + return processIcomVoiceData(data); + default: + return false; + } +} + +bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[30U]; + ::memset(outData, 0x00U, 30U); + + // SACCH + outData[0U] = inData[2U]; + outData[1U] = inData[1U]; + outData[2U] = inData[4U] & 0xC0U; + outData[3U] = inData[3U]; + + // FACCH 1+2 + outData[4U] = outData[14U] = inData[6U]; + outData[5U] = outData[15U] = inData[5U]; + outData[6U] = outData[16U] = inData[8U]; + outData[7U] = outData[17U] = inData[7U]; + outData[8U] = outData[18U] = inData[10U]; + outData[9U] = outData[19U] = inData[9U]; + outData[10U] = outData[20U] = inData[12U]; + outData[11U] = outData[21U] = inData[11U]; + + unsigned short src = (inData[8U] << 8) + (inData[9U] << 0); + unsigned short dst = (inData[10U] << 8) + (inData[11U] << 0); + unsigned char type = (inData[7U] >> 5) & 0x07U; + + switch (inData[5U] & 0x3FU) { + case 0x01U: + m_hangTimer.stop(); + m_rtcpTimer.start(); + writeRTCPStart(); + return writeRTPVoiceHeader(outData); + case 0x08U: { + m_hangTimer.start(); + bool ret = writeRTPVoiceTrailer(outData); + writeRTCPHang(type, src, dst); + return ret; + } + default: + return false; + } +} + +bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[40U], temp[10U]; + ::memset(outData, 0x00U, 40U); + + // SACCH + outData[0U] = inData[2U]; + outData[1U] = inData[1U]; + outData[2U] = inData[4U] & 0xC0U; + outData[3U] = inData[3U]; + + // Audio 1 + ::memset(temp, 0x00U, 10U); + for (unsigned int i = 0U; i < 49U; i++) { + unsigned int offset = (5U * 8U) + i; + bool b = READ_BIT(inData, offset); + WRITE_BIT(temp, i, b); + } + outData[4U] = temp[1U]; + outData[5U] = temp[0U]; + outData[6U] = temp[3U]; + outData[7U] = temp[2U]; + outData[8U] = temp[5U]; + outData[9U] = temp[4U]; + outData[10U] = temp[7U]; + outData[11U] = temp[6U]; + + // Audio 2 + ::memset(temp, 0x00U, 10U); + for (unsigned int i = 0U; i < 49U; i++) { + unsigned int offset = (5U * 8U) + 49U + i; + bool b = READ_BIT(inData, offset); + WRITE_BIT(temp, i, b); + } + outData[12U] = temp[1U]; + outData[13U] = temp[0U]; + outData[14U] = temp[3U]; + outData[15U] = temp[2U]; + outData[16U] = temp[5U]; + outData[17U] = temp[4U]; + outData[18U] = temp[7U]; + outData[19U] = temp[6U]; + + // Audio 3 + ::memset(temp, 0x00U, 10U); + for (unsigned int i = 0U; i < 49U; i++) { + unsigned int offset = (19U * 8U) + i; + bool b = READ_BIT(inData, offset); + WRITE_BIT(temp, i, b); + } + outData[20U] = temp[1U]; + outData[21U] = temp[0U]; + outData[22U] = temp[3U]; + outData[23U] = temp[2U]; + outData[24U] = temp[5U]; + outData[25U] = temp[4U]; + outData[26U] = temp[7U]; + outData[27U] = temp[6U]; + + // Audio 4 + ::memset(temp, 0x00U, 10U); + for (unsigned int i = 0U; i < 49U; i++) { + unsigned int offset = (19U * 8U) + 49U + i; + bool b = READ_BIT(inData, offset); + WRITE_BIT(temp, i, b); + } + outData[28U] = temp[1U]; + outData[29U] = temp[0U]; + outData[30U] = temp[3U]; + outData[31U] = temp[2U]; + outData[32U] = temp[5U]; + outData[33U] = temp[4U]; + outData[34U] = temp[7U]; + outData[35U] = temp[6U]; + + return writeRTPVoiceData(outData); +} + +bool CKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[50U]; + ::memset(buffer, 0x00U, 50U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + m_sessionId++; + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x03U; + buffer[17U] = 0x03U; + buffer[18U] = 0x04U; + buffer[19U] = 0x04U; + buffer[20U] = 0x0AU; + buffer[21U] = 0x05U; + buffer[22U] = 0x0AU; + + ::memcpy(buffer + 23U, data, 24U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U); + + return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); +} + +bool CKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[50U]; + ::memset(buffer, 0x00U, 50U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x03U; + buffer[17U] = 0x03U; + buffer[18U] = 0x04U; + buffer[19U] = 0x04U; + buffer[20U] = 0x0AU; + buffer[21U] = 0x05U; + buffer[22U] = 0x0AU; + + ::memcpy(buffer + 23U, data, 24U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 47U); + + return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); +} + +bool CKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[60U]; + ::memset(buffer, 0x00U, 60U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x03U; + buffer[17U] = 0x02U; + buffer[18U] = 0x04U; + buffer[19U] = 0x07U; + buffer[20U] = 0x10U; + buffer[21U] = 0x08U; + buffer[22U] = 0x10U; + + ::memcpy(buffer + 23U, data, 36U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 59U); + + return m_rtpSocket.write(buffer, 59U, m_address, m_rtpPort); +} + +bool CKenwoodNetwork::writeRTCPStart() +{ +#if defined(_WIN32) || defined(_WIN64) + time_t now; + ::time(&now); + + m_startSecs = uint32_t(now); + + SYSTEMTIME st; + ::GetSystemTime(&st); + + m_startUSecs = st.wMilliseconds * 1000U; +#else + struct timeval tod; + ::gettimeofday(&tod, NULL); + + m_startSecs = tod.tv_sec; + m_startUSecs = tod.tv_usec; +#endif + + unsigned char buffer[30U]; + ::memset(buffer, 0x00U, 30U); + + buffer[0U] = 0x8AU; + buffer[1U] = 0xCCU; + buffer[2U] = 0x00U; + buffer[3U] = 0x06U; + + buffer[4U] = (m_ssrc >> 24) & 0xFFU; + buffer[5U] = (m_ssrc >> 16) & 0xFFU; + buffer[6U] = (m_ssrc >> 8) & 0xFFU; + buffer[7U] = (m_ssrc >> 0) & 0xFFU; + + buffer[8U] = 'K'; + buffer[9U] = 'W'; + buffer[10U] = 'N'; + buffer[11U] = 'E'; + + buffer[12U] = (m_startSecs >> 24) & 0xFFU; + buffer[13U] = (m_startSecs >> 16) & 0xFFU; + buffer[14U] = (m_startSecs >> 8) & 0xFFU; + buffer[15U] = (m_startSecs >> 0) & 0xFFU; + + buffer[16U] = (m_startUSecs >> 24) & 0xFFU; + buffer[17U] = (m_startUSecs >> 16) & 0xFFU; + buffer[18U] = (m_startUSecs >> 8) & 0xFFU; + buffer[19U] = (m_startUSecs >> 0) & 0xFFU; + + buffer[22U] = 0x02U; + + buffer[24U] = 0x01U; + + buffer[27U] = 0x0AU; + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U); + + return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); +} + +bool CKenwoodNetwork::writeRTCPPing() +{ + unsigned char buffer[30U]; + ::memset(buffer, 0x00U, 30U); + + buffer[0U] = 0x8AU; + buffer[1U] = 0xCCU; + buffer[2U] = 0x00U; + buffer[3U] = 0x06U; + + buffer[4U] = (m_ssrc >> 24) & 0xFFU; + buffer[5U] = (m_ssrc >> 16) & 0xFFU; + buffer[6U] = (m_ssrc >> 8) & 0xFFU; + buffer[7U] = (m_ssrc >> 0) & 0xFFU; + + buffer[8U] = 'K'; + buffer[9U] = 'W'; + buffer[10U] = 'N'; + buffer[11U] = 'E'; + + buffer[12U] = (m_startSecs >> 24) & 0xFFU; + buffer[13U] = (m_startSecs >> 16) & 0xFFU; + buffer[14U] = (m_startSecs >> 8) & 0xFFU; + buffer[15U] = (m_startSecs >> 0) & 0xFFU; + + buffer[16U] = (m_startUSecs >> 24) & 0xFFU; + buffer[17U] = (m_startUSecs >> 16) & 0xFFU; + buffer[18U] = (m_startUSecs >> 8) & 0xFFU; + buffer[19U] = (m_startUSecs >> 0) & 0xFFU; + + buffer[22U] = 0x02U; + + buffer[24U] = 0x01U; + + buffer[27U] = 0x7BU; + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 28U); + + return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); +} + +bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst) +{ + m_hangType = type; + m_hangSrc = src; + m_hangDst = dst; + + return writeRTCPHang(); +} + +bool CKenwoodNetwork::writeRTCPHang() +{ + unsigned char buffer[30U]; + ::memset(buffer, 0x00U, 30U); + + buffer[0U] = 0x8BU; + buffer[1U] = 0xCCU; + buffer[2U] = 0x00U; + buffer[3U] = 0x04U; + + buffer[4U] = (m_ssrc >> 24) & 0xFFU; + buffer[5U] = (m_ssrc >> 16) & 0xFFU; + buffer[6U] = (m_ssrc >> 8) & 0xFFU; + buffer[7U] = (m_ssrc >> 0) & 0xFFU; + + buffer[8U] = 'K'; + buffer[9U] = 'W'; + buffer[10U] = 'N'; + buffer[11U] = 'E'; + + buffer[12U] = (m_hangSrc >> 8) & 0xFFU; + buffer[13U] = (m_hangSrc >> 0) & 0xFFU; + + buffer[14U] = (m_hangDst >> 8) & 0xFFU; + buffer[15U] = (m_hangDst >> 0) & 0xFFU; + + buffer[16U] = m_hangType; + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTCP Data Sent", buffer, 20U); + + return m_rtcpSocket.write(buffer, 20U, m_address, m_rtcpPort); +} + +unsigned int CKenwoodNetwork::read(unsigned char* data) +{ + assert(data != NULL); + + unsigned char dummy[BUFFER_LENGTH]; + readRTCP(dummy); + + unsigned int len = readRTP(data); + switch (len) { + case 0U: // Nothing received + return 0U; + case 35U: // Voice header or trailer + return processKenwoodVoiceHeader(data); + case 47U: // Voice data + if (m_headerSeen) + return processKenwoodVoiceData(data); + else + return processKenwoodVoiceLateEntry(data); + case 31U: // Data + return processKenwoodData(data); + default: + CUtils::dump(5U, "Unknown data received from the Kenwood network", data, len); + return 0U; + } +} + +unsigned int CKenwoodNetwork::readRTP(unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[BUFFER_LENGTH]; + + in_addr address; + unsigned int port; + int length = m_rtpSocket.read(buffer, BUFFER_LENGTH, address, port); + if (length <= 0) + return 0U; + + // Check if the data is for us + if (m_address.s_addr != address.s_addr) { + LogMessage("Kenwood RTP packet received from an invalid source, %08X != %08X", m_address.s_addr, address.s_addr); + return 0U; + } + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Received", buffer, length); + + ::memcpy(data, buffer + 12U, length - 12U); + + return length - 12U; +} + +unsigned int CKenwoodNetwork::readRTCP(unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[BUFFER_LENGTH]; + + in_addr address; + unsigned int port; + int length = m_rtcpSocket.read(buffer, BUFFER_LENGTH, address, port); + if (length <= 0) + return 0U; + + // Check if the data is for us + if (m_address.s_addr != address.s_addr) { + LogMessage("Kenwood RTCP packet received from an invalid source, %08X != %08X", m_address.s_addr, address.s_addr); + return 0U; + } + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTCP Data Received", buffer, length); + + if (::memcmp(buffer + 8U, "KWNE", 4U) != 0) { + LogError("Missing RTCP KWNE signature"); + return 0U; + } + + ::memcpy(data, buffer + 12U, length - 12U); + + return length - 12U; +} + +void CKenwoodNetwork::close() +{ + m_rtcpSocket.close(); + m_rtpSocket.close(); + + LogMessage("Closing Kenwood connection"); +} + +void CKenwoodNetwork::clock(unsigned int ms) +{ + m_rtcpTimer.clock(ms); + if (m_rtcpTimer.isRunning() && m_rtcpTimer.hasExpired()) { + if (m_hangTimer.isRunning()) + writeRTCPHang(); + else + writeRTCPPing(); + m_rtcpTimer.start(); + } + + m_hangTimer.clock(ms); + if (m_hangTimer.isRunning() && m_hangTimer.hasExpired()) { + m_rtcpTimer.stop(); + m_hangTimer.stop(); + } +} + +unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[50U], temp[20U]; + ::memset(outData, 0x00U, 50U); + + // LICH + outData[0U] = 0x83U; + + // SACCH + ::memset(temp, 0x00U, 20U); + temp[0U] = inData[12U]; + temp[1U] = inData[11U]; + temp[2U] = inData[14U]; + temp[3U] = inData[13U]; + CNXDNCRC::encodeCRC6(temp, 26U); + ::memcpy(outData + 1U, temp, 4U); + + // FACCH 1+2 + ::memset(temp, 0x00U, 20U); + temp[0U] = inData[16U]; + temp[1U] = inData[15U]; + temp[2U] = inData[18U]; + temp[3U] = inData[17U]; + temp[4U] = inData[20U]; + temp[5U] = inData[19U]; + temp[6U] = inData[22U]; + temp[7U] = inData[21U]; + temp[8U] = inData[24U]; + temp[9U] = inData[23U]; + CNXDNCRC::encodeCRC12(temp, 80U); + ::memcpy(outData + 5U, temp, 12U); + ::memcpy(outData + 19U, temp, 12U); + + switch (outData[5U] & 0x3FU) { + case 0x01U: + ::memcpy(inData, outData, 33U); + m_headerSeen = true; + m_seen1 = false; + m_seen2 = false; + m_seen3 = false; + m_seen4 = false; + return 33U; + case 0x08U: + ::memcpy(inData, outData, 33U); + m_headerSeen = false; + m_seen1 = false; + m_seen2 = false; + m_seen3 = false; + m_seen4 = false; + return 33U; + default: + return 0U; + } +} + +unsigned int CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[50U], temp[20U]; + ::memset(outData, 0x00U, 50U); + + // LICH + outData[0U] = 0xAEU; + + // SACCH + ::memset(temp, 0x00U, 20U); + temp[0U] = inData[12U]; + temp[1U] = inData[11U]; + temp[2U] = inData[14U]; + temp[3U] = inData[13U]; + CNXDNCRC::encodeCRC6(temp, 26U); + ::memcpy(outData + 1U, temp, 4U); + + // AMBE 1+2 + unsigned int n = 5U * 8U; + + temp[0U] = inData[16U]; + temp[1U] = inData[15U]; + temp[2U] = inData[18U]; + temp[3U] = inData[17U]; + temp[4U] = inData[20U]; + temp[5U] = inData[19U]; + temp[6U] = inData[22U]; + temp[7U] = inData[21U]; + + for (unsigned int i = 0U; i < 49U; i++, n++) { + bool b = READ_BIT(temp, i); + WRITE_BIT(outData, n, b); + } + + temp[0U] = inData[24U]; + temp[1U] = inData[23U]; + temp[2U] = inData[26U]; + temp[3U] = inData[25U]; + temp[4U] = inData[28U]; + temp[5U] = inData[27U]; + temp[6U] = inData[30U]; + temp[7U] = inData[29U]; + + for (unsigned int i = 0U; i < 49U; i++, n++) { + bool b = READ_BIT(temp, i); + WRITE_BIT(outData, n, b); + } + + // AMBE 3+4 + n = 19U * 8U; + + temp[0U] = inData[32U]; + temp[1U] = inData[31U]; + temp[2U] = inData[34U]; + temp[3U] = inData[33U]; + temp[4U] = inData[36U]; + temp[5U] = inData[35U]; + temp[6U] = inData[38U]; + temp[7U] = inData[37U]; + + for (unsigned int i = 0U; i < 49U; i++, n++) { + bool b = READ_BIT(temp, i); + WRITE_BIT(outData, n, b); + } + + temp[0U] = inData[40U]; + temp[1U] = inData[39U]; + temp[2U] = inData[42U]; + temp[3U] = inData[41U]; + temp[4U] = inData[44U]; + temp[5U] = inData[43U]; + temp[6U] = inData[46U]; + temp[7U] = inData[45U]; + + for (unsigned int i = 0U; i < 49U; i++, n++) { + bool b = READ_BIT(temp, i); + WRITE_BIT(outData, n, b); + } + + ::memcpy(inData, outData, 33U); + + return 33U; +} + +unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) +{ + if (inData[7U] != 0x09U && inData[7U] != 0x0BU && inData[7U] != 0x08U) + return 0U; + + unsigned char outData[50U]; + + if (inData[7U] == 0x09U || inData[7U] == 0x08U) { + outData[0U] = 0x90U; + outData[1U] = inData[8U]; + outData[2U] = inData[7U]; + outData[3U] = inData[10U]; + outData[4U] = inData[9U]; + outData[5U] = inData[12U]; + outData[6U] = inData[11U]; + ::memcpy(inData, outData, 7U); + return 7U; + } else { + outData[0U] = 0x90U; + outData[1U] = inData[8U]; + outData[2U] = inData[7U]; + outData[3U] = inData[10U]; + outData[4U] = inData[9U]; + outData[5U] = inData[12U]; + outData[6U] = inData[11U]; + outData[7U] = inData[14U]; + outData[8U] = inData[13U]; + outData[9U] = inData[16U]; + outData[10U] = inData[15U]; + outData[11U] = inData[18U]; + outData[12U] = inData[17U]; + outData[13U] = inData[20U]; + outData[14U] = inData[19U]; + outData[15U] = inData[22U]; + outData[16U] = inData[21U]; + outData[17U] = inData[24U]; + outData[18U] = inData[23U]; + outData[19U] = inData[26U]; + outData[20U] = inData[25U]; + outData[21U] = inData[28U]; + outData[22U] = inData[27U]; + outData[23U] = inData[29U]; + ::memcpy(inData, outData, 24U); + return 24U; + } +} + +unsigned long CKenwoodNetwork::getTimeStamp() const +{ + unsigned long timeStamp = 0UL; + +#if defined(_WIN32) || defined(_WIN64) + SYSTEMTIME st; + ::GetSystemTime(&st); + + unsigned int hh = st.wHour; + unsigned int mm = st.wMinute; + unsigned int ss = st.wSecond; + unsigned int ms = st.wMilliseconds; + + timeStamp += hh * 3600U * 1000U * 80U; + timeStamp += mm * 60U * 1000U * 80U; + timeStamp += ss * 1000U * 80U; + timeStamp += ms * 80U; +#else + struct timeval tod; + ::gettimeofday(&tod, NULL); + + unsigned int ss = tod.tv_sec; + unsigned int ms = tod.tv_usec / 1000U; + + timeStamp += ss * 1000U * 80U; + timeStamp += ms * 80U; +#endif + + return timeStamp; +} + +unsigned int CKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char sacch[4U]; + sacch[0U] = inData[12U]; + sacch[1U] = inData[11U]; + sacch[2U] = inData[14U]; + sacch[3U] = inData[13U]; + + switch (sacch[0U] & 0xC0U) { + case 0xC0U: + if (!m_seen1) { + unsigned int offset = 0U; + for (unsigned int i = 8U; i < 26U; i++, offset++) { + bool b = READ_BIT(sacch, i) != 0U; + WRITE_BIT(m_sacch, offset, b); + } + m_seen1 = true; + } + break; + case 0x80U: + if (!m_seen2) { + unsigned int offset = 18U; + for (unsigned int i = 8U; i < 26U; i++, offset++) { + bool b = READ_BIT(sacch, i) != 0U; + WRITE_BIT(m_sacch, offset, b); + } + m_seen2 = true; + } + break; + case 0x40U: + if (!m_seen3) { + unsigned int offset = 36U; + for (unsigned int i = 8U; i < 26U; i++, offset++) { + bool b = READ_BIT(sacch, i) != 0U; + WRITE_BIT(m_sacch, offset, b); + } + m_seen3 = true; + } + break; + case 0x00U: + if (!m_seen4) { + unsigned int offset = 54U; + for (unsigned int i = 8U; i < 26U; i++, offset++) { + bool b = READ_BIT(sacch, i) != 0U; + WRITE_BIT(m_sacch, offset, b); + } + m_seen4 = true; + } + break; + } + + if (!m_seen1 || !m_seen2 || !m_seen3 || !m_seen4) + return 0U; + + // Create a dummy header + // Header SACCH + inData[11U] = 0x10U; + inData[12U] = 0x01U; + inData[13U] = 0x00U; + inData[14U] = 0x00U; + + // Header FACCH + inData[15U] = m_sacch[1U]; + inData[16U] = m_sacch[0U]; + inData[17U] = m_sacch[3U]; + inData[18U] = m_sacch[2U]; + inData[19U] = m_sacch[5U]; + inData[20U] = m_sacch[4U]; + inData[21U] = m_sacch[7U]; + inData[22U] = m_sacch[6U]; + inData[23U] = 0x00U; + inData[24U] = m_sacch[8U]; + + return processKenwoodVoiceHeader(inData); +} diff --git a/NXDNKenwoodNetwork.h b/NXDNKenwoodNetwork.h new file mode 100644 index 0000000..aa52d64 --- /dev/null +++ b/NXDNKenwoodNetwork.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009-2014,2016,2018,2020 by Jonathan Naylor G4KLX + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef KenwoodNetwork_H +#define KenwoodNetwork_H + +#include "RptNetwork.h" +#include "UDPSocket.h" +#include "Timer.h" + +#include +#include + +class CKenwoodNetwork : public IRptNetwork { +public: + CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug); + virtual ~CKenwoodNetwork(); + + virtual bool open(); + + virtual bool write(const unsigned char* data, unsigned int length); + + virtual unsigned int read(unsigned char* data); + + virtual void close(); + + virtual void clock(unsigned int ms); + +private: + CUDPSocket m_rtpSocket; + CUDPSocket m_rtcpSocket; + in_addr m_address; + unsigned int m_rtcpPort; + unsigned int m_rtpPort; + bool m_headerSeen; + bool m_seen1; + bool m_seen2; + bool m_seen3; + bool m_seen4; + unsigned char* m_sacch; + uint8_t m_sessionId; + uint16_t m_seqNo; + unsigned int m_ssrc; + bool m_debug; + uint32_t m_startSecs; + uint32_t m_startUSecs; + CTimer m_rtcpTimer; + CTimer m_hangTimer; + unsigned char m_hangType; + unsigned short m_hangSrc; + unsigned short m_hangDst; + + bool processIcomVoiceHeader(const unsigned char* data); + bool processIcomVoiceData(const unsigned char* data); + unsigned int processKenwoodVoiceHeader(unsigned char* data); + unsigned int processKenwoodVoiceData(unsigned char* data); + unsigned int processKenwoodVoiceLateEntry(unsigned char* data); + unsigned int processKenwoodData(unsigned char* data); + bool writeRTPVoiceHeader(const unsigned char* data); + bool writeRTPVoiceData(const unsigned char* data); + bool writeRTPVoiceTrailer(const unsigned char* data); + bool writeRTCPStart(); + bool writeRTCPPing(); + bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst); + bool writeRTCPHang(); + unsigned int readRTP(unsigned char* data); + unsigned int readRTCP(unsigned char* data); + unsigned long getTimeStamp() const; +}; + +#endif diff --git a/NXDNNetwork.cpp b/NXDNNetwork.cpp index 9e26900..0f55011 100644 --- a/NXDNNetwork.cpp +++ b/NXDNNetwork.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014,2016,2018,2019 by Jonathan Naylor G4KLX + * Copyright (C) 2020 by Jonathan Naylor G4KLX * * 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 @@ -16,154 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "NXDNDefines.h" #include "NXDNNetwork.h" -#include "Defines.h" -#include "Utils.h" -#include "Log.h" -#include -#include -#include - -const unsigned int BUFFER_LENGTH = 200U; - -CNXDNNetwork::CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) : -m_socket(localAddress, localPort), -m_address(), -m_port(gatewayPort), -m_debug(debug), -m_enabled(false), -m_buffer(1000U, "NXDN Network") -{ - assert(gatewayPort > 0U); - assert(!gatewayAddress.empty()); - - m_address = CUDPSocket::lookup(gatewayAddress); -} - -CNXDNNetwork::~CNXDNNetwork() +INXDNNetwork::~INXDNNetwork() { } - -bool CNXDNNetwork::open() -{ - LogMessage("Opening NXDN network connection"); - - if (m_address.s_addr == INADDR_NONE) - return false; - - return m_socket.open(); -} - -bool CNXDNNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type) -{ - assert(data != NULL); - - unsigned char buffer[110U]; - ::memset(buffer, 0x00U, 110U); - - buffer[0U] = 'I'; - buffer[1U] = 'C'; - buffer[2U] = 'O'; - buffer[3U] = 'M'; - buffer[4U] = 0x01U; - buffer[5U] = 0x01U; - buffer[6U] = 0x08U; - buffer[7U] = 0xE0U; - - switch (type) { - case NNMT_VOICE_HEADER: - case NNMT_VOICE_TRAILER: - buffer[37U] = 0x23U; - buffer[38U] = 0x1CU; - buffer[39U] = 0x21U; - break; - case NNMT_VOICE_BODY: - buffer[37U] = 0x23U; - buffer[38U] = 0x10U; - buffer[39U] = 0x21U; - break; - case NNMT_DATA_HEADER: - case NNMT_DATA_BODY: - case NNMT_DATA_TRAILER: - buffer[37U] = 0x23U; - buffer[38U] = 0x02U; - buffer[39U] = 0x18U; - break; - default: - return false; - } - - ::memcpy(buffer + 40U, data, 33U); - - if (m_debug) - CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U); - - return m_socket.write(buffer, 102U, m_address, m_port); -} - -void CNXDNNetwork::clock(unsigned int ms) -{ - unsigned char buffer[BUFFER_LENGTH]; - - in_addr address; - unsigned int port; - int length = m_socket.read(buffer, BUFFER_LENGTH, address, port); - if (length <= 0) - return; - - // Check if the data is for us - if (m_address.s_addr != address.s_addr || port != m_port) { - LogMessage("NXDN packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port); - return; - } - - // Invalid packet type? - if (::memcmp(buffer, "ICOM", 4U) != 0) - return; - - if (length != 102) - return; - - if (!m_enabled) - return; - - if (m_debug) - CUtils::dump(1U, "NXDN Network Data Received", buffer, length); - - m_buffer.addData(buffer + 40U, 33U); -} - -bool CNXDNNetwork::read(unsigned char* data) -{ - assert(data != NULL); - - if (m_buffer.isEmpty()) - return false; - - m_buffer.getData(data, 33U); - - return true; -} - -void CNXDNNetwork::reset() -{ -} - -void CNXDNNetwork::close() -{ - m_socket.close(); - - LogMessage("Closing NXDN network connection"); -} - -void CNXDNNetwork::enable(bool enabled) -{ - if (enabled && !m_enabled) - reset(); - else if (!enabled && m_enabled) - m_buffer.clear(); - - m_enabled = enabled; -} diff --git a/NXDNNetwork.h b/NXDNNetwork.h index 3a5b784..564196b 100644 --- a/NXDNNetwork.h +++ b/NXDNNetwork.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX + * Copyright (C) 2020 by Jonathan Naylor G4KLX * * 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 @@ -20,12 +20,8 @@ #define NXDNNetwork_H #include "NXDNDefines.h" -#include "RingBuffer.h" -#include "UDPSocket.h" -#include "Timer.h" #include -#include enum NXDN_NETWORK_MESSAGE_TYPE { NNMT_VOICE_HEADER, @@ -36,32 +32,25 @@ enum NXDN_NETWORK_MESSAGE_TYPE { NNMT_DATA_TRAILER }; -class CNXDNNetwork { +class INXDNNetwork { public: - CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug); - ~CNXDNNetwork(); + virtual ~INXDNNetwork() = 0; - bool open(); + virtual bool open() = 0; - void enable(bool enabled); + virtual void enable(bool enabled) = 0; - bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type); + virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type) = 0; - bool read(unsigned char* data); + virtual bool read(unsigned char* data) = 0; - void reset(); + virtual void reset() = 0; - void close(); + virtual void close() = 0; - void clock(unsigned int ms); + virtual void clock(unsigned int ms) = 0; private: - CUDPSocket m_socket; - in_addr m_address; - unsigned int m_port; - bool m_debug; - bool m_enabled; - CRingBuffer m_buffer; }; #endif From 924baeacd1bf55dc77e33e766caf19a7a6f41008 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 27 May 2020 12:07:21 +0100 Subject: [PATCH 03/19] More work on integrating the Kenwood NXDN protocol. --- Conf.cpp | 8 ++++ Conf.h | 2 + MMDVMHost.cpp | 9 +++- NXDNControl.cpp | 4 +- NXDNControl.h | 6 +-- NXDNKenwoodNetwork.cpp | 101 ++++++++++++++++++++++------------------- NXDNKenwoodNetwork.h | 32 +++++++------ UDPSocket.cpp | 30 +++++++++++- UDPSocket.h | 6 ++- 9 files changed, 130 insertions(+), 68 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index ee4034b..8d61b30 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -236,6 +236,7 @@ m_p25LocalPort(0U), m_p25NetworkModeHang(3U), m_p25NetworkDebug(false), m_nxdnNetworkEnabled(false), +m_nxdnNetworkProtocol("Icom"), m_nxdnGatewayAddress(), m_nxdnGatewayPort(0U), m_nxdnLocalAddress(), @@ -842,6 +843,8 @@ bool CConf::read() } else if (section == SECTION_NXDN_NETWORK) { if (::strcmp(key, "Enable") == 0) m_nxdnNetworkEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Protocol") == 0) + m_nxdnNetworkProtocol = value; else if (::strcmp(key, "LocalAddress") == 0) m_nxdnLocalAddress = value; else if (::strcmp(key, "LocalPort") == 0) @@ -1832,6 +1835,11 @@ bool CConf::getNXDNNetworkEnabled() const return m_nxdnNetworkEnabled; } +std::string CConf::getNXDNNetworkProtocol() const +{ + return m_nxdnNetworkProtocol; +} + std::string CConf::getNXDNGatewayAddress() const { return m_nxdnGatewayAddress; diff --git a/Conf.h b/Conf.h index 40e81a0..77cff6c 100644 --- a/Conf.h +++ b/Conf.h @@ -244,6 +244,7 @@ public: // The NXDN Network section bool getNXDNNetworkEnabled() const; + std::string getNXDNNetworkProtocol() const; std::string getNXDNGatewayAddress() const; unsigned int getNXDNGatewayPort() const; std::string getNXDNLocalAddress() const; @@ -509,6 +510,7 @@ private: bool m_p25NetworkDebug; bool m_nxdnNetworkEnabled; + std::string m_nxdnNetworkProtocol; std::string m_nxdnGatewayAddress; unsigned int m_nxdnGatewayPort; std::string m_nxdnLocalAddress; diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d344409..3213959 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -17,6 +17,8 @@ */ #include "MMDVMHost.h" +#include "NXDNKenwoodNetwork.h" +#include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" #include "SerialController.h" #include "Version.h" @@ -1472,6 +1474,7 @@ bool CMMDVMHost::createP25Network() bool CMMDVMHost::createNXDNNetwork() { + std::string protocol = m_conf.getNXDNNetworkProtocol(); std::string gatewayAddress = m_conf.getNXDNGatewayAddress(); unsigned int gatewayPort = m_conf.getNXDNGatewayPort(); std::string localAddress = m_conf.getNXDNLocalAddress(); @@ -1480,13 +1483,17 @@ bool CMMDVMHost::createNXDNNetwork() bool debug = m_conf.getNXDNNetworkDebug(); LogInfo("NXDN Network Parameters"); + LogInfo(" Protocol: %s", protocol.c_str()); LogInfo(" Gateway Address: %s", gatewayAddress.c_str()); LogInfo(" Gateway Port: %u", gatewayPort); LogInfo(" Local Address: %s", localAddress.c_str()); LogInfo(" Local Port: %u", localPort); LogInfo(" Mode Hang: %us", m_nxdnNetModeHang); - m_nxdnNetwork = new CNXDNNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); + if (protocol == "Kenwood") + m_nxdnNetwork = new CNXDNKenwoodNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); + else + m_nxdnNetwork = new CNXDNIcomNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug); bool ret = m_nxdnNetwork->open(); if (!ret) { diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 1f3fa4c..1e200c4 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2020 Jonathan Naylor, G4KLX * * 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 @@ -39,7 +39,7 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -CNXDNControl::CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, CNXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper) : +CNXDNControl::CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, INXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper) : m_ran(ran), m_id(id), m_selfOnly(selfOnly), diff --git a/NXDNControl.h b/NXDNControl.h index 5c441e2..af2fba1 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2019 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX * * 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 @@ -36,7 +36,7 @@ class CNXDNControl { public: - CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, CNXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper); + CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, INXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper); ~CNXDNControl(); bool writeModem(unsigned char* data, unsigned int len); @@ -53,7 +53,7 @@ private: unsigned int m_ran; unsigned int m_id; bool m_selfOnly; - CNXDNNetwork* m_network; + INXDNNetwork* m_network; CDisplay* m_display; bool m_duplex; bool m_remoteGateway; diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp index c5a4a20..e294d96 100644 --- a/NXDNKenwoodNetwork.cpp +++ b/NXDNKenwoodNetwork.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "KenwoodNetwork.h" +#include "NXDNKenwoodNetwork.h" #include "NXDNCRC.h" #include "Utils.h" #include "Log.h" @@ -33,12 +33,12 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 const unsigned int BUFFER_LENGTH = 200U; -CKenwoodNetwork::CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug) : -m_rtpSocket(localPort + 0U), -m_rtcpSocket(localPort + 1U), +CNXDNKenwoodNetwork::CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) : +m_rtpSocket(localAddress, localPort + 0U), +m_rtcpSocket(localAddress, localPort + 1U), m_address(), -m_rtcpPort(rptPort + 1U), -m_rtpPort(rptPort + 0U), +m_rtcpPort(gwyPort + 1U), +m_rtpPort(gwyPort + 0U), m_headerSeen(false), m_seen1(false), m_seen2(false), @@ -58,20 +58,20 @@ m_hangSrc(0U), m_hangDst(0U) { assert(localPort > 0U); - assert(!rptAddress.empty()); - assert(rptPort > 0U); + assert(!gwyAddress.empty()); + assert(gwyPort > 0U); m_sacch = new unsigned char[10U]; - m_address = CUDPSocket::lookup(rptAddress); + m_address = CUDPSocket::lookup(gwyAddress); } -CKenwoodNetwork::~CKenwoodNetwork() +CNXDNKenwoodNetwork::~CNXDNKenwoodNetwork() { delete[] m_sacch; } -bool CKenwoodNetwork::open() +bool CNXDNKenwoodNetwork::open() { LogMessage("Opening Kenwood connection"); @@ -91,23 +91,27 @@ bool CKenwoodNetwork::open() return true; } -bool CKenwoodNetwork::write(const unsigned char* data, unsigned int length) +bool CNXDNKenwoodNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type) { assert(data != NULL); - switch (data[0U]) { - case 0x81U: // Voice header or trailer - case 0x83U: + switch (type) { + case NNMT_VOICE_HEADER: // Voice header or trailer + case NNMT_VOICE_TRAILER: + case NNMT_DATA_TRAILER: // Data trailer return processIcomVoiceHeader(data); - case 0xACU: // Voice data - case 0xAEU: + case NNMT_VOICE_BODY: // Voice data return processIcomVoiceData(data); + case NNMT_DATA_HEADER: // Voice header or trailer + return processIcomDataHeader(data); + case NNMT_DATA_BODY: // Voice data + return processIcomDataData(data); default: return false; } } -bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) +bool CNXDNKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) { assert(inData != NULL); @@ -151,7 +155,7 @@ bool CKenwoodNetwork::processIcomVoiceHeader(const unsigned char* inData) } } -bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) +bool CNXDNKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) { assert(inData != NULL); @@ -231,7 +235,7 @@ bool CKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) return writeRTPVoiceData(outData); } -bool CKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) { assert(data != NULL); @@ -278,7 +282,7 @@ bool CKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) { assert(data != NULL); @@ -324,7 +328,7 @@ bool CKenwoodNetwork::writeRTPVoiceTrailer(const unsigned char* data) return m_rtpSocket.write(buffer, 47U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) +bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) { assert(data != NULL); @@ -370,7 +374,7 @@ bool CKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) return m_rtpSocket.write(buffer, 59U, m_address, m_rtpPort); } -bool CKenwoodNetwork::writeRTCPStart() +bool CNXDNKenwoodNetwork::writeRTCPStart() { #if defined(_WIN32) || defined(_WIN64) time_t now; @@ -430,7 +434,7 @@ bool CKenwoodNetwork::writeRTCPStart() return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); } -bool CKenwoodNetwork::writeRTCPPing() +bool CNXDNKenwoodNetwork::writeRTCPPing() { unsigned char buffer[30U]; ::memset(buffer, 0x00U, 30U); @@ -472,7 +476,7 @@ bool CKenwoodNetwork::writeRTCPPing() return m_rtcpSocket.write(buffer, 28U, m_address, m_rtcpPort); } -bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst) +bool CNXDNKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst) { m_hangType = type; m_hangSrc = src; @@ -481,7 +485,7 @@ bool CKenwoodNetwork::writeRTCPHang(unsigned char type, unsigned short src, unsi return writeRTCPHang(); } -bool CKenwoodNetwork::writeRTCPHang() +bool CNXDNKenwoodNetwork::writeRTCPHang() { unsigned char buffer[30U]; ::memset(buffer, 0x00U, 30U); @@ -515,7 +519,7 @@ bool CKenwoodNetwork::writeRTCPHang() return m_rtcpSocket.write(buffer, 20U, m_address, m_rtcpPort); } -unsigned int CKenwoodNetwork::read(unsigned char* data) +bool CNXDNKenwoodNetwork::read(unsigned char* data) { assert(data != NULL); @@ -525,7 +529,7 @@ unsigned int CKenwoodNetwork::read(unsigned char* data) unsigned int len = readRTP(data); switch (len) { case 0U: // Nothing received - return 0U; + return false; case 35U: // Voice header or trailer return processKenwoodVoiceHeader(data); case 47U: // Voice data @@ -537,11 +541,11 @@ unsigned int CKenwoodNetwork::read(unsigned char* data) return processKenwoodData(data); default: CUtils::dump(5U, "Unknown data received from the Kenwood network", data, len); - return 0U; + return false; } } -unsigned int CKenwoodNetwork::readRTP(unsigned char* data) +unsigned int CNXDNKenwoodNetwork::readRTP(unsigned char* data) { assert(data != NULL); @@ -567,7 +571,7 @@ unsigned int CKenwoodNetwork::readRTP(unsigned char* data) return length - 12U; } -unsigned int CKenwoodNetwork::readRTCP(unsigned char* data) +unsigned int CNXDNKenwoodNetwork::readRTCP(unsigned char* data) { assert(data != NULL); @@ -598,7 +602,11 @@ unsigned int CKenwoodNetwork::readRTCP(unsigned char* data) return length - 12U; } -void CKenwoodNetwork::close() +void CNXDNKenwoodNetwork::reset() +{ +} + +void CNXDNKenwoodNetwork::close() { m_rtcpSocket.close(); m_rtpSocket.close(); @@ -606,7 +614,7 @@ void CKenwoodNetwork::close() LogMessage("Closing Kenwood connection"); } -void CKenwoodNetwork::clock(unsigned int ms) +void CNXDNKenwoodNetwork::clock(unsigned int ms) { m_rtcpTimer.clock(ms); if (m_rtcpTimer.isRunning() && m_rtcpTimer.hasExpired()) { @@ -624,7 +632,7 @@ void CKenwoodNetwork::clock(unsigned int ms) } } -unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) { assert(inData != NULL); @@ -667,7 +675,7 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) m_seen2 = false; m_seen3 = false; m_seen4 = false; - return 33U; + return true; case 0x08U: ::memcpy(inData, outData, 33U); m_headerSeen = false; @@ -675,13 +683,13 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceHeader(unsigned char* inData) m_seen2 = false; m_seen3 = false; m_seen4 = false; - return 33U; + return true; default: - return 0U; + return false; } } -unsigned int CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) { assert(inData != NULL); @@ -764,17 +772,18 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceData(unsigned char* inData) ::memcpy(inData, outData, 33U); - return 33U; + return true; } -unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodData(unsigned char* inData) { if (inData[7U] != 0x09U && inData[7U] != 0x0BU && inData[7U] != 0x08U) - return 0U; + return false; unsigned char outData[50U]; if (inData[7U] == 0x09U || inData[7U] == 0x08U) { + // XXX outData[0U] = 0x90U; outData[1U] = inData[8U]; outData[2U] = inData[7U]; @@ -783,7 +792,7 @@ unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) outData[5U] = inData[12U]; outData[6U] = inData[11U]; ::memcpy(inData, outData, 7U); - return 7U; + return true; } else { outData[0U] = 0x90U; outData[1U] = inData[8U]; @@ -810,11 +819,11 @@ unsigned int CKenwoodNetwork::processKenwoodData(unsigned char* inData) outData[22U] = inData[27U]; outData[23U] = inData[29U]; ::memcpy(inData, outData, 24U); - return 24U; + return true; } } -unsigned long CKenwoodNetwork::getTimeStamp() const +unsigned long CNXDNKenwoodNetwork::getTimeStamp() const { unsigned long timeStamp = 0UL; @@ -845,7 +854,7 @@ unsigned long CKenwoodNetwork::getTimeStamp() const return timeStamp; } -unsigned int CKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) +bool CNXDNKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) { assert(inData != NULL); @@ -899,7 +908,7 @@ unsigned int CKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData } if (!m_seen1 || !m_seen2 || !m_seen3 || !m_seen4) - return 0U; + return false; // Create a dummy header // Header SACCH diff --git a/NXDNKenwoodNetwork.h b/NXDNKenwoodNetwork.h index aa52d64..96da4f3 100644 --- a/NXDNKenwoodNetwork.h +++ b/NXDNKenwoodNetwork.h @@ -16,28 +16,32 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef KenwoodNetwork_H -#define KenwoodNetwork_H +#ifndef NXDNKenwoodNetwork_H +#define NXDNKenwoodNetwork_H -#include "RptNetwork.h" +#include "NXDNNetwork.h" #include "UDPSocket.h" #include "Timer.h" #include #include -class CKenwoodNetwork : public IRptNetwork { +class CNXDNKenwoodNetwork : public INXDNNetwork { public: - CKenwoodNetwork(unsigned int localPort, const std::string& rptAddress, unsigned int rptPort, bool debug); - virtual ~CKenwoodNetwork(); + CNXDNKenwoodNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug); + virtual ~CNXDNKenwoodNetwork(); virtual bool open(); - virtual bool write(const unsigned char* data, unsigned int length); + virtual void enable(bool enabled); - virtual unsigned int read(unsigned char* data); + virtual bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type); - virtual void close(); + virtual bool read(unsigned char* data); + + virtual void reset(); + + virtual void close(); virtual void clock(unsigned int ms); @@ -67,10 +71,12 @@ private: bool processIcomVoiceHeader(const unsigned char* data); bool processIcomVoiceData(const unsigned char* data); - unsigned int processKenwoodVoiceHeader(unsigned char* data); - unsigned int processKenwoodVoiceData(unsigned char* data); - unsigned int processKenwoodVoiceLateEntry(unsigned char* data); - unsigned int processKenwoodData(unsigned char* data); + bool processIcomDataHeader(const unsigned char* data); + bool processIcomDataData(const unsigned char* data); + bool processKenwoodVoiceHeader(unsigned char* data); + bool processKenwoodVoiceData(unsigned char* data); + bool processKenwoodVoiceLateEntry(unsigned char* data); + bool processKenwoodData(unsigned char* data); bool writeRTPVoiceHeader(const unsigned char* data); bool writeRTPVoiceData(const unsigned char* data); bool writeRTPVoiceTrailer(const unsigned char* data); diff --git a/UDPSocket.cpp b/UDPSocket.cpp index ba0e35f..2899faf 100644 --- a/UDPSocket.cpp +++ b/UDPSocket.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX * * 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 @@ -258,3 +258,31 @@ void CUDPSocket::close() ::close(m_fd); #endif } + +unsigned long CUDPSocket::getLocalAddress() const +{ + unsigned long address = 0UL; + + char hostname[80U]; + int ret = ::gethostname(hostname, 80); + if (ret == -1) + return 0UL; + + struct hostent* phe = ::gethostbyname(hostname); + if (phe == NULL) + return 0UL; + + if (phe->h_addrtype != AF_INET) + return 0UL; + + for (unsigned int i = 0U; phe->h_addr_list[i] != NULL; i++) { + struct in_addr addr; + ::memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); + if (addr.s_addr != INADDR_LOOPBACK) { + address = addr.s_addr; + break; + } + } + + return address; +} diff --git a/UDPSocket.h b/UDPSocket.h index e0af272..4c21a43 100644 --- a/UDPSocket.h +++ b/UDPSocket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX * * 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 @@ -47,7 +47,9 @@ public: void close(); - static in_addr lookup(const std::string& hostName); + unsigned long getLocalAddress() const; + + static in_addr lookup(const std::string& hostName); private: std::string m_address; From 0b7efee2a76eeed256118bcc9cf95f826274e592 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 27 May 2020 12:47:21 +0100 Subject: [PATCH 04/19] Upgrade the Kenwood protocol to pass data calls. --- NXDNKenwoodNetwork.cpp | 270 ++++++++++++++++++++++++++++++++++++++--- NXDNKenwoodNetwork.h | 5 + Version.h | 2 +- 3 files changed, 260 insertions(+), 17 deletions(-) diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp index e294d96..8531f90 100644 --- a/NXDNKenwoodNetwork.cpp +++ b/NXDNKenwoodNetwork.cpp @@ -39,6 +39,7 @@ m_rtcpSocket(localAddress, localPort + 1U), m_address(), m_rtcpPort(gwyPort + 1U), m_rtpPort(gwyPort + 0U), +m_enabled(false), m_headerSeen(false), m_seen1(false), m_seen2(false), @@ -98,13 +99,13 @@ bool CNXDNKenwoodNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_ switch (type) { case NNMT_VOICE_HEADER: // Voice header or trailer case NNMT_VOICE_TRAILER: - case NNMT_DATA_TRAILER: // Data trailer return processIcomVoiceHeader(data); case NNMT_VOICE_BODY: // Voice data return processIcomVoiceData(data); - case NNMT_DATA_HEADER: // Voice header or trailer + case NNMT_DATA_HEADER: // Data header or trailer + case NNMT_DATA_TRAILER: return processIcomDataHeader(data); - case NNMT_DATA_BODY: // Voice data + case NNMT_DATA_BODY: // Data data return processIcomDataData(data); default: return false; @@ -235,6 +236,83 @@ bool CNXDNKenwoodNetwork::processIcomVoiceData(const unsigned char* inData) return writeRTPVoiceData(outData); } +bool CNXDNKenwoodNetwork::processIcomDataHeader(const unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[30U]; + ::memset(outData, 0x00U, 30U); + + // SACCH + outData[0U] = inData[2U]; + outData[1U] = inData[1U]; + outData[2U] = inData[4U] & 0xC0U; + outData[3U] = inData[3U]; + + // FACCH 1+2 + outData[4U] = outData[14U] = inData[6U]; + outData[5U] = outData[15U] = inData[5U]; + outData[6U] = outData[16U] = inData[8U]; + outData[7U] = outData[17U] = inData[7U]; + outData[8U] = outData[18U] = inData[10U]; + outData[9U] = outData[19U] = inData[9U]; + outData[10U] = outData[20U] = inData[12U]; + outData[11U] = outData[21U] = inData[11U]; + + unsigned short src = (inData[8U] << 8) + (inData[9U] << 0); + unsigned short dst = (inData[10U] << 8) + (inData[11U] << 0); + unsigned char type = (inData[7U] >> 5) & 0x07U; + + switch (inData[5U] & 0x3FU) { + case 0x09U: + m_hangTimer.stop(); + m_rtcpTimer.start(); + writeRTCPStart(); + return writeRTPDataHeader(outData); + case 0x08U: { + m_hangTimer.start(); + bool ret = writeRTPDataTrailer(outData); + writeRTCPHang(type, src, dst); + return ret; + } + default: + return false; + } +} + +bool CNXDNKenwoodNetwork::processIcomDataData(const unsigned char* inData) +{ + assert(inData != NULL); + + unsigned char outData[40U]; + ::memset(outData, 0x00U, 40U); + + outData[0U] = inData[2U]; + outData[1U] = inData[1U]; + outData[2U] = inData[4U]; + outData[3U] = inData[3U]; + outData[4U] = inData[6U]; + outData[5U] = inData[5U]; + outData[6U] = inData[8U]; + outData[7U] = inData[7U]; + outData[8U] = inData[10U]; + outData[9U] = inData[9U]; + outData[10U] = inData[12U]; + outData[11U] = inData[11U]; + outData[12U] = inData[14U]; + outData[13U] = inData[13U]; + outData[14U] = inData[16U]; + outData[15U] = inData[15U]; + outData[16U] = inData[18U]; + outData[17U] = inData[17U]; + outData[18U] = inData[20U]; + outData[19U] = inData[19U]; + outData[20U] = inData[22U]; + outData[21U] = inData[21U]; + + return writeRTPDataData(outData); +} + bool CNXDNKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) { assert(data != NULL); @@ -252,11 +330,11 @@ bool CNXDNKenwoodNetwork::writeRTPVoiceHeader(const unsigned char* data) unsigned long timeStamp = getTimeStamp(); buffer[4U] = (timeStamp >> 24) & 0xFFU; buffer[5U] = (timeStamp >> 16) & 0xFFU; - buffer[6U] = (timeStamp >> 8) & 0xFFU; - buffer[7U] = (timeStamp >> 0) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; - buffer[8U] = (m_ssrc >> 24) & 0xFFU; - buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; buffer[10U] = (m_ssrc >> 8) & 0xFFU; buffer[11U] = (m_ssrc >> 0) & 0xFFU; @@ -374,6 +452,132 @@ bool CNXDNKenwoodNetwork::writeRTPVoiceData(const unsigned char* data) return m_rtpSocket.write(buffer, 59U, m_address, m_rtpPort); } +bool CNXDNKenwoodNetwork::writeRTPDataHeader(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[50U]; + ::memset(buffer, 0x00U, 50U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + m_sessionId++; + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x01U; + buffer[17U] = 0x01U; + + ::memcpy(buffer + 18U, data, 24U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U); + + return m_rtpSocket.write(buffer, 42U, m_address, m_rtpPort); +} + +bool CNXDNKenwoodNetwork::writeRTPDataTrailer(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[50U]; + ::memset(buffer, 0x00U, 50U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + m_sessionId++; + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x01U; + buffer[17U] = 0x06U; + + ::memcpy(buffer + 18U, data, 24U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U); + + return m_rtpSocket.write(buffer, 42U, m_address, m_rtpPort); +} + +bool CNXDNKenwoodNetwork::writeRTPDataData(const unsigned char* data) +{ + assert(data != NULL); + + unsigned char buffer[50U]; + ::memset(buffer, 0x00U, 50U); + + buffer[0U] = 0x80U; + buffer[1U] = 0x66U; + + m_seqNo++; + buffer[2U] = (m_seqNo >> 8) & 0xFFU; + buffer[3U] = (m_seqNo >> 0) & 0xFFU; + + unsigned long timeStamp = getTimeStamp(); + buffer[4U] = (timeStamp >> 24) & 0xFFU; + buffer[5U] = (timeStamp >> 16) & 0xFFU; + buffer[6U] = (timeStamp >> 8) & 0xFFU; + buffer[7U] = (timeStamp >> 0) & 0xFFU; + + buffer[8U] = (m_ssrc >> 24) & 0xFFU; + buffer[9U] = (m_ssrc >> 16) & 0xFFU; + buffer[10U] = (m_ssrc >> 8) & 0xFFU; + buffer[11U] = (m_ssrc >> 0) & 0xFFU; + + m_sessionId++; + buffer[12U] = m_sessionId; + + buffer[13U] = 0x00U; + buffer[14U] = 0x00U; + buffer[15U] = 0x00U; + buffer[16U] = 0x01U; + buffer[17U] = 0x01U; + + ::memcpy(buffer + 18U, data, 24U); + + if (m_debug) + CUtils::dump(1U, "Kenwood Network RTP Data Sent", buffer, 42U); + + return m_rtpSocket.write(buffer, 42U, m_address, m_rtpPort); +} + bool CNXDNKenwoodNetwork::writeRTCPStart() { #if defined(_WIN32) || defined(_WIN64) @@ -563,6 +767,9 @@ unsigned int CNXDNKenwoodNetwork::readRTP(unsigned char* data) return 0U; } + if (!m_enabled) + return 0U; + if (m_debug) CUtils::dump(1U, "Kenwood Network RTP Data Received", buffer, length); @@ -589,6 +796,9 @@ unsigned int CNXDNKenwoodNetwork::readRTCP(unsigned char* data) return 0U; } + if (!m_enabled) + return 0U; + if (m_debug) CUtils::dump(1U, "Kenwood Network RTCP Data Received", buffer, length); @@ -604,6 +814,14 @@ unsigned int CNXDNKenwoodNetwork::readRTCP(unsigned char* data) void CNXDNKenwoodNetwork::reset() { + m_rtcpTimer.stop(); + m_hangTimer.stop(); + + m_headerSeen = false; + m_seen1 = false; + m_seen2 = false; + m_seen3 = false; + m_seen4 = false; } void CNXDNKenwoodNetwork::close() @@ -783,15 +1001,27 @@ bool CNXDNKenwoodNetwork::processKenwoodData(unsigned char* inData) unsigned char outData[50U]; if (inData[7U] == 0x09U || inData[7U] == 0x08U) { - // XXX - outData[0U] = 0x90U; - outData[1U] = inData[8U]; - outData[2U] = inData[7U]; - outData[3U] = inData[10U]; - outData[4U] = inData[9U]; - outData[5U] = inData[12U]; - outData[6U] = inData[11U]; - ::memcpy(inData, outData, 7U); + outData[0U] = 0x90U; + outData[1U] = inData[8U]; + outData[2U] = inData[7U]; + outData[3U] = inData[10U]; + outData[4U] = inData[9U]; + outData[5U] = inData[12U]; + outData[6U] = inData[11U]; + outData[7U] = inData[14U]; + outData[8U] = inData[13U]; + outData[9U] = inData[16U]; + outData[10U] = inData[15U]; + outData[11U] = inData[18U]; + outData[12U] = inData[17U]; + outData[13U] = inData[20U]; + outData[14U] = inData[19U]; + outData[15U] = inData[22U]; + outData[16U] = inData[21U]; + outData[17U] = inData[24U]; + outData[18U] = inData[23U]; + outData[19U] = inData[26U]; + ::memcpy(inData, outData, 20U); return true; } else { outData[0U] = 0x90U; @@ -931,3 +1161,11 @@ bool CNXDNKenwoodNetwork::processKenwoodVoiceLateEntry(unsigned char* inData) return processKenwoodVoiceHeader(inData); } + +void CNXDNKenwoodNetwork::enable(bool enabled) +{ + if (enabled && !m_enabled) + reset(); + + m_enabled = enabled; +} diff --git a/NXDNKenwoodNetwork.h b/NXDNKenwoodNetwork.h index 96da4f3..e0c1099 100644 --- a/NXDNKenwoodNetwork.h +++ b/NXDNKenwoodNetwork.h @@ -51,6 +51,7 @@ private: in_addr m_address; unsigned int m_rtcpPort; unsigned int m_rtpPort; + bool m_enabled; bool m_headerSeen; bool m_seen1; bool m_seen2; @@ -73,6 +74,7 @@ private: bool processIcomVoiceData(const unsigned char* data); bool processIcomDataHeader(const unsigned char* data); bool processIcomDataData(const unsigned char* data); + bool processIcomDataTrailer(const unsigned char* data); bool processKenwoodVoiceHeader(unsigned char* data); bool processKenwoodVoiceData(unsigned char* data); bool processKenwoodVoiceLateEntry(unsigned char* data); @@ -80,6 +82,9 @@ private: bool writeRTPVoiceHeader(const unsigned char* data); bool writeRTPVoiceData(const unsigned char* data); bool writeRTPVoiceTrailer(const unsigned char* data); + bool writeRTPDataHeader(const unsigned char* data); + bool writeRTPDataData(const unsigned char* data); + bool writeRTPDataTrailer(const unsigned char* data); bool writeRTCPStart(); bool writeRTCPPing(); bool writeRTCPHang(unsigned char type, unsigned short src, unsigned short dst); diff --git a/Version.h b/Version.h index 19a3d8e..fe64411 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200518"; +const char* VERSION = "20200527"; #endif From 7bfe2f2b2fbe532e68962000f4b09a4632db13ff Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 27 May 2020 12:52:15 +0100 Subject: [PATCH 05/19] Fix Linux compile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 33cc689..e14f51c 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OBJECTS = \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o \ - NXDNKenwoodNetwork.oNXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ + NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o \ SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBentry.o Utils.o \ YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o From 36a852b38bc07e2cbec783440617c03f82258bcd Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Sun, 14 Jun 2020 16:00:20 +0900 Subject: [PATCH 06/19] change ScreenLayout definition for Nextion to add new feature easily, the definition of ScreenLayout in [Nextion] has changed like this. ScreenLayout < 8: compatibile setting for old config file 0: G4KLX @ 9600bps 1: (reserved) 2: ON7LDS @ 9600bps 3: ON7LDS-DIY @ 9600bps 4: ON7LDS-DIY @ 115200bps ScreenLayout >= 8: new world, set the bit to enable each feature bit3 (8) use 115200bps bit4 (16) Display DMR Talker Alias bit5 (32) Colour change when displaying TA bit6 (64) Font size change when displaying long TA text bit7 (128) Display DIY status when MMDVM IDLE old settings are same as: 0 -> 0 2 -> 112 (16+32+64) 3 -> 144 (16+128) 4 -> 152 (8+16+128) --- Display.cpp | 2 +- Nextion.cpp | 106 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/Display.cpp b/Display.cpp index 0b47b64..d0e6fd0 100644 --- a/Display.cpp +++ b/Display.cpp @@ -566,7 +566,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem) } } else { SERIAL_SPEED baudrate = SERIAL_9600; - if (screenLayout==4U) + if (screenLayout&0x0cU) baudrate = SERIAL_115200; LogInfo(" Display baudrate: %u ",baudrate); diff --git a/Nextion.cpp b/Nextion.cpp index f15d6cf..adb8e76 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -38,6 +38,16 @@ const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms +#define LAYOUT_COMPAT_MASK (7 << 0) // compatibility for old setting +#define LAYOUT_TA_ENABLE (1 << 4) // enable Talker Alias (TA) display +#define LAYOUT_TA_COLOUR (1 << 5) // TA display with font colour change +#define LAYOUT_TA_FONTSIZE (1 << 6) // TA display with font size change +#define LAYOUT_DIY (1 << 7) // use ON7LDS-DIY layout + +// bit[3:2] is used in Display.cpp to set connection speed for LCD panel. +// 00:low, others:high-speed. bit[2] is overlapped with LAYOUT_COMPAT_MASK. +#define LAYOUT_HIGHSPEED (3 << 2) + CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, const std::string& location) : CDisplay(), m_callsign(callsign), @@ -49,7 +59,7 @@ m_mode(MODE_IDLE), m_displayClock(displayClock), m_utc(utc), m_idleBrightness(idleBrightness), -m_screenLayout(screenLayout), +m_screenLayout(0), m_clockDisplayTimer(1000U, 0U, 400U), m_rssiAccum1(0U), m_rssiAccum2(0U), @@ -68,6 +78,23 @@ m_location(location) { assert(serial != NULL); assert(brightness >= 0U && brightness <= 100U); + + static const unsigned int feature_set[] = { + 0, // 0: G4KLX + 0, // 1: (reserved, low speed) + // 2: ON7LDS + LAYOUT_TA_ENABLE | LAYOUT_TA_COLOUR | LAYOUT_TA_FONTSIZE, + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 3: ON7LDS-DIY + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 4: ON7LDS-DIY (high speed) + 0, // 5: (reserved, high speed) + 0, // 6: (reserved, high speed) + 0, // 7: (reserved, high speed) + }; + + if (screenLayout & ~LAYOUT_COMPAT_MASK) + m_screenLayout = screenLayout & ~LAYOUT_COMPAT_MASK; + else + m_screenLayout = feature_set[screenLayout]; } CNextion::~CNextion() @@ -118,7 +145,7 @@ void CNextion::setIdleInt() ::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid); sendCommand(command); - if (m_screenLayout > 2U) { + if (m_screenLayout & LAYOUT_DIY) { ::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str()); sendCommand(command); ::sprintf(command, "t5.txt=\"%u\"", m_dmrid); @@ -350,17 +377,21 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro if (slotNo == 1U) { - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand("t2.txt=\"2 Listening\""); sendCommandAction(69U); } else { - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand("t0.txt=\"1 Listening\""); @@ -377,9 +408,11 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro if (slotNo == 1U) { ::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str()); - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand(text); @@ -391,9 +424,11 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro } else { ::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str()); - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand(text); @@ -448,15 +483,17 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type) { - if (m_screenLayout < 2U) + if (!(m_screenLayout & LAYOUT_TA_ENABLE)) return; if (type[0] == ' ') { if (slotNo == 1U) { - if (m_screenLayout == 2U) sendCommand("t0.pco=33808"); + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=33808"); sendCommandAction(64U); } else { - if (m_screenLayout == 2U) sendCommand("t2.pco=33808"); + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=33808"); sendCommandAction(72U); } @@ -467,33 +504,36 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co char text[50U]; ::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias); - if (m_screenLayout == 2U) { + if (m_screenLayout & LAYOUT_TA_FONTSIZE) { if (::strlen((char*)talkerAlias) > (16U-4U)) sendCommand("t0.font=3"); if (::strlen((char*)talkerAlias) > (20U-4U)) sendCommand("t0.font=2"); if (::strlen((char*)talkerAlias) > (24U-4U)) sendCommand("t0.font=1"); - - sendCommand("t0.pco=1024"); } + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=1024"); + sendCommand(text); sendCommandAction(63U); } else { char text[50U]; ::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias); - if (m_screenLayout == 2U) { + if (m_screenLayout & LAYOUT_TA_FONTSIZE) { if (::strlen((char*)talkerAlias) > (16U-4U)) sendCommand("t2.font=3"); if (::strlen((char*)talkerAlias) > (20U-4U)) sendCommand("t2.font=2"); if (::strlen((char*)talkerAlias) > (24U-4U)) sendCommand("t2.font=1"); - - sendCommand("t2.pco=1024"); } + + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=1024"); + sendCommand(text); sendCommandAction(71U); } @@ -535,9 +575,11 @@ void CNextion::clearDMRInt(unsigned int slotNo) sendCommand("t0.txt=\"1 Listening\""); sendCommandAction(61U); - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand("t1.txt=\"\""); @@ -547,9 +589,11 @@ void CNextion::clearDMRInt(unsigned int slotNo) sendCommand("t2.txt=\"2 Listening\""); sendCommandAction(69U); - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand("t3.txt=\"\""); @@ -862,7 +906,7 @@ void CNextion::close() void CNextion::sendCommandAction(unsigned int status) { - if (m_screenLayout<3U) + if (!(m_screenLayout & LAYOUT_DIY)) return; char text[30U]; @@ -881,4 +925,4 @@ void CNextion::sendCommand(const char* command) // we must add a bit of a delay to allow the display to process the commands, else some are getting mangled. // 10 ms is just a guess, but seems to be sufficient. CThread::sleep(10U); - } +} From 3313fe8ec3528f107172855a240a8d7839e881cf Mon Sep 17 00:00:00 2001 From: Andy Taylor Date: Mon, 15 Jun 2020 17:00:37 +0100 Subject: [PATCH 07/19] Update OLED.cpp Modify the OLED code to only allow scroll commands when scrolling is enabled --- OLED.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/OLED.cpp b/OLED.cpp index 6f9b4ec..02afc2d 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -240,7 +240,8 @@ void COLED::setIdleInt() // m_display.print("Idle"); // m_display.setTextSize(1); - m_display.startscrolldiagright(0x00,0x0f); //the MMDVM logo scrolls the whole screen + if (m_displayScroll && m_displayLogoScreensaver) + m_display.startscrolldiagright(0x00,0x0f); //the MMDVM logo scrolls the whole screen m_display.display(); unsigned char info[100U]; @@ -568,7 +569,8 @@ void COLED::writeCWInt() m_display.setTextSize(1); m_display.display(); - m_display.startscrollright(0x02,0x0f); + if (m_displayScroll) + m_display.startscrollright(0x02,0x0f); } void COLED::clearCWInt() @@ -581,14 +583,16 @@ void COLED::clearCWInt() m_display.setTextSize(1); m_display.display(); - m_display.startscrollleft(0x02,0x0f); + if (m_displayScroll) + m_display.startscrollleft(0x02,0x0f); } void COLED::close() { m_display.clearDisplay(); m_display.fillRect(0, 0, m_display.width(), 16, BLACK); - m_display.startscrollright(0x00,0x01); + if (m_displayScroll) + m_display.startscrollright(0x00,0x01); m_display.setCursor(0,00); m_display.setTextSize(2); m_display.print("-CLOSE-"); From 325b30d30b1111566c22cf107ed34fe3a689f79c Mon Sep 17 00:00:00 2001 From: Kimi Jin Date: Wed, 24 Jun 2020 13:33:23 +0800 Subject: [PATCH 08/19] Add install rules into Makefile. This will insatll MMDVMHost and RemoteCommand to /usr/local/bin/ path, so need exec with command 'sudo make install'. --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index e14f51c..984a3dc 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h From 1dc91b9a6459acf59f378589f13a8bec0b2c5d7f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 25 Jun 2020 09:55:28 +0100 Subject: [PATCH 09/19] Add the install target to the other makefiles. --- Makefile.Pi | 4 ++++ Makefile.Pi.Adafruit | 4 ++++ Makefile.Pi.HD44780 | 4 ++++ Makefile.Pi.OLED | 4 ++++ Makefile.Pi.PCF8574 | 4 ++++ Makefile.Solaris | 39 --------------------------------------- 6 files changed, 20 insertions(+), 39 deletions(-) delete mode 100644 Makefile.Solaris diff --git a/Makefile.Pi b/Makefile.Pi index d9c1acd..5a1334b 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -27,6 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index a9c0b35..fbeaf80 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -28,6 +28,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index a0127af..02ff78d 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -27,6 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 5629489..387a0a7 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -27,6 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index cd6b67f..5ac5b48 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -28,6 +28,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o %.o: %.cpp $(CXX) $(CFLAGS) -c -o $@ $< +install: + install -m 755 MMDVMHost /usr/local/bin/ + install -m 755 RemoteCommand /usr/local/bin/ + clean: $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h diff --git a/Makefile.Solaris b/Makefile.Solaris deleted file mode 100644 index 4d46985..0000000 --- a/Makefile.Solaris +++ /dev/null @@ -1,39 +0,0 @@ -# This makefile is for Solaris using gcc - -CC = gcc -CXX = g++ -CFLAGS = -g -O3 -Wall -std=c++0x -pthread -LIBS = -lpthread -lsocket -LDFLAGS = -g - -OBJECTS = \ - AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ - DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \ - NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o \ - NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o \ - P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o \ - StopWatch.o Sync.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o UserDBebtry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o \ - YSFNetwork.o YSFPayload.o - -all: MMDVMHost RemoteCommand - -MMDVMHost: GitVersion.h $(OBJECTS) - $(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost - -RemoteCommand: Log.o RemoteCommand.o UDPSocket.o - $(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand - -%.o: %.cpp - $(CXX) $(CFLAGS) -c -o $@ $< - -clean: - $(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h - -# Export the current git version if the index file exists, else 000... -GitVersion.h: -ifneq ("$(wildcard .git/index)","") - echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@ -else - echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@ -endif From edce66701894d48424a0512bb9f4a20d89a8d9bc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 29 Jun 2020 11:25:10 +0100 Subject: [PATCH 10/19] Replace MobileGPS with gpsd. --- Conf.cpp | 32 ++++++------- Conf.h | 14 +++--- GPSD.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++ MobileGPS.h => GPSD.h | 42 +++++++---------- MMDVM.ini | 4 +- MMDVMHost.cpp | 42 ++++++++++------- MMDVMHost.h | 6 ++- Makefile | 9 +++- Makefile.Pi | 8 +++- Makefile.Pi.Adafruit | 8 +++- Makefile.Pi.HD44780 | 9 +++- Makefile.Pi.OLED | 9 +++- Makefile.Pi.PCF8574 | 9 +++- MobileGPS.cpp | 101 ---------------------------------------- Version.h | 2 +- 15 files changed, 222 insertions(+), 177 deletions(-) create mode 100644 GPSD.cpp rename MobileGPS.h => GPSD.h (60%) delete mode 100644 MobileGPS.cpp diff --git a/Conf.cpp b/Conf.cpp index 8d61b30..5bc7dba 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -57,7 +57,7 @@ enum SECTION { SECTION_OLED, SECTION_LCDPROC, SECTION_LOCK_FILE, - SECTION_MOBILE_GPS, + SECTION_GPSD, SECTION_REMOTE_CONTROL }; @@ -283,9 +283,9 @@ m_lcdprocUTC(false), m_lcdprocDimOnIdle(false), m_lockFileEnabled(false), m_lockFileName(), -m_mobileGPSEnabled(false), -m_mobileGPSAddress(), -m_mobileGPSPort(0U), +m_gpsdEnabled(false), +m_gpsdAddress(), +m_gpsdPort(), m_remoteControlEnabled(false), m_remoteControlPort(0U) { @@ -367,8 +367,8 @@ bool CConf::read() section = SECTION_LCDPROC; else if (::strncmp(buffer, "[Lock File]", 11U) == 0) section = SECTION_LOCK_FILE; - else if (::strncmp(buffer, "[Mobile GPS]", 12U) == 0) - section = SECTION_MOBILE_GPS; + else if (::strncmp(buffer, "[GPSD]", 6U) == 0) + section = SECTION_GPSD; else if (::strncmp(buffer, "[Remote Control]", 16U) == 0) section = SECTION_REMOTE_CONTROL; else @@ -950,13 +950,13 @@ bool CConf::read() m_lockFileEnabled = ::atoi(value) == 1; else if (::strcmp(key, "File") == 0) m_lockFileName = value; - } else if (section == SECTION_MOBILE_GPS) { + } else if (section == SECTION_GPSD) { if (::strcmp(key, "Enable") == 0) - m_mobileGPSEnabled = ::atoi(value) == 1; + m_gpsdEnabled = ::atoi(value) == 1; else if (::strcmp(key, "Address") == 0) - m_mobileGPSAddress = value; + m_gpsdAddress = value; else if (::strcmp(key, "Port") == 0) - m_mobileGPSPort = (unsigned int)::atoi(value); + m_gpsdPort = value; } else if (section == SECTION_REMOTE_CONTROL) { if (::strcmp(key, "Enable") == 0) m_remoteControlEnabled = ::atoi(value) == 1; @@ -2071,19 +2071,19 @@ std::string CConf::getLockFileName() const return m_lockFileName; } -bool CConf::getMobileGPSEnabled() const +bool CConf::getGPSDEnabled() const { - return m_mobileGPSEnabled; + return m_gpsdEnabled; } -std::string CConf::getMobileGPSAddress() const +std::string CConf::getGPSDAddress() const { - return m_mobileGPSAddress; + return m_gpsdAddress; } -unsigned int CConf::getMobileGPSPort() const +std::string CConf::getGPSDPort() const { - return m_mobileGPSPort; + return m_gpsdPort; } bool CConf::getRemoteControlEnabled() const diff --git a/Conf.h b/Conf.h index 77cff6c..a4f94eb 100644 --- a/Conf.h +++ b/Conf.h @@ -306,10 +306,10 @@ public: bool getLockFileEnabled() const; std::string getLockFileName() const; - // The Mobile GPS section - bool getMobileGPSEnabled() const; - std::string getMobileGPSAddress() const; - unsigned int getMobileGPSPort() const; + // The GPSD section + bool getGPSDEnabled() const; + std::string getGPSDAddress() const; + std::string getGPSDPort() const; // The Remote Control section bool getRemoteControlEnabled() const; @@ -565,9 +565,9 @@ private: bool m_lockFileEnabled; std::string m_lockFileName; - bool m_mobileGPSEnabled; - std::string m_mobileGPSAddress; - unsigned int m_mobileGPSPort; + bool m_gpsdEnabled; + std::string m_gpsdAddress; + std::string m_gpsdPort; bool m_remoteControlEnabled; unsigned int m_remoteControlPort; diff --git a/GPSD.cpp b/GPSD.cpp new file mode 100644 index 0000000..aec42f0 --- /dev/null +++ b/GPSD.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018,2020 by Jonathan Naylor G4KLX + * + * 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "GPSD.h" + +#if defined(USE_GPS) + +#include +#include +#include +#include + +CGPSD::CGPSD(const std::string& address, const std::string& port, CDMRNetwork* network) : +m_gpsdAddress(address), +m_gpsdPort(port), +m_network(network), +m_gpsdData(), +m_idTimer(1000U, 60U) +{ + assert(!address.empty()); + assert(!port.empty()); + assert(network != NULL); +} + +CGPSD::~CGPSD() +{ +} + +bool CGPSD::open() +{ + int ret = ::gps_open(m_gpsdAddress.c_str(), m_gpsdPort.c_str(), &m_gpsdData); + if (ret != 0) { + LogError("Error when opening access to gpsd - %d - %s", errno, ::gps_errstr(errno)); + return false; + } + + ::gps_stream(&m_gpsdData, WATCH_ENABLE | WATCH_JSON, NULL); + + LogMessage("Connected to GPSD"); + + m_idTimer.start(); + + return true; +} + +void CGPSD::clock(unsigned int ms) +{ + m_idTimer.clock(ms); + + if (m_idTimer.hasExpired()) { + sendReport(); + m_idTimer.start(); + } +} + +void CGPSD::close() +{ + ::gps_stream(&m_gpsdData, WATCH_DISABLE, NULL); + ::gps_close(&m_gpsdData); +} + +void CGPSD::sendReport() +{ + if (!::gps_waiting(&m_gpsdData, 0)) + return; + +#if GPSD_API_MAJOR_VERSION >= 7 + if (::gps_read(&m_gpsdData, NULL, 0) <= 0) + return; +#else + if (::gps_read(&m_gpsdData) <= 0) + return; +#endif + + if (m_gpsdData.status != STATUS_FIX) + return; + + bool latlonSet = (m_gpsdData.set & LATLON_SET) == LATLON_SET; + if (!latlonSet) + return; + + float latitude = float(m_gpsdData.fix.latitude); + float longitude = float(m_gpsdData.fix.longitude); + + m_network->writeHomePosition(latitude, longitude); +} + +#endif + diff --git a/MobileGPS.h b/GPSD.h similarity index 60% rename from MobileGPS.h rename to GPSD.h index 8d69572..d8838db 100644 --- a/MobileGPS.h +++ b/GPSD.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 by Jonathan Naylor G4KLX + * Copyright (C) 2018,2020 by Jonathan Naylor G4KLX * * 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 @@ -16,32 +16,22 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef MobileGPS_H -#define MobileGPS_H +#ifndef GPSD_H +#define GPSD_H + +#if defined(USE_GPS) #include "DMRNetwork.h" -#include "UDPSocket.h" #include "Timer.h" #include -#if !defined(_WIN32) && !defined(_WIN64) -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#endif +#include -class CMobileGPS { +class CGPSD { public: - CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network); - ~CMobileGPS(); + CGPSD(const std::string& address, const std::string& port, CDMRNetwork* network); + ~CGPSD(); bool open(); @@ -50,14 +40,16 @@ public: void close(); private: - CTimer m_idTimer; - in_addr m_address; - unsigned int m_port; - CUDPSocket m_socket; - CDMRNetwork* m_network; + std::string m_gpsdAddress; + std::string m_gpsdPort; + CDMRNetwork* m_network; + struct gps_data_t m_gpsdData; + CTimer m_idTimer; - bool pollGPS(); void sendReport(); }; #endif + +#endif + diff --git a/MMDVM.ini b/MMDVM.ini index 9b02e83..fc0e4db 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -288,10 +288,10 @@ UTC=0 Enable=0 File=/tmp/MMDVM_Active.lck -[Mobile GPS] +[GPSD] Enable=0 Address=127.0.0.1 -Port=7834 +Port=2947 [Remote Control] Enable=0 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 8cbf318..b736a42 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -161,7 +161,9 @@ m_id(0U), m_cwCallsign(), m_lockFileEnabled(false), m_lockFileName(), -m_mobileGPS(NULL), +#if defined(USE_GPS) +m_gpsd(NULL), +#endif m_remoteControl(NULL), m_fixedMode(false) { @@ -1004,8 +1006,10 @@ int CMMDVMHost::run() if (m_pocsagNetwork != NULL) m_pocsagNetwork->clock(ms); - if (m_mobileGPS != NULL) - m_mobileGPS->clock(ms); +#if defined(USE_GPS) + if (m_gpsd != NULL) + m_gpsd->clock(ms); +#endif m_cwIdTimer.clock(ms); if (m_cwIdTimer.isRunning() && m_cwIdTimer.hasExpired()) { @@ -1082,10 +1086,12 @@ int CMMDVMHost::run() m_display->close(); delete m_display; - if (m_mobileGPS != NULL) { - m_mobileGPS->close(); - delete m_mobileGPS; +#if defined(USE_GPS) + if (m_gpsd != NULL) { + m_gpsd->close(); + delete m_gpsd; } +#endif if (m_ump != NULL) { m_ump->close(); @@ -1392,23 +1398,25 @@ bool CMMDVMHost::createDMRNetwork() return false; } - bool mobileGPSEnabled = m_conf.getMobileGPSEnabled(); - if (mobileGPSEnabled) { - std::string mobileGPSAddress = m_conf.getMobileGPSAddress(); - unsigned int mobileGPSPort = m_conf.getMobileGPSPort(); +#if defined(USE_GPS) + bool gpsdEnabled = m_conf.getGPSDEnabled(); + if (gpsdEnabled) { + std::string gpsdAddress = m_conf.getGPSDAddress(); + std::string gpsdPort = m_conf.getGPSDPort(); - LogInfo("Mobile GPS Parameters"); - LogInfo(" Address: %s", mobileGPSAddress.c_str()); - LogInfo(" Port: %u", mobileGPSPort); + LogInfo("GPSD Parameters"); + LogInfo(" Address: %s", gpsdAddress.c_str()); + LogInfo(" Port: %s", gpsdPort.c_str()); - m_mobileGPS = new CMobileGPS(address, port, m_dmrNetwork); + m_gpsd = new CGPSD(gpsdAddress, gpsdPort, m_dmrNetwork); - ret = m_mobileGPS->open(); + ret = m_gpsd->open(); if (!ret) { - delete m_mobileGPS; - m_mobileGPS = NULL; + delete m_gpsd; + m_gpsd = NULL; } } +#endif m_dmrNetwork->enable(true); diff --git a/MMDVMHost.h b/MMDVMHost.h index 6b1e078..4e2b039 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -34,11 +34,11 @@ #include "P25Network.h" #include "DMRNetwork.h" #include "DMRLookup.h" -#include "MobileGPS.h" #include "Display.h" #include "Timer.h" #include "Modem.h" #include "Conf.h" +#include "GPSD.h" #include "UMP.h" #include @@ -102,7 +102,9 @@ private: std::string m_cwCallsign; bool m_lockFileEnabled; std::string m_lockFileName; - CMobileGPS* m_mobileGPS; +#if defined(USE_GPS) + CGPSD* m_gpsd; +#endif CRemoteControl* m_remoteControl; bool m_fixedMode; diff --git a/Makefile b/Makefile index 984a3dc..029f36e 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,21 @@ CC = cc CXX = c++ + +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread +#LIBS = -lpthread -lgps + LDFLAGS = -g OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o \ NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o \ diff --git a/Makefile.Pi b/Makefile.Pi index 5a1334b..24650a3 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -2,14 +2,20 @@ CC = gcc CXX = g++ +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include +#LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps + LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index fbeaf80..c273ce5 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -3,14 +3,20 @@ CC = gcc CXX = g++ +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include +#LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps + LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 02ff78d..eccc3cc 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -2,14 +2,21 @@ CC = gcc CXX = g++ + +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -I/usr/local/include +#LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps + LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 387a0a7..513e3f1 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -2,14 +2,21 @@ CC = gcc CXX = g++ + +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include LIBS = -lArduiPi_OLED -lwiringPi -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DOLED -I/usr/local/include +#LIBS = -lArduiPi_OLED -lwiringPi -lpthread -lgps + LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 5ac5b48..ad46379 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -3,14 +3,21 @@ CC = gcc CXX = g++ + +# Use the following CFLAGS and LIBS if you don't want to use gpsd. CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread + +# Use the following CFLAGS and LIBS if you do want to use gpsd. +#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include +#LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps + LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \ DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \ - DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \ + DStarSlowData.o Golay2087.o Golay24128.o GPSD.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o \ NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \ NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o \ P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ diff --git a/MobileGPS.cpp b/MobileGPS.cpp deleted file mode 100644 index 27721bd..0000000 --- a/MobileGPS.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2018 by Jonathan Naylor G4KLX - * - * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "MobileGPS.h" - -#include -#include -#include -#include - -CMobileGPS::CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network) : -m_idTimer(1000U, 60U), -m_address(), -m_port(port), -m_socket(), -m_network(network) -{ - assert(!address.empty()); - assert(port > 0U); - assert(network != NULL); - - m_address = CUDPSocket::lookup(address); -} - -CMobileGPS::~CMobileGPS() -{ -} - -bool CMobileGPS::open() -{ - bool ret = m_socket.open(); - if (!ret) - return false; - - m_idTimer.start(); - - return true; -} - -void CMobileGPS::clock(unsigned int ms) -{ - m_idTimer.clock(ms); - - if (m_idTimer.hasExpired()) { - pollGPS(); - m_idTimer.start(); - } - - sendReport(); -} - -void CMobileGPS::close() -{ - m_socket.close(); -} - -bool CMobileGPS::pollGPS() -{ - return m_socket.write((unsigned char*)"MMDVMHost", 9U, m_address, m_port); -} - -void CMobileGPS::sendReport() -{ - // Grab GPS data if it's available - unsigned char buffer[200U]; - in_addr address; - unsigned int port; - int ret = m_socket.read(buffer, 200U, address, port); - if (ret <= 0) - return; - - buffer[ret] = '\0'; - - // Parse the GPS data - char* pLatitude = ::strtok((char*)buffer, ",\n"); // Latitude - char* pLongitude = ::strtok(NULL, ",\n"); // Longitude - - if (pLatitude == NULL || pLongitude == NULL) - return; - - float latitude = float(::atof(pLatitude)); - float longitude = float(::atof(pLongitude)); - - m_network->writeHomePosition(latitude, longitude); -} - diff --git a/Version.h b/Version.h index 101ca94..68d6440 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200608"; +const char* VERSION = "20200629"; #endif From be8c29da3e62e6fb4a1b49132aa70936f7fc34f2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 29 Jun 2020 11:50:33 +0100 Subject: [PATCH 11/19] Fix Windows compilation. --- MMDVMHost.vcxproj | 4 ++-- MMDVMHost.vcxproj.filters | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 44b50f2..b17f851 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -183,13 +183,13 @@ + - @@ -281,12 +281,12 @@ + - diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 01fcd3f..7168194 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -278,9 +278,6 @@ Header Files - - Header Files - Header Files @@ -305,6 +302,9 @@ Header Files + + Header Files + @@ -547,9 +547,6 @@ Source Files - - Source Files - Source Files @@ -574,5 +571,8 @@ Source Files + + Source Files + \ No newline at end of file From df47466aa2881ff3774f4660727c39227c97bc6c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Jun 2020 11:38:25 +0100 Subject: [PATCH 12/19] Use USE_GPSD instead of USE_GPS. --- GPSD.cpp | 3 +-- GPSD.h | 3 +-- MMDVMHost.cpp | 8 ++++---- MMDVMHost.h | 2 +- Makefile | 2 +- Makefile.Pi | 2 +- Makefile.Pi.Adafruit | 2 +- Makefile.Pi.HD44780 | 2 +- Makefile.Pi.OLED | 2 +- Makefile.Pi.PCF8574 | 2 +- Version.h | 2 +- 11 files changed, 14 insertions(+), 16 deletions(-) diff --git a/GPSD.cpp b/GPSD.cpp index aec42f0..c06321a 100644 --- a/GPSD.cpp +++ b/GPSD.cpp @@ -18,7 +18,7 @@ #include "GPSD.h" -#if defined(USE_GPS) +#if defined(USE_GPSD) #include #include @@ -101,4 +101,3 @@ void CGPSD::sendReport() } #endif - diff --git a/GPSD.h b/GPSD.h index d8838db..cef93b5 100644 --- a/GPSD.h +++ b/GPSD.h @@ -19,7 +19,7 @@ #ifndef GPSD_H #define GPSD_H -#if defined(USE_GPS) +#if defined(USE_GPSD) #include "DMRNetwork.h" #include "Timer.h" @@ -52,4 +52,3 @@ private: #endif #endif - diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index b736a42..b5a8aef 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -161,7 +161,7 @@ m_id(0U), m_cwCallsign(), m_lockFileEnabled(false), m_lockFileName(), -#if defined(USE_GPS) +#if defined(USE_GPSD) m_gpsd(NULL), #endif m_remoteControl(NULL), @@ -1006,7 +1006,7 @@ int CMMDVMHost::run() if (m_pocsagNetwork != NULL) m_pocsagNetwork->clock(ms); -#if defined(USE_GPS) +#if defined(USE_GPSD) if (m_gpsd != NULL) m_gpsd->clock(ms); #endif @@ -1086,7 +1086,7 @@ int CMMDVMHost::run() m_display->close(); delete m_display; -#if defined(USE_GPS) +#if defined(USE_GPSD) if (m_gpsd != NULL) { m_gpsd->close(); delete m_gpsd; @@ -1398,7 +1398,7 @@ bool CMMDVMHost::createDMRNetwork() return false; } -#if defined(USE_GPS) +#if defined(USE_GPSD) bool gpsdEnabled = m_conf.getGPSDEnabled(); if (gpsdEnabled) { std::string gpsdAddress = m_conf.getGPSDAddress(); diff --git a/MMDVMHost.h b/MMDVMHost.h index 4e2b039..3d77653 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -102,7 +102,7 @@ private: std::string m_cwCallsign; bool m_lockFileEnabled; std::string m_lockFileName; -#if defined(USE_GPS) +#if defined(USE_GPSD) CGPSD* m_gpsd; #endif CRemoteControl* m_remoteControl; diff --git a/Makefile b/Makefile index 029f36e..1ad3c8a 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread LIBS = -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread #LIBS = -lpthread -lgps LDFLAGS = -g diff --git a/Makefile.Pi b/Makefile.Pi index 24650a3..53e457e 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -7,7 +7,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include #LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps LDFLAGS = -g -L/usr/local/lib diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index c273ce5..0a8fa85 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -8,7 +8,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/l LIBS = -lwiringPi -lwiringPiDev -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include #LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps LDFLAGS = -g -L/usr/local/lib diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index eccc3cc..5417946 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -8,7 +8,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include LIBS = -lwiringPi -lwiringPiDev -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -I/usr/local/include +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread -DHD44780 -I/usr/local/include #LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps LDFLAGS = -g -L/usr/local/lib diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 513e3f1..9949cf2 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -8,7 +8,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include LIBS = -lArduiPi_OLED -lwiringPi -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DOLED -I/usr/local/include +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread -DOLED -I/usr/local/include #LIBS = -lArduiPi_OLED -lwiringPi -lpthread -lgps LDFLAGS = -g -L/usr/local/lib diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index ad46379..aa84cc8 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -9,7 +9,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/lo LIBS = -lwiringPi -lwiringPiDev -lpthread # Use the following CFLAGS and LIBS if you do want to use gpsd. -#CFLAGS = -g -O3 -Wall -DUSE_GPS -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include +#CFLAGS = -g -O3 -Wall -DUSE_GPSD -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include #LIBS = -lwiringPi -lwiringPiDev -lpthread -lgps LDFLAGS = -g -L/usr/local/lib diff --git a/Version.h b/Version.h index 68d6440..bb444d2 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200629"; +const char* VERSION = "20200630"; #endif From 236d467c1a4268dee6e79f65dc839a0affd48aa9 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Sun, 14 Jun 2020 16:00:20 +0900 Subject: [PATCH 13/19] change ScreenLayout definition for Nextion to add new feature easily, the definition of ScreenLayout in [Nextion] has changed like this. ScreenLayout < 8: compatibile setting for old config file 0: G4KLX @ 9600bps 1: (reserved) 2: ON7LDS @ 9600bps 3: ON7LDS-DIY @ 9600bps 4: ON7LDS-DIY @ 115200bps ScreenLayout >= 8: new world, set the bit to enable each feature bit3 (8) use 115200bps bit4 (16) Display DMR Talker Alias bit5 (32) Colour change when displaying TA bit6 (64) Font size change when displaying long TA text bit7 (128) Display DIY status when MMDVM IDLE old settings are same as: 0 -> 0 2 -> 112 (16+32+64) 3 -> 144 (16+128) 4 -> 152 (8+16+128) --- Display.cpp | 2 +- Nextion.cpp | 106 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/Display.cpp b/Display.cpp index 0b47b64..d0e6fd0 100644 --- a/Display.cpp +++ b/Display.cpp @@ -566,7 +566,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem) } } else { SERIAL_SPEED baudrate = SERIAL_9600; - if (screenLayout==4U) + if (screenLayout&0x0cU) baudrate = SERIAL_115200; LogInfo(" Display baudrate: %u ",baudrate); diff --git a/Nextion.cpp b/Nextion.cpp index f15d6cf..adb8e76 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -38,6 +38,16 @@ const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms +#define LAYOUT_COMPAT_MASK (7 << 0) // compatibility for old setting +#define LAYOUT_TA_ENABLE (1 << 4) // enable Talker Alias (TA) display +#define LAYOUT_TA_COLOUR (1 << 5) // TA display with font colour change +#define LAYOUT_TA_FONTSIZE (1 << 6) // TA display with font size change +#define LAYOUT_DIY (1 << 7) // use ON7LDS-DIY layout + +// bit[3:2] is used in Display.cpp to set connection speed for LCD panel. +// 00:low, others:high-speed. bit[2] is overlapped with LAYOUT_COMPAT_MASK. +#define LAYOUT_HIGHSPEED (3 << 2) + CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, const std::string& location) : CDisplay(), m_callsign(callsign), @@ -49,7 +59,7 @@ m_mode(MODE_IDLE), m_displayClock(displayClock), m_utc(utc), m_idleBrightness(idleBrightness), -m_screenLayout(screenLayout), +m_screenLayout(0), m_clockDisplayTimer(1000U, 0U, 400U), m_rssiAccum1(0U), m_rssiAccum2(0U), @@ -68,6 +78,23 @@ m_location(location) { assert(serial != NULL); assert(brightness >= 0U && brightness <= 100U); + + static const unsigned int feature_set[] = { + 0, // 0: G4KLX + 0, // 1: (reserved, low speed) + // 2: ON7LDS + LAYOUT_TA_ENABLE | LAYOUT_TA_COLOUR | LAYOUT_TA_FONTSIZE, + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 3: ON7LDS-DIY + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 4: ON7LDS-DIY (high speed) + 0, // 5: (reserved, high speed) + 0, // 6: (reserved, high speed) + 0, // 7: (reserved, high speed) + }; + + if (screenLayout & ~LAYOUT_COMPAT_MASK) + m_screenLayout = screenLayout & ~LAYOUT_COMPAT_MASK; + else + m_screenLayout = feature_set[screenLayout]; } CNextion::~CNextion() @@ -118,7 +145,7 @@ void CNextion::setIdleInt() ::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid); sendCommand(command); - if (m_screenLayout > 2U) { + if (m_screenLayout & LAYOUT_DIY) { ::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str()); sendCommand(command); ::sprintf(command, "t5.txt=\"%u\"", m_dmrid); @@ -350,17 +377,21 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro if (slotNo == 1U) { - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand("t2.txt=\"2 Listening\""); sendCommandAction(69U); } else { - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand("t0.txt=\"1 Listening\""); @@ -377,9 +408,11 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro if (slotNo == 1U) { ::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str()); - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand(text); @@ -391,9 +424,11 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro } else { ::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str()); - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand(text); @@ -448,15 +483,17 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi) void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type) { - if (m_screenLayout < 2U) + if (!(m_screenLayout & LAYOUT_TA_ENABLE)) return; if (type[0] == ' ') { if (slotNo == 1U) { - if (m_screenLayout == 2U) sendCommand("t0.pco=33808"); + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=33808"); sendCommandAction(64U); } else { - if (m_screenLayout == 2U) sendCommand("t2.pco=33808"); + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=33808"); sendCommandAction(72U); } @@ -467,33 +504,36 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co char text[50U]; ::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias); - if (m_screenLayout == 2U) { + if (m_screenLayout & LAYOUT_TA_FONTSIZE) { if (::strlen((char*)talkerAlias) > (16U-4U)) sendCommand("t0.font=3"); if (::strlen((char*)talkerAlias) > (20U-4U)) sendCommand("t0.font=2"); if (::strlen((char*)talkerAlias) > (24U-4U)) sendCommand("t0.font=1"); - - sendCommand("t0.pco=1024"); } + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=1024"); + sendCommand(text); sendCommandAction(63U); } else { char text[50U]; ::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias); - if (m_screenLayout == 2U) { + if (m_screenLayout & LAYOUT_TA_FONTSIZE) { if (::strlen((char*)talkerAlias) > (16U-4U)) sendCommand("t2.font=3"); if (::strlen((char*)talkerAlias) > (20U-4U)) sendCommand("t2.font=2"); if (::strlen((char*)talkerAlias) > (24U-4U)) sendCommand("t2.font=1"); - - sendCommand("t2.pco=1024"); } + + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=1024"); + sendCommand(text); sendCommandAction(71U); } @@ -535,9 +575,11 @@ void CNextion::clearDMRInt(unsigned int slotNo) sendCommand("t0.txt=\"1 Listening\""); sendCommandAction(61U); - if (m_screenLayout == 2U) { - sendCommand("t0.pco=0"); - sendCommand("t0.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t0.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t0.font=4"); } sendCommand("t1.txt=\"\""); @@ -547,9 +589,11 @@ void CNextion::clearDMRInt(unsigned int slotNo) sendCommand("t2.txt=\"2 Listening\""); sendCommandAction(69U); - if (m_screenLayout == 2U) { - sendCommand("t2.pco=0"); - sendCommand("t2.font=4"); + if (m_screenLayout & LAYOUT_TA_ENABLE) { + if (m_screenLayout & LAYOUT_TA_COLOUR) + sendCommand("t2.pco=0"); + if (m_screenLayout & LAYOUT_TA_FONTSIZE) + sendCommand("t2.font=4"); } sendCommand("t3.txt=\"\""); @@ -862,7 +906,7 @@ void CNextion::close() void CNextion::sendCommandAction(unsigned int status) { - if (m_screenLayout<3U) + if (!(m_screenLayout & LAYOUT_DIY)) return; char text[30U]; @@ -881,4 +925,4 @@ void CNextion::sendCommand(const char* command) // we must add a bit of a delay to allow the display to process the commands, else some are getting mangled. // 10 ms is just a guess, but seems to be sufficient. CThread::sleep(10U); - } +} From 79b3eaa57afaa7a6efd765645d415e8712ffbb28 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Wed, 1 Jul 2020 19:48:07 +0900 Subject: [PATCH 14/19] replace SSRC source from IPv4 address to random number Previous implementation uses SSRC as IPv4 address that is same behaviour of Kenwood's NXDN repeater. RFC 3350 RTP protocol recommends SSRC uses random number. So I use MT19937 random number generator instead of IP address. And if this is no problem, I will do two changes. - replace rand() in DMRNetwork.cpp and DStarNetwork.cpp to MT19937 - remove getLocalAddress() in UDPSocket.cpp --- NXDNKenwoodNetwork.cpp | 9 +++++++-- NXDNKenwoodNetwork.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp index 8531f90..496462f 100644 --- a/NXDNKenwoodNetwork.cpp +++ b/NXDNKenwoodNetwork.cpp @@ -56,7 +56,8 @@ m_rtcpTimer(1000U, 0U, 200U), m_hangTimer(1000U, 5U), m_hangType(0U), m_hangSrc(0U), -m_hangDst(0U) +m_hangDst(0U), +m_random() { assert(localPort > 0U); assert(!gwyAddress.empty()); @@ -65,6 +66,10 @@ m_hangDst(0U) m_sacch = new unsigned char[10U]; m_address = CUDPSocket::lookup(gwyAddress); + + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; } CNXDNKenwoodNetwork::~CNXDNKenwoodNetwork() @@ -87,7 +92,7 @@ bool CNXDNKenwoodNetwork::open() return false; } - m_ssrc = m_rtpSocket.getLocalAddress(); + m_ssrc = m_random(); return true; } diff --git a/NXDNKenwoodNetwork.h b/NXDNKenwoodNetwork.h index e0c1099..6645c23 100644 --- a/NXDNKenwoodNetwork.h +++ b/NXDNKenwoodNetwork.h @@ -25,6 +25,7 @@ #include #include +#include class CNXDNKenwoodNetwork : public INXDNNetwork { public: @@ -69,6 +70,7 @@ private: unsigned char m_hangType; unsigned short m_hangSrc; unsigned short m_hangDst; + std::mt19937 m_random; bool processIcomVoiceHeader(const unsigned char* data); bool processIcomVoiceData(const unsigned char* data); From 0892aaaaae746f0a8e103502e4aa573aef8f207f Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Wed, 1 Jul 2020 20:39:22 +0900 Subject: [PATCH 15/19] eliminate SSRC range 0x00000001 - 0xfffffffe --- NXDNKenwoodNetwork.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NXDNKenwoodNetwork.cpp b/NXDNKenwoodNetwork.cpp index 496462f..e873bd3 100644 --- a/NXDNKenwoodNetwork.cpp +++ b/NXDNKenwoodNetwork.cpp @@ -92,7 +92,8 @@ bool CNXDNKenwoodNetwork::open() return false; } - m_ssrc = m_random(); + std::uniform_int_distribution dist(0x00000001, 0xfffffffe); + m_ssrc = dist(m_random); return true; } From 4dd39696b4ce35fbf26b630746322221b10872c8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 1 Jul 2020 13:38:23 +0100 Subject: [PATCH 16/19] Remove unused UDPSocket code. --- UDPSocket.cpp | 30 +----------------------------- UDPSocket.h | 4 +--- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/UDPSocket.cpp b/UDPSocket.cpp index 2899faf..ba0e35f 100644 --- a/UDPSocket.cpp +++ b/UDPSocket.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2016,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2006-2016 by Jonathan Naylor G4KLX * * 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 @@ -258,31 +258,3 @@ void CUDPSocket::close() ::close(m_fd); #endif } - -unsigned long CUDPSocket::getLocalAddress() const -{ - unsigned long address = 0UL; - - char hostname[80U]; - int ret = ::gethostname(hostname, 80); - if (ret == -1) - return 0UL; - - struct hostent* phe = ::gethostbyname(hostname); - if (phe == NULL) - return 0UL; - - if (phe->h_addrtype != AF_INET) - return 0UL; - - for (unsigned int i = 0U; phe->h_addr_list[i] != NULL; i++) { - struct in_addr addr; - ::memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); - if (addr.s_addr != INADDR_LOOPBACK) { - address = addr.s_addr; - break; - } - } - - return address; -} diff --git a/UDPSocket.h b/UDPSocket.h index 4c21a43..3437b53 100644 --- a/UDPSocket.h +++ b/UDPSocket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011,2013,2015,2016,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2009-2011,2013,2015,2016 by Jonathan Naylor G4KLX * * 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 @@ -47,8 +47,6 @@ public: void close(); - unsigned long getLocalAddress() const; - static in_addr lookup(const std::string& hostName); private: From dfaedb450b4eb4c8b6165da9383771f801cb8609 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Thu, 2 Jul 2020 06:40:26 +0900 Subject: [PATCH 17/19] replace rand() -> MT19937 random number generator sometimes rand() makes problem so replace it to MT19937 in C++11 . --- DMRNetwork.cpp | 18 +++++++++++------- DMRNetwork.h | 2 ++ DStarNetwork.cpp | 11 +++++++---- DStarNetwork.h | 2 ++ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp index b2aedb5..fece49c 100644 --- a/DMRNetwork.cpp +++ b/DMRNetwork.cpp @@ -66,7 +66,8 @@ m_height(0), m_location(), m_description(), m_url(), -m_beacon(false) +m_beacon(false), +m_random() { assert(!address.empty()); assert(port > 0U); @@ -85,11 +86,13 @@ m_beacon(false) m_id[2U] = id >> 8; m_id[3U] = id >> 0; - CStopWatch stopWatch; - ::srand(stopWatch.start()); + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; - m_streamId[0U] = ::rand() + 1U; - m_streamId[1U] = ::rand() + 1U; + std::uniform_int_distribution dist(0x00000001, 0xfffffffe); + m_streamId[0U] = dist(m_random); + m_streamId[1U] = dist(m_random); } CDMRNetwork::~CDMRNetwork() @@ -246,6 +249,7 @@ bool CDMRNetwork::write(const CDMRData& data) unsigned int slotIndex = slotNo - 1U; + std::uniform_int_distribution dist(0x00000001, 0xfffffffe); unsigned char dataType = data.getDataType(); if (dataType == DT_VOICE_SYNC) { buffer[15U] |= 0x10U; @@ -253,10 +257,10 @@ bool CDMRNetwork::write(const CDMRData& data) buffer[15U] |= data.getN(); } else { if (dataType == DT_VOICE_LC_HEADER) - m_streamId[slotIndex] = ::rand() + 1U; + m_streamId[slotIndex] = dist(m_random); if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) - m_streamId[slotIndex] = ::rand() + 1U; + m_streamId[slotIndex] = dist(m_random); buffer[15U] |= (0x20U | dataType); } diff --git a/DMRNetwork.h b/DMRNetwork.h index 9d1c52e..754c970 100644 --- a/DMRNetwork.h +++ b/DMRNetwork.h @@ -27,6 +27,7 @@ #include #include +#include class CDMRNetwork { @@ -106,6 +107,7 @@ private: std::string m_url; bool m_beacon; + std::mt19937 m_random; bool writeLogin(); bool writeAuthorisation(); diff --git a/DStarNetwork.cpp b/DStarNetwork.cpp index de0af69..d13d773 100644 --- a/DStarNetwork.cpp +++ b/DStarNetwork.cpp @@ -44,14 +44,16 @@ m_inId(0U), m_buffer(1000U, "D-Star Network"), m_pollTimer(1000U, 60U), m_linkStatus(LS_NONE), -m_linkReflector(NULL) +m_linkReflector(NULL), +m_random() { m_address = CUDPSocket::lookup(gatewayAddress); m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH]; - CStopWatch stopWatch; - ::srand(stopWatch.start()); + std::random_device rd; + std::mt19937 mt(rd()); + m_random = mt; } CDStarNetwork::~CDStarNetwork() @@ -85,7 +87,8 @@ bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length buffer[4] = busy ? 0x22U : 0x20U; // Create a random id for this transmission - m_outId = (::rand() % 65535U) + 1U; + std::uniform_int_distribution dist(0x0001, 0xfffe); + m_outId = dist(m_random); buffer[5] = m_outId / 256U; // Unique session id buffer[6] = m_outId % 256U; diff --git a/DStarNetwork.h b/DStarNetwork.h index aeebbbf..991c031 100644 --- a/DStarNetwork.h +++ b/DStarNetwork.h @@ -26,6 +26,7 @@ #include #include +#include class CDStarNetwork { public: @@ -64,6 +65,7 @@ private: CTimer m_pollTimer; LINK_STATUS m_linkStatus; unsigned char* m_linkReflector; + std::mt19937 m_random; bool writePoll(const char* text); }; From 4217ccebc4266f972db50d11e64df356b9ab54f5 Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Thu, 2 Jul 2020 06:59:51 +0900 Subject: [PATCH 18/19] remove getLocalAddress() It was used for NXDNKenwoodNetwork.cpp to creates SSRC. currently SSRC uses random value, this function is no longer used. --- UDPSocket.cpp | 28 ---------------------------- UDPSocket.h | 2 -- 2 files changed, 30 deletions(-) diff --git a/UDPSocket.cpp b/UDPSocket.cpp index 2899faf..abfa885 100644 --- a/UDPSocket.cpp +++ b/UDPSocket.cpp @@ -258,31 +258,3 @@ void CUDPSocket::close() ::close(m_fd); #endif } - -unsigned long CUDPSocket::getLocalAddress() const -{ - unsigned long address = 0UL; - - char hostname[80U]; - int ret = ::gethostname(hostname, 80); - if (ret == -1) - return 0UL; - - struct hostent* phe = ::gethostbyname(hostname); - if (phe == NULL) - return 0UL; - - if (phe->h_addrtype != AF_INET) - return 0UL; - - for (unsigned int i = 0U; phe->h_addr_list[i] != NULL; i++) { - struct in_addr addr; - ::memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr)); - if (addr.s_addr != INADDR_LOOPBACK) { - address = addr.s_addr; - break; - } - } - - return address; -} diff --git a/UDPSocket.h b/UDPSocket.h index 4c21a43..4aa16bd 100644 --- a/UDPSocket.h +++ b/UDPSocket.h @@ -47,8 +47,6 @@ public: void close(); - unsigned long getLocalAddress() const; - static in_addr lookup(const std::string& hostName); private: From 15a8e87c3ecc9c770271de65b1937b5e433e152b Mon Sep 17 00:00:00 2001 From: SASANO Takayoshi Date: Thu, 2 Jul 2020 18:47:33 +0900 Subject: [PATCH 19/19] permit inline comment and ScreenLayout of Nextion two minor improvements - ScreenLayout in Nextion section can use hexadecimal (0xXXXXX), octal (0XXXX) and decimal value - in-line comment enabled example: # conventional comment, the line starts with # [Section] Key=value # this is new style comment Key="quoted value # this is not comment" Key="quoted value" # this is prohibited (not comment) --- Conf.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Conf.cpp b/Conf.cpp index 5bc7dba..6602b3c 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -390,6 +390,9 @@ bool CConf::read() if (len > 1U && *value == '"' && value[len - 1U] == '"') { value[len - 1U] = '\0'; value++; + } else { + // if value is not quoted, remove after # (to make comment) + strtok(value, "#"); } if (section == SECTION_GENERAL) { @@ -916,7 +919,7 @@ bool CConf::read() else if (::strcmp(key, "IdleBrightness") == 0) m_nextionIdleBrightness = (unsigned int)::atoi(value); else if (::strcmp(key, "ScreenLayout") == 0) - m_nextionScreenLayout = (unsigned int)::atoi(value); + m_nextionScreenLayout = (unsigned int)::strtoul(value, NULL, 0); else if (::strcmp(key, "DisplayTempInFahrenheit") == 0) m_nextionTempInFahrenheit = ::atoi(value) == 1; } else if (section == SECTION_OLED) {