From 48f95be982f30dee942179b454c4002943cedae1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 17 Oct 2020 21:59:27 +0100 Subject: [PATCH] Mostly complete processing of RF frames. --- M17Control.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++------ M17Control.h | 4 ++- M17Defines.h | 7 ++-- M17LICH.h | 5 +++ M17Network.cpp | 32 +++++++++-------- M17Network.h | 6 ++-- MMDVM.ini | 2 +- MMDVMHost.cpp | 4 +-- 8 files changed, 118 insertions(+), 35 deletions(-) diff --git a/M17Control.cpp b/M17Control.cpp index 1169a5c..39b83d3 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -72,7 +72,7 @@ m_networkWatchdog(1000U, 0U, 1500U), m_elapsed(), m_rfFrames(0U), m_netFrames(0U), -m_rfLastFN(0U), +m_rfFN(0U), m_rfErrs(0U), m_rfBits(1U), m_rfLICH(), @@ -179,7 +179,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) m_maxRSSI = m_rssi; m_aveRSSI = m_rssi; m_rssiCount = 1U; - m_rfLastFN = 0U; + m_rfFN = 0U; #if defined(DUMP_M17) openFile(); @@ -259,7 +259,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS); if (valid) { - m_rfLastFN = (frame[0U] << 8) + (frame[1U] << 0); + m_rfFN = (frame[0U] << 8) + (frame[1U] << 0); unsigned int frag1, frag2, frag3, frag4; @@ -270,7 +270,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) unsigned int lich3 = CGolay24128::decode24128(frag3); unsigned int lich4 = CGolay24128::decode24128(frag4); - m_rfLICH.setFragment(data + 2U + M17_SYNC_LENGTH_BYTES, m_rfLastFN & 0x7FFFU); + m_rfLICH.setFragment(data + 2U + M17_SYNC_LENGTH_BYTES, m_rfFN & 0x7FFFU); valid = m_rfLICH.isValid(); if (valid) { @@ -343,12 +343,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) #if defined(DUMP_M17) writeFile(data + 2U); #endif - CM17Convolution conv; conv.start(); unsigned int n = 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_LENGTH_BYTES; - for (unsigned int i = 0U; i < (M17_LICH_LENGTH_BYTES / 2U); i++) { + for (unsigned int i = 0U; i < ((M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES) / 2U); i++) { uint8_t s0 = data[n++]; uint8_t s1 = data[n++]; @@ -360,19 +359,77 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS); if (valid) { - m_rfLastFN = (frame[0U] << 8) + (frame[1U] << 0); - + m_rfFN = (frame[0U] << 8) + (frame[1U] << 0); } else { - m_rfLastFN++; + // Create a silence frame + m_rfFN++; + + // The new FN + frame[0U] = m_rfFN >> 8; + frame[1U] = m_rfFN >> 0; + + // Add silent audio + unsigned char dataType = m_rfLICH.getDataType(); + switch (dataType) { + case 2U: + ::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_3200_SILENCE, 8U); + ::memcpy(frame + M17_FN_LENGTH_BYTES + 8U, M17_3200_SILENCE, 8U); + break; + case 3U: + ::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_1600_SILENCE, 8U); + break; + default: + break; + } + + // Add the CRC + CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS); + } + + unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES]; + + rfData[0U] = TAG_DATA; + rfData[1U] = 0x00U; + + CSync::addM17Sync(rfData + 2U); + + // Re-encode the LICH fragment + m_rfLICH.getFragment(rfData + 2U + M17_SYNC_LENGTH_BYTES, m_rfFN & 0x7FFFU); + + // XXX TODO Golay on LICH fragment + + // Re-encode the payload + conv.encode(frame, rfData + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_LENGTH_BYTES, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS); + + // Calculate the BER + if (valid) { + for (unsigned int i = 2U; i < 50U; i++) + m_rfErrs += countBits(rfData[i] ^ data[i]); + + m_rfBits += 272U; + + float ber = float(m_rfErrs) / float(m_rfBits); + m_display->writeM17BER(ber); } if (m_duplex) - writeQueueRF(data); + writeQueueRF(rfData); + + unsigned char netData[M17_LICH_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES]; + + m_rfLICH.getNetworkData(netData + 0U); + + // Copy the FN and payload from the frame + ::memcpy(netData + M17_LICH_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES); + + CM17CRC::encodeCRC(netData, M17_LICH_LENGTH_BITS + M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS); + + writeNetwork(netData); m_rfFrames++; // EOT? - if ((m_rfLastFN & 0x8000U) == 0x8000U) { + if ((m_rfFN & 0x8000U) == 0x8000U) { std::string source = m_rfLICH.getSource(); std::string dest = m_rfLICH.getDest(); @@ -737,3 +794,17 @@ void CM17Control::enable(bool enabled) m_enabled = enabled; } + +unsigned int CM17Control::countBits(unsigned char byte) +{ + unsigned int count = 0U; + + const unsigned char* p = &byte; + + for (unsigned int i = 0U; i < 8U; i++) { + if (READ_BIT(p, i) != 0U) + count++; + } + + return count; +} diff --git a/M17Control.h b/M17Control.h index ed39f3a..1c2a271 100644 --- a/M17Control.h +++ b/M17Control.h @@ -63,7 +63,7 @@ private: CStopWatch m_elapsed; unsigned int m_rfFrames; unsigned int m_netFrames; - unsigned int m_rfLastFN; + unsigned int m_rfFN; unsigned int m_rfErrs; unsigned int m_rfBits; CM17LICH m_rfLICH; @@ -85,6 +85,8 @@ private: void interleaver(const unsigned char* in, unsigned char* out) const; void decorrelator(const unsigned char* in, unsigned char* out) const; + unsigned int countBits(unsigned char byte); + void writeEndRF(); void writeEndNet(); diff --git a/M17Defines.h b/M17Defines.h index 9e061e8..201f049 100644 --- a/M17Defines.h +++ b/M17Defines.h @@ -28,8 +28,8 @@ const unsigned char M17_SYNC_BYTES[] = {0x32U, 0x43U}; const unsigned int M17_SYNC_LENGTH_BITS = 16U; const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U; -const unsigned int M17_LICH_LENGTH_BITS = 244U; -const unsigned int M17_LICH_LENGTH_BYTES = 31U; +const unsigned int M17_LICH_LENGTH_BITS = 224U; +const unsigned int M17_LICH_LENGTH_BYTES = M17_LICH_LENGTH_BITS / 8U; const unsigned int M17_LICH_FRAGMENT_LENGTH_BITS = 96U; const unsigned int M17_LICH_FRAGMENT_LENGTH_BYTES = M17_LICH_FRAGMENT_LENGTH_BITS / 8U; @@ -43,4 +43,7 @@ const unsigned int M17_FN_LENGTH_BYTES = M17_FN_LENGTH_BITS / 8U; const unsigned int M17_CRC_LENGTH_BITS = 16U; const unsigned int M17_CRC_LENGTH_BYTES = M17_CRC_LENGTH_BITS / 8U; +const unsigned char M17_3200_SILENCE[] = {0x01U, 0x00U, 0x09U, 0x43U, 0x9CU, 0xE4U, 0x21U, 0x08U}; +const unsigned char M17_1600_SILENCE[] = {0x01U, 0x00U, 0x04U, 0x00U, 0x25U, 0x75U, 0xDDU, 0xF2U}; + #endif diff --git a/M17LICH.h b/M17LICH.h index 4c4346c..4ab48d0 100644 --- a/M17LICH.h +++ b/M17LICH.h @@ -31,8 +31,13 @@ public: void setNetworkData(const unsigned char* data); std::string getSource() const; + void setSource(const std::string& callsign); + std::string getDest() const; + void setDest(const std::string& callsign); + unsigned char getDataType() const; + void setDataType(unsigned char type); void reset(); bool isValid() const; diff --git a/M17Network.cpp b/M17Network.cpp index 28314cd..8c8d251 100644 --- a/M17Network.cpp +++ b/M17Network.cpp @@ -29,7 +29,8 @@ const unsigned int BUFFER_LENGTH = 200U; -CM17Network::CM17Network(unsigned int port, bool debug) : +CM17Network::CM17Network(const std::string& callsign, unsigned int port, bool debug) : +m_callsign(callsign), m_socket(port), m_addr(), m_addrLen(0U), @@ -40,7 +41,7 @@ m_inId(0U), m_buffer(1000U, "M17 Network"), m_random(), m_state(M17N_NOTLINKED), -m_reflector(NULL), +m_encoded(NULL), m_module(' '), m_timer(1000U, 5U) { @@ -49,6 +50,8 @@ m_timer(1000U, 5U) m_random = mt; m_encoded = new unsigned char[6U]; + + CM17Utils::encodeCallsign(m_callsign, m_encoded); } CM17Network::~CM17Network() @@ -63,17 +66,14 @@ bool CM17Network::open() return m_socket.open(m_addr); } -bool CM17Network::link(const std::string& address, unsigned int port, const std::string& reflector, char module) +bool CM17Network::link(const std::string& address, unsigned int port, char module) { if (CUDPSocket::lookup(address, port, m_addr, m_addrLen) != 0) { m_state = M17N_NOTLINKED; return false; } - m_reflector = reflector; - m_module = module; - - CM17Utils::encodeCallsign(m_reflector, m_encoded); + m_module = module; m_state = M17N_LINKING; @@ -119,10 +119,12 @@ bool CM17Network::write(const unsigned char* data) buffer[4U] = m_outId / 256U; // Unique session id buffer[5U] = m_outId % 256U; - if (m_debug) - CUtils::dump(1U, "M17 data transmitted", buffer, 36U); + ::memcpy(buffer + 6U, data, 48U); - return m_socket.write(buffer, 36U, m_addr, m_addrLen); + if (m_debug) + CUtils::dump(1U, "M17 data transmitted", buffer, 54U); + + return m_socket.write(buffer, 54U, m_addr, m_addrLen); } void CM17Network::clock(unsigned int ms) @@ -163,21 +165,21 @@ void CM17Network::clock(unsigned int ms) if (::memcmp(buffer + 0U, "ACKN", 4U) == 0) { m_timer.stop(); m_state = M17N_LINKED; - LogMessage("M17, linked to %s", m_reflector.c_str()); + LogMessage("M17, linked to reflector"); return; } if (::memcmp(buffer + 0U, "NACK", 4U) == 0) { m_timer.stop(); m_state = M17N_NOTLINKED; - LogMessage("M17, link refused by %s", m_reflector.c_str()); + LogMessage("M17, link refused by reflector"); return; } if (::memcmp(buffer + 0U, "DISC", 4U) == 0) { m_timer.stop(); m_state = M17N_NOTLINKED; - LogMessage("M17, unlinked from %s", m_reflector.c_str()); + LogMessage("M17, unlinked from reflector"); return; } @@ -208,10 +210,10 @@ void CM17Network::clock(unsigned int ms) if ((fn & 0x8000U) == 0x8000U) m_inId = 0U; - unsigned char c = length; + unsigned char c = length - 6U; m_buffer.addData(&c, 1U); - m_buffer.addData(buffer, length); + m_buffer.addData(buffer + 6U, length - 6U); } bool CM17Network::read(unsigned char* data) diff --git a/M17Network.h b/M17Network.h index b1d3710..ff357cf 100644 --- a/M17Network.h +++ b/M17Network.h @@ -36,12 +36,12 @@ enum M17NET_STATUS { class CM17Network { public: - CM17Network(unsigned int port, bool debug); + CM17Network(const std::string& callsign, unsigned int port, bool debug); ~CM17Network(); bool open(); - bool link(const std::string& address, unsigned int port, const std::string& reflector, char module); + bool link(const std::string& address, unsigned int port, char module); void unlink(); @@ -58,6 +58,7 @@ public: void clock(unsigned int ms); private: + std::string m_callsign; CUDPSocket m_socket; sockaddr_storage m_addr; unsigned int m_addrLen; @@ -68,7 +69,6 @@ private: CRingBuffer m_buffer; std::mt19937 m_random; M17NET_STATUS m_state; - std::string m_reflector; unsigned char* m_encoded; char m_module; CTimer m_timer; diff --git a/MMDVM.ini b/MMDVM.ini index 83eb5fb..7075501 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -224,7 +224,7 @@ Debug=0 [M17 Network] Enable=1 -GatewayAddress=127.0.0.1 +GatewayAddress=3.138.122.152 GatewayPort=17000 LocalPort=17000 # ModeHang=3 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index b30263f..b665905 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1551,7 +1551,7 @@ bool CMMDVMHost::createM17Network() LogInfo(" Local Port: %u", localPort); LogInfo(" Mode Hang: %us", m_m17NetModeHang); - m_m17Network = new CM17Network(localPort, debug); + m_m17Network = new CM17Network(m_callsign, localPort, debug); bool ret = m_m17Network->open(); if (!ret) { delete m_m17Network; @@ -1559,7 +1559,7 @@ bool CMMDVMHost::createM17Network() return false; } - m_m17Network->link(gatewayAddress, gatewayPort, "M17-USA", 'A'); + m_m17Network->link(gatewayAddress, gatewayPort, 'A'); m_m17Network->enable(true);