From 656be113f5ef3eb2d2b41db7ad199637ecd4fad2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 15 Feb 2016 18:01:21 +0000 Subject: [PATCH] Allow half-duplex DMR for use with hotspot hardware. --- DMRControl.cpp | 4 +-- DMRControl.h | 2 +- DMRSlot.cpp | 93 ++++++++++++++++++++++++++++++++------------------ DMRSlot.h | 3 +- MMDVMHost.cpp | 8 ++--- 5 files changed, 67 insertions(+), 43 deletions(-) diff --git a/DMRControl.cpp b/DMRControl.cpp index 0909223..65d49fd 100644 --- a/DMRControl.cpp +++ b/DMRControl.cpp @@ -18,7 +18,7 @@ #include -CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int timeout, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display) : +CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int timeout, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display, bool duplex) : m_id(id), m_colorCode(colorCode), m_modem(modem), @@ -29,7 +29,7 @@ m_slot2(2U, timeout) assert(modem != NULL); assert(display != NULL); - CDMRSlot::init(colorCode, modem, network, display); + CDMRSlot::init(colorCode, modem, network, display, duplex); } CDMRControl::~CDMRControl() diff --git a/DMRControl.h b/DMRControl.h index bc33e69..440140c 100644 --- a/DMRControl.h +++ b/DMRControl.h @@ -28,7 +28,7 @@ class CDMRControl { public: - CDMRControl(unsigned int id, unsigned int colorCode, unsigned int timeout, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display); + CDMRControl(unsigned int id, unsigned int colorCode, unsigned int timeout, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display, bool duplex); ~CDMRControl(); bool processWakeup(const unsigned char* data); diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 75d5f14..84aa677 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -29,6 +29,7 @@ unsigned int CDMRSlot::m_colorCode = 0U; CModem* CDMRSlot::m_modem = NULL; CHomebrewDMRIPSC* CDMRSlot::m_network = NULL; IDisplay* CDMRSlot::m_display = NULL; +bool CDMRSlot::m_duplex = true; unsigned char* CDMRSlot::m_idle = NULL; @@ -132,11 +133,14 @@ void CDMRSlot::writeModem(unsigned char *data) m_bits = 1U; m_errs = 0U; - for (unsigned i = 0U; i < 3U; i++) { - writeNetwork(data, DT_VOICE_LC_HEADER); - writeQueue(data); + if (m_duplex) { + for (unsigned i = 0U; i < 3U; i++) + writeQueue(data); } + for (unsigned i = 0U; i < 3U; i++) + writeNetwork(data, DT_VOICE_LC_HEADER); + m_state = RS_RELAYING_RF_AUDIO; setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO(), true); @@ -160,8 +164,10 @@ void CDMRSlot::writeModem(unsigned char *data) m_n = 0U; + if (m_duplex) + writeQueue(data); + writeNetwork(data, DT_VOICE_PI_HEADER); - writeQueue(data); } else if (dataType == DT_TERMINATOR_WITH_LC) { if (m_state != RS_RELAYING_RF_AUDIO) return; @@ -180,8 +186,10 @@ void CDMRSlot::writeModem(unsigned char *data) writeNetwork(data, DT_TERMINATOR_WITH_LC); // 480ms of terminator to space things out - for (unsigned int i = 0U; i < 8U; i++) - writeQueue(data); + if (m_duplex) { + for (unsigned int i = 0U; i < 8U; i++) + writeQueue(data); + } if (m_bits == 0U) m_bits = 1U; LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, float(m_errs * 100U) / float(m_bits)); @@ -220,11 +228,14 @@ void CDMRSlot::writeModem(unsigned char *data) m_seqNo = 0U; m_n = 0U; - for (unsigned i = 0U; i < 3U; i++) { - writeNetwork(data, DT_DATA_HEADER); - writeQueue(data); + if (m_duplex) { + for (unsigned i = 0U; i < 3U; i++) + writeQueue(data); } + for (unsigned i = 0U; i < 3U; i++) + writeNetwork(data, DT_DATA_HEADER); + m_state = RS_RELAYING_RF_DATA; setShortLC(m_slotNo, m_lc->getDstId(), gi ? FLCO_GROUP : FLCO_USER_USER, false); @@ -260,8 +271,10 @@ void CDMRSlot::writeModem(unsigned char *data) m_seqNo = 0U; + if (m_duplex) + writeQueue(data); + writeNetwork(data, DT_CSBK, FLCO_USER_USER, csbk.getSrcId(), csbk.getDstId()); - writeQueue(data); LogMessage("DMR Slot %u, received RF CSBK from %u to %u", m_slotNo, csbk.getSrcId(), csbk.getDstId()); } @@ -287,8 +300,10 @@ void CDMRSlot::writeModem(unsigned char *data) data[0U] = m_frames == 0U ? TAG_EOT : TAG_DATA; data[1U] = 0x00U; + if (m_duplex) + writeQueue(data); + writeNetwork(data, dataType); - writeQueue(data); if (m_frames == 0U) { LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo); @@ -314,7 +329,9 @@ void CDMRSlot::writeModem(unsigned char *data) m_n = 0U; - writeQueue(data); + if (m_duplex) + writeQueue(data); + writeNetwork(data, DT_VOICE_SYNC); } else if (m_state == RS_LISTENING) { m_state = RS_LATE_ENTRY; @@ -338,7 +355,9 @@ void CDMRSlot::writeModem(unsigned char *data) m_n++; - writeQueue(data); + if (m_duplex) + writeQueue(data); + writeNetwork(data, DT_VOICE); } else if (m_state == RS_LATE_ENTRY) { // If we haven't received an LC yet, then be strict on the color code @@ -374,11 +393,14 @@ void CDMRSlot::writeModem(unsigned char *data) m_bits = 1U; m_errs = 0U; - for (unsigned int i = 0U; i < 3U; i++) { - writeNetwork(start, DT_VOICE_LC_HEADER); - writeQueue(start); + if (m_duplex) { + for (unsigned int i = 0U; i < 3U; i++) + writeQueue(start); } + for (unsigned int i = 0U; i < 3U; i++) + writeNetwork(start, DT_VOICE_LC_HEADER); + // Regenerate the EMB emb.getData(data + 2U); @@ -393,7 +415,9 @@ void CDMRSlot::writeModem(unsigned char *data) m_n++; - writeQueue(data); + if (m_duplex) + writeQueue(data); + writeNetwork(data, DT_VOICE); m_state = RS_RELAYING_RF_AUDIO; @@ -440,26 +464,28 @@ void CDMRSlot::writeEndOfTransmission(bool writeEnd) m_bits = 0U; if (writeEnd) { - // Create a dummy start end frame - unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U]; + if (m_state == RS_RELAYING_NETWORK_AUDIO || (m_state == RS_RELAYING_RF_AUDIO && m_duplex)) { + // Create a dummy start end frame + unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U]; - CDMRSync sync; - sync.addDataSync(data + 2U); + CDMRSync sync; + sync.addDataSync(data + 2U); - CFullLC fullLC; - fullLC.encode(*m_lc, data + 2U, DT_TERMINATOR_WITH_LC); + CFullLC fullLC; + fullLC.encode(*m_lc, data + 2U, DT_TERMINATOR_WITH_LC); - CSlotType slotType; - slotType.setColorCode(m_colorCode); - slotType.setDataType(DT_TERMINATOR_WITH_LC); - slotType.getData(data + 2U); + CSlotType slotType; + slotType.setColorCode(m_colorCode); + slotType.setDataType(DT_TERMINATOR_WITH_LC); + slotType.getData(data + 2U); - data[0U] = TAG_DATA; - data[1U] = 0x00U; + data[0U] = TAG_DATA; + data[1U] = 0x00U; - // 480ms of terminator to space things out - for (unsigned int i = 0U; i < 8U; i++) - writeQueue(data); + // 480ms of terminator to space things out + for (unsigned int i = 0U; i < 8U; i++) + writeQueue(data); + } } delete m_lc; @@ -904,7 +930,7 @@ void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType) writeNetwork(data, dataType, m_lc->getFLCO(), m_lc->getSrcId(), m_lc->getDstId()); } -void CDMRSlot::init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display) +void CDMRSlot::init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display, bool duplex) { assert(modem != NULL); assert(display != NULL); @@ -913,6 +939,7 @@ void CDMRSlot::init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* net m_modem = modem; m_network = network; m_display = display; + m_duplex = duplex; m_idle = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U]; diff --git a/DMRSlot.h b/DMRSlot.h index 3843ee4..a80fa0e 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -46,7 +46,7 @@ public: void clock(unsigned int ms); - static void init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display); + static void init(unsigned int colorCode, CModem* modem, CHomebrewDMRIPSC* network, IDisplay* display, bool duplex); private: unsigned int m_slotNo; @@ -73,6 +73,7 @@ private: static CModem* m_modem; static CHomebrewDMRIPSC* m_network; static IDisplay* m_display; + static bool m_duplex; static unsigned char* m_idle; diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index a2621b4..0f2ef98 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -156,13 +156,14 @@ int CMMDVMHost::run() unsigned int id = m_conf.getDMRId(); unsigned int colorCode = m_conf.getDMRColorCode(); unsigned int timeout = m_conf.getTimeout(); + bool duplex = m_conf.getDuplex(); LogInfo("DMR Parameters"); LogInfo(" Id: %u", id); LogInfo(" Color Code: %u", colorCode); LogInfo(" Timeout: %us", timeout); - dmr = new CDMRControl(id, colorCode, timeout, m_modem, m_dmrNetwork, m_display); + dmr = new CDMRControl(id, colorCode, timeout, m_modem, m_dmrNetwork, m_display, duplex); } CYSFEcho* ysf = NULL; @@ -490,11 +491,6 @@ void CMMDVMHost::readParams() m_dstarEnabled = m_conf.getDStarEnabled(); m_dmrEnabled = m_conf.getDMREnabled(); m_ysfEnabled = m_conf.getFusionEnabled(); - - if (!m_conf.getDuplex() && m_dmrEnabled) { - LogWarning("DMR operation disabled because system is not duplex"); - m_dmrEnabled = false; - } } void CMMDVMHost::createDisplay()