diff --git a/Conf.cpp b/Conf.cpp index 513cae3..251a128 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -165,6 +165,7 @@ m_dmrNetworkLocal(0U), m_dmrNetworkPassword(), m_dmrNetworkOptions(), m_dmrNetworkDebug(false), +m_dmrNetworkJitterEnabled(true), m_dmrNetworkJitter(300U), m_dmrNetworkSlot1(true), m_dmrNetworkSlot2(true), @@ -595,6 +596,8 @@ bool CConf::read() m_dmrNetworkOptions = value; else if (::strcmp(key, "Debug") == 0) m_dmrNetworkDebug = ::atoi(value) == 1; + else if (::strcmp(key, "JitterEnabled") == 0) + m_dmrNetworkJitterEnabled = ::atoi(value) == 1; else if (::strcmp(key, "Jitter") == 0) m_dmrNetworkJitter = (unsigned int)::atoi(value); else if (::strcmp(key, "Slot1") == 0) @@ -1266,6 +1269,11 @@ bool CConf::getDMRNetworkDebug() const return m_dmrNetworkDebug; } +bool CConf::getDMRNetworkJitterEnabled() const +{ + return m_dmrNetworkJitterEnabled; +} + unsigned int CConf::getDMRNetworkJitter() const { return m_dmrNetworkJitter; diff --git a/Conf.h b/Conf.h index 016f77c..d464495 100644 --- a/Conf.h +++ b/Conf.h @@ -167,6 +167,7 @@ public: std::string getDMRNetworkPassword() const; std::string getDMRNetworkOptions() const; bool getDMRNetworkDebug() const; + bool getDMRNetworkJitterEnabled() const; unsigned int getDMRNetworkJitter() const; bool getDMRNetworkSlot1() const; bool getDMRNetworkSlot2() const; @@ -360,6 +361,7 @@ private: std::string m_dmrNetworkPassword; std::string m_dmrNetworkOptions; bool m_dmrNetworkDebug; + bool m_dmrNetworkJitterEnabled; unsigned int m_dmrNetworkJitter; bool m_dmrNetworkSlot1; bool m_dmrNetworkSlot2; diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp index 51843db..c9f251a 100644 --- a/DMRNetwork.cpp +++ b/DMRNetwork.cpp @@ -32,7 +32,7 @@ const unsigned int BUFFER_LENGTH = 500U; const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U; -CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType, unsigned int jitter) : +CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType, bool jitterEnabled, unsigned int jitter) : m_address(), m_port(port), m_id(NULL), @@ -44,6 +44,7 @@ m_socket(local), m_enabled(false), m_slot1(slot1), m_slot2(slot2), +m_jitterEnabled(jitterEnabled), m_jitterBuffers(NULL), m_hwType(hwType), m_status(WAITING_CONNECT), @@ -498,23 +499,23 @@ 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) || - dataType == (0x20U | DT_RATE_1_DATA) || - dataType == (0x20U | DT_RATE_34_DATA) || - dataType == (0x20U | DT_RATE_12_DATA)) { - // Data & CSBK frames - m_jitterBuffers[slotNo]->appendData(data, length); + if (m_jitterEnabled) { + unsigned char dataType = data[15U] & 0x3FU; + if (dataType == (0x20U | DT_CSBK) || + dataType == (0x20U | DT_DATA_HEADER) || + dataType == (0x20U | DT_RATE_1_DATA) || + dataType == (0x20U | DT_RATE_34_DATA) || + dataType == (0x20U | DT_RATE_12_DATA)) { + // Data & CSBK frames + m_jitterBuffers[slotNo]->appendData(data, length); + } else { + // Voice frames + unsigned char seqNo = data[4U]; + m_jitterBuffers[slotNo]->addData(data, length, seqNo); + } } else { - // Voice frames - unsigned char seqNo = data[4U]; - m_jitterBuffers[slotNo]->addData(data, length, seqNo); + m_jitterBuffers[slotNo]->appendData(data, length); } - */ } bool CDMRNetwork::writeLogin() diff --git a/DMRNetwork.h b/DMRNetwork.h index 53f579e..cfacb77 100644 --- a/DMRNetwork.h +++ b/DMRNetwork.h @@ -31,7 +31,7 @@ class CDMRNetwork { public: - CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType, unsigned int jitter); + CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType, bool jitterEnabled, unsigned int jitter); ~CDMRNetwork(); void setOptions(const std::string& options); @@ -70,6 +70,7 @@ private: bool m_enabled; bool m_slot1; bool m_slot2; + bool m_jitterEnabled; CJitterBuffer** m_jitterBuffers; HW_TYPE m_hwType; diff --git a/MMDVM.ini b/MMDVM.ini index d08272e..c43590a 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -131,6 +131,7 @@ Debug=0 Enable=1 Address=44.131.4.1 Port=62031 +JitterEnabled=1 Jitter=500 # Local=62032 Password=PASSWORD diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d7e87be..06bcf5d 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1035,6 +1035,7 @@ bool CMMDVMHost::createDMRNetwork() unsigned int id = m_conf.getDMRId(); std::string password = m_conf.getDMRNetworkPassword(); bool debug = m_conf.getDMRNetworkDebug(); + bool jitterEnabled = m_conf.getDMRNetworkJitterEnabled(); unsigned int jitter = m_conf.getDMRNetworkJitter(); bool slot1 = m_conf.getDMRNetworkSlot1(); bool slot2 = m_conf.getDMRNetworkSlot2(); @@ -1048,12 +1049,13 @@ bool CMMDVMHost::createDMRNetwork() LogInfo(" Local: %u", local); else LogInfo(" Local: random"); + LogInfo(" Jitter Buffer: %s", jitterEnabled ? "enabled" : "disabled"); LogInfo(" Jitter: %ums", jitter); LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled"); LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled"); LogInfo(" Mode Hang: %us", m_dmrNetModeHang); - m_dmrNetwork = new CDMRNetwork(address, port, local, id, password, m_duplex, VERSION, debug, slot1, slot2, hwType, jitter); + m_dmrNetwork = new CDMRNetwork(address, port, local, id, password, m_duplex, VERSION, debug, slot1, slot2, hwType, jitterEnabled, jitter); std::string options = m_conf.getDMRNetworkOptions(); if (!options.empty()) { diff --git a/NXDNCRC.cpp b/NXDNCRC.cpp index 0e2ad06..29da35c 100644 --- a/NXDNCRC.cpp +++ b/NXDNCRC.cpp @@ -22,30 +22,25 @@ #include const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; -const uint16_t BIT_MASK_TABLE2[] = { 0x8000U, 0x4000U, 0x2000U, 0x1000U, 0x0800U, 0x0400U, 0x0200U, 0x0100U, - 0x0080U, 0x0040U, 0x0020U, 0x0010U, 0x0008U, 0x0004U, 0x0002U, 0x0001U }; #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7]) -#define READ_BIT2(p,i) (p[(i)>>4] & BIT_MASK_TABLE2[(i)&15]) - bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int length) { assert(in != NULL); - uint8_t crc[1U]; - crc[0U] = createCRC6(in, length); + uint8_t crc = createCRC6(in, length); - unsigned int n = length; - for (unsigned int i = 0U; i < 6U; i++, n++) { - bool b1 = READ_BIT1(crc, i); - bool b2 = READ_BIT1(in, n); - if (b1 != b2) - return false; + uint8_t temp[1U]; + temp[0U] = 0x00U; + unsigned int j = length; + for (unsigned int i = 2U; i < 8U; i++, j++) { + bool b = READ_BIT1(in, j); + WRITE_BIT1(temp, i, b); } - return true; + return crc == temp[0U]; } void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length) @@ -56,7 +51,7 @@ void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length) crc[0U] = createCRC6(in, length); unsigned int n = length; - for (unsigned int i = 0U; i < 6U; i++, n++) { + for (unsigned int i = 2U; i < 8U; i++, n++) { bool b = READ_BIT1(crc, i); WRITE_BIT1(in, n, b); } @@ -66,30 +61,36 @@ bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int length) { assert(in != NULL); - uint16_t crc[1U]; - crc[0U] = createCRC12(in, length); + uint16_t crc = createCRC12(in, length); + uint8_t temp1[2U]; + temp1[0U] = (crc >> 8) & 0xFFU; + temp1[1U] = (crc >> 0) & 0xFFU; - unsigned int n = length; - for (unsigned int i = 0U; i < 12U; i++, n++) { - bool b1 = READ_BIT2(crc, i); - bool b2 = READ_BIT1(in, n); - if (b1 != b2) - return false; + uint8_t temp2[2U]; + temp2[0U] = 0x00U; + temp2[1U] = 0x00U; + unsigned int j = length; + for (unsigned int i = 4U; i < 16U; i++, j++) { + bool b = READ_BIT1(in, j); + WRITE_BIT1(temp2, i, b); } - return true; + return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U]; } void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int length) { assert(in != NULL); - uint16_t crc[1U]; - crc[0U] = createCRC12(in, length); + uint16_t crc = createCRC12(in, length); + + uint8_t temp[2U]; + temp[0U] = (crc >> 8) & 0xFFU; + temp[1U] = (crc >> 0) & 0xFFU; unsigned int n = length; - for (unsigned int i = 0U; i < 12U; i++, n++) { - bool b = READ_BIT2(crc, i); + for (unsigned int i = 4U; i < 16U; i++, n++) { + bool b = READ_BIT1(temp, i); WRITE_BIT1(in, n, b); } } @@ -98,123 +99,90 @@ bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int length) { assert(in != NULL); - uint16_t crc[1U]; - crc[0U] = createCRC15(in, length); + uint16_t crc = createCRC15(in, length); + uint8_t temp1[2U]; + temp1[0U] = (crc >> 8) & 0xFFU; + temp1[1U] = (crc >> 0) & 0xFFU; - unsigned int n = length; - for (unsigned int i = 0U; i < 15U; i++, n++) { - bool b1 = READ_BIT2(crc, i); - bool b2 = READ_BIT1(in, n); - if (b1 != b2) - return false; + uint16_t temp2[2U]; + temp2[0U] = 0x00U; + temp2[1U] = 0x00U; + unsigned int j = length; + for (unsigned int i = 1U; i < 16U; i++, j++) { + bool b = READ_BIT1(in, j); + WRITE_BIT1(temp2, i, b); } - return true; + return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U]; } void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int length) { assert(in != NULL); - uint16_t crc[1U]; - crc[0U] = createCRC15(in, length); + uint16_t crc = createCRC15(in, length); + + uint8_t temp[2U]; + temp[0U] = (crc >> 8) & 0xFFU; + temp[1U] = (crc >> 0) & 0xFFU; unsigned int n = length; - for (unsigned int i = 0U; i < 15U; i++, n++) { - bool b = READ_BIT2(crc, i); + for (unsigned int i = 1U; i < 16U; i++, n++) { + bool b = READ_BIT1(temp, i); WRITE_BIT1(in, n, b); } } uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int length) { - uint8_t crc = 0x3EU; + uint8_t crc = 0x3FU; for (unsigned int i = 0U; i < length; i++) { bool bit1 = READ_BIT1(in, i) != 0x00U; bool bit2 = (crc & 0x20U) == 0x20U; crc <<= 1; + crc &= 0x3EU; - if (bit1) - crc |= 0x01U; - - if (bit2) - crc ^= 0x27U; - - crc &= 0x3FU; - } - - for (unsigned int i = 0U; i < 6U; i++) { - bool bit = (crc & 0x20U) == 0x20U; - - crc <<= 1; - - if (bit) + if (bit1 ^ bit2) crc ^= 0x27U; } - return (crc & 0x3FU) << 2U; + return crc; } uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int length) { - uint16_t crc = 0x0D9EU; + uint16_t crc = 0x0FFFU; for (unsigned int i = 0U; i < length; i++) { bool bit1 = READ_BIT1(in, i) != 0x00U; bool bit2 = (crc & 0x0800U) == 0x0800U; crc <<= 1; + crc &= 0x0FFEU; - if (bit1) - crc |= 0x0001U; - - if (bit2) - crc ^= 0x080FU; - - crc &= 0x0FFFU; - } - - for (unsigned int i = 0U; i < 12U; i++) { - bool bit = (crc & 0x0800U) == 0x0800U; - - crc <<= 1; - - if (bit) + if (bit1 ^ bit2) crc ^= 0x080FU; } - return (crc & 0x0FFFU) << 4U; + return crc & 0x0FFFU; } uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int length) { - uint16_t crc = 0x02E4U; + uint16_t crc = 0x7FFFU; for (unsigned int i = 0U; i < length; i++) { bool bit1 = READ_BIT1(in, i) != 0x00U; bool bit2 = (crc & 0x4000U) == 0x4000U; crc <<= 1; + crc &= 0x7FFEU; - if (bit1) - crc |= 0x0001U; - - if (bit2) - crc ^= 0x4CC5U; - - crc &= 0x7FFFU; - } - - for (unsigned int i = 0U; i < 15U; i++) { - bool bit = (crc & 0x4000U) == 0x4000U; - - crc <<= 1; - - if (bit) + if (bit1 ^ bit2) crc ^= 0x4CC5U; } - return (crc & 0x7FFFU) << 1U; + return crc & 0x7FFFU; } diff --git a/NXDNControl.cpp b/NXDNControl.cpp index 74b2991..35973f3 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -91,9 +91,9 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) { if (m_rssi != 0U) - LogMessage("NXDN, transmission lost, %.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); + LogMessage("NXDN, transmission lost, %.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, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 10.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + LogMessage("NXDN, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); writeEndRF(); return false; } @@ -174,183 +174,172 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne unsigned char ran = sacch.getRAN(); if (ran != m_ran && ran != 0U) return false; + } else if (m_rfState == RS_RF_LISTENING) { + return false; } // XXX Reconstruct invalid LICH 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); - - CNXDNFACCH1 facch12; - bool valid2 = facch12.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + CNXDNFACCH1 facch; + bool valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + if (!valid) + valid = facch.decode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + if (!valid) + return false; unsigned char buffer[10U]; - if (valid1) - facch11.getData(buffer); - else if (valid2) - facch12.getData(buffer); + facch.getData(buffer); - if (valid1 || valid2) { - CNXDNLayer3 layer3; - layer3.decode(buffer, NXDN_FACCH1_LENGTH_BITS); + 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; - } - } - } - - data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA; - data[1U] = 0x00U; - - CSync::addNXDNSync(data + 2U); - - CNXDNLICH lich = m_rfLastLICH; - lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); - lich.encode(data + 2U); - - CNXDNSACCH sacch; - sacch.setRAN(m_ran); - sacch.setStructure(NXDN_SR_SINGLE); - sacch.setData(SACCH_IDLE); - sacch.encode(data + 2U); - - 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); - } - - scrambler(data + 2U); - - // writeNetwork(data, m_rfFrames, ); - -#if defined(DUMP_NXDN) - writeFile(data + 2U); -#endif - - 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; - } - } - - return false; - } else { - unsigned char message[3U]; - sacch.getData(message); - - 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; - } - - if (m_rfMask != 0x0FU) - return false; - - unsigned char messageType = m_rfLayer3.getMessageType(); - if (messageType != NXDN_MESSAGE_TYPE_VCALL) - return false; - - 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; + 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 { + bool hasInfo = layer3.getHasInfo(); + if (m_rfState == RS_RF_LISTENING && m_selfOnly && hasInfo) { + unsigned short srcId = layer3.getSourceUnitId(); + 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; + data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA; + data[1U] = 0x00U; + + CSync::addNXDNSync(data + 2U); + + CNXDNLICH lich = m_rfLastLICH; + lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); + lich.encode(data + 2U); + + CNXDNSACCH sacch; + sacch.setRAN(m_ran); + sacch.setStructure(NXDN_SR_SINGLE); + sacch.setData(SACCH_IDLE); + sacch.encode(data + 2U); + + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS); + facch.encode(data + 2U, NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS + NXDN_FACCH1_LENGTH_BITS); + + scrambler(data + 2U); + + // writeNetwork(data, m_rfFrames, ); - m_minRSSI = m_rssi; - m_maxRSSI = m_rssi; - m_aveRSSI = m_rssi; - m_rssiCount = 1U; #if defined(DUMP_NXDN) - openFile(); + writeFile(data + 2U); #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) + writeQueueRF(data); - m_rfState = RS_RF_AUDIO; + 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) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits)); + writeEndRF(); + } 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 header from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId); + m_display->writeNXDN(source.c_str(), grp, dstId, "R"); + } + + return true; + } else { + if (m_rfState == RS_RF_LISTENING) { + unsigned char message[3U]; + sacch.getData(message); + + 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; + } + + if (m_rfMask != 0x0FU) + return false; + + bool hasInfo = m_rfLayer3.getHasInfo(); + if (!hasInfo) + return false; + + 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) + openFile(); +#endif + std::string source = m_lookup->find(srcId); + LogMessage("NXDN, received RF late entry 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; + } } - // if (m_rfState == RS_RF_AUDIO) { + if (m_rfState == RS_RF_AUDIO) { // Regenerate the sync CSync::addNXDNSync(data + 2U); @@ -460,24 +449,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne 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 { - m_rfState = RS_RF_LISTENING; - m_rfMask = 0x00U; - return false; - } } -#endif return true; } diff --git a/NXDNConvolution.cpp b/NXDNConvolution.cpp index 8db6a05..d5292fc 100755 --- a/NXDNConvolution.cpp +++ b/NXDNConvolution.cpp @@ -21,6 +21,7 @@ #include #include #include +#include const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -72,7 +73,7 @@ void CNXDNConvolution::decode(uint8_t s0, uint8_t s1) for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) { uint8_t j = i * 2U; - uint16_t metric = abs(BRANCH_TABLE1[i] - s0) + abs(BRANCH_TABLE2[i] - s1); + uint16_t metric = ::abs(BRANCH_TABLE1[i] - s0) + ::abs(BRANCH_TABLE2[i] - s1); uint16_t m0 = m_oldMetrics[i] + metric; uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric); diff --git a/NXDNFACCH1.cpp b/NXDNFACCH1.cpp index 5ae0136..ca2a9fc 100644 --- a/NXDNFACCH1.cpp +++ b/NXDNFACCH1.cpp @@ -115,7 +115,7 @@ bool CNXDNFACCH1::decode(const unsigned char* data, unsigned int offset) conv.chainback(m_data, 96U); - CUtils::dump("NXDN, FACCH1 decoded", m_data, 12U); + // CUtils::dump("NXDN, FACCH1 decoded", m_data, 12U); return CNXDNCRC::checkCRC12(m_data, 80U); } @@ -126,11 +126,7 @@ void CNXDNFACCH1::encode(unsigned char* data, unsigned int offset) const 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); - } + ::memcpy(temp1, m_data, 10U); CNXDNCRC::encodeCRC12(temp1, 80U); diff --git a/NXDNLayer3.cpp b/NXDNLayer3.cpp index f4da16b..dce3d17 100644 --- a/NXDNLayer3.cpp +++ b/NXDNLayer3.cpp @@ -93,6 +93,15 @@ unsigned char CNXDNLayer3::getCallOptions() const return m_data[2U] & 0x1FU; } +bool CNXDNLayer3::getHasInfo() const +{ + unsigned char type = getMessageType(); + + return type != NXDN_MESSAGE_TYPE_IDLE && + type != NXDN_MESSAGE_TYPE_VCALL_IV && + type != NXDN_MESSAGE_TYPE_SDCALL_IV; +} + CNXDNLayer3& CNXDNLayer3::operator=(const CNXDNLayer3& layer3) { if (&layer3 != this) diff --git a/NXDNLayer3.h b/NXDNLayer3.h index 81aff2b..bd4ba6a 100644 --- a/NXDNLayer3.h +++ b/NXDNLayer3.h @@ -34,6 +34,7 @@ public: unsigned short getDestinationGroupId() const; bool getIsGroup() const; unsigned char getCallOptions() const; + bool getHasInfo() const; CNXDNLayer3& operator=(const CNXDNLayer3& layer3); diff --git a/NXDNSACCH.cpp b/NXDNSACCH.cpp index 3b69d11..b060fa4 100755 --- a/NXDNSACCH.cpp +++ b/NXDNSACCH.cpp @@ -108,7 +108,7 @@ bool CNXDNSACCH::decode(const unsigned char* data) conv.chainback(m_data, 36U); - CUtils::dump("NXDN, SACCH decoded", m_data, 4U); + // CUtils::dump("NXDN, SACCH decoded", m_data, 4U); return CNXDNCRC::checkCRC6(m_data, 26U); } @@ -127,14 +127,14 @@ void CNXDNSACCH::encode(unsigned char* data) const CNXDNCRC::encodeCRC6(temp1, 26U); - CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 4U); + // CUtils::dump("NXDN, SACCH encoded with CRC", temp1, 4U); - unsigned char temp2[8U]; + unsigned char temp2[9U]; CNXDNConvolution conv; conv.encode(temp1, temp2, 36U); - // CUtils::dump("NXDN, SACCH convolved", temp2, 8U); + // CUtils::dump("NXDN, SACCH convolved", temp2, 9U); unsigned char temp3[8U]; diff --git a/NXDNUDCH.cpp b/NXDNUDCH.cpp index 1e2a278..c4ead27 100644 --- a/NXDNUDCH.cpp +++ b/NXDNUDCH.cpp @@ -93,7 +93,7 @@ bool CNXDNUDCH::decode(const unsigned char* data) { assert(data != NULL); - CUtils::dump("NXDN, UDCH/FACCH2 input", data, 44U); + // CUtils::dump("NXDN, UDCH/FACCH2 input", data, 44U); unsigned char temp1[44U]; @@ -103,7 +103,7 @@ bool CNXDNUDCH::decode(const unsigned char* data) WRITE_BIT1(temp1, i, b); } - CUtils::dump("NXDN, UDCH/FACCH2 de-interleaved", temp1, 44U); + // CUtils::dump("NXDN, UDCH/FACCH2 de-interleaved", temp1, 44U); uint8_t temp2[420U]; @@ -136,7 +136,7 @@ bool CNXDNUDCH::decode(const unsigned char* data) conv.chainback(m_data, 203U); - CUtils::dump("NXDN, UDCH/FACCH2 decoded", m_data, 25U); + // CUtils::dump("NXDN, UDCH/FACCH2 decoded", m_data, 25U); return CNXDNCRC::checkCRC15(m_data, 184U); } @@ -147,22 +147,18 @@ void CNXDNUDCH::encode(unsigned char* data) const 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); - } + ::memcpy(temp1, m_data, 23U); CNXDNCRC::encodeCRC15(temp1, 184U); - CUtils::dump("NXDN, UDCH/FACCH2 encoded with CRC", temp1, 25U); + // 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); + // CUtils::dump("NXDN, UDCH/FACCH2 convolved", temp2, 51U); unsigned char temp3[44U]; @@ -178,7 +174,7 @@ void CNXDNUDCH::encode(unsigned char* data) const } } - CUtils::dump("NXDN, UDCH/FACCH2 punctured", temp3, 44U); + // 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;