diff --git a/CSBK.cpp b/CSBK.cpp index e285af2..10ace99 100644 --- a/CSBK.cpp +++ b/CSBK.cpp @@ -18,10 +18,8 @@ #include "CSBK.h" #include "BPTC19696.h" -#include "CRC.h" -#include "Log.h" // XXXX - #include "Utils.h" +#include "CRC.h" #include #include @@ -31,6 +29,7 @@ m_CSBKO(CSBKO_NONE), m_FID(0x00U), m_bsId(0U), m_srcId(0U), +m_dstId(0U), m_valid(false) { assert(bytes != NULL); @@ -45,12 +44,40 @@ m_valid(false) m_CSBKO = CSBKO(data[0U] & 0x3FU); m_FID = data[1U]; - if (m_CSBKO == CSBKO_BSDWNACT) { + switch (m_CSBKO) { + case CSBKO_BSDWNACT: m_bsId = data[4U] << 16 | data[5U] << 8 | data[6U]; m_srcId = data[7U] << 16 | data[8U] << 8 | data[9U]; - CUtils::dump("Download activate CSBK", data, 12U); - } else { + CUtils::dump("Download Activate CSBK", data, 12U); + break; + + case CSBKO_UUVREQ: + m_dstId = data[4U] << 16 | data[5U] << 8 | data[6U]; + m_srcId = data[7U] << 16 | data[8U] << 8 | data[9U]; + CUtils::dump("Unit to Unit Service Request CSBK", data, 12U); + break; + + case CSBKO_UUANSRSP: + m_dstId = data[4U] << 16 | data[5U] << 8 | data[6U]; + m_srcId = data[7U] << 16 | data[8U] << 8 | data[9U]; + CUtils::dump("Unit to Unit Service Answer Response CSBK", data, 12U); + break; + + case CSBKO_PRECCSBK: + m_dstId = data[4U] << 16 | data[5U] << 8 | data[6U]; + m_srcId = data[7U] << 16 | data[8U] << 8 | data[9U]; + CUtils::dump("Preamble CSBK", data, 12U); + break; + + case CSBKO_NACKRSP: + m_srcId = data[4U] << 16 | data[5U] << 8 | data[6U]; + m_dstId = data[7U] << 16 | data[8U] << 8 | data[9U]; + CUtils::dump("Negative Acknowledge Response CSBK", data, 12U); + break; + + default: CUtils::dump("Unhandled CSBK type", data, 12U); + break; } } @@ -82,3 +109,8 @@ unsigned int CCSBK::getSrcId() const { return m_srcId; } + +unsigned int CCSBK::getDstId() const +{ + return m_dstId; +} diff --git a/CSBK.h b/CSBK.h index 91b6973..40454b9 100644 --- a/CSBK.h +++ b/CSBK.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016 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 @@ -45,13 +45,16 @@ public: // For BS Dwn Act unsigned int getBSId() const; + unsigned int getSrcId() const; + unsigned int getDstId() const; private: CSBKO m_CSBKO; unsigned char m_FID; unsigned int m_bsId; unsigned int m_srcId; + unsigned int m_dstId; bool m_valid; }; diff --git a/DMRDefines.h b/DMRDefines.h index 6b88271..b402266 100644 --- a/DMRDefines.h +++ b/DMRDefines.h @@ -59,12 +59,6 @@ const unsigned char DMR_IDLE_DATA[] = {TAG_DATA, 0x00U, 0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U, 0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U}; -// A silence frame with no EMB and a null Short LC -const unsigned char DMR_SILENCE_DATA[] = {TAG_DATA, 0x00U, - 0x88U, 0xC8U, 0xA3U, 0x54U, 0x22U, 0x16U, 0x31U, 0x69U, 0x6AU, 0xAAU, 0xCAU, - 0x81U, 0x54U, 0x20U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x27U, 0x13U, - 0x29U, 0x48U, 0xAAU, 0xCAU, 0x81U, 0x54U, 0x21U, 0x27U, 0x31U, 0x39U, 0x6AU}; - const unsigned char PAYLOAD_LEFT_MASK[] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U}; const unsigned char PAYLOAD_RIGHT_MASK[] = {0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU}; diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 9d4e165..1f3a918 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -16,9 +16,8 @@ #include "DMRSlot.h" #include "DMRSync.h" #include "FullLC.h" -#include "CSBK.h" #include "Utils.h" -#include "EMB.h" +#include "CSBK.h" #include "CRC.h" #include "Log.h" @@ -31,7 +30,6 @@ CHomebrewDMRIPSC* CDMRSlot::m_network = NULL; IDisplay* CDMRSlot::m_display = NULL; unsigned char* CDMRSlot::m_idle = NULL; -unsigned char* CDMRSlot::m_silence = NULL; FLCO CDMRSlot::m_flco1; unsigned char CDMRSlot::m_id1 = 0U; @@ -50,19 +48,23 @@ m_seqNo(0U), m_n(0U), m_networkWatchdog(1000U, 0U, 1500U), m_timeoutTimer(1000U, timeout), -m_packetTimer(1000U, 0U, 300U), +m_packetTimer(1000U, 0U, 100U), m_elapsed(), m_frames(0U), m_lost(0U), m_fec(), m_bits(0U), m_errs(0U), +m_lastFrame(NULL), +m_lastEMB(), m_fp(NULL) { + m_lastFrame = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U]; } CDMRSlot::~CDMRSlot() { + delete[] m_lastFrame; } void CDMRSlot::writeModem(unsigned char *data) @@ -121,14 +123,11 @@ void CDMRSlot::writeModem(unsigned char *data) m_timeoutTimer.start(); m_seqNo = 0U; - m_n = 0U; + m_n = 0U; m_bits = 1U; m_errs = 0U; - // Put a small delay into starting retransmission - writeQueue(m_idle); - for (unsigned i = 0U; i < 3U; i++) { writeNetwork(data, DT_VOICE_LC_HEADER); writeQueue(data); @@ -200,9 +199,6 @@ void CDMRSlot::writeModem(unsigned char *data) m_seqNo = 0U; m_n = 0U; - // Put a small delay into starting retransmission - writeQueue(m_idle); - for (unsigned i = 0U; i < 3U; i++) { writeNetwork(data, DT_DATA_HEADER); writeQueue(data); @@ -215,6 +211,38 @@ void CDMRSlot::writeModem(unsigned char *data) // LogMessage("DMR Slot %u, received RF data header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId()); LogMessage("DMR Slot %u, received RF data header", m_slotNo); + } else if (dataType == DT_CSBK) { + CCSBK csbk(data + 2U); + + CSBKO csbko = csbk.getCSBKO(); + switch (csbko) { + case CSBKO_BSDWNACT: + return; + + case CSBKO_UUVREQ: + case CSBKO_UUANSRSP: + case CSBKO_NACKRSP: + case CSBKO_PRECCSBK: { + // Convert the Data Sync to be from the BS + CDMRSync sync; + sync.addSync(data + 2U, DST_BS_DATA); + + data[0U] = TAG_DATA; + data[1U] = 0x00U; + + m_seqNo = 0U; + + writeNetwork(data, DT_CSBK, FLCO_USER_USER, csbk.getSrcId(), csbk.getDstId()); + writeQueue(data); + } + break; + + default: + LogWarning("DMR Slot %u, unhandled CSBK type - 0x%02X", m_slotNo, csbko); + break; + } + + LogMessage("DMR Slot %u, received CSBK", m_slotNo); } else { // Regenerate the Slot Type slotType.getData(data + 2U); @@ -415,8 +443,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_bits = 1U; m_errs = 0U; - // 540ms of idle to give breathing space for lost frames - for (unsigned int i = 0U; i < 9U; i++) + // 120ms of idle to give breathing space for lost frames + for (unsigned int i = 0U; i < 2U; i++) writeQueue(m_idle); for (unsigned int i = 0U; i < 3U; i++) @@ -545,22 +573,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) } if (m_state == RS_RELAYING_NETWORK_AUDIO) { - // Initialise the lost packet data - if (m_frames == 0U) { - m_seqNo = dmrData.getSeqNo(); - m_n = dmrData.getN(); - m_elapsed.start(); - m_lost = 0U; - } else { - bool allow = insertSilence(dmrData); - if (!allow) - return; - } - - // Convert the Audio Sync to be from the BS - CDMRSync sync; - sync.addSync(data + 2U, DST_BS_AUDIO); - unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) m_errs += m_fec.regenerateDMR(data + 2U); @@ -569,6 +581,23 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) data[0U] = TAG_DATA; data[1U] = 0x00U; + // Initialise the lost packet data + if (m_frames == 0U) { + ::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U); + m_seqNo = dmrData.getSeqNo(); + m_n = dmrData.getN(); + m_elapsed.start(); + m_lost = 0U; + } else { + bool allow = insertSilence(data, dmrData.getSeqNo()); + if (!allow) + return; + } + + // Convert the Audio Sync to be from the BS + CDMRSync sync; + sync.addSync(data + 2U, DST_BS_AUDIO); + writeQueue(data); m_packetTimer.start(); @@ -586,32 +615,32 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) if (m_state != RS_RELAYING_NETWORK_AUDIO) return; - // Initialise the lost packet data - if (m_frames == 0U) { - m_seqNo = dmrData.getSeqNo(); - m_n = dmrData.getN(); - m_elapsed.start(); - m_lost = 0U; - } else { - bool allow = insertSilence(dmrData); - if (!allow) - return; - } - unsigned char fid = m_lc->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) m_errs += m_fec.regenerateDMR(data + 2U); m_bits += 216U; // Change the color code in the EMB - CEMB emb; - emb.putData(data + 2U); - emb.setColorCode(m_colorCode); - emb.getData(data + 2U); + m_lastEMB.putData(data + 2U); + m_lastEMB.setColorCode(m_colorCode); + m_lastEMB.getData(data + 2U); data[0U] = TAG_DATA; data[1U] = 0x00U; + // Initialise the lost packet data + if (m_frames == 0U) { + ::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U); + m_seqNo = dmrData.getSeqNo(); + m_n = dmrData.getN(); + m_elapsed.start(); + m_lost = 0U; + } else { + bool allow = insertSilence(data, dmrData.getSeqNo()); + if (!allow) + return; + } + writeQueue(data); m_packetTimer.start(); @@ -680,10 +709,9 @@ void CDMRSlot::clock(unsigned int ms) if (frames > m_frames) { unsigned int count = frames - m_frames; - if (count > 3U) { - count -= 1U; - LogMessage("DMR Slot %u, lost audio for 300ms filling in", m_slotNo); - insertSilence(m_seqNo + count); + if (count > 2U) { + LogMessage("DMR Slot %u, lost audio for 100ms filling in", m_slotNo); + insertSilence(count - 1U); } } @@ -704,9 +732,9 @@ void CDMRSlot::writeQueue(const unsigned char *data) m_queue.addData(data, len); } -void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType) +void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId) { - assert(m_lc != NULL); + assert(data != NULL); if (m_network == NULL) return; @@ -718,9 +746,9 @@ void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType) CDMRData dmrData; dmrData.setSlotNo(m_slotNo); dmrData.setDataType(dataType); - dmrData.setSrcId(m_lc->getSrcId()); - dmrData.setDstId(m_lc->getDstId()); - dmrData.setFLCO(m_lc->getFLCO()); + dmrData.setSrcId(srcId); + dmrData.setDstId(dstId); + dmrData.setFLCO(flco); dmrData.setN(m_n); dmrData.setSeqNo(m_seqNo); @@ -731,6 +759,14 @@ void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType) m_network->write(dmrData); } +void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType) +{ + assert(data != NULL); + assert(m_lc != NULL); + + writeNetwork(data, dataType, m_lc->getFLCO(), m_lc->getSrcId(), m_lc->getDstId()); +} + void CDMRSlot::init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display) { assert(modem != NULL); @@ -741,22 +777,15 @@ void CDMRSlot::init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* net m_network = network; m_display = display; - m_silence = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U]; m_idle = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memcpy(m_silence, DMR_SILENCE_DATA, DMR_FRAME_LENGTH_BYTES + 2U); - ::memcpy(m_idle, DMR_IDLE_DATA, DMR_FRAME_LENGTH_BYTES + 2U); + ::memcpy(m_idle, DMR_IDLE_DATA, DMR_FRAME_LENGTH_BYTES + 2U); // Generate the Slot Type for the Idle frame CSlotType slotType; slotType.setColorCode(colorCode); slotType.setDataType(DT_IDLE); slotType.getData(m_idle + 2U); - - // Generate the EMB for the silence frame - CEMB emb; - emb.setColorCode(colorCode); - emb.getData(m_silence + 2U); } void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco) @@ -863,10 +892,20 @@ void CDMRSlot::closeFile() } } -bool CDMRSlot::insertSilence(const CDMRData& dmrData) +bool CDMRSlot::insertSilence(const unsigned char* data, unsigned char seqNo) { - unsigned int oldSeqNo = m_seqNo; - unsigned int newSeqNo = dmrData.getSeqNo(); + assert(data != NULL); + + // Check to see if we have any spaces to fill? + unsigned char seq = m_seqNo + 1U; + if (seq == seqNo) { + // Just copy the data, nothing else to do here + ::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U); + return true; + } + + unsigned int oldSeqNo = m_seqNo + 1U; + unsigned int newSeqNo = seqNo; unsigned int count; if (newSeqNo > oldSeqNo) @@ -879,31 +918,29 @@ bool CDMRSlot::insertSilence(const CDMRData& dmrData) return false; } - insertSilence(dmrData.getSeqNo()); + insertSilence(count); - // Store frame for last frame here if needed + ::memcpy(m_lastFrame, data, DMR_FRAME_LENGTH_BYTES + 2U); return true; } -void CDMRSlot::insertSilence(unsigned char newSeqNo) +void CDMRSlot::insertSilence(unsigned int count) { - // Check to see if we have any spaces to fill - unsigned char seqNo = m_seqNo + 1U; - if (newSeqNo == seqNo) - return; - unsigned char n = (m_n + 1U) % 6U; + unsigned char seqNo = m_seqNo + 1U; - unsigned int count = 0U; - while (seqNo < newSeqNo) { + for (unsigned int i = 0U; i < count; i++) { unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memcpy(data, m_silence, DMR_FRAME_LENGTH_BYTES + 2U); + ::memcpy(data, m_lastFrame, DMR_FRAME_LENGTH_BYTES + 2U); if (n == 0U) { - // Replace the EMB and Null Short LC with a voice sync CDMRSync sync; sync.addSync(data + 2U, DST_BS_AUDIO); + } else { + // Color Code will have been set earlier + m_lastEMB.setLCSS(0U); + m_lastEMB.getData(data + 2U); } writeQueue(data); @@ -911,7 +948,6 @@ void CDMRSlot::insertSilence(unsigned char newSeqNo) m_seqNo = seqNo; m_n = n; - count++; m_frames++; m_lost++; diff --git a/DMRSlot.h b/DMRSlot.h index 58605c5..f60e84d 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -30,6 +30,7 @@ #include "Defines.h" #include "Timer.h" #include "Modem.h" +#include "EMB.h" #include "LC.h" class CDMRSlot { @@ -64,6 +65,8 @@ private: CAMBEFEC m_fec; unsigned int m_bits; unsigned int m_errs; + unsigned char* m_lastFrame; + CEMB m_lastEMB; FILE* m_fp; static unsigned int m_colorCode; @@ -72,7 +75,6 @@ private: static IDisplay* m_display; static unsigned char* m_idle; - static unsigned char* m_silence; static FLCO m_flco1; static unsigned char m_id1; @@ -81,6 +83,7 @@ private: void writeQueue(const unsigned char* data); void writeNetwork(const unsigned char* data, unsigned char dataType); + void writeNetwork(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId); void writeEndOfTransmission(); @@ -88,8 +91,8 @@ private: bool writeFile(const unsigned char* data); void closeFile(); - bool insertSilence(const CDMRData& dmrData); - void insertSilence(unsigned char seqNo); + bool insertSilence(const unsigned char* data, unsigned char seqNo); + void insertSilence(unsigned int count); static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP); }; diff --git a/Makefile b/Makefile index 6af2627..61c770e 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ Conf.o: Conf.cpp Conf.h Log.h CRC.o: CRC.cpp CRC.h Utils.h $(CC) $(CFLAGS) -c CRC.cpp -CSBK.o: CSBK.cpp CSBK.h Utils.h DMRDefines.h BPTC19696.h CRC.h Log.h +CSBK.o: CSBK.cpp CSBK.h Utils.h DMRDefines.h BPTC19696.h CRC.h $(CC) $(CFLAGS) -c CSBK.cpp Display.o: Display.cpp Display.h