diff --git a/Conf.cpp b/Conf.cpp index 122be9a..854a970 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -172,6 +172,7 @@ m_nxdnRemoteGateway(false), m_nxdnTXHang(5U), m_nxdnModeHang(10U), m_m17Enabled(false), +m_m17ColorCode(1U), m_m17SelfOnly(false), m_m17AllowEncryption(false), m_m17TXHang(5U), @@ -739,6 +740,8 @@ bool CConf::read() } else if (section == SECTION_M17) { if (::strcmp(key, "Enable") == 0) m_m17Enabled = ::atoi(value) == 1; + else if (::strcmp(key, "ColorCode") == 0) + m_m17ColorCode = (unsigned int)::atoi(value); else if (::strcmp(key, "SelfOnly") == 0) m_m17SelfOnly = ::atoi(value) == 1; else if (::strcmp(key, "AllowEncryption") == 0) @@ -1603,6 +1606,11 @@ bool CConf::getM17Enabled() const return m_m17Enabled; } +unsigned int CConf::getM17ColorCode() const +{ + return m_m17ColorCode; +} + bool CConf::getM17SelfOnly() const { return m_m17SelfOnly; diff --git a/Conf.h b/Conf.h index 01d36fd..96b40a0 100644 --- a/Conf.h +++ b/Conf.h @@ -163,6 +163,7 @@ public: // The M17 section bool getM17Enabled() const; + unsigned int getM17ColorCode() const; bool getM17SelfOnly() const; bool getM17AllowEncryption() const; unsigned int getM17TXHang() const; @@ -469,6 +470,7 @@ private: unsigned int m_nxdnModeHang; bool m_m17Enabled; + unsigned int m_m17ColorCode; bool m_m17SelfOnly; bool m_m17AllowEncryption; unsigned int m_m17TXHang; diff --git a/M17Control.cpp b/M17Control.cpp index 9a9f359..d9239ad 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -57,8 +57,9 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -CM17Control::CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : +CM17Control::CM17Control(const std::string& callsign, unsigned int colorCode, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : m_callsign(callsign), +m_colorCode(colorCode), m_selfOnly(selfOnly), m_allowEncryption(allowEncryption), m_network(network), @@ -154,7 +155,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) decorrelator(data + 2U, temp); interleaver(temp, data + 2U); - if (m_rfState == RS_RF_LISTENING) { + if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_HEADER) { m_rfLICH.reset(); CM17Convolution conv; @@ -225,11 +226,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) writeFile(data + 2U); #endif if (m_duplex) { - data[0U] = TAG_DATA; + data[0U] = TAG_HEADER; data[1U] = 0x00U; // Generate the sync - CSync::addM17Sync(data + 2U); + CSync::addM17HeaderSync(data + 2U); unsigned char setup[M17_LICH_LENGTH_BYTES]; m_rfLICH.getLinkSetup(setup); @@ -251,7 +252,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) } } - if (m_rfState == RS_RF_LATE_ENTRY) { + if (m_rfState == RS_RF_LATE_ENTRY && data[0U] == TAG_DATA) { CM17Convolution conv; unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame); @@ -323,11 +324,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) if (m_duplex) { // Create a Link Setup frame - data[0U] = TAG_DATA; + data[0U] = TAG_HEADER; data[1U] = 0x00U; // Generate the sync - CSync::addM17Sync(data + 2U); + CSync::addM17HeaderSync(data + 2U); unsigned char setup[M17_LICH_LENGTH_BYTES]; m_rfLICH.getLinkSetup(setup); @@ -348,7 +349,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) } } - if (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) { + if ((m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) && data[0U] == TAG_DATA) { #if defined(DUMP_M17) writeFile(data + 2U); #endif @@ -391,7 +392,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) rfData[1U] = 0x00U; // Generate the sync - CSync::addM17Sync(rfData + 2U); + CSync::addM17DataSync(rfData + 2U); unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES]; m_netLICH.getFragment(lich, m_rfFN); @@ -460,7 +461,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) return true; } - if (m_rfState == RS_RF_REJECTED) { + if (m_rfState == RS_RF_REJECTED && data[0U] == TAG_DATA) { CM17Convolution conv; unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame); @@ -583,11 +584,11 @@ void CM17Control::writeNetwork() // Create a dummy start message unsigned char start[M17_FRAME_LENGTH_BYTES + 2U]; - start[0U] = TAG_DATA; + start[0U] = TAG_HEADER; start[1U] = 0x00U; // Generate the sync - CSync::addM17Sync(start + 2U); + CSync::addM17HeaderSync(start + 2U); unsigned char setup[M17_LICH_LENGTH_BYTES]; m_netLICH.getLinkSetup(setup); @@ -609,7 +610,7 @@ void CM17Control::writeNetwork() data[1U] = 0x00U; // Generate the sync - CSync::addM17Sync(data + 2U); + CSync::addM17DataSync(data + 2U); m_netFrames++; diff --git a/M17Control.h b/M17Control.h index bff2d19..6838aa7 100644 --- a/M17Control.h +++ b/M17Control.h @@ -34,7 +34,7 @@ class CM17Control { public: - CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); + CM17Control(const std::string& callsign, unsigned int colorCode, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); ~CM17Control(); bool writeModem(unsigned char* data, unsigned int len); @@ -49,6 +49,7 @@ public: private: std::string m_callsign; + unsigned int m_colorCode; bool m_selfOnly; bool m_allowEncryption; CM17Network* m_network; diff --git a/M17Defines.h b/M17Defines.h index 53b5f63..7cdad35 100644 --- a/M17Defines.h +++ b/M17Defines.h @@ -24,7 +24,9 @@ const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate const unsigned int M17_FRAME_LENGTH_BITS = 384U; const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U; -const unsigned char M17_SYNC_BYTES[] = {0x32U, 0x43U}; +const unsigned char M17_HEADER_SYNC_BYTES[] = {0x5DU, 0xDDU}; +const unsigned char M17_DATA_SYNC_BYTES[] = {0xDDU, 0xDDU}; + const unsigned int M17_SYNC_LENGTH_BITS = 16U; const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U; diff --git a/MMDVM.ini b/MMDVM.ini index a6ae4e8..5880d16 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -133,6 +133,7 @@ TXHang=5 [M17] Enable=1 +ColorCode=3 SelfOnly=0 TXHang=5 # ModeHang=10 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 238c14a..0673fea 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -619,18 +619,20 @@ int CMMDVMHost::run() } if (m_m17Enabled) { - bool selfOnly = m_conf.getM17SelfOnly(); - bool allowEncryption = m_conf.getM17AllowEncryption(); - unsigned int txHang = m_conf.getM17TXHang(); - m_m17RFModeHang = m_conf.getM17ModeHang(); + bool selfOnly = m_conf.getM17SelfOnly(); + unsigned int colorCode = m_conf.getM17ColorCode(); + bool allowEncryption = m_conf.getM17AllowEncryption(); + unsigned int txHang = m_conf.getM17TXHang(); + m_m17RFModeHang = m_conf.getM17ModeHang(); LogInfo("M17 RF Parameters"); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); + LogInfo(" Color Code: %u", colorCode); LogInfo(" Allow Encryption: %s", allowEncryption ? "yes" : "no"); LogInfo(" TX Hang: %us", txHang); LogInfo(" Mode Hang: %us", m_m17RFModeHang); - m_m17 = new CM17Control(m_callsign, selfOnly, allowEncryption, m_m17Network, m_display, m_timeout, m_duplex, rssi); + m_m17 = new CM17Control(m_callsign, colorCode, selfOnly, allowEncryption, m_m17Network, m_display, m_timeout, m_duplex, rssi); } CTimer pocsagTimer(1000U, 30U); diff --git a/SerialModem.cpp b/SerialModem.cpp index 3d7652d..721c736 100644 --- a/SerialModem.cpp +++ b/SerialModem.cpp @@ -79,8 +79,9 @@ const unsigned char MMDVM_P25_LOST = 0x32U; const unsigned char MMDVM_NXDN_DATA = 0x40U; const unsigned char MMDVM_NXDN_LOST = 0x41U; -const unsigned char MMDVM_M17_DATA = 0x45U; -const unsigned char MMDVM_M17_LOST = 0x46U; +const unsigned char MMDVM_M17_HEADER = 0x45U; +const unsigned char MMDVM_M17_DATA = 0x46U; +const unsigned char MMDVM_M17_LOST = 0x47U; const unsigned char MMDVM_POCSAG_DATA = 0x50U; @@ -659,6 +660,20 @@ void CSerialModem::clock(unsigned int ms) } break; + case MMDVM_M17_HEADER: { + if (m_trace) + CUtils::dump(1U, "RX M17 Header", m_buffer, m_length); + + unsigned char data = m_length - 2U; + m_rxM17Data.addData(&data, 1U); + + data = TAG_HEADER; + m_rxM17Data.addData(&data, 1U); + + m_rxM17Data.addData(m_buffer + 3U, m_length - 3U); + } + break; + case MMDVM_M17_DATA: { if (m_trace) CUtils::dump(1U, "RX M17 Data", m_buffer, m_length); @@ -1015,8 +1030,12 @@ void CSerialModem::clock(unsigned int ms) m_txM17Data.getData(&len, 1U); m_txM17Data.getData(m_buffer, len); - if (m_trace) - CUtils::dump(1U, "TX M17 Data", m_buffer, len); + if (m_trace) { + if (m_buffer[2U] == MMDVM_M17_HEADER) + CUtils::dump(1U, "TX M17 Header", m_buffer, len); + else + CUtils::dump(1U, "TX M17 Data", m_buffer, len); + } int ret = m_serial->write(m_buffer, len); if (ret != int(len)) @@ -1471,14 +1490,18 @@ bool CSerialModem::writeM17Data(const unsigned char* data, unsigned int length) assert(data != NULL); assert(length > 0U); - if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) + if (data[0U] != TAG_HEADER && data[0U] != TAG_DATA && data[0U] != TAG_EOT) return false; unsigned char buffer[130U]; buffer[0U] = MMDVM_FRAME_START; buffer[1U] = length + 2U; - buffer[2U] = MMDVM_M17_DATA; + + if (data[0U] == TAG_HEADER) + buffer[2U] = MMDVM_M17_HEADER; + else + buffer[2U] = MMDVM_M17_DATA; ::memcpy(buffer + 3U, data + 1U, length - 1U); diff --git a/Sync.cpp b/Sync.cpp index 34dec37..3e53f64 100644 --- a/Sync.cpp +++ b/Sync.cpp @@ -85,9 +85,16 @@ void CSync::addNXDNSync(unsigned char* data) data[i] = (data[i] & ~NXDN_FSW_BYTES_MASK[i]) | NXDN_FSW_BYTES[i]; } -void CSync::addM17Sync(unsigned char* data) +void CSync::addM17HeaderSync(unsigned char* data) { assert(data != NULL); - ::memcpy(data, M17_SYNC_BYTES, M17_SYNC_LENGTH_BYTES); + ::memcpy(data, M17_HEADER_SYNC_BYTES, M17_SYNC_LENGTH_BYTES); +} + +void CSync::addM17DataSync(unsigned char* data) +{ + assert(data != NULL); + + ::memcpy(data, M17_DATA_SYNC_BYTES, M17_SYNC_LENGTH_BYTES); } diff --git a/Sync.h b/Sync.h index 2118c96..20ee2dd 100644 --- a/Sync.h +++ b/Sync.h @@ -33,7 +33,8 @@ public: static void addNXDNSync(unsigned char* data); - static void addM17Sync(unsigned char* data); + static void addM17HeaderSync(unsigned char* data); + static void addM17DataSync(unsigned char* data); private: }; diff --git a/Version.h b/Version.h index 7fc09f6..c648bad 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20201116"; +const char* VERSION = "20201126"; #endif