From e0a5ae7fb3ea686e31d2ca9b1340b0367f6e33c3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 16 Jan 2018 20:10:35 +0000 Subject: [PATCH] Add the NXDN LICH processing. --- MMDVMHost.cpp | 3 +- MMDVMHost.vcxproj | 2 + MMDVMHost.vcxproj.filters | 6 ++ Makefile | 7 +- Makefile.Pi | 7 +- Makefile.Pi.Adafruit | 5 +- Makefile.Pi.HD44780 | 5 +- Makefile.Pi.OLED | 5 +- Makefile.Pi.PCF8574 | 5 +- Makefile.Solaris | 7 +- NXDNControl.cpp | 78 ++++++++++---- NXDNControl.h | 12 ++- NXDNDefines.h | 21 +++- NXDNLICH.cpp | 209 ++++++++++++++++++++++++++++++++++++++ NXDNLICH.h | 48 +++++++++ 15 files changed, 374 insertions(+), 46 deletions(-) create mode 100644 NXDNLICH.cpp create mode 100644 NXDNLICH.h diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 1a99c5a..c26a60e 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -784,8 +784,7 @@ int CMMDVMHost::run() if (m_mode == MODE_NXDN) { m_modem->writeNXDNData(data, len); m_modeTimer.start(); - } - else if (m_mode != MODE_LOCKOUT) { + } else if (m_mode != MODE_LOCKOUT) { LogWarning("NXDN data received when in mode %u", m_mode); } } diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 6feb302..5a66b6f 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -195,6 +195,7 @@ + @@ -269,6 +270,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 1d5a94c..ba4a45d 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -239,6 +239,9 @@ Header Files + + Header Files + @@ -445,5 +448,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 42ccbfe..b414d09 100644 --- a/Makefile +++ b/Makefile @@ -9,9 +9,10 @@ LDFLAGS = -g OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o P25Audio.o \ - P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ - SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o NXDNLICH.o \ + NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o \ + YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi b/Makefile.Pi index 2d4c1a2..8934c4f 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -9,9 +9,10 @@ LDFLAGS = -g -L/usr/local/lib OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o P25Audio.o \ - P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ - SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o NXDNLICH.o \ + NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 5121a6f..25d6aef 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -10,8 +10,9 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \ - P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o \ - SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NXDNLICH.o NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 0c5fc11..7d5e7b5 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -10,8 +10,9 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \ - P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o \ - SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NXDNLICH.o NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 36b223c..7ef9f81 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -10,8 +10,9 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o JitterBuffer.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \ - P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o \ - SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NXDNLICH.o NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 3942c66..8bd0b64 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -10,8 +10,9 @@ OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \ - P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o \ - SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + NXDNLICH.o NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o \ + SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost diff --git a/Makefile.Solaris b/Makefile.Solaris index 1275515..831c097 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -9,9 +9,10 @@ LDFLAGS = -g OBJECTS = \ AMBEFEC.o BCH.o BPTC19696.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 DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ - Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o P25Audio.o \ - P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \ - SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Golay24128.o Hamming.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \ + NXDNLICH.o NXDNNetwork.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \ + YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 4865f94..aaebec9 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -51,6 +51,7 @@ m_rfErrs(0U), m_rfBits(1U), m_netErrs(0U), m_netBits(1U), +m_lastLICH(), m_netN(0U), m_rssiMapper(rssiMapper), m_rssi(0U), @@ -115,49 +116,74 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) m_rssiCount++; } + CUtils::dump(2U, "NXDN, raw data", data, len); + scrambler(data + 2U); - CYSFFICH fich; - bool valid = fich.decode(data + 2U); + CUtils::dump(2U, "NXDN, after descrambling", data, len); + + CNXDNLICH lich; + bool valid = lich.decode(data + 2U); if (valid) - m_lastFICH = fich; + m_lastLICH = lich; // Stop repeater packets coming through, unless we're acting as a remote gateway if (m_remoteGateway) { - unsigned char mr = m_lastFICH.getMR(); - if (mr != YSF_MR_BUSY) + unsigned char direction = m_lastLICH.getDirection(); + if (direction != NXDN_LICH_DIRECTION_INBOUND) return false; } else { - unsigned char mr = m_lastFICH.getMR(); - if (mr == YSF_MR_BUSY) + unsigned char direction = m_lastLICH.getDirection(); + if (direction == NXDN_LICH_DIRECTION_OUTBOUND) return false; } - unsigned char dt = m_lastFICH.getDT(); + unsigned char usc = m_lastLICH.getFCT(); + unsigned char option = m_lastLICH.getOption(); bool ret = false; - switch (dt) { - case YSF_DT_VOICE_FR_MODE: - ret = processVWData(valid, data); - break; +#ifdef notdef + if (usc == NXDN_LICH_USC_SACCH_NS || usc == NXDN_LICH_USC_SACCH_SS) { + switch (option) { + case NXDN_LICH_STEAL_NONE: + ret = processVCHOnly(valid, data); + break; - case YSF_DT_VD_MODE1: - case YSF_DT_VD_MODE2: - ret = processDNData(valid, data); - break; + case NXDN_LICH_STEAL_FACCH1_1: + ret = processFACCH11(valid, data); + break; - case YSF_DT_DATA_FR_MODE: - ret = processFRData(valid, data); - break; + case NXDN_LICH_STEAL_FACCH1_2: + ret = processFACCH12(valid, data); + break; - default: - break; + case NXDN_LICH_STEAL_FACCH: + ret = processFACCH1(valid, data); + break; + + default: + break; + } + } else if (usc == NXDN_LICH_USC_UDCH) { + switch (option) { + case NXDN_LICH_STEAL_NONE: + ret = processUDCH(valid, data); + break; + + case NXDN_LICH_STEAL_FACCH: + ret = processFACCH2(valid, data); + break; + + default: + break; + } } - +#endif return ret; } +#ifdef notdef bool CNXDNControl::processVWData(bool valid, unsigned char *data) { unsigned char fi = m_lastFICH.getFI(); @@ -810,6 +836,8 @@ bool CNXDNControl::processFRData(bool valid, unsigned char *data) return false; } +#endif + unsigned int CNXDNControl::readModem(unsigned char* data) { assert(data != NULL); @@ -857,6 +885,8 @@ void CNXDNControl::writeEndNet() m_network->reset(); } +#ifdef notdef + void CNXDNControl::writeNetwork() { unsigned char data[200U]; @@ -986,10 +1016,14 @@ void CNXDNControl::writeNetwork() } } +#endif + void CNXDNControl::clock(unsigned int ms) { +#ifdef notdef if (m_network != NULL) writeNetwork(); +#endif m_rfTimeoutTimer.clock(ms); m_netTimeoutTimer.clock(ms); diff --git a/NXDNControl.h b/NXDNControl.h index a86b3d4..935110a 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -25,7 +25,7 @@ // #include "YSFPayload.h" #include "RingBuffer.h" #include "StopWatch.h" -// #include "YSFFICH.h" +#include "NXDNLICH.h" #include "Display.h" #include "Defines.h" #include "Timer.h" @@ -67,6 +67,7 @@ private: unsigned int m_rfBits; unsigned int m_netErrs; unsigned int m_netBits; + CNXDNLICH m_lastLICH; unsigned char m_netN; CRSSIInterpolator* m_rssiMapper; unsigned char m_rssi; @@ -76,9 +77,12 @@ private: unsigned int m_rssiCount; FILE* m_fp; - bool processVWData(bool valid, unsigned char *data); - bool processDNData(bool valid, unsigned char *data); - bool processFRData(bool valid, unsigned char *data); + bool processVCHOnly(bool valid, unsigned char *data); + bool processFACCH11(bool valid, unsigned char *data); + bool processFACCH12(bool valid, unsigned char *data); + bool processFACCH1(bool valid, unsigned char *data); + bool processUDCH(bool valid, unsigned char *data); + bool processFACCH2(bool valid, unsigned char *data); void writeQueueRF(const unsigned char* data); void writeQueueNet(const unsigned char* data); diff --git a/NXDNDefines.h b/NXDNDefines.h index ce39d00..487923b 100644 --- a/NXDNDefines.h +++ b/NXDNDefines.h @@ -31,5 +31,24 @@ const unsigned char NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U}; const unsigned char NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U}; const unsigned int NXDN_FSW_BYTES_LENGTH = 3U; -#endif +const unsigned int NXDN_LICH_LENGTH_BITS = 16U; +const unsigned char NXDN_LICH_RFCT_RCCH = 0U; +const unsigned char NXDN_LICH_RFCT_RTCH = 1U; +const unsigned char NXDN_LICH_RFCT_RDCH = 2U; +const unsigned char NXDN_LICH_RFCT_RTCH_C = 3U; + +const unsigned char NXDN_LICH_USC_SACCH_NS = 0U; +const unsigned char NXDN_LICH_USC_UDCH = 1U; +const unsigned char NXDN_LICH_USC_SACCH_SS = 2U; +const unsigned char NXDN_LICH_USC_SACCH_SS_IDLE = 3U; + +const unsigned char NXDN_LICH_STEAL_NONE = 3U; +const unsigned char NXDN_LICH_STEAL_FACCH1_2 = 2U; +const unsigned char NXDN_LICH_STEAL_FACCH1_1 = 1U; +const unsigned char NXDN_LICH_STEAL_FACCH = 0U; + +const unsigned char NXDN_LICH_DIRECTION_INBOUND = 0U; +const unsigned char NXDN_LICH_DIRECTION_OUTBOUND = 1U; + +#endif diff --git a/NXDNLICH.cpp b/NXDNLICH.cpp new file mode 100644 index 0000000..9014328 --- /dev/null +++ b/NXDNLICH.cpp @@ -0,0 +1,209 @@ +/* + * 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 "NXDNDefines.h" +#include "NXDNLICH.h" +#include "Log.h" + +#include +#include +#include + +const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#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]) + +CNXDNLICH::CNXDNLICH(const CNXDNLICH& lich) : +m_lich(lich.m_lich) +{ +} + +CNXDNLICH::CNXDNLICH() : +m_lich(0U) +{ +} + +CNXDNLICH::~CNXDNLICH() +{ +} + +bool CNXDNLICH::decode(const unsigned char* bytes) +{ + assert(bytes != NULL); + + unsigned char lich[1U]; + lich[0U] = 0x00U; + + unsigned int offset = NXDN_FSW_LENGTH_BITS; + bool b7 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 7U, b7); + + offset++; + bool b6 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 6U, b6); + + offset++; + bool b5 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 5U, b5); + + offset++; + bool b4 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 4U, b4); + + offset++; + bool b3 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 3U, b3); + + offset++; + bool b2 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 2U, b2); + + offset++; + bool b1 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 1U, b1); + + offset++; + bool b0 = READ_BIT1(bytes, offset); + WRITE_BIT1(lich, 0U, b0); + + bool parity = b7 ^ b6 ^ b5 ^ b4; + + LogMessage("NXDN, LICH bits: %d%d %d%d %d%d %d - %d, parity: %d", b7 ? 1 : 0, b6 ? 1 : 0, b5 ? 1 : 0, b4 ? 1 : 0, b3 ? 1 : 0, b2 ? 1 : 0, b1 ? 1 : 0, b0 ? 1 : 0, parity ? 1 : 0); + + if (parity != b0) + return false; + + m_lich = lich[0U] >> 1; + + return true; +} + +void CNXDNLICH::encode(unsigned char* bytes) +{ + assert(bytes != NULL); + + unsigned char lich[1U]; + + lich[0U] = m_lich << 1; + + bool b7 = READ_BIT1(lich, 7U); + bool b6 = READ_BIT1(lich, 6U); + bool b5 = READ_BIT1(lich, 5U); + bool b4 = READ_BIT1(lich, 4U); + bool b3 = READ_BIT1(lich, 3U); + bool b2 = READ_BIT1(lich, 2U); + bool b1 = READ_BIT1(lich, 1U); + bool b0 = READ_BIT1(lich, 0U); + + bool parity = b7 ^ b6 ^ b5 ^ b4; + + WRITE_BIT1(lich, 0U, parity); + + unsigned int offset = NXDN_FSW_LENGTH_BITS; + WRITE_BIT1(bytes, offset, b7); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b6); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b5); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b4); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b3); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b2); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b1); + offset++; + WRITE_BIT1(bytes, offset, true); + offset++; + + WRITE_BIT1(bytes, offset, b0); + offset++; + WRITE_BIT1(bytes, offset, true); +} + +unsigned char CNXDNLICH::getRFCT() const +{ + return (m_lich >> 5) & 0x03U; +} + +unsigned char CNXDNLICH::getFCT() const +{ + return (m_lich >> 3) & 0x03U; +} + +unsigned char CNXDNLICH::getOption() const +{ + return (m_lich >> 1) & 0x03U; +} + +unsigned char CNXDNLICH::getDirection() const +{ + return m_lich & 0x01U; +} + +void CNXDNLICH::setRFCT(unsigned char rfct) +{ + m_lich &= 0x1FU; + m_lich |= (rfct << 5) & 0x60U; +} + +void CNXDNLICH::setFCT(unsigned char usc) +{ + m_lich &= 0x67U; + m_lich |= (usc << 3) & 0x18U; +} + +void CNXDNLICH::setOption(unsigned char option) +{ + m_lich &= 0x79U; + m_lich |= (option << 1) & 0x06U; +} + +void CNXDNLICH::setDirection(unsigned char direction) +{ + m_lich &= 0x7EU; + m_lich |= direction & 0x01U; +} + +CNXDNLICH& CNXDNLICH::operator=(const CNXDNLICH& lich) +{ + if (&lich != this) + m_lich = lich.m_lich; + + return *this; +} diff --git a/NXDNLICH.h b/NXDNLICH.h new file mode 100644 index 0000000..e5ecd2b --- /dev/null +++ b/NXDNLICH.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#if !defined(NXDNLICH_H) +#define NXDNLICH_H + +class CNXDNLICH { +public: + CNXDNLICH(const CNXDNLICH& fich); + CNXDNLICH(); + ~CNXDNLICH(); + + bool decode(const unsigned char* bytes); + + void encode(unsigned char* bytes); + + unsigned char getRFCT() const; + unsigned char getFCT() const; + unsigned char getOption() const; + unsigned char getDirection() const; + + void setRFCT(unsigned char rfct); + void setFCT(unsigned char usc); + void setOption(unsigned char option); + void setDirection(unsigned char direction); + + CNXDNLICH& operator=(const CNXDNLICH& fich); + +private: + unsigned char m_lich; +}; + +#endif