diff --git a/DMREmbeddedLC.cpp b/DMREmbeddedLC.cpp index 829a25071..1e6b85d1d 100644 --- a/DMREmbeddedLC.cpp +++ b/DMREmbeddedLC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,21 +26,26 @@ #include #include -CDMREmbeddedLC::CDMREmbeddedLC() : -m_rawLC(NULL), -m_state(LCS_NONE) +CDMREmbeddedLC::CDMREmbeddedLC(unsigned int slotNo) : +m_slotNo(slotNo), +m_raw(NULL), +m_state(LCS_NONE), +m_data(NULL), +m_FLCO(FLCO_GROUP), +m_valid(false) { - // Allow for multi-block non embedded LC data - m_rawLC = new bool[300U]; + m_raw = new bool[128U]; + m_data = new bool[72U]; } CDMREmbeddedLC::~CDMREmbeddedLC() { - delete[] m_rawLC; + delete[] m_raw; + delete[] m_data; } // Add LC data (which may consist of 4 blocks) to the data store -CDMRLC* CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss) +bool CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss) { assert(data != NULL); @@ -54,49 +59,48 @@ CDMRLC* CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss) // Is this the first block of a 4 block embedded LC ? if (lcss == 1U) { for (unsigned int a = 0U; a < 32U; a++) - m_rawLC[a] = rawData[a + 4U]; + m_raw[a] = rawData[a + 4U]; // Show we are ready for the next LC block m_state = LCS_FIRST; - return NULL; + m_valid = false; + return false; } // Is this the 2nd block of a 4 block embedded LC ? if (lcss == 3U && m_state == LCS_FIRST) { for (unsigned int a = 0U; a < 32U; a++) - m_rawLC[a + 32U] = rawData[a + 4U]; + m_raw[a + 32U] = rawData[a + 4U]; // Show we are ready for the next LC block m_state = LCS_SECOND; - return NULL; + return false; } // Is this the 3rd block of a 4 block embedded LC ? if (lcss == 3U && m_state == LCS_SECOND) { for (unsigned int a = 0U; a < 32U; a++) - m_rawLC[a + 64U] = rawData[a + 4U]; + m_raw[a + 64U] = rawData[a + 4U]; // Show we are ready for the final LC block m_state = LCS_THIRD; - return NULL; + return false; } // Is this the final block of a 4 block embedded LC ? if (lcss == 2U && m_state == LCS_THIRD) { for (unsigned int a = 0U; a < 32U; a++) - m_rawLC[a + 96U] = rawData[a + 4U]; + m_raw[a + 96U] = rawData[a + 4U]; // Process the complete data block - return processMultiBlockEmbeddedLC(); + return processEmbeddedData(); } // Is this a single block embedded LC - if (lcss == 0U) { - processSingleBlockEmbeddedLC(rawData + 4U); - return NULL; - } + if (lcss == 0U) + return false; - return NULL; + return false; } void CDMREmbeddedLC::setData(const CDMRLC& lc) @@ -143,7 +147,7 @@ void CDMREmbeddedLC::setData(const CDMRLC& lc) // The data is packed downwards in columns b = 0U; for (unsigned int a = 0U; a < 128U; a++) { - m_rawLC[a] = data[b]; + m_raw[a] = data[b]; b += 16U; if (b > 127U) b -= 127U; @@ -159,7 +163,7 @@ unsigned char CDMREmbeddedLC::getData(unsigned char* data, unsigned char n) cons bool bits[40U]; ::memset(bits, 0x00U, 40U * sizeof(bool)); - ::memcpy(bits + 4U, m_rawLC + n * 32U, 32U * sizeof(bool)); + ::memcpy(bits + 4U, m_raw + n * 32U, 32U * sizeof(bool)); unsigned char bytes[5U]; CUtils::bitsToByteBE(bits + 0U, bytes[0U]); @@ -194,7 +198,7 @@ unsigned char CDMREmbeddedLC::getData(unsigned char* data, unsigned char n) cons } // Unpack and error check an embedded LC -CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC() +bool CDMREmbeddedLC::processEmbeddedData() { // The data is unpacked downwards in columns bool data[128U]; @@ -202,7 +206,7 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC() unsigned int b = 0U; for (unsigned int a = 0U; a < 128U; a++) { - data[b] = m_rawLC[a]; + data[b] = m_raw[a]; b += 16U; if (b > 127U) b -= 127U; @@ -211,33 +215,32 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC() // Hamming (16,11,4) check each row except the last one for (unsigned int a = 0U; a < 112U; a += 16U) { if (!CHamming::decode16114(data + a)) - return NULL; + return false; } // Check the parity bits for (unsigned int a = 0U; a < 16U; a++) { bool parity = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U] ^ data[a + 112U]; if (parity) - return NULL; + return false; } // We have passed the Hamming check so extract the actual payload - bool lcData[72U]; b = 0U; for (unsigned int a = 0U; a < 11U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 16U; a < 27U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 32U; a < 42U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 48U; a < 58U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 64U; a < 74U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 80U; a < 90U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; for (unsigned int a = 96U; a < 106U; a++, b++) - lcData[b] = data[a]; + m_data[b] = data[a]; // Extract the 5 bit CRC unsigned int crc = 0U; @@ -248,45 +251,63 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC() if (data[106]) crc += 1U; // Now CRC check this - if (!CCRC::checkFiveBit(lcData, crc)) - return NULL; + if (!CCRC::checkFiveBit(m_data, crc)) + return false; + + // Extract the FLCO + unsigned char flco; + CUtils::bitsToByteBE(m_data + 0U, flco); + m_FLCO = FLCO(flco & 0x3FU); - CDMRLC* lc = new CDMRLC(lcData); + char text[80U]; // Only generate the LC when it's the correct FLCO - switch (lc->getFLCO()) { + switch (m_FLCO) { case FLCO_GROUP: case FLCO_USER_USER: - return lc; + ::sprintf(text, "DMR Slot %u, Embedded LC Data", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; case FLCO_GPS_INFO: - CUtils::dump(1U, "DMR, Embedded GPS Info", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; case FLCO_TALKER_ALIAS_HEADER: - CUtils::dump(1U, "DMR, Embedded Talker Alias Header", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; case FLCO_TALKER_ALIAS_BLOCK1: - CUtils::dump(1U, "DMR, Embedded Talker Alias Block 1", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; case FLCO_TALKER_ALIAS_BLOCK2: - CUtils::dump(1U, "DMR, Embedded Talker Alias Block 2", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; case FLCO_TALKER_ALIAS_BLOCK3: - CUtils::dump(1U, "DMR, Embedded Talker Alias Block 3", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return true; default: - CUtils::dump(1U, "DMR, Unknown Embedded Data", lcData, 72U); - delete lc; - return NULL; + ::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo); + CUtils::dump(1U, text, m_data, 72U); + return false; } } -// Deal with a single block embedded LC -void CDMREmbeddedLC::processSingleBlockEmbeddedLC(const bool* data) +CDMRLC* CDMREmbeddedLC::getLC() const { - // Nothing interesting, or just NULL (I think) + if (!m_valid) + return NULL; + + if (m_FLCO != FLCO_GROUP && m_FLCO != FLCO_USER_USER) + return NULL; + + return new CDMRLC(m_data); } + +void CDMREmbeddedLC::reset() +{ + m_state = LCS_NONE; + m_valid = false; +} \ No newline at end of file diff --git a/DMREmbeddedLC.h b/DMREmbeddedLC.h index c316580d4..259a5a0f3 100644 --- a/DMREmbeddedLC.h +++ b/DMREmbeddedLC.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #ifndef DMREmbeddedLC_H #define DMREmbeddedLC_H +#include "DMRDefines.h" #include "DMRLC.h" enum LC_STATE { @@ -31,20 +32,27 @@ enum LC_STATE { class CDMREmbeddedLC { public: - CDMREmbeddedLC(); + CDMREmbeddedLC(unsigned int slotNo); ~CDMREmbeddedLC(); - CDMRLC* addData(const unsigned char* data, unsigned char lcss); + bool addData(const unsigned char* data, unsigned char lcss); + CDMRLC* getLC() const; void setData(const CDMRLC& lc); + unsigned char getData(unsigned char* data, unsigned char n) const; -private: - bool* m_rawLC; - LC_STATE m_state; + void reset(); - CDMRLC* processMultiBlockEmbeddedLC(); - void processSingleBlockEmbeddedLC(const bool* data); +private: + unsigned int m_slotNo; + bool* m_raw; + LC_STATE m_state; + bool* m_data; + FLCO m_FLCO; + bool m_valid; + + bool processEmbeddedData(); }; #endif diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 26237faa0..8d2291ce7 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX + * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +58,8 @@ m_slotNo(slotNo), m_queue(5000U, "DMR Slot"), m_rfState(RS_RF_LISTENING), m_netState(RS_NET_IDLE), -m_rfEmbeddedLC(), +m_rfEmbeddedLC(slotNo), +m_netEmbeddedLC(slotNo), m_rfLC(NULL), m_netLC(NULL), m_rfDataHeader(), @@ -176,6 +177,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) data[1U] = 0x00U; m_rfTimeoutTimer.start(); + m_rfEmbeddedLC.reset(); m_rfFrames = 0U; m_rfSeqNo = 0U; @@ -433,11 +435,14 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) data[0U] = TAG_DATA; data[1U] = 0x00U; + m_rfEmbeddedLC.reset(); + if (m_duplex) writeQueueRF(data); writeNetworkRF(data, DT_VOICE_SYNC, errors); } else if (m_rfState == RS_RF_LISTENING) { + m_rfEmbeddedLC.reset(); m_rfState = RS_RF_LATE_ENTRY; } } else { @@ -458,6 +463,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) m_rfErrs += errors; } + m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS()); + m_rfBits += 141U; m_rfFrames++; @@ -478,7 +485,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len) if (colorCode != m_colorCode) return; - CDMRLC* lc = m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS()); + m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS()); + CDMRLC* lc = m_rfEmbeddedLC.getLC(); if (lc != NULL) { unsigned int srcId = lc->getSrcId(); unsigned int dstId = lc->getDstId(); @@ -778,6 +786,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_lastFrameValid = false; m_netTimeoutTimer.start(); + m_netEmbeddedLC.reset(); m_netFrames = 0U; m_netLost = 0U; @@ -823,6 +832,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_lastFrameValid = false; m_netTimeoutTimer.start(); + m_netEmbeddedLC.reset(); if (m_duplex) { m_queue.clear(); @@ -1071,6 +1081,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) writeQueueNet(data); + m_netEmbeddedLC.reset(); m_packetTimer.start(); m_elapsed.start(); @@ -1098,6 +1109,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_lastEMB.setColorCode(m_colorCode); m_lastEMB.getData(data + 2U); + m_netEmbeddedLC.addData(data + 2U, m_lastEMB.getLCSS()); + data[0U] = TAG_DATA; data[1U] = 0x00U; diff --git a/DMRSlot.h b/DMRSlot.h index 42e173437..8c54bd6ce 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,6 +59,7 @@ class CDMRSlot { RPT_RF_STATE m_rfState; RPT_NET_STATE m_netState; CDMREmbeddedLC m_rfEmbeddedLC; + CDMREmbeddedLC m_netEmbeddedLC; CDMRLC* m_rfLC; CDMRLC* m_netLC; CDMRDataHeader m_rfDataHeader;