From 9f47e6763053ab383f27819dff75aefc68c3e6c1 Mon Sep 17 00:00:00 2001 From: g4eml Date: Sun, 1 Jan 2017 14:22:49 +0000 Subject: [PATCH 1/3] Fix crash in DMR DMO Mode Modem was crashing on Teensy when running in DMO mode. Crashed as soon as Tx started. Traced to exceeding the bounds of m_poBuffer during the txdelay phase. m_poBuffer was dimensioned to 80 but m_txdelay could be 600 to 1200 so a massive overwrite was happening. Surprisingly this didn't crash on the Due only on the Teensy. --- DMRDMOTX.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRDMOTX.h b/DMRDMOTX.h index 3650d0d..d904ca6 100644 --- a/DMRDMOTX.h +++ b/DMRDMOTX.h @@ -41,7 +41,7 @@ private: CSerialRB m_fifo; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare - uint8_t m_poBuffer[80U]; + uint8_t m_poBuffer[1200U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; From 8777c2b29c99ab059211aff405382fea7656c708 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 3 Jan 2017 16:36:34 +0000 Subject: [PATCH 2/3] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 030f94c..053d010 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25. +This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25 modes. -It runs on the Arduino Due and the ST-Micro STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.5/3.6) is being added. +It runs on the Arduino Due, the ST-Micro STM32F407-DISCO and STM32F446-NUCLEO, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3 or M4 processor with a clock speed greater than 70 MHz, and access to at least one analogue to digital converter and one digital to analogue converter. A Cortex-M7 processor is also probably adequate. In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is being supplied via the Coocox IDE with ARM GCC. The Teensy support is via the latest beta of Teensyduino. From 57fde3afcccb52c401f912f30ff6c47c0cf89bf4 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 5 Jan 2017 18:59:15 +0000 Subject: [PATCH 3/3] Add RSSI reporting for all modes. --- DMRDMORX.cpp | 96 ++++++++++++++++++--------------------------------- DMRDMORX.h | 5 ++- DMRSlotRX.cpp | 89 +++++++++++++++-------------------------------- DMRSlotRX.h | 5 ++- DStarRX.cpp | 53 ++++++++++++++++++++-------- DStarRX.h | 12 ++++--- DStarTX.cpp | 4 +-- DStarTX.h | 4 +-- IO.cpp | 14 ++++---- IO.h | 4 +-- IODue.cpp | 8 ++--- IOSTM.cpp | 7 ++-- IOTeensy.cpp | 59 +++++++++++-------------------- P25RX.cpp | 21 ++++++++--- P25RX.h | 7 ++-- P25TX.h | 4 +-- YSFRX.cpp | 21 ++++++++--- YSFRX.h | 7 ++-- YSFTX.h | 4 +-- 19 files changed, 198 insertions(+), 226 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index df9e717..35028b8 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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,7 +59,6 @@ m_colorCode(0U), m_state(DMORXS_NONE), m_n(0U), m_type(0U), -m_rssiCount(0U), m_rssi() { } @@ -73,7 +72,6 @@ void CDMRDMORX::reset() m_state = DMORXS_NONE; m_startPtr = 0U; m_endPtr = NOENDPTR; - m_rssiCount = 0U; } void CDMRDMORX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) @@ -146,7 +144,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) switch (dataType) { case DT_DATA_HEADER: DEBUG4("DMRDMORX: data header found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMORXS_DATA; m_type = 0x00U; break; @@ -155,32 +153,32 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) case DT_RATE_1_DATA: if (m_state == DMORXS_DATA) { DEBUG4("DMRDMORX: data payload found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_type = dataType; } break; case DT_VOICE_LC_HEADER: DEBUG4("DMRDMORX: voice header found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMORXS_VOICE; break; case DT_VOICE_PI_HEADER: if (m_state == DMORXS_VOICE) { DEBUG4("DMRDMORX: voice pi header found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); } m_state = DMORXS_VOICE; break; case DT_TERMINATOR_WITH_LC: if (m_state == DMORXS_VOICE) { DEBUG4("DMRDMORX: voice terminator found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); reset(); } break; default: // DT_CSBK DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold); - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); reset(); break; } @@ -188,24 +186,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) } else if (m_control == CONTROL_VOICE) { // Voice sync DEBUG4("DMRDMORX: voice sync found pos/centre/threshold", m_syncPtr, centre, threshold); -#if defined(SEND_RSSI_DATA) - // Send RSSI data approximately every second - if (m_rssiCount == 2U) { - // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end - uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); - frame[34U] = (rssi_avg >> 8) & 0xFFU; - frame[35U] = (rssi_avg >> 0) & 0xFFU; - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); - } - - m_rssiCount++; - if (m_rssiCount >= 16U) - m_rssiCount = 0U; -#else - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); -#endif + writeRSSIData(frame); m_state = DMORXS_VOICE; m_syncCount = 0U; m_n = 0U; @@ -225,28 +206,12 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) } else { frame[0U] = ++m_n; } -#if defined(SEND_RSSI_DATA) - // Send RSSI data approximately every second - if (m_rssiCount == 2U) { - // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end - uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); - frame[34U] = (rssi_avg >> 8) & 0xFFU; - frame[35U] = (rssi_avg >> 0) & 0xFFU; - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); - } - - m_rssiCount++; - if (m_rssiCount >= 16U) - m_rssiCount = 0U; -#else + serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); -#endif } else if (m_state == DMORXS_DATA) { if (m_type != 0x00U) { frame[0U] = CONTROL_DATA | m_type; - serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); } } } @@ -337,7 +302,6 @@ void CDMRDMORX::correlateSync(bool first) m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold; m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; - m_rssiCount = 0U; } else { m_threshold[m_averagePtr] = threshold; m_centre[m_averagePtr] = centre; @@ -373,7 +337,6 @@ void CDMRDMORX::correlateSync(bool first) m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold; m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; - m_rssiCount = 0U; } else { m_threshold[m_averagePtr] = threshold; m_centre[m_averagePtr] = centre; @@ -400,21 +363,6 @@ void CDMRDMORX::correlateSync(bool first) } } -uint16_t CDMRDMORX::avgRSSI(uint16_t start, uint16_t count) -{ - float rssi_tmp = 0.0F; - - for (uint16_t i = 0U; i < count; i++) { - rssi_tmp += float(m_rssi[start]); - - start++; - if (start >= DMO_BUFFER_LENGTH_SAMPLES) - start -= DMO_BUFFER_LENGTH_SAMPLES; - } - - return uint16_t(rssi_tmp / count); -} - void CDMRDMORX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold) { for (uint8_t i = 0U; i < count; i++) { @@ -453,3 +401,27 @@ void CDMRDMORX::setColorCode(uint8_t colorCode) m_colorCode = colorCode; } +void CDMRDMORX::writeRSSIData(uint8_t* frame) +{ +#if defined(SEND_RSSI_DATA) + // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end + uint16_t start = m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U; + + uint32_t accum = 0U; + for (uint16_t i = 0U; i < (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); i++) { + accum += m_rssi[start]; + + start++; + if (start >= DMO_BUFFER_LENGTH_SAMPLES) + start -= DMO_BUFFER_LENGTH_SAMPLES; + } + + uint16_t avg = accum / (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); + frame[34U] = (avg >> 8) & 0xFFU; + frame[35U] = (avg >> 0) & 0xFFU; + + serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U); +#else + serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); +#endif +} diff --git a/DMRDMORX.h b/DMRDMORX.h index e342348..21de2cc 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.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 @@ -58,13 +58,12 @@ private: DMORX_STATE m_state; uint8_t m_n; uint8_t m_type; - uint16_t m_rssiCount; uint16_t m_rssi[DMO_BUFFER_LENGTH_SAMPLES]; bool processSample(q15_t sample, uint16_t rssi); void correlateSync(bool first); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); - uint16_t avgRSSI(uint16_t start, uint16_t count); + void writeRSSIData(uint8_t* frame); }; #endif diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 708d008..e8d7052 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -65,7 +65,6 @@ m_delay(0U), m_state(DMRRXS_NONE), m_n(0U), m_type(0U), -m_rssiCount(0U), m_rssi() { } @@ -91,7 +90,6 @@ void CDMRSlotRX::reset() m_state = DMRRXS_NONE; m_startPtr = 0U; m_endPtr = NOENDPTR; - m_rssiCount = 0U; } bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) @@ -149,7 +147,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) switch (dataType) { case DT_DATA_HEADER: DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMRRXS_DATA; m_type = 0x00U; break; @@ -158,33 +156,33 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) case DT_RATE_1_DATA: if (m_state == DMRRXS_DATA) { DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_type = dataType; } break; case DT_VOICE_LC_HEADER: DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMRRXS_VOICE; break; case DT_VOICE_PI_HEADER: if (m_state == DMRRXS_VOICE) { DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); } m_state = DMRRXS_VOICE; break; case DT_TERMINATOR_WITH_LC: if (m_state == DMRRXS_VOICE) { DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } break; default: // DT_CSBK DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; break; @@ -193,24 +191,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) } else if (m_control == CONTROL_VOICE) { // Voice sync DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); -#if defined(SEND_RSSI_DATA) - // Send RSSI data approximately every second - if (m_rssiCount == 2U) { - // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end - uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); - frame[34U] = (rssi_avg >> 8) & 0xFFU; - frame[35U] = (rssi_avg >> 0) & 0xFFU; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - } - - m_rssiCount++; - if (m_rssiCount >= 16U) - m_rssiCount = 0U; -#else - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); -#endif + writeRSSIData(frame); m_state = DMRRXS_VOICE; m_syncCount = 0U; m_n = 0U; @@ -231,28 +212,12 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) } else { frame[0U] = ++m_n; } -#if defined(SEND_RSSI_DATA) - // Send RSSI data approximately every second - if (m_rssiCount == 2U) { - // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end - uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); - frame[34U] = (rssi_avg >> 8) & 0xFFU; - frame[35U] = (rssi_avg >> 0) & 0xFFU; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - } - m_rssiCount++; - if (m_rssiCount >= 16U) - m_rssiCount = 0U; -#else serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); -#endif } else if (m_state == DMRRXS_DATA) { if (m_type != 0x00U) { frame[0U] = CONTROL_DATA | m_type; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(frame); } } } @@ -319,7 +284,6 @@ void CDMRSlotRX::correlateSync(bool first) m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold; m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; - m_rssiCount = 0U; } else { m_threshold[m_averagePtr] = threshold; m_centre[m_averagePtr] = centre; @@ -345,7 +309,6 @@ void CDMRSlotRX::correlateSync(bool first) m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold; m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre; m_averagePtr = 0U; - m_rssiCount = 0U; } else { m_threshold[m_averagePtr] = threshold; m_centre[m_averagePtr] = centre; @@ -366,21 +329,6 @@ void CDMRSlotRX::correlateSync(bool first) } } -uint16_t CDMRSlotRX::avgRSSI(uint16_t start, uint16_t count) -{ - float rssi_tmp = 0.0F; - - for (uint16_t i = 0U; i < count; i++) { - rssi_tmp += float(m_rssi[start]); - - start++; - if (start >= 900U) - start -= 900U; - } - - return uint16_t(rssi_tmp / count); -} - void CDMRSlotRX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold) { for (uint8_t i = 0U; i < count; i++, start += DMR_RADIO_SYMBOL_LENGTH) { @@ -420,3 +368,22 @@ void CDMRSlotRX::setDelay(uint8_t delay) m_delay = delay; } +void CDMRSlotRX::writeRSSIData(uint8_t* frame) +{ +#if defined(SEND_RSSI_DATA) + // Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end + uint16_t start = m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U; + + uint32_t accum = 0U; + for (uint16_t i = 0U; i < (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); i++) + accum += m_rssi[start++]; + + uint16_t avg = accum / (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); + frame[34U] = (avg >> 8) & 0xFFU; + frame[35U] = (avg >> 0) & 0xFFU; + + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U); +#else + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); +#endif +} diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 1a4376b..aab79ff 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.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 @@ -62,12 +62,11 @@ private: DMRRX_STATE m_state; uint8_t m_n; uint8_t m_type; - uint16_t m_rssiCount; uint16_t m_rssi[900U]; void correlateSync(bool first); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); - uint16_t avgRSSI(uint16_t start, uint16_t count); + void writeRSSIData(uint8_t* frame); }; #endif diff --git a/DStarRX.cpp b/DStarRX.cpp index 81268cb..c606c79 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -275,7 +275,7 @@ void CDStarRX::reset() m_samplesPtr = 0U; } -void CDStarRX::samples(const q15_t* samples, uint8_t length) +void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) { for (uint16_t i = 0U; i < length; i++) { m_samples[m_samplesPtr] = samples[i]; @@ -298,13 +298,13 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length) switch (m_rxState) { case DSRXS_NONE: - processNone(bit); + processNone(bit, rssi[i]); break; case DSRXS_HEADER: - processHeader(bit); + processHeader(bit, rssi[i]); break; case DSRXS_DATA: - processData(bit); + processData(bit, rssi[i]); break; default: break; @@ -317,7 +317,7 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length) } } -void CDStarRX::processNone(bool bit) +void CDStarRX::processNone(bool bit, uint16_t rssi) { m_patternBuffer <<= 1; if (bit) @@ -341,7 +341,8 @@ void CDStarRX::processNone(bool bit) io.setDecode(true); io.setADCDetection(true); - serial.writeDStarData(DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES); + ::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES); + writeRSSIData(m_rxBuffer, rssi); ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); m_rxBufferBits = 0U; @@ -352,7 +353,7 @@ void CDStarRX::processNone(bool bit) } } -void CDStarRX::processHeader(bool bit) +void CDStarRX::processHeader(bool bit, uint16_t rssi) { m_patternBuffer <<= 1; if (bit) @@ -370,7 +371,7 @@ void CDStarRX::processHeader(bool bit) io.setDecode(true); io.setADCDetection(true); - serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); + writeRSSIHeader(header, rssi); ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); m_rxBufferBits = 0U; @@ -384,7 +385,7 @@ void CDStarRX::processHeader(bool bit) } } -void CDStarRX::processData(bool bit) +void CDStarRX::processData(bool bit, uint16_t rssi) { m_patternBuffer <<= 1; if (bit) @@ -457,9 +458,10 @@ void CDStarRX::processData(bool bit) m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; - } - - serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); + writeRSSIData(m_rxBuffer, rssi); + } else { + serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); + } // Start the next frame ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); @@ -467,6 +469,30 @@ void CDStarRX::processData(bool bit) } } +void CDStarRX::writeRSSIHeader(unsigned char* header, uint16_t rssi) +{ +#if defined(SEND_RSSI_DATA) + header[41U] = (rssi >> 8) & 0xFFU; + header[42U] = (rssi >> 0) & 0xFFU; + + serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES + 2U); +#else + serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES + 0U); +#endif +} + +void CDStarRX::writeRSSIData(unsigned char* data, uint16_t rssi) +{ +#if defined(SEND_RSSI_DATA) + data[12U] = (rssi >> 8) & 0xFFU; + data[13U] = (rssi >> 0) & 0xFFU; + + serial.writeDStarData(data, DSTAR_DATA_LENGTH_BYTES + 2U); +#else + serial.writeDStarData(data, DSTAR_DATA_LENGTH_BYTES + 0U); +#endif +} + bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out) { int i; @@ -682,4 +708,3 @@ bool CDStarRX::checksum(const uint8_t* header) const return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U]; } - diff --git a/DStarRX.h b/DStarRX.h index dd63ed3..5154be7 100644 --- a/DStarRX.h +++ b/DStarRX.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 @@ -32,7 +32,7 @@ class CDStarRX { public: CDStarRX(); - void samples(const q15_t* samples, uint8_t length); + void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length); void reset(); @@ -54,9 +54,11 @@ private: q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS]; uint8_t m_samplesPtr; - void processNone(bool bit); - void processHeader(bool bit); - void processData(bool bit); + void processNone(bool bit, uint16_t rssi); + void processHeader(bool bit, uint16_t rssi); + void processData(bool bit, uint16_t rssi); + void writeRSSIHeader(unsigned char* header, uint16_t rssi); + void writeRSSIData(unsigned char* data, uint16_t rssi); bool rxHeader(uint8_t* in, uint8_t* out); void acs(int* metric); void viterbiDecode(int* data); diff --git a/DStarTX.cpp b/DStarTX.cpp index 03caa31..3e08aa9 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -457,7 +457,7 @@ void CDStarTX::writeByte(uint8_t c) void CDStarTX::setTXDelay(uint8_t delay) { - m_txDelay = 150U + uint16_t(delay) * 6U; // 250ms + tx delay + m_txDelay = 300U + uint16_t(delay) * 6U; // 250ms + tx delay } uint16_t CDStarTX::getSpace() const diff --git a/DStarTX.h b/DStarTX.h index 828974c..24bb7af 100644 --- a/DStarTX.h +++ b/DStarTX.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 @@ -41,7 +41,7 @@ private: CSerialRB m_buffer; arm_fir_instance_q15 m_modFilter; q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare - uint8_t m_poBuffer[500U]; + uint8_t m_poBuffer[600U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; // In bytes diff --git a/IO.cpp b/IO.cpp index 5da8eb1..61f4bd8 100644 --- a/IO.cpp +++ b/IO.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM * Copyright (C) 2016 by Colin Durbridge G4EML * @@ -184,7 +184,7 @@ void CIO::process() q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - dstarRX.samples(GMSKVals, blockSize); + dstarRX.samples(GMSKVals, rssi, blockSize); } if (m_dmrEnable || m_ysfEnable || m_p25Enable) { @@ -199,17 +199,17 @@ void CIO::process() } if (m_ysfEnable) - ysfRX.samples(C4FSKVals, blockSize); + ysfRX.samples(C4FSKVals, rssi, blockSize); if (m_p25Enable) - p25RX.samples(C4FSKVals, blockSize); + p25RX.samples(C4FSKVals, rssi, blockSize); } } else if (m_modemState == STATE_DSTAR) { if (m_dstarEnable) { q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - dstarRX.samples(GMSKVals, blockSize); + dstarRX.samples(GMSKVals, rssi, blockSize); } } else if (m_modemState == STATE_DMR) { if (m_dmrEnable) { @@ -231,14 +231,14 @@ void CIO::process() q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); - ysfRX.samples(C4FSKVals, blockSize); + ysfRX.samples(C4FSKVals, rssi, blockSize); } } else if (m_modemState == STATE_P25) { if (m_p25Enable) { q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); - p25RX.samples(C4FSKVals, blockSize); + p25RX.samples(C4FSKVals, rssi, blockSize); } } else if (m_modemState == STATE_DSTARCAL) { q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; diff --git a/IO.h b/IO.h index 357c04e..d1ec266 100644 --- a/IO.h +++ b/IO.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 @@ -40,7 +40,7 @@ public: void setADCDetection(bool detect); void setMode(); - void interrupt(uint8_t source); + void interrupt(); void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel); diff --git a/IODue.cpp b/IODue.cpp index ab71d46..8d1e034 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM * Copyright (C) 2016 by Colin Durbridge G4EML * @@ -77,7 +77,7 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { void ADC_Handler() { - io.interrupt(0U); + io.interrupt(); } } @@ -101,7 +101,7 @@ void CIO::initInt() void CIO::startInt() { if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg - io.interrupt(0U); + io.interrupt(); // Set up the ADC NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector @@ -164,7 +164,7 @@ void CIO::startInt() digitalWrite(PIN_LED, HIGH); } -void CIO::interrupt(uint8_t source) +void CIO::interrupt() { if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg uint8_t control = MARK_NONE; diff --git a/IOSTM.cpp b/IOSTM.cpp index bb27e20..b1bfad4 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016 by Andy Uribe CA6JAU + * Copyright (C) 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 @@ -213,7 +214,7 @@ extern "C" { void TIM2_IRQHandler() { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - io.interrupt(0U); + io.interrupt(); } } } @@ -280,7 +281,7 @@ void CIO::initInt() void CIO::startInt() { if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)) - io.interrupt(0U); + io.interrupt(); // Init the ADC GPIO_InitTypeDef GPIO_InitStruct; @@ -421,7 +422,7 @@ void CIO::startInt() GPIO_SetBits(PORT_LED, PIN_LED); } -void CIO::interrupt(uint8_t source) +void CIO::interrupt() { uint8_t control = MARK_NONE; uint16_t sample = DC_OFFSET; diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 8c22c77..3f4d9b9 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 by Jonathan Naylor G4KLX + * Copyright (C) 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 @@ -45,15 +45,8 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { void adc0_isr() { - io.interrupt(0U); + io.interrupt(); } - -#if defined(SEND_RSSI_DATA) - void adc1_isr() - { - io.interrupt(1U); - } -#endif } void CIO::initInt() @@ -116,7 +109,6 @@ void CIO::startInt() ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; - #endif #if defined(EXTERNAL_OSC) @@ -149,42 +141,33 @@ void CIO::startInt() digitalWrite(PIN_LED, HIGH); } -void CIO::interrupt(uint8_t source) +void CIO::interrupt() { - if (source == 0U) { // ADC0 - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; - m_txBuffer.get(sample, control); - *(int16_t *)&(DAC0_DAT0L) = sample; + m_txBuffer.get(sample, control); + *(int16_t *)&(DAC0_DAT0L) = sample; - if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - sample = ADC0_RA; - m_rxBuffer.put(sample, control); - } + if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { + sample = ADC0_RA; + m_rxBuffer.put(sample, control); + } #if defined(SEND_RSSI_DATA) - - if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - uint16_t rssi = ADC1_RA; - m_rssiBuffer.put(rssi); - } - else { - m_rssiBuffer.put(0U); - } - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; //start the next RSSI conversion - -#else - m_rssiBuffer.put(0U); -#endif - - - m_watchdog++; + if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { + uint16_t rssi = ADC1_RA; + m_rssiBuffer.put(rssi); + } else { + m_rssiBuffer.put(0U); } + ADC1_SC1A = PIN_RSSI; // Start the next RSSI conversion +#else + m_rssiBuffer.put(0U); +#endif - - + m_watchdog++; } bool CIO::getCOSInt() diff --git a/P25RX.cpp b/P25RX.cpp index bb7ad25..071910a 100644 --- a/P25RX.cpp +++ b/P25RX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 by Jonathan Naylor G4KLX + * Copyright (C) 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 @@ -73,7 +73,7 @@ void CP25RX::reset() m_threshold = 0; } -void CP25RX::samples(const q15_t* samples, uint8_t length) +void CP25RX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) { for (uint16_t i = 0U; i < length; i++) { bool bit = samples[i] < 0; @@ -95,7 +95,7 @@ void CP25RX::samples(const q15_t* samples, uint8_t length) if (m_state == P25RXS_NONE) processNone(samples[i]); else - processData(samples[i]); + processData(samples[i], rssi[i]); } } } @@ -173,7 +173,7 @@ void CP25RX::processNone(q15_t sample) m_symbolPtr = 0U; } -void CP25RX::processData(q15_t sample) +void CP25RX::processData(q15_t sample, uint16_t rssi) { sample -= m_centre; @@ -251,7 +251,7 @@ void CP25RX::processData(q15_t sample) } else { m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; - serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U); + writeRSSILdu(m_outBuffer, rssi); // Start the next frame ::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U); @@ -260,3 +260,14 @@ void CP25RX::processData(q15_t sample) } } +void CP25RX::writeRSSILdu(uint8_t* ldu, uint16_t rssi) +{ +#if defined(SEND_RSSI_DATA) + ldu[216U] = (rssi >> 8) & 0xFFU; + ldu[217U] = (rssi >> 0) & 0xFFU; + + serial.writeP25Ldu(ldu, P25_LDU_FRAME_LENGTH_BYTES + 3U); +#else + serial.writeP25Ldu(ldu, P25_LDU_FRAME_LENGTH_BYTES + 1U); +#endif +} diff --git a/P25RX.h b/P25RX.h index 691763d..f68fe93 100644 --- a/P25RX.h +++ b/P25RX.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 @@ -31,7 +31,7 @@ class CP25RX { public: CP25RX(); - void samples(const q15_t* samples, uint8_t length); + void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length); void reset(); @@ -51,7 +51,8 @@ private: q15_t m_threshold; void processNone(q15_t sample); - void processData(q15_t sample); + void processData(q15_t sample, uint16_t rssi); + void writeRSSILdu(uint8_t* data, uint16_t rssi); }; #endif diff --git a/P25TX.h b/P25TX.h index bbe6393..4340d35 100644 --- a/P25TX.h +++ b/P25TX.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 by Jonathan Naylor G4KLX + * Copyright (C) 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 @@ -41,7 +41,7 @@ private: arm_fir_instance_q15 m_lpFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare q15_t m_lpState[70U]; // NoTaps + BlockSize - 1, 44 + 20 - 1 plus some spare - uint8_t m_poBuffer[920U]; + uint8_t m_poBuffer[1200U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; diff --git a/YSFRX.cpp b/YSFRX.cpp index cfe4fab..cb54e23 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -73,7 +73,7 @@ void CYSFRX::reset() m_threshold = 0; } -void CYSFRX::samples(const q15_t* samples, uint8_t length) +void CYSFRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) { for (uint16_t i = 0U; i < length; i++) { bool bit = samples[i] < 0; @@ -95,7 +95,7 @@ void CYSFRX::samples(const q15_t* samples, uint8_t length) if (m_state == YSFRXS_NONE) processNone(samples[i]); else - processData(samples[i]); + processData(samples[i], rssi[i]); } } } @@ -173,7 +173,7 @@ void CYSFRX::processNone(q15_t sample) m_symbolPtr = 0U; } -void CYSFRX::processData(q15_t sample) +void CYSFRX::processData(q15_t sample, uint16_t rssi) { sample -= m_centre; @@ -233,7 +233,7 @@ void CYSFRX::processData(q15_t sample) } else { m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; - serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); + writeRSSIData(m_outBuffer, rssi); // Start the next frame ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); @@ -242,3 +242,14 @@ void CYSFRX::processData(q15_t sample) } } +void CYSFRX::writeRSSIData(uint8_t* data, uint16_t rssi) +{ +#if defined(SEND_RSSI_DATA) + data[120U] = (rssi >> 8) & 0xFFU; + data[121U] = (rssi >> 0) & 0xFFU; + + serial.writeYSFData(data, YSF_FRAME_LENGTH_BYTES + 3U); +#else + serial.writeYSFData(data, YSF_FRAME_LENGTH_BYTES + 1U); +#endif +} diff --git a/YSFRX.h b/YSFRX.h index 8f8f770..5f18993 100644 --- a/YSFRX.h +++ b/YSFRX.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 @@ -31,7 +31,7 @@ class CYSFRX { public: CYSFRX(); - void samples(const q15_t* samples, uint8_t length); + void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length); void reset(); @@ -51,7 +51,8 @@ private: q15_t m_threshold; void processNone(q15_t sample); - void processData(q15_t sample); + void processData(q15_t sample, uint16_t rssi); + void writeRSSIData(unsigned char* data, uint16_t rssi); }; #endif diff --git a/YSFTX.h b/YSFTX.h index 309cacc..21fcabc 100644 --- a/YSFTX.h +++ b/YSFTX.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 @@ -39,7 +39,7 @@ private: CSerialRB m_buffer; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare - uint8_t m_poBuffer[920U]; + uint8_t m_poBuffer[1200U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay;