diff --git a/Conf.cpp b/Conf.cpp
index 7e68f9d..513cae3 100644
--- a/Conf.cpp
+++ b/Conf.cpp
@@ -298,7 +298,14 @@ bool CConf::read()
char* value = ::strtok(NULL, "\r\n");
if (value == NULL)
continue;
-
+
+ // Remove quotes from the value
+ size_t len = ::strlen(value);
+ if (len > 1U && *value == '"' && value[len - 1U] == '"') {
+ value[len - 1U] = '\0';
+ value++;
+ }
+
if (section == SECTION_GENERAL) {
if (::strcmp(key, "Callsign") == 0) {
// Convert the callsign to upper case
diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp
index d296b57..51843db 100644
--- a/DMRNetwork.cpp
+++ b/DMRNetwork.cpp
@@ -498,6 +498,9 @@ void CDMRNetwork::receiveData(const unsigned char* data, unsigned int length)
if (slotNo == 2U && !m_slot2)
return;
+ m_jitterBuffers[slotNo]->appendData(data, length);
+
+ /*
unsigned char dataType = data[15U] & 0x3FU;
if (dataType == (0x20U | DT_CSBK) ||
dataType == (0x20U | DT_DATA_HEADER) ||
@@ -511,6 +514,7 @@ void CDMRNetwork::receiveData(const unsigned char* data, unsigned int length)
unsigned char seqNo = data[4U];
m_jitterBuffers[slotNo]->addData(data, length, seqNo);
}
+ */
}
bool CDMRNetwork::writeLogin()
diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj
index 21583f8..5e39637 100644
--- a/MMDVMHost.vcxproj
+++ b/MMDVMHost.vcxproj
@@ -198,7 +198,7 @@
-
+
@@ -280,7 +280,7 @@
-
+
diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters
index c0b4ae1..8eedd67 100644
--- a/MMDVMHost.vcxproj.filters
+++ b/MMDVMHost.vcxproj.filters
@@ -257,10 +257,10 @@
Header Files
-
+
Header Files
-
+
Header Files
@@ -487,10 +487,10 @@
Source Files
-
+
Source Files
-
+
Source Files
diff --git a/Makefile b/Makefile
index 9176107..12f36e8 100644
--- a/Makefile
+++ b/Makefile
@@ -10,9 +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 LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.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 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
+ 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 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 900cfc0..7379f9f 100644
--- a/Makefile.Pi
+++ b/Makefile.Pi
@@ -10,9 +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 LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.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 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
+ 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 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 a46caee..564c4a4 100644
--- a/Makefile.Pi.Adafruit
+++ b/Makefile.Pi.Adafruit
@@ -10,9 +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 \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.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 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
+ 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 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 5bde70a..dbb7df5 100644
--- a/Makefile.Pi.HD44780
+++ b/Makefile.Pi.HD44780
@@ -10,7 +10,7 @@ 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 \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.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 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
diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED
index e8b4e5e..19c0c62 100644
--- a/Makefile.Pi.OLED
+++ b/Makefile.Pi.OLED
@@ -3,16 +3,16 @@
CC = gcc
CXX = g++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include
-LIBS = -lArduiPi_OLED -lpthread
+LIBS = -lArduiPi_OLED -li2c -lpthread
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 OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.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 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
+ 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 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 d4dacca..5d28a2b 100644
--- a/Makefile.Pi.PCF8574
+++ b/Makefile.Pi.PCF8574
@@ -10,7 +10,7 @@ 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 \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.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 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
diff --git a/Makefile.Solaris b/Makefile.Solaris
index 3a93712..d40317f 100644
--- a/Makefile.Solaris
+++ b/Makefile.Solaris
@@ -10,9 +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 LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NXDNControl.o \
- NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNFACCH2.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 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
+ 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 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 fd0809f..74b2991 100644
--- a/NXDNControl.cpp
+++ b/NXDNControl.cpp
@@ -13,7 +13,6 @@
#include "NXDNControl.h"
#include "NXDNFACCH1.h"
-#include "NXDNFACCH2.h"
#include "NXDNSACCH.h"
#include "NXDNUDCH.h"
#include "AMBEFEC.h"
@@ -63,7 +62,9 @@ m_rfErrs(0U),
m_rfBits(1U),
m_netErrs(0U),
m_netBits(1U),
-m_lastLICH(),
+m_rfLastLICH(),
+m_rfLayer3(),
+m_rfMask(0x00U),
m_netN(0U),
m_rssiMapper(rssiMapper),
m_rssi(0U),
@@ -97,13 +98,14 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len)
return false;
}
- if (type == TAG_LOST && m_rfState == RS_RF_REJECTED) {
- m_rfState = RS_RF_LISTENING;
+ if (type == TAG_LOST && m_rfState == RS_RF_DATA) {
+ writeEndRF();
return false;
}
if (type == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
+ m_rfMask = 0x00U;
return false;
}
@@ -139,21 +141,21 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len)
bool valid = lich.decode(data + 2U);
if (valid)
- m_lastLICH = lich;
+ m_rfLastLICH = lich;
// Stop repeater packets coming through, unless we're acting as a remote gateway
if (m_remoteGateway) {
- unsigned char direction = m_lastLICH.getDirection();
+ unsigned char direction = m_rfLastLICH.getDirection();
if (direction == NXDN_LICH_DIRECTION_INBOUND)
return false;
} else {
- unsigned char direction = m_lastLICH.getDirection();
+ unsigned char direction = m_rfLastLICH.getDirection();
if (direction == NXDN_LICH_DIRECTION_OUTBOUND)
return false;
}
- unsigned char usc = m_lastLICH.getFCT();
- unsigned char option = m_lastLICH.getOption();
+ unsigned char usc = m_rfLastLICH.getFCT();
+ unsigned char option = m_rfLastLICH.getOption();
bool ret;
if (usc == NXDN_LICH_USC_UDCH)
@@ -174,397 +176,346 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
return false;
}
- if (option == NXDN_LICH_STEAL_NONE) {
- CAMBEFEC ambe;
- unsigned int errors = 0U;
- //errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
- //errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 9U);
- //errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
- //errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 27U);
- //LogDebug("NXDN, EHR, AMBE FEC %u/188 (%.1f%%)", errors, float(errors) / 1.88F);
- //errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
- //errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
- //LogDebug("NXDN, EFR, AMBE FEC %u/288 (%.1f%%)", errors, float(errors) / 2.88F);
- }
+ // XXX Reconstruct invalid LICH
-#ifdef notdef
- unsigned char fi = m_lastFICH.getFI();
- if (valid && fi == YSF_FI_HEADER) {
- if (m_rfState == RS_RF_LISTENING) {
- bool valid = m_rfPayload.processHeaderData(data + 2U);
- if (!valid)
- return false;
+ if (usc == NXDN_LICH_USC_SACCH_NS) {
+ // The SACCH on a non-superblock frame is usually an idle and not interesting apart from the RAN.
+ CNXDNFACCH1 facch11;
+ bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
- m_rfSource = m_rfPayload.getSource();
+ CNXDNFACCH1 facch12;
+ bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
- if (m_selfOnly) {
- bool ret = checkCallsign(m_rfSource);
- if (!ret) {
- LogMessage("NXDN, invalid access attempt from %10.10s", m_rfSource);
- m_rfState = RS_RF_REJECTED;
+ unsigned char buffer[10U];
+ if (valid1)
+ facch11.getData(buffer);
+ else if (valid2)
+ facch12.getData(buffer);
+
+ if (valid1 || valid2) {
+ CNXDNLayer3 layer3;
+ layer3.decode(buffer, NXDN_FACCH1_LENGTH_BITS);
+
+ unsigned char type = layer3.getMessageType();
+ if (type == NXDN_MESSAGE_TYPE_TX_REL) {
+ if (m_rfState != RS_RF_AUDIO) {
+ m_rfState = RS_RF_LISTENING;
+ m_rfMask = 0x00U;
return false;
}
+ } else {
+ if (m_selfOnly) {
+ unsigned short srcId = layer3.getSourceUnitId();
+ if (srcId != m_id) {
+ m_rfState = RS_RF_REJECTED;
+ return false;
+ }
+ }
}
- unsigned char cm = m_lastFICH.getCM();
- if (cm == YSF_CM_GROUP1 || cm == YSF_CM_GROUP2)
- m_rfDest = (unsigned char*)"ALL ";
- else
- m_rfDest = m_rfPayload.getDest();
-
- m_rfFrames = 0U;
- m_rfErrs = 0U;
- m_rfBits = 1U;
- m_rfTimeoutTimer.start();
- m_rfState = RS_RF_AUDIO;
-
- m_minRSSI = m_rssi;
- m_maxRSSI = m_rssi;
- m_aveRSSI = m_rssi;
- m_rssiCount = 1U;
-#if defined(DUMP_NXDN)
- openFile();
-#endif
-
- m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " ");
- LogMessage("NXDN, received RF header from %10.10s to %10.10s", m_rfSource, m_rfDest);
+ data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA;
+ data[1U] = 0x00U;
CSync::addNXDNSync(data + 2U);
- CYSFFICH fich = m_lastFICH;
+ CNXDNLICH lich = m_rfLastLICH;
+ lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
+ lich.encode(data + 2U);
- // Remove any DSQ information
- fich.setSQL(false);
- fich.setSQ(0U);
- fich.encode(data + 2U);
+ CNXDNSACCH sacch;
+ sacch.setRAN(m_ran);
+ sacch.setStructure(NXDN_SR_SINGLE);
+ sacch.setData(SACCH_IDLE);
+ sacch.encode(data + 2U);
- data[0U] = TAG_DATA;
- data[1U] = 0x00U;
+ if (valid1) {
+ facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+ facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ } else {
+ facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+ facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ }
- writeNetwork(data, m_rfFrames % 128U);
+ scrambler(data + 2U);
+
+ // writeNetwork(data, m_rfFrames, );
#if defined(DUMP_NXDN)
writeFile(data + 2U);
#endif
- if (m_duplex) {
- fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
- fich.encode(data + 2U);
+ if (m_duplex)
writeQueueRF(data);
+
+ if (type == NXDN_MESSAGE_TYPE_TX_REL) {
+ m_rfFrames++;
+ if (m_rssi != 0U)
+ LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
+ else
+ LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits));
+ writeEndRF();
+ return true;
+ } else {
+ m_rfFrames = 0U;
+ m_rfErrs = 0U;
+ m_rfBits = 1U;
+ m_rfTimeoutTimer.start();
+ m_rfState = RS_RF_AUDIO;
+
+ m_minRSSI = m_rssi;
+ m_maxRSSI = m_rssi;
+ m_aveRSSI = m_rssi;
+ m_rssiCount = 1U;
+#if defined(DUMP_NXDN)
+ openFile();
+#endif
+ m_rfLayer3 = layer3;
+
+ unsigned short srcId = m_rfLayer3.getSourceUnitId();
+ unsigned short dstId = m_rfLayer3.getDestinationGroupId();
+ bool grp = m_rfLayer3.getIsGroup();
+
+ std::string source = m_lookup->find(srcId);
+ LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
+ m_display->writeNXDN(source.c_str(), grp, dstId, "R");
+
+ m_rfState = RS_RF_AUDIO;
+
+ return true;
}
-
- m_rfFrames++;
-
- m_display->writeFusionRSSI(m_rssi);
-
- return true;
}
- } else if (valid && fi == YSF_FI_TERMINATOR) {
- if (m_rfState == RS_RF_REJECTED) {
- m_rfPayload.reset();
- m_rfSource = NULL;
- m_rfDest = NULL;
- m_rfState = RS_RF_LISTENING;
- } else if (m_rfState == RS_RF_AUDIO) {
- m_rfPayload.processHeaderData(data + 2U);
- CSync::addNXDNSync(data + 2U);
+ return false;
+ } else {
+ unsigned char message[3U];
+ sacch.getData(message);
- CYSFFICH fich = m_lastFICH;
+ unsigned char structure = sacch.getStructure();
+ switch (structure) {
+ case NXDN_SR_1_4:
+ m_rfMask |= 0x01U;
+ m_rfLayer3.decode(message, 18U, 0U);
+ break;
+ case NXDN_SR_2_4:
+ m_rfMask |= 0x02U;
+ m_rfLayer3.decode(message, 18U, 18U);
+ break;
+ case NXDN_SR_3_4:
+ m_rfMask |= 0x04U;
+ m_rfLayer3.decode(message, 18U, 36U);
+ break;
+ case NXDN_SR_4_4:
+ m_rfMask |= 0x08U;
+ m_rfLayer3.decode(message, 18U, 54U);
+ break;
+ default:
+ break;
+ }
- // Remove any DSQ information
- fich.setSQL(false);
- fich.setSQ(0U);
- fich.encode(data + 2U);
+ if (m_rfMask != 0x0FU)
+ return false;
- data[0U] = TAG_EOT;
- data[1U] = 0x00U;
+ unsigned char messageType = m_rfLayer3.getMessageType();
+ if (messageType != NXDN_MESSAGE_TYPE_VCALL)
+ return false;
- writeNetwork(data, m_rfFrames % 128U);
+ unsigned short srcId = m_rfLayer3.getSourceUnitId();
+ unsigned short dstId = m_rfLayer3.getDestinationGroupId();
+ bool grp = m_rfLayer3.getIsGroup();
+ if (m_selfOnly) {
+ if (srcId != m_id) {
+ m_rfState = RS_RF_REJECTED;
+ return false;
+ }
+ }
+
+ m_rfFrames = 0U;
+ m_rfErrs = 0U;
+ m_rfBits = 1U;
+ m_rfTimeoutTimer.start();
+ m_rfState = RS_RF_AUDIO;
+
+ m_minRSSI = m_rssi;
+ m_maxRSSI = m_rssi;
+ m_aveRSSI = m_rssi;
+ m_rssiCount = 1U;
#if defined(DUMP_NXDN)
- writeFile(data + 2U);
+ openFile();
#endif
+ std::string source = m_lookup->find(srcId);
+ LogMessage("NXDN, received RF voice transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
+ m_display->writeNXDN(source.c_str(), grp, dstId, "R");
- if (m_duplex) {
- fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
- fich.encode(data + 2U);
- writeQueueRF(data);
+ m_rfState = RS_RF_AUDIO;
+ }
+
+ // if (m_rfState == RS_RF_AUDIO) {
+ // Regenerate the sync
+ CSync::addNXDNSync(data + 2U);
+
+ // Regenerate the LICH
+ CNXDNLICH lich;
+ lich.setRFCT(NXDN_LICH_RFCT_RDCH);
+ lich.setFCT(usc);
+ lich.setOption(option);
+ lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
+ lich.encode(data + 2U);
+
+ // XXX Regenerate SACCH here
+
+ // Regenerate the audio and interpret the FACCH1 data
+ unsigned char voiceMode = m_rfLayer3.getCallOptions() & 0x07U;
+
+ if (option == NXDN_LICH_STEAL_NONE) {
+ CAMBEFEC ambe;
+ unsigned int errors = 0U;
+ if (voiceMode == NXDN_VOICE_CALL_OPTION_9600_EFR) {
+ errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
+ errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
+ m_rfErrs += errors;
+ m_rfBits += 288U;
+ m_display->writeNXDNBER(float(errors) / 2.88F);
+ LogDebug("NXDN, EFR, AMBE FEC %u/288 (%.1f%%)", errors, float(errors) / 2.88F);
+ } else {
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 9U);
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 27U);
+ m_rfErrs += errors;
+ m_rfBits += 188U;
+ m_display->writeNXDNBER(float(errors) / 1.88F);
+ LogDebug("NXDN, EHR, AMBE FEC %u/188 (%.1f%%)", errors, float(errors) / 1.88F);
+ }
+ } else if (option == NXDN_LICH_STEAL_FACCH1_1) {
+ CNXDNFACCH1 facch1;
+ bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+ if (valid)
+ facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+
+ CAMBEFEC ambe;
+ unsigned int errors = 0U;
+ if (voiceMode == NXDN_VOICE_CALL_OPTION_9600_EFR) {
+ errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
+ m_rfErrs += errors;
+ m_rfBits += 144U;
+ m_display->writeNXDNBER(float(errors) / 1.44F);
+ LogDebug("NXDN, EFR, AMBE FEC %u/144 (%.1f%%)", errors, float(errors) / 1.44F);
+ } else {
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 18U);
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 27U);
+ m_rfErrs += errors;
+ m_rfBits += 94U;
+ m_display->writeNXDNBER(float(errors) / 0.94F);
+ LogDebug("NXDN, EHR, AMBE FEC %u/94 (%.1f%%)", errors, float(errors) / 0.94F);
+ }
+ } else if (option == NXDN_LICH_STEAL_FACCH1_2) {
+ CAMBEFEC ambe;
+ unsigned int errors = 0U;
+ if (voiceMode == NXDN_VOICE_CALL_OPTION_9600_EFR) {
+ errors += ambe.regenerateIMBE(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
+ m_rfErrs += errors;
+ m_rfBits += 144U;
+ m_display->writeNXDNBER(float(errors) / 1.44F);
+ LogDebug("NXDN, EFR, AMBE FEC %u/144 (%.1f%%)", errors, float(errors) / 1.44F);
+ } else {
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES);
+ errors += ambe.regenerateDMR(data + 2U + NXDN_FSW_LICH_SACCH_LENGTH_BYTES + 9U);
+ m_rfErrs += errors;
+ m_rfBits += 94U;
+ m_display->writeNXDNBER(float(errors) / 0.94F);
+ LogDebug("NXDN, EHR, AMBE FEC %u/94 (%.1f%%)", errors, float(errors) / 0.94F);
}
- m_rfFrames++;
+ CNXDNFACCH1 facch1;
+ bool valid = facch1.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ if (valid)
+ facch1.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ } else {
+ CNXDNFACCH1 facch11;
+ bool valid1 = facch11.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+ if (valid1)
+ facch11.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS);
+ CNXDNFACCH1 facch12;
+ bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ if (valid2)
+ facch12.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS);
+ }
+
+ data[0U] = TAG_DATA;
+ data[1U] = 0x00U;
+
+ scrambler(data + 2U);
+
+ // writeNetwork(data, m_rfFrames, );
+
+#if defined(DUMP_NXDN)
+ writeFile(data + 2U);
+#endif
+
+ if (m_duplex)
+ writeQueueRF(data);
+
+ m_rfFrames++;
+
+ m_display->writeNXDNRSSI(m_rssi);
+
+#ifdef notdef
+ // Process end of audio here
+ if (endofdata) {
+ if (m_rfState == RS_RF_AUDIO) {
if (m_rssi != 0U)
LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("NXDN, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
- }
- } else {
- if (m_rfState == RS_RF_AUDIO) {
- // If valid is false, update the m_lastFICH for this transmission
- if (!valid) {
- unsigned char ft = m_lastFICH.getFT();
- unsigned char fn = m_lastFICH.getFN() + 1U;
-
- if (fn > ft)
- fn = 0U;
-
- m_lastFICH.setFN(fn);
- }
-
- CSync::addNXDNSync(data + 2U);
-
- unsigned char fn = m_lastFICH.getFN();
- unsigned char dt = m_lastFICH.getDT();
-
- switch (dt) {
- case YSF_DT_VD_MODE1: {
- m_rfPayload.processVDMode1Data(data + 2U, fn);
- unsigned int errors = m_rfPayload.processVDMode1Audio(data + 2U);
- m_rfErrs += errors;
- m_rfBits += 235U;
- m_display->writeFusionBER(float(errors) / 2.35F);
- LogDebug("NXDN, V/D Mode 1, seq %u, AMBE FEC %u/235 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 2.35F);
- }
- break;
-
- case YSF_DT_VD_MODE2: {
- m_rfPayload.processVDMode2Data(data + 2U, fn);
- unsigned int errors = m_rfPayload.processVDMode2Audio(data + 2U);
- m_rfErrs += errors;
- m_rfBits += 135U;
- m_display->writeFusionBER(float(errors) / 1.35F);
- LogDebug("NXDN, V/D Mode 2, seq %u, Repetition FEC %u/135 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 1.35F);
- }
- break;
-
- default:
- break;
- }
-
- CYSFFICH fich = m_lastFICH;
-
- // Remove any DSQ information
- fich.setSQL(false);
- fich.setSQ(0U);
- fich.encode(data + 2U);
-
- data[0U] = TAG_DATA;
- data[1U] = 0x00U;
-
- writeNetwork(data, m_rfFrames % 128U);
-
- if (m_duplex) {
- fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
- fich.encode(data + 2U);
- writeQueueRF(data);
- }
-
-#if defined(DUMP_NXDN)
- writeFile(data + 2U);
-#endif
-
- m_rfFrames++;
-
- m_display->writeFusionRSSI(m_rssi);
-
- return true;
- } else if (valid && m_rfState == RS_RF_LISTENING) {
- // Only use clean frames for late entry.
- unsigned char fn = m_lastFICH.getFN();
- unsigned char dt = m_lastFICH.getDT();
-
- switch (dt) {
- case YSF_DT_VD_MODE1:
- valid = m_rfPayload.processVDMode1Data(data + 2U, fn);
- break;
-
- case YSF_DT_VD_MODE2:
- valid = m_rfPayload.processVDMode2Data(data + 2U, fn);
- break;
-
- default:
- valid = false;
- break;
- }
-
- if (!valid)
- return false;
-
- unsigned char cm = m_lastFICH.getCM();
- if (cm == YSF_CM_GROUP1 || cm == YSF_CM_GROUP2)
- m_rfDest = (unsigned char*)"ALL ";
- else
- m_rfDest = m_rfPayload.getDest();
-
- m_rfSource = m_rfPayload.getSource();
-
- if (m_rfSource == NULL || m_rfDest == NULL)
- return false;
-
- if (m_selfOnly) {
- bool ret = checkCallsign(m_rfSource);
- if (!ret) {
- LogMessage("NXDN, invalid access attempt from %10.10s", m_rfSource);
- m_rfState = RS_RF_REJECTED;
- return false;
- }
- }
-
- m_rfFrames = 0U;
- m_rfErrs = 0U;
- m_rfBits = 1U;
- m_rfTimeoutTimer.start();
- m_rfState = RS_RF_AUDIO;
-
- m_minRSSI = m_rssi;
- m_maxRSSI = m_rssi;
- m_aveRSSI = m_rssi;
- m_rssiCount = 1U;
-#if defined(DUMP_NXDN)
- openFile();
-#endif
-
- // Build a new header and transmit it
- unsigned char buffer[YSF_FRAME_LENGTH_BYTES + 2U];
-
- CSync::addNXDNSync(buffer + 2U);
-
- CYSFFICH fich = m_lastFICH;
- fich.setFI(YSF_FI_HEADER);
- fich.setSQL(false);
- fich.setSQ(0U);
- fich.encode(buffer + 2U);
-
- unsigned char csd1[20U], csd2[20U];
- memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_rfSource, YSF_CALLSIGN_LENGTH);
- memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
-
- if (cm == YSF_CM_GROUP1 || cm == YSF_CM_GROUP2)
- memset(csd1 + 0U, '*', YSF_CALLSIGN_LENGTH);
- else
- memcpy(csd1 + 0U, m_rfDest, YSF_CALLSIGN_LENGTH);
-
- CYSFPayload payload;
- payload.writeHeader(buffer + 2U, csd1, csd2);
-
- buffer[0U] = TAG_DATA;
- buffer[1U] = 0x00U;
-
- writeNetwork(buffer, m_rfFrames % 128U);
-
- if (m_duplex) {
- fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
- fich.encode(buffer + 2U);
- writeQueueRF(buffer);
- }
-
-#if defined(DUMP_NXDN)
- writeFile(buffer + 2U);
-#endif
-
- m_display->writeFusion((char*)m_rfSource, (char*)m_rfDest, "R", " ");
- LogMessage("NXDN, received RF late entry from %10.10s to %10.10s", m_rfSource, m_rfDest);
-
- CSync::addNXDNSync(data + 2U);
-
- fich = m_lastFICH;
-
- // Remove any DSQ information
- fich.setSQL(false);
- fich.setSQ(0U);
- fich.encode(data + 2U);
-
- data[0U] = TAG_DATA;
- data[1U] = 0x00U;
-
- writeNetwork(data, m_rfFrames % 128U);
-
- if (m_duplex) {
- fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
- fich.encode(data + 2U);
- writeQueueRF(data);
- }
-
-#if defined(DUMP_NXDN)
- writeFile(data + 2U);
-#endif
-
- m_rfFrames++;
-
- m_display->writeFusionRSSI(m_rssi);
-
- return true;
+ } else {
+ m_rfState = RS_RF_LISTENING;
+ m_rfMask = 0x00U;
+ return false;
}
}
#endif
- return false;
+ return true;
}
bool CNXDNControl::processData(unsigned char option, unsigned char *data)
{
- if (option == NXDN_LICH_STEAL_FACCH) {
- CNXDNFACCH2 facch2;
- bool valid = facch2.decode(data + 2U);
- if (valid) {
- unsigned char ran = facch2.getRAN();
- if (ran != m_ran && ran != 0U)
- return false;
+ CNXDNUDCH udch;
+ bool valid = udch.decode(data + 2U);
+ if (valid) {
+ unsigned char ran = udch.getRAN();
+ if (ran != m_ran && ran != 0U)
+ return false;
- data[0U] = TAG_DATA;
- data[1U] = 0x00U;
+ data[0U] = TAG_DATA;
+ data[1U] = 0x00U;
- CSync::addNXDNSync(data + 2U);
+ CSync::addNXDNSync(data + 2U);
- CNXDNLICH lich;
- lich.setRFCT(NXDN_LICH_RFCT_RDCH);
- lich.setFCT(NXDN_LICH_USC_UDCH);
- lich.setOption(NXDN_LICH_STEAL_FACCH);
- lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
- lich.encode(data + 2U);
+ CNXDNLICH lich;
+ lich.setRFCT(NXDN_LICH_RFCT_RDCH);
+ lich.setFCT(NXDN_LICH_USC_UDCH);
+ lich.setOption(option);
+ lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
+ lich.encode(data + 2U);
- facch2.setRAN(m_ran);
- facch2.encode(data + 2U);
+ udch.setRAN(m_ran);
+ udch.encode(data + 2U);
- writeQueueNet(data);
+ scrambler(data + 2U);
- if (m_duplex)
- writeQueueRF(data);
+ writeQueueNet(data);
+
+ if (m_duplex)
+ writeQueueRF(data);
#if defined(DUMP_NXDN)
- writeFile(data + 2U);
+ writeFile(data + 2U);
#endif
- return true;
- }
- } else {
- CNXDNUDCH udch;
- bool valid = udch.decode(data + 2U);
- if (valid) {
- data[0U] = TAG_DATA;
- data[1U] = 0x00U;
-
- CSync::addNXDNSync(data + 2U);
-
- CNXDNLICH lich;
- lich.setRFCT(NXDN_LICH_RFCT_RDCH);
- lich.setFCT(NXDN_LICH_USC_UDCH);
- lich.setOption(NXDN_LICH_STEAL_NONE);
- lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
- lich.encode(data + 2U);
-
- udch.encode(data + 2U);
-
- writeQueueNet(data);
-
- if (m_duplex)
- writeQueueRF(data);
-#if defined(DUMP_NXDN)
- writeFile(data + 2U);
-#endif
- return true;
- }
+ return true;
}
#ifdef notdef
@@ -618,7 +569,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data)
data[0U] = TAG_DATA;
data[1U] = 0x00U;
- writeNetwork(data, m_rfFrames % 128U);
+ writeNetwork(data, m_rfFrames);
#if defined(DUMP_NXDN)
writeFile(data + 2U);
@@ -657,7 +608,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data)
data[0U] = TAG_EOT;
data[1U] = 0x00U;
- writeNetwork(data, m_rfFrames % 128U);
+ writeNetwork(data, m_rfFrames);
#if defined(DUMP_NXDN)
writeFile(data + 2U);
@@ -707,7 +658,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data)
data[0U] = TAG_DATA;
data[1U] = 0x00U;
- writeNetwork(data, m_rfFrames % 128U);
+ writeNetwork(data, m_rfFrames);
if (m_duplex) {
fich.setMR(m_remoteGateway ? YSF_MR_NOT_BUSY : YSF_MR_BUSY);
@@ -749,6 +700,8 @@ void CNXDNControl::writeEndRF()
{
m_rfState = RS_RF_LISTENING;
+ m_rfMask = 0x00U;
+
m_rfTimeoutTimer.stop();
if (m_netState == RS_NET_IDLE) {
@@ -973,7 +926,7 @@ void CNXDNControl::writeQueueNet(const unsigned char *data)
m_queue.addData(data, len);
}
-void CNXDNControl::writeNetwork(const unsigned char *data, unsigned int count)
+void CNXDNControl::writeNetwork(const unsigned char *data, unsigned int count, bool end)
{
assert(data != NULL);
@@ -983,7 +936,11 @@ void CNXDNControl::writeNetwork(const unsigned char *data, unsigned int count)
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
- m_network->write(data + 2U, count, data[0U] == TAG_EOT);
+ unsigned short srcId = m_rfLayer3.getSourceUnitId();
+ unsigned short dstId = m_rfLayer3.getDestinationGroupId();
+ bool grp = m_rfLayer3.getIsGroup();
+
+ m_network->write(data + 2U, srcId, grp, dstId, count % 256U, end);
}
void CNXDNControl::scrambler(unsigned char* data) const
diff --git a/NXDNControl.h b/NXDNControl.h
index da2fd12..5f000e7 100644
--- a/NXDNControl.h
+++ b/NXDNControl.h
@@ -22,6 +22,7 @@
#include "RSSIInterpolator.h"
#include "NXDNNetwork.h"
#include "NXDNDefines.h"
+#include "NXDNLayer3.h"
#include "NXDNLookup.h"
#include "RingBuffer.h"
#include "StopWatch.h"
@@ -68,7 +69,9 @@ private:
unsigned int m_rfBits;
unsigned int m_netErrs;
unsigned int m_netBits;
- CNXDNLICH m_lastLICH;
+ CNXDNLICH m_rfLastLICH;
+ CNXDNLayer3 m_rfLayer3;
+ unsigned char m_rfMask;
unsigned char m_netN;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
@@ -83,7 +86,7 @@ private:
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
- void writeNetwork(const unsigned char* data, unsigned int count);
+ void writeNetwork(const unsigned char* data, unsigned int count, bool end);
void writeNetwork();
void scrambler(unsigned char* data) const;
diff --git a/NXDNConvolution.cpp b/NXDNConvolution.cpp
index 2881412..049bdb6 100755
--- a/NXDNConvolution.cpp
+++ b/NXDNConvolution.cpp
@@ -45,7 +45,7 @@ m_dp(NULL)
{
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
- m_decisions = new uint64_t[180U];
+ m_decisions = new uint64_t[300U];
}
CNXDNConvolution::~CNXDNConvolution()
@@ -98,7 +98,7 @@ void CNXDNConvolution::decode(uint8_t s0, uint8_t s1)
++m_dp;
- assert((m_dp - m_decisions) <= 180);
+ assert((m_dp - m_decisions) <= 300);
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
diff --git a/NXDNDefines.h b/NXDNDefines.h
index c9ab105..463ca61 100644
--- a/NXDNDefines.h
+++ b/NXDNDefines.h
@@ -66,4 +66,41 @@ const unsigned char NXDN_SR_3_4 = 1U;
const unsigned char NXDN_SR_2_4 = 2U;
const unsigned char NXDN_SR_1_4 = 3U;
+const unsigned char NXDN_MESSAGE_TYPE_VCALL = 0x01U;
+const unsigned char NXDN_MESSAGE_TYPE_VCALL_IV = 0x03U;
+const unsigned char NXDN_MESSAGE_TYPE_DCALL_HDR = 0x09U;
+const unsigned char NXDN_MESSAGE_TYPE_DCALL_DATA = 0x0BU;
+const unsigned char NXDN_MESSAGE_TYPE_DCALL_ACK = 0x0CU;
+const unsigned char NXDN_MESSAGE_TYPE_TX_REL = 0x08U;
+const unsigned char NXDN_MESSAGE_TYPE_HEAD_DLY = 0x0FU;
+const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_HDR = 0x38U;
+const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_DATA = 0x39U;
+const unsigned char NXDN_MESSAGE_TYPE_SDCALL_RESP = 0x3BU;
+const unsigned char NXDN_MESSAGE_TYPE_SDCALL_IV = 0x3AU;
+const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_REQ = 0x30U;
+const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_RESP = 0x31U;
+const unsigned char NXDN_MESSAGE_TYPE_STAT_REQ = 0x32U;
+const unsigned char NXDN_MESSAGE_TYPE_STAT_RESP = 0x33U;
+const unsigned char NXDN_MESSAGE_TYPE_REM_CON_REQ = 0x34U;
+const unsigned char NXDN_MESSAGE_TYPE_REM_CON_RESP = 0x35U;
+const unsigned char NXDN_MESSAGE_TYPE_IDLE = 0x10U;
+const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_REQ = 0x28U;
+const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_RESP = 0x29U;
+const unsigned char NXDN_MESSAGE_TYPE_PROP_FORM = 0x3FU;
+
+const unsigned char NXDN_VOICE_CALL_OPTION_HALF_DUPLEX = 0x00U;
+const unsigned char NXDN_VOICE_CALL_OPTION_DUPLEX = 0x10U;
+
+const unsigned char NXDN_VOICE_CALL_OPTION_4800_EHR = 0x00U;
+const unsigned char NXDN_VOICE_CALL_OPTION_9600_EHR = 0x02U;
+const unsigned char NXDN_VOICE_CALL_OPTION_9600_EFR = 0x03U;
+
+const unsigned char NXDN_DATA_CALL_OPTION_HALF_DUPLEX = 0x00U;
+const unsigned char NXDN_DATA_CALL_OPTION_DUPLEX = 0x10U;
+
+const unsigned char NXDN_DATA_CALL_OPTION_4800 = 0x00U;
+const unsigned char NXDN_DATA_CALL_OPTION_9600 = 0x02U;
+
+const unsigned char SACCH_IDLE[] = { NXDN_MESSAGE_TYPE_IDLE, 0x00U, 0x00U };
+
#endif
diff --git a/NXDNFACCH1.cpp b/NXDNFACCH1.cpp
index f548a8d..48f4639 100644
--- a/NXDNFACCH1.cpp
+++ b/NXDNFACCH1.cpp
@@ -28,6 +28,22 @@
#include
#include
+const unsigned int INTERLEAVE_TABLE[] = {
+ 0U, 9U, 18U, 27U, 36U, 45U, 54U, 63U, 72U, 81U, 90U, 99U, 108U, 117U, 126U, 135U,
+ 1U, 10U, 19U, 28U, 37U, 46U, 55U, 64U, 73U, 82U, 91U, 100U, 109U, 118U, 127U, 136U,
+ 2U, 11U, 20U, 29U, 38U, 47U, 56U, 65U, 74U, 83U, 92U, 101U, 110U, 119U, 128U, 137U,
+ 3U, 12U, 21U, 30U, 39U, 48U, 57U, 66U, 75U, 84U, 93U, 102U, 111U, 120U, 129U, 138U,
+ 4U, 13U, 22U, 31U, 40U, 49U, 58U, 67U, 76U, 85U, 94U, 103U, 112U, 121U, 130U, 139U,
+ 5U, 14U, 23U, 32U, 41U, 50U, 59U, 68U, 77U, 86U, 95U, 104U, 113U, 122U, 131U, 140U,
+ 6U, 15U, 24U, 33U, 42U, 51U, 60U, 69U, 78U, 87U, 96U, 105U, 114U, 123U, 132U, 141U,
+ 7U, 16U, 25U, 34U, 43U, 52U, 61U, 70U, 79U, 88U, 97U, 106U, 115U, 124U, 133U, 142U,
+ 8U, 17U, 26U, 35U, 44U, 53U, 62U, 71U, 80U, 89U, 98U, 107U, 116U, 125U, 134U, 143U };
+
+const unsigned int PUNCTURE_LIST[] = { 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U,
+ 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U,
+ 81U, 85U, 89U, 93U, 97U, 101U, 105U, 109U, 113U, 117U,
+ 121U, 125U, 129U, 133U, 137U, 141U};
+
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])
@@ -51,16 +67,98 @@ CNXDNFACCH1::~CNXDNFACCH1()
delete[] m_data;
}
-bool CNXDNFACCH1::decode(const unsigned char* data)
+bool CNXDNFACCH1::decode(const unsigned char* data, unsigned int offset)
{
assert(data != NULL);
- return true;
+ // CUtils::dump("NXDN, FACCH1 input", data, 18U);
+
+ unsigned char temp1[18U];
+
+ for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
+ unsigned int n = INTERLEAVE_TABLE[i] + offset;
+ bool b = READ_BIT1(data, n);
+ WRITE_BIT1(temp1, i, b);
+ }
+
+ // CUtils::dump("NXDN, FACCH1 de-interleaved", temp1, 18U);
+
+ uint8_t temp2[192U];
+
+ unsigned int n = 0U;
+ unsigned int index = 0U;
+ for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
+ if (n == PUNCTURE_LIST[index]) {
+ temp2[n++] = 99U;
+ index++;
+ }
+
+ bool b = READ_BIT1(temp1, i);
+ temp2[n++] = b ? 1U : 0U;
+ }
+
+ CNXDNConvolution conv;
+ conv.start();
+
+ n = 0U;
+ for (unsigned int i = 0U; i < 96U; i++) {
+ uint8_t s0 = temp2[n++];
+ uint8_t s1 = temp2[n++];
+
+ conv.decode(s0, s1);
+ }
+
+ conv.chainback(m_data, 92U);
+
+ CUtils::dump("NXDN, FACCH1 decoded", m_data, 12U);
+
+ return CNXDNCRC::checkCRC12(m_data, 80U);
}
-void CNXDNFACCH1::encode(unsigned char* data) const
+void CNXDNFACCH1::encode(unsigned char* data, unsigned int offset) const
{
assert(data != NULL);
+
+ unsigned char temp1[12U];
+ ::memset(temp1, 0x00U, 12U);
+
+ for (unsigned int i = 0U; i < 80U; i++) {
+ bool b = READ_BIT1(m_data, i);
+ WRITE_BIT1(temp1, i, b);
+ }
+
+ CNXDNCRC::encodeCRC12(temp1, 80U);
+
+ // CUtils::dump("NXDN, FACCH1 encoded with CRC", temp1, 12U);
+
+ unsigned char temp2[24U];
+
+ CNXDNConvolution conv;
+ conv.encode(temp1, temp2, 96U);
+
+ // CUtils::dump("NXDN, FACCH1 convolved", temp2, 24U);
+
+ unsigned char temp3[18U];
+
+ unsigned int n = 0U;
+ unsigned int index = 0U;
+ for (unsigned int i = 0U; i < 192U; i++) {
+ if (i != PUNCTURE_LIST[index]) {
+ bool b = READ_BIT1(temp2, i);
+ WRITE_BIT1(temp3, n, b);
+ n++;
+ } else {
+ index++;
+ }
+ }
+
+ // CUtils::dump("NXDN, FACCH1 punctured", temp3, 18U);
+
+ for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
+ unsigned int n = INTERLEAVE_TABLE[i] + offset;
+ bool b = READ_BIT1(temp3, i);
+ WRITE_BIT1(data, n, b);
+ }
}
void CNXDNFACCH1::getData(unsigned char* data) const
diff --git a/NXDNFACCH1.h b/NXDNFACCH1.h
index 3c9c664..adb4112 100644
--- a/NXDNFACCH1.h
+++ b/NXDNFACCH1.h
@@ -25,9 +25,10 @@ public:
CNXDNFACCH1();
~CNXDNFACCH1();
- bool decode(const unsigned char* data);
+ bool decode(const unsigned char* data, unsigned int offset);
+
+ void encode(unsigned char* data, unsigned int offset) const;
- void encode(unsigned char* data) const;
void getData(unsigned char* data) const;
void setData(const unsigned char* data);
diff --git a/NXDNLICH.cpp b/NXDNLICH.cpp
index b5e363c..df735b9 100644
--- a/NXDNLICH.cpp
+++ b/NXDNLICH.cpp
@@ -61,7 +61,7 @@ bool CNXDNLICH::decode(const unsigned char* bytes)
bool parity = b[7U] ^ b[6U] ^ b[5U] ^ b[4U];
- LogMessage("NXDN, LICH bits: %d%d %d%d %d%d %d - %d, parity: %d", b[7U] ? 1 : 0, b[6U] ? 1 : 0, b[5U] ? 1 : 0, b[4U] ? 1 : 0, b[3U] ? 1 : 0, b[2U] ? 1 : 0, b[1U] ? 1 : 0, b[0U] ? 1 : 0, parity ? 1 : 0);
+ // LogMessage("NXDN, LICH bits: %d%d %d%d %d%d %d - %d, parity: %d", b[7U] ? 1 : 0, b[6U] ? 1 : 0, b[5U] ? 1 : 0, b[4U] ? 1 : 0, b[3U] ? 1 : 0, b[2U] ? 1 : 0, b[1U] ? 1 : 0, b[0U] ? 1 : 0, parity ? 1 : 0);
if (parity != b[0U])
return false;
diff --git a/NXDNFACCH2.cpp b/NXDNLayer3.cpp
similarity index 50%
rename from NXDNFACCH2.cpp
rename to NXDNLayer3.cpp
index ac705fa..f4da16b 100644
--- a/NXDNFACCH2.cpp
+++ b/NXDNLayer3.cpp
@@ -16,11 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "NXDNFACCH2.h"
-
#include "NXDNDefines.h"
-#include "NXDNUDCH.h"
-#include "Utils.h"
+#include "NXDNLayer3.h"
#include "Log.h"
#include
@@ -32,78 +29,74 @@ 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])
-CNXDNFACCH2::CNXDNFACCH2(const CNXDNFACCH2& facch2) :
+CNXDNLayer3::CNXDNLayer3(const CNXDNLayer3& layer3) :
m_data(NULL)
{
- m_data = new unsigned char[23U];
- ::memcpy(m_data, facch2.m_data, 23U);
+ m_data = new unsigned char[22U];
+ ::memcpy(m_data, layer3.m_data, 22U);
}
-CNXDNFACCH2::CNXDNFACCH2() :
+CNXDNLayer3::CNXDNLayer3() :
m_data(NULL)
{
- m_data = new unsigned char[23U];
+ m_data = new unsigned char[22U];
+ ::memset(m_data, 0x00U, 22U);
}
-CNXDNFACCH2::~CNXDNFACCH2()
+CNXDNLayer3::~CNXDNLayer3()
{
delete[] m_data;
}
-bool CNXDNFACCH2::decode(const unsigned char* data)
+void CNXDNLayer3::decode(const unsigned char* bytes, unsigned int length, unsigned int offset)
{
- assert(data != NULL);
+ assert(bytes != NULL);
- CNXDNUDCH udch;
- bool valid = udch.decode(data);
- if (!valid)
- return false;
-
- udch.getData(m_data);
-
- return true;
+ for (unsigned int i = 0U; i < length; i++, offset++) {
+ bool b = READ_BIT1(bytes, offset);
+ WRITE_BIT1(m_data, i, b);
+ }
}
-void CNXDNFACCH2::encode(unsigned char* data) const
+void CNXDNLayer3::encode(unsigned char* bytes, unsigned int length, unsigned int offset)
{
- assert(data != NULL);
+ assert(bytes != NULL);
- CNXDNUDCH udch;
-
- udch.setData(m_data);
-
- udch.encode(data);
+ for (unsigned int i = 0U; i < length; i++, offset++) {
+ bool b = READ_BIT1(m_data, i);
+ WRITE_BIT1(bytes, offset, b);
+ }
}
-unsigned char CNXDNFACCH2::getRAN() const
+unsigned char CNXDNLayer3::getMessageType() const
{
return m_data[0U] & 0x3FU;
}
-void CNXDNFACCH2::getData(unsigned char* data) const
+unsigned short CNXDNLayer3::getSourceUnitId() const
{
- assert(data != NULL);
-
- ::memcpy(data, m_data + 1U, 22U);
+ return (m_data[3U] << 8) | m_data[4U];
}
-void CNXDNFACCH2::setRAN(unsigned char ran)
+unsigned short CNXDNLayer3::getDestinationGroupId() const
{
- m_data[0U] &= 0xC0U;
- m_data[0U] |= ran;
+ return (m_data[5U] << 8) | m_data[6U];
}
-void CNXDNFACCH2::setData(const unsigned char* data)
+bool CNXDNLayer3::getIsGroup() const
{
- assert(data != NULL);
-
- ::memcpy(m_data + 1U, data, 22U);
+ return (m_data[2U] & 0x80U) != 0x80U;
}
-CNXDNFACCH2& CNXDNFACCH2::operator=(const CNXDNFACCH2& facch2)
+unsigned char CNXDNLayer3::getCallOptions() const
{
- if (&facch2 != this)
- ::memcpy(m_data, facch2.m_data, 23U);
+ return m_data[2U] & 0x1FU;
+}
+
+CNXDNLayer3& CNXDNLayer3::operator=(const CNXDNLayer3& layer3)
+{
+ if (&layer3 != this)
+ ::memcpy(m_data, layer3.m_data, 22U);
return *this;
}
diff --git a/NXDNFACCH2.h b/NXDNLayer3.h
similarity index 58%
rename from NXDNFACCH2.h
rename to NXDNLayer3.h
index 7f8ee57..81aff2b 100644
--- a/NXDNFACCH2.h
+++ b/NXDNLayer3.h
@@ -16,28 +16,26 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#if !defined(NXDNFACCH2_H)
-#define NXDNFACCH2_H
+#if !defined(NXDNLayer3_H)
+#define NXDNLayer3_H
-class CNXDNFACCH2 {
+class CNXDNLayer3 {
public:
- CNXDNFACCH2(const CNXDNFACCH2& facch);
- CNXDNFACCH2();
- ~CNXDNFACCH2();
+ CNXDNLayer3(const CNXDNLayer3& layer3);
+ CNXDNLayer3();
+ ~CNXDNLayer3();
- bool decode(const unsigned char* data);
+ void decode(const unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
- void encode(unsigned char* data) const;
+ void encode(unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
- unsigned char getRAN() const;
+ unsigned char getMessageType() const;
+ unsigned short getSourceUnitId() const;
+ unsigned short getDestinationGroupId() const;
+ bool getIsGroup() const;
+ unsigned char getCallOptions() const;
- void getData(unsigned char* data) const;
-
- void setRAN(unsigned char ran);
-
- void setData(const unsigned char* data);
-
- CNXDNFACCH2& operator=(const CNXDNFACCH2& facch);
+ CNXDNLayer3& operator=(const CNXDNLayer3& layer3);
private:
unsigned char* m_data;
diff --git a/NXDNNetwork.cpp b/NXDNNetwork.cpp
index 5476766..6453829 100644
--- a/NXDNNetwork.cpp
+++ b/NXDNNetwork.cpp
@@ -56,11 +56,11 @@ bool CNXDNNetwork::open()
return m_socket.open();
}
-bool CNXDNNetwork::write(const unsigned char* data, unsigned int count, bool end)
+bool CNXDNNetwork::write(const unsigned char* data, unsigned short src, bool grp, unsigned short dst, unsigned char cnt, bool end)
{
assert(data != NULL);
- unsigned char buffer[200U];
+ unsigned char buffer[100U];
buffer[0U] = 'N';
buffer[1U] = 'X';
@@ -68,15 +68,23 @@ bool CNXDNNetwork::write(const unsigned char* data, unsigned int count, bool end
buffer[3U] = 'N';
buffer[4U] = 'D';
- buffer[5U] = end ? 0x01U : 0x00U;
- buffer[5U] |= (count & 0x7FU) << 1;
+ buffer[5U] = (src >> 8) & 0xFFU;
+ buffer[6U] = (src >> 8) & 0xFFU;
- ::memcpy(buffer + 6U, data, NXDN_FRAME_LENGTH_BYTES);
+ buffer[7U] = grp ? 0x01U : 0x00U;
+ buffer[7U] |= end ? 0x80U : 0x00U;
+
+ buffer[8U] = (dst >> 8) & 0xFFU;
+ buffer[9U] = (dst >> 8) & 0xFFU;
+
+ buffer[10U] = cnt;
+
+ ::memcpy(buffer + 11U, data, NXDN_FRAME_LENGTH_BYTES);
if (m_debug)
- CUtils::dump(1U, "NXDN Network Data Sent", buffer, 54U);
+ CUtils::dump(1U, "NXDN Network Data Sent", buffer, 59U);
- return m_socket.write(buffer, 54U, m_address, m_port);
+ return m_socket.write(buffer, 59U, m_address, m_port);
}
bool CNXDNNetwork::writePoll()
@@ -131,19 +139,29 @@ void CNXDNNetwork::clock(unsigned int ms)
if (m_debug)
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
- m_buffer.addData(buffer, 54U);
+ m_buffer.addData(buffer, 59U);
}
-unsigned int CNXDNNetwork::read(unsigned char* data)
+unsigned int CNXDNNetwork::read(unsigned char* data, unsigned short& src, bool& grp, unsigned short& dst, unsigned char& cnt, bool& end)
{
assert(data != NULL);
if (m_buffer.isEmpty())
return 0U;
- m_buffer.getData(data, 54U);
+ unsigned char buffer[100U];
+ m_buffer.getData(buffer, 59U);
- return 155U;
+ src = (buffer[5U] << 8) + buffer[6U];
+ grp = (buffer[7U] & 0x01U) == 0x01U;
+ end = (buffer[7U] & 0x80U) == 0x80U;
+ dst = (buffer[8U] << 8) + buffer[9U];
+
+ cnt = buffer[10U];
+
+ ::memcpy(data, buffer + 11U, NXDN_FRAME_LENGTH_BYTES);
+
+ return NXDN_FRAME_LENGTH_BYTES;
}
void CNXDNNetwork::reset()
diff --git a/NXDNNetwork.h b/NXDNNetwork.h
index ea96826..c69602a 100644
--- a/NXDNNetwork.h
+++ b/NXDNNetwork.h
@@ -36,9 +36,9 @@ public:
void enable(bool enabled);
- bool write(const unsigned char* data, unsigned int count, bool end);
+ bool write(const unsigned char* data, unsigned short src, bool grp, unsigned short dst, unsigned char cnt, bool end);
- unsigned int read(unsigned char* data);
+ unsigned int read(unsigned char* data, unsigned short& src, bool& grp, unsigned short& dst, unsigned char& cnt, bool& end);
void reset();
diff --git a/NXDNSACCH.cpp b/NXDNSACCH.cpp
index 262cde2..304b20d 100755
--- a/NXDNSACCH.cpp
+++ b/NXDNSACCH.cpp
@@ -65,7 +65,7 @@ bool CNXDNSACCH::decode(const unsigned char* data)
{
assert(data != NULL);
- CUtils::dump("NXDN, SACCH input", data, 12U);
+ // CUtils::dump("NXDN, SACCH input", data, 12U);
unsigned char temp1[8U];
@@ -75,29 +75,22 @@ bool CNXDNSACCH::decode(const unsigned char* data)
WRITE_BIT1(temp1, i, b);
}
- CUtils::dump("NXDN, SACCH de-interleaved", temp1, 8U);
+ // CUtils::dump("NXDN, SACCH de-interleaved", temp1, 8U);
uint8_t temp2[72U];
- char text[500U];
- ::strcpy(text, "NXDN, SACCH de-punctured: ");
-
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
if (n == PUNCTURE_LIST[index]) {
- ::strcat(text, "X, ");
temp2[n++] = 99U;
index++;
}
bool b = READ_BIT1(temp1, i);
temp2[n++] = b ? 1U : 0U;
- ::strcat(text, b ? "1, " : "0, ");
}
- LogMessage(text);
-
CNXDNConvolution conv;
conv.start();
@@ -111,7 +104,7 @@ bool CNXDNSACCH::decode(const unsigned char* data)
conv.chainback(m_data, 32U);
- CUtils::dump("NXDN, SACCH decoded", m_data, 5U);
+ CUtils::dump("NXDN, SACCH decoded", m_data, 4U);
return CNXDNCRC::checkCRC6(m_data, 26U);
}
@@ -130,14 +123,14 @@ void CNXDNSACCH::encode(unsigned char* data) const
CNXDNCRC::encodeCRC6(temp1, 26U);
- CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 5U);
+ CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 4U);
- unsigned char temp2[9U];
+ unsigned char temp2[8U];
CNXDNConvolution conv;
conv.encode(temp1, temp2, 36U);
- CUtils::dump("NXDN, SACCH convolved", temp2, 9U);
+ // CUtils::dump("NXDN, SACCH convolved", temp2, 8U);
unsigned char temp3[8U];
@@ -153,15 +146,13 @@ void CNXDNSACCH::encode(unsigned char* data) const
}
}
- CUtils::dump("NXDN, SACCH punctured", temp3, 8U);
+ // CUtils::dump("NXDN, SACCH punctured", temp3, 8U);
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(temp3, i);
WRITE_BIT1(data, n, b);
}
-
- CUtils::dump("NXDN, SACCH re-encoded", data, 12U);
}
unsigned char CNXDNSACCH::getRAN() const
diff --git a/NXDNUDCH.cpp b/NXDNUDCH.cpp
index 1d194b9..e58460e 100644
--- a/NXDNUDCH.cpp
+++ b/NXDNUDCH.cpp
@@ -28,6 +28,43 @@
#include
#include
+const unsigned int INTERLEAVE_TABLE[] = {
+ 0U, 29U, 58U, 87U, 116U, 145U, 174U, 203U, 232U, 261U, 290U, 319U,
+ 1U, 30U, 59U, 88U, 117U, 146U, 175U, 204U, 233U, 262U, 291U, 320U,
+ 2U, 31U, 60U, 89U, 118U, 147U, 176U, 205U, 234U, 263U, 292U, 321U,
+ 3U, 32U, 61U, 90U, 119U, 148U, 177U, 206U, 235U, 264U, 293U, 322U,
+ 4U, 33U, 62U, 91U, 120U, 149U, 178U, 207U, 236U, 265U, 294U, 323U,
+ 5U, 34U, 63U, 92U, 121U, 150U, 179U, 208U, 237U, 266U, 295U, 324U,
+ 6U, 35U, 64U, 93U, 122U, 151U, 180U, 209U, 238U, 267U, 296U, 325U,
+ 7U, 36U, 65U, 94U, 123U, 152U, 181U, 210U, 239U, 268U, 297U, 326U,
+ 8U, 37U, 66U, 95U, 124U, 153U, 182U, 211U, 240U, 269U, 298U, 327U,
+ 9U, 38U, 67U, 96U, 125U, 154U, 183U, 212U, 241U, 270U, 299U, 328U,
+ 10U, 39U, 68U, 97U, 126U, 155U, 184U, 213U, 242U, 271U, 300U, 329U,
+ 11U, 40U, 69U, 98U, 127U, 156U, 185U, 214U, 243U, 272U, 301U, 330U,
+ 12U, 41U, 70U, 99U, 128U, 157U, 186U, 215U, 244U, 273U, 302U, 331U,
+ 13U, 42U, 71U, 100U, 129U, 158U, 187U, 216U, 245U, 274U, 303U, 332U,
+ 14U, 43U, 72U, 101U, 130U, 159U, 188U, 217U, 246U, 275U, 304U, 333U,
+ 15U, 44U, 73U, 102U, 131U, 160U, 189U, 218U, 247U, 276U, 305U, 334U,
+ 16U, 45U, 74U, 103U, 132U, 161U, 190U, 219U, 248U, 277U, 306U, 335U,
+ 17U, 46U, 75U, 104U, 133U, 162U, 191U, 220U, 249U, 278U, 307U, 336U,
+ 18U, 47U, 76U, 105U, 134U, 163U, 192U, 221U, 250U, 279U, 308U, 337U,
+ 19U, 48U, 77U, 106U, 135U, 164U, 193U, 222U, 251U, 280U, 309U, 338U,
+ 20U, 49U, 78U, 107U, 136U, 165U, 194U, 223U, 252U, 281U, 310U, 339U,
+ 21U, 50U, 79U, 108U, 137U, 166U, 195U, 224U, 253U, 282U, 311U, 340U,
+ 22U, 51U, 80U, 109U, 138U, 167U, 196U, 225U, 254U, 283U, 312U, 341U,
+ 23U, 52U, 81U, 110U, 139U, 168U, 197U, 226U, 255U, 284U, 313U, 342U,
+ 24U, 53U, 82U, 111U, 140U, 169U, 198U, 227U, 256U, 285U, 314U, 343U,
+ 25U, 54U, 83U, 112U, 141U, 170U, 199U, 228U, 257U, 286U, 315U, 344U,
+ 26U, 55U, 84U, 113U, 142U, 171U, 200U, 229U, 258U, 287U, 316U, 345U,
+ 27U, 56U, 85U, 114U, 143U, 172U, 201U, 230U, 259U, 288U, 317U, 346U,
+ 28U, 57U, 86U, 115U, 144U, 173U, 202U, 231U, 260U, 289U, 318U, 347U };
+
+const unsigned int PUNCTURE_LIST[] = { 3U, 11U, 17U, 25U, 31U, 39U, 45U, 53U, 59U, 67U,
+ 73U, 81U, 87U, 95U, 101U, 109U, 115U, 123U, 129U, 137U,
+ 143U, 151U, 157U, 165U, 171U, 179U, 185U, 193U, 199U, 207U,
+ 213U, 221U, 227U, 235U, 241U, 249U, 255U, 263U, 269U, 277U,
+ 283U, 291U, 297U, 305U, 311U, 319U, 325U, 333U, 339U, 347U };
+
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])
@@ -55,26 +92,119 @@ bool CNXDNUDCH::decode(const unsigned char* data)
{
assert(data != NULL);
- return true;
+ CUtils::dump("NXDN, UDCH/FACCH2 input", data, 44U);
+
+ unsigned char temp1[44U];
+
+ for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
+ unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
+ bool b = READ_BIT1(data, n);
+ WRITE_BIT1(temp1, i, b);
+ }
+
+ CUtils::dump("NXDN, UDCH/FACCH2 de-interleaved", temp1, 44U);
+
+ uint8_t temp2[406U];
+
+ unsigned int n = 0U;
+ unsigned int index = 0U;
+ for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
+ if (n == PUNCTURE_LIST[index]) {
+ temp2[n++] = 99U;
+ index++;
+ }
+
+ bool b = READ_BIT1(temp1, i);
+ temp2[n++] = b ? 1U : 0U;
+ }
+
+ CNXDNConvolution conv;
+ conv.start();
+
+ n = 0U;
+ for (unsigned int i = 0U; i < 203U; i++) {
+ uint8_t s0 = temp2[n++];
+ uint8_t s1 = temp2[n++];
+
+ conv.decode(s0, s1);
+ }
+
+ conv.chainback(m_data, 199U);
+
+ CUtils::dump("NXDN, UDCH/FACCH2 decoded", m_data, 25U);
+
+ return CNXDNCRC::checkCRC15(m_data, 184U);
}
void CNXDNUDCH::encode(unsigned char* data) const
{
assert(data != NULL);
+
+ unsigned char temp1[25U];
+ ::memset(temp1, 0x00U, 25U);
+
+ for (unsigned int i = 0U; i < 184U; i++) {
+ bool b = READ_BIT1(m_data, i);
+ WRITE_BIT1(temp1, i, b);
+ }
+
+ CNXDNCRC::encodeCRC15(temp1, 184U);
+
+ CUtils::dump("NXDN, UDCH/FACCH2 encoded with CRC", temp1, 25U);
+
+ unsigned char temp2[51U];
+
+ CNXDNConvolution conv;
+ conv.encode(temp1, temp2, 203U);
+
+ CUtils::dump("NXDN, UDCH/FACCH2 convolved", temp2, 51U);
+
+ unsigned char temp3[44U];
+
+ unsigned int n = 0U;
+ unsigned int index = 0U;
+ for (unsigned int i = 0U; i < 406U; i++) {
+ if (i != PUNCTURE_LIST[index]) {
+ bool b = READ_BIT1(temp2, i);
+ WRITE_BIT1(temp3, n, b);
+ n++;
+ } else {
+ index++;
+ }
+ }
+
+ CUtils::dump("NXDN, UDCH/FACCH2 punctured", temp3, 44U);
+
+ for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
+ unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
+ bool b = READ_BIT1(temp3, i);
+ WRITE_BIT1(data, n, b);
+ }
+}
+
+unsigned char CNXDNUDCH::getRAN() const
+{
+ return m_data[0U] & 0x3FU;
}
void CNXDNUDCH::getData(unsigned char* data) const
{
assert(data != NULL);
- ::memcpy(data, m_data, 23U);
+ ::memcpy(data, m_data + 1U, 22U);
+}
+
+void CNXDNUDCH::setRAN(unsigned char ran)
+{
+ m_data[0U] &= 0xC0U;
+ m_data[0U] |= ran;
}
void CNXDNUDCH::setData(const unsigned char* data)
{
assert(data != NULL);
- ::memcpy(m_data, data, 23U);
+ ::memcpy(m_data + 1U, data, 22U);
}
CNXDNUDCH& CNXDNUDCH::operator=(const CNXDNUDCH& udch)
diff --git a/NXDNUDCH.h b/NXDNUDCH.h
index 6847c9c..366cd09 100644
--- a/NXDNUDCH.h
+++ b/NXDNUDCH.h
@@ -29,8 +29,12 @@ public:
void encode(unsigned char* data) const;
+ unsigned char getRAN() const;
+
void getData(unsigned char* data) const;
+ void setRAN(unsigned char ran);
+
void setData(const unsigned char* data);
CNXDNUDCH& operator=(const CNXDNUDCH& udch);