From 0683b0ddc4b3c62e7ad8b213b6d2fc7845a1703c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 1 Mar 2016 07:30:00 +0000 Subject: [PATCH 001/329] Make the new ZUM board the default type. --- Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Config.h b/Config.h index 560dc0d..fd01960 100644 --- a/Config.h +++ b/Config.h @@ -22,10 +22,10 @@ // #define WANT_DEBUG // For the original Arduino Due pin layout -#define ARDUINO_DUE_PAPA +// #define ARDUINO_DUE_PAPA // For the new Arduino Due pin layout -// #define ARDUINO_DUE_ZUM +#define ARDUINO_DUE_ZUM // For the SP8NTH board // #define ARDUINO_DUE_NTH From 4971605151086c762c93fc34a1679cf1e2da9a1c Mon Sep 17 00:00:00 2001 From: George Smart Date: Tue, 1 Mar 2016 15:40:35 +0000 Subject: [PATCH 002/329] Updated BUILD.txt for Linux Updated with Linux information tested on Ubuntu. Had to install sam-1.6.6 myself, download from ttp://downloads.arduino.cc/cores/sam-1.6.6.tar.bz2 and extract to arduino-1.6.7/hardware/arduino/ Modify platform.txt as with Windows/OSX, but path changes slightly from ARM to GCC: "{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" --- BUILD.txt | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/BUILD.txt b/BUILD.txt index 6975edb..2f95bd1 100644 --- a/BUILD.txt +++ b/BUILD.txt @@ -58,8 +58,18 @@ On Mac OS X it's located in: /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam -2. You'll need to open the file in a text editor and find the line: +On Linux, it's located in my home directory, downloaded and extracted from Arduino website, but must be installed. +/home/m1geo/arduino-1.6.7/hardware/arduino/sam + + I (M1GEO) found it was necessary to download SAM-1.6.6 outside of the Arduino IDE, and manually extract the files. + The Board Manager didn't seem to install the SAM files correctly. Here's how I did it: + + a) wget http://downloads.arduino.cc/cores/sam-1.6.6.tar.bz2 -O /tmp/sam-1.6.6.tar.bz2 (download and save in /tmp) + b) cd arduino-1.6.7/hardware/arduino/ (Arduino root, here, in my home directory) + c) tar xvfj /tmp/sam-1.6.6.tar.bz2 + +2. You'll need to open the file in a text editor and find the line: ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc @@ -68,7 +78,6 @@ In my version it's line 73. 3. Modify it to read as follows: - ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc @@ -76,15 +85,10 @@ The change is near the end, and is the addition of: "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" +On Linux, the path was found to differ slightly (GCC instead of ARM): + +"{build.system.path}/CMSIS/CMSIS/Lib/GCC/arm_cortexM3l_math.lib" + Which is the CMSIS AMR3 DSP library for little-endian operation. 4. Save the file and start up the Arduino GUI and build MMDVM. - -I would like to get instructions for doing the same on a Linux platform. As a -starter find the relevent platform.txt and try adding: - -"{build.system.path}/CMSIS/CMSIS/Lib/ARM/libarm_cortexM3l_math.a" - -or maybe: - -"{build.variant.path}/libarm_cortexM3l_math.a" From 0564372a43a017d21151ab428b28d1c35faf4932 Mon Sep 17 00:00:00 2001 From: George Smart Date: Tue, 1 Mar 2016 15:54:32 +0000 Subject: [PATCH 003/329] Updated BUILD.txt for Linux Fixed typo; added note in "For Arduino 1.6.3 with SAM 1.6.4" referring to "For Arduino 1.6.7 with SAM 1.6.6" section. --- BUILD.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/BUILD.txt b/BUILD.txt index 2f95bd1..b9dc4e0 100644 --- a/BUILD.txt +++ b/BUILD.txt @@ -46,6 +46,13 @@ or maybe: "{build.variant.path}/libarm_cortexM3l_math.a" +Likely on Linux + +"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" + +As with Arduino 1.6.7 with SAM 1.6.6, see below. + + For Arduino 1.6.7 with SAM 1.6.6 -------------------------------- @@ -87,7 +94,7 @@ The change is near the end, and is the addition of: On Linux, the path was found to differ slightly (GCC instead of ARM): -"{build.system.path}/CMSIS/CMSIS/Lib/GCC/arm_cortexM3l_math.lib" +"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" Which is the CMSIS AMR3 DSP library for little-endian operation. From 7258bf34fb5e44341f59622e2760e39de0a9cd51 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 17:15:07 +0000 Subject: [PATCH 004/329] Remove the minimal Teensy support. --- Globals.h | 2 +- IO.cpp | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/Globals.h b/Globals.h index ccb4cd0..8a7509e 100644 --- a/Globals.h +++ b/Globals.h @@ -27,7 +27,7 @@ #if defined(__SAM3X8E__) || defined(__STM32F1__) || defined(__STM32F2__) #define ARM_MATH_CM3 -#elif defined(__MK20DX256__) || defined(__STM32F3__) || defined(__STM32F4__) +#elif defined(__STM32F3__) || defined(__STM32F4__) #define ARM_MATH_CM4 #else #error "Unknown processor type" diff --git a/IO.cpp b/IO.cpp index 6953d3a..65300a5 100644 --- a/IO.cpp +++ b/IO.cpp @@ -67,11 +67,6 @@ const uint16_t RX_BUFFER_SIZE = 601U; #else #error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM, or ARDUINO_DUE_NTH need to be defined" #endif -#elif defined(__MK20DX256__) -// A Teensy 3.1/3.2 -#define PIN_COS 14 -#define PIN_PTT 15 -#define PIN_COSLED 13 #elif defined(__MBED__) // A generic MBED platform #define PIN_COS PC_1 @@ -89,7 +84,6 @@ extern "C" { #if defined(__SAM3X8E__) if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg io.interrupt(); -#elif defined(__MK20DX256__) #elif defined(__MBED__) io.interrupt(); #endif @@ -187,10 +181,6 @@ void CIO::start() DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel - digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); - digitalWrite(PIN_COSLED, LOW); - digitalWrite(PIN_LED, HIGH); -#elif defined(__MK20DX256__) digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); @@ -363,7 +353,6 @@ void CIO::interrupt() #if defined(__SAM3X8E__) DACC->DACC_CDR = sample; sample = ADC->ADC_CDR[ADC_CDR_Chan]; -#elif defined(__MK20DX256__) #elif defined(__MBED__) m_pinDAC.write_u16(sample); sample = m_pinADC.read_u16(); @@ -379,7 +368,7 @@ void CIO::setDecode(bool dcd) if (dcd != m_dcd) #if defined(__MBED__) m_pinCOSLED.write(dcd ? 1 : 0); -#elif defined(PIN_COSLED) +#else digitalWrite(PIN_COSLED, dcd ? HIGH : LOW); #endif From e7334a2d7a6d19efc24461b45312abe302a9b9d6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 17:49:03 +0000 Subject: [PATCH 005/329] Add lockout functionality with the option to use the COS line. --- Config.h | 3 +++ IO.cpp | 34 +++++++++++++++++++++++++++++++++- IO.h | 5 +++++ SerialPort.cpp | 5 ++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Config.h b/Config.h index fd01960..9189105 100644 --- a/Config.h +++ b/Config.h @@ -21,6 +21,9 @@ // #define WANT_DEBUG +// Allow the use of the COS line to lockout the modem +// #define USE_COS_AS_LOCKOUT + // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA diff --git a/IO.cpp b/IO.cpp index 65300a5..5ed3cdf 100644 --- a/IO.cpp +++ b/IO.cpp @@ -95,6 +95,7 @@ CIO::CIO() : m_pinPTT(PIN_PTT), m_pinCOSLED(PIN_COSLED), m_pinLED(LED1), +m_pinCOS(PIN_COS), m_pinADC(PIN_ADC), m_pinDAC(PIN_DAC), m_ticker(), @@ -114,7 +115,8 @@ m_ledValue(true), m_dcd(false), m_overflow(0U), m_overcount(0U), -m_watchdog(0U) +m_watchdog(0U), +m_lockout(false) { ::memset(m_C4FSKState, 0x00U, 70U * sizeof(q15_t)); ::memset(m_GMSKState, 0x00U, 40U * sizeof(q15_t)); @@ -132,6 +134,7 @@ m_watchdog(0U) pinMode(PIN_PTT, OUTPUT); pinMode(PIN_COSLED, OUTPUT); pinMode(PIN_LED, OUTPUT); + pinMode(PIN_COS, INPUT); #endif } @@ -232,6 +235,14 @@ void CIO::process() return; } +#if defined(USE_COS_AS_LOCKOUT) +#if defined(__MBED__) + m_lockout = m_pinCOS.read() == 1; +#else + m_lockout = digitalRead(PIN_COS) == HIGH; +#endif +#endif + // Switch off the transmitter if needed if (m_txBuffer.getData() == 0U && m_tx) { m_tx = false; @@ -242,6 +253,19 @@ void CIO::process() #endif } + if (m_lockout) { + // Drain the receive queue + if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + uint16_t sample; + uint8_t control; + m_rxBuffer.get(sample, control); + } + } + + return; + } + if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { q15_t samples[RX_BLOCK_SIZE]; uint8_t control[RX_BLOCK_SIZE]; @@ -317,6 +341,9 @@ void CIO::write(q15_t* samples, uint16_t length, const uint8_t* control) if (!m_started) return; + if (m_lockout) + return; + // Switch the transmitter on if needed if (!m_tx) { m_tx = true; @@ -419,3 +446,8 @@ void CIO::resetWatchdog() m_watchdog = 0U; } +bool CIO::hasLockout() const +{ + return m_lockout; +} + diff --git a/IO.h b/IO.h index 2ac77fd..962f6f4 100644 --- a/IO.h +++ b/IO.h @@ -46,6 +46,8 @@ public: bool hasTXOverflow(); bool hasRXOverflow(); + bool hasLockout() const; + void resetWatchdog(); private: @@ -53,6 +55,7 @@ private: DigitalOut m_pinPTT; DigitalOut m_pinCOSLED; DigitalOut m_pinLED; + DigitalIn m_pinCOS; AnalogIn m_pinADC; AnalogOut m_pinDAC; @@ -83,6 +86,8 @@ private: uint16_t m_overcount; volatile uint32_t m_watchdog; + + bool m_lockout; }; #endif diff --git a/SerialPort.cpp b/SerialPort.cpp index 251de85..f9bb4a2 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160229 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160303 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; @@ -129,6 +129,9 @@ void CSerialPort::getStatus() const if (io.hasTXOverflow()) reply[5U] |= 0x08U; + if (io.hasLockout()) + reply[5U] |= 0x10U; + if (m_dstarEnable) reply[6U] = dstarTX.getSpace(); else From 19fd226e2b813f4c1a44326dc30186d94374738c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 18:08:25 +0000 Subject: [PATCH 006/329] MBED changes from Mathis Schmieder DB9MAT. --- IO.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/IO.cpp b/IO.cpp index 5ed3cdf..51029ab 100644 --- a/IO.cpp +++ b/IO.cpp @@ -69,11 +69,11 @@ const uint16_t RX_BUFFER_SIZE = 601U; #endif #elif defined(__MBED__) // A generic MBED platform -#define PIN_COS PC_1 -#define PIN_PTT PA_1 -#define PIN_COSLED PB_0 -#define PIN_ADC PA_0 -#define PIN_DAC PA_2 +#define PIN_COS PB_4 // D5 +#define PIN_PTT PA_8 // D7 +#define PIN_COSLED PB_10 // D6 +#define PIN_ADC PA_0 // A0 +#define PIN_DAC PA_4 // A2 #else #error "Unknown hardware type" #endif From 28c065ffcb0893069caed294c830b71f1bc8e76f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 18:15:13 +0000 Subject: [PATCH 007/329] The MBED main MMDVM function. --- MMDVM.cpp | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 MMDVM.cpp diff --git a/MMDVM.cpp b/MMDVM.cpp new file mode 100644 index 0000000..134e949 --- /dev/null +++ b/MMDVM.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Mathis Schmieder DB9MAT + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(__MBED__) + +#include "Config.h" +#include "Globals.h" + +// Global variables +MMDVM_STATE m_modemState = STATE_IDLE; + +bool m_dstarEnable = true; +bool m_dmrEnable = true; +bool m_ysfEnable = true; + +bool m_tx = false; + +CDStarRX dstarRX; +CDStarTX dstarTX; + +CDMRIdleRX dmrIdleRX; +CDMRRX dmrRX; +CDMRTX dmrTX; + +CYSFRX ysfRX; +CYSFTX ysfTX; + +CCalRX calRX; +CCalTX calTX; + +CSerialPort serial; +CIO io; + +void setup() +{ + serial.start(); +} + +void loop() +{ + serial.process(); + + io.process(); + + // The following is for transmitting + if (m_dstarEnable && m_modemState == STATE_DSTAR) + dstarTX.process(); + + if (m_dmrEnable && m_modemState == STATE_DMR) + dmrTX.process(); + + if (m_ysfEnable && m_modemState == STATE_YSF) + ysfTX.process(); + + if (m_modemState == STATE_CALIBRATE) + calTX.process(); +} + +int main() +{ + setup(); + + for (;;) + loop(); +} + +#endif + From 6bf70a95953b9b3ea17b2af5f6b98a70057ae801 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 18:34:47 +0000 Subject: [PATCH 008/329] A cleaner lockout mechanism on receive. --- IO.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/IO.cpp b/IO.cpp index 51029ab..42cedb6 100644 --- a/IO.cpp +++ b/IO.cpp @@ -253,19 +253,6 @@ void CIO::process() #endif } - if (m_lockout) { - // Drain the receive queue - if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { - for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { - uint16_t sample; - uint8_t control; - m_rxBuffer.get(sample, control); - } - } - - return; - } - if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { q15_t samples[RX_BLOCK_SIZE]; uint8_t control[RX_BLOCK_SIZE]; @@ -284,6 +271,9 @@ void CIO::process() samples[i] = q15_t(__SSAT((res2 >> 15), 16)); } + if (m_lockout) + return; + if (m_modemState == STATE_IDLE) { if (m_dstarEnable) { q15_t GMSKVals[RX_BLOCK_SIZE]; From 1e7b5a7951cd61250699702ccf84e05233a0e10c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Mar 2016 19:02:19 +0000 Subject: [PATCH 009/329] Remove const's for MBED. --- SerialPort.cpp | 10 +++++----- SerialPort.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index f9bb4a2..e9c4fc1 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -72,7 +72,7 @@ m_len(0U) { } -void CSerialPort::sendACK() const +void CSerialPort::sendACK() { uint8_t reply[4U]; @@ -84,7 +84,7 @@ void CSerialPort::sendACK() const write(reply, 4); } -void CSerialPort::sendNAK(uint8_t err) const +void CSerialPort::sendNAK(uint8_t err) { uint8_t reply[5U]; @@ -97,7 +97,7 @@ void CSerialPort::sendNAK(uint8_t err) const write(reply, 5); } -void CSerialPort::getStatus() const +void CSerialPort::getStatus() { io.resetWatchdog(); @@ -153,7 +153,7 @@ void CSerialPort::getStatus() const write(reply, 10); } -void CSerialPort::getVersion() const +void CSerialPort::getVersion() { uint8_t reply[100U]; @@ -676,7 +676,7 @@ void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) write(reply, count); } -void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) const +void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) { #if defined(__MBED__) for (uint16_t i = 0U; i < length; i++) diff --git a/SerialPort.h b/SerialPort.h index 850799a..0d8ce7c 100644 --- a/SerialPort.h +++ b/SerialPort.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 @@ -63,13 +63,13 @@ private: uint8_t m_ptr; uint8_t m_len; - void sendACK() const; - void sendNAK(uint8_t err) const; - void getStatus() const; - void getVersion() const; + void sendACK(); + void sendNAK(uint8_t err); + void getStatus(); + void getVersion(); uint8_t setConfig(const uint8_t* data, uint8_t length); uint8_t setMode(const uint8_t* data, uint8_t length); - void write(const uint8_t* data, uint16_t length, bool flush = false) const; + void write(const uint8_t* data, uint16_t length, bool flush = false); void setMode(MMDVM_STATE modemState); }; From 8bb07f62bd5c9a552e7764a914e618e02eea64f9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Mar 2016 18:17:26 +0000 Subject: [PATCH 010/329] Add sync location debugging messages. --- Config.h | 6 +++--- DMRSlotRX.cpp | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Config.h b/Config.h index 9189105..a2a0251 100644 --- a/Config.h +++ b/Config.h @@ -19,16 +19,16 @@ #if !defined(CONFIG_H) #define CONFIG_H -// #define WANT_DEBUG +#define WANT_DEBUG // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT // For the original Arduino Due pin layout -// #define ARDUINO_DUE_PAPA +#define ARDUINO_DUE_PAPA // For the new Arduino Due pin layout -#define ARDUINO_DUE_ZUM +// #define ARDUINO_DUE_ZUM // For the SP8NTH board // #define ARDUINO_DUE_NTH diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index b84c5a3..c5dcbd1 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -119,25 +119,25 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - DEBUG3("DMRSlotRX: data header for slot/data type", m_slot ? 2U : 1U, dataType); + // DEBUG3("DMRSlotRX: data header for slot/data type", m_slot ? 2U : 1U, dataType); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_VOICE_LC_HEADER: - DEBUG3("DMRSlotRX: voice header for slot/data type", m_slot ? 2U : 1U, dataType); + // DEBUG3("DMRSlotRX: voice header for slot/data type", m_slot ? 2U : 1U, dataType); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_VOICE_PI_HEADER: - DEBUG3("DMRSlotRX: pi header for slot/data type", m_slot ? 2U : 1U, dataType); + // DEBUG3("DMRSlotRX: pi header for slot/data type", m_slot ? 2U : 1U, dataType); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_TERMINATOR_WITH_LC: - DEBUG2("DMRSlotRX: terminator for slot", m_slot ? 2U : 1U); + // DEBUG2("DMRSlotRX: terminator for slot", m_slot ? 2U : 1U); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; default: - DEBUG3("DMRSlotRX: data sync for slot/data type", m_slot ? 2U : 1U, dataType); + // DEBUG3("DMRSlotRX: data sync for slot/data type", m_slot ? 2U : 1U, dataType); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; @@ -145,14 +145,14 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == 0x20U) { // Voice sync - DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); + // DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_syncCount = 0U; m_n = 0U; } else { m_syncCount++; if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { - DEBUG2("DMRSlotRX: lost for slot", m_slot ? 2U : 1U); + // DEBUG2("DMRSlotRX: lost for slot", m_slot ? 2U : 1U); serial.writeDMRLost(m_slot); m_syncCount = 0U; m_threshold = 0; @@ -224,7 +224,11 @@ void CDMRSlotRX::correlateSync(q15_t sample) errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + // DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + if (m_endPtr == NOENDPTR) + DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + else + DEBUG3("DMRSlotRX: data sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); m_maxCorr = corr; m_centre = centre; m_threshold = threshold; @@ -238,7 +242,11 @@ void CDMRSlotRX::correlateSync(q15_t sample) errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + // DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + if (m_endPtr == NOENDPTR) + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + else + DEBUG3("DMRSlotRX: voice sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); m_maxCorr = corr; m_centre = centre; m_threshold = threshold; From 12ca69c48d518c9ecc895ca598468f7b15a8a468 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Mar 2016 18:18:43 +0000 Subject: [PATCH 011/329] Revert to the ZUM board config. --- Config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Config.h b/Config.h index a2a0251..83adc12 100644 --- a/Config.h +++ b/Config.h @@ -25,10 +25,10 @@ // #define USE_COS_AS_LOCKOUT // For the original Arduino Due pin layout -#define ARDUINO_DUE_PAPA +// #define ARDUINO_DUE_PAPA // For the new Arduino Due pin layout -// #define ARDUINO_DUE_ZUM +#define ARDUINO_DUE_ZUM // For the SP8NTH board // #define ARDUINO_DUE_NTH From 314b58912b79200fab6ff21238230079701a27f2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 8 Mar 2016 21:11:22 +0000 Subject: [PATCH 012/329] Reduce the amount of logging information. --- DMRSlotRX.cpp | 4 ++++ DStarRX.cpp | 10 +++++----- SerialPort.cpp | 12 ++++++------ YSFRX.cpp | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index c5dcbd1..c266ad2 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -225,10 +225,12 @@ void CDMRSlotRX::correlateSync(q15_t sample) if (errs <= MAX_SYNC_BYTES_ERRS) { // DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); +#if defined(WANT_DEBUG) if (m_endPtr == NOENDPTR) DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); else DEBUG3("DMRSlotRX: data sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); +#endif m_maxCorr = corr; m_centre = centre; m_threshold = threshold; @@ -243,10 +245,12 @@ void CDMRSlotRX::correlateSync(q15_t sample) if (errs <= MAX_SYNC_BYTES_ERRS) { // DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); +#if defined(WANT_DEBUG) if (m_endPtr == NOENDPTR) DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); else DEBUG3("DMRSlotRX: voice sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); +#endif m_maxCorr = corr; m_centre = centre; m_threshold = threshold; diff --git a/DStarRX.cpp b/DStarRX.cpp index 47629ef..b77ddd6 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -319,7 +319,7 @@ void CDStarRX::processNone(bool bit) // Exact matching of the frame sync sequence if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) == 0U) { - DEBUG1("DStarRX: found frame sync in None"); + // DEBUG1("DStarRX: found frame sync in None"); ::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES); m_rxBufferBits = 0U; @@ -371,7 +371,7 @@ void CDStarRX::processHeader(bool bit) unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; bool ok = rxHeader(m_rxBuffer, header); if (ok) { - DEBUG1("DStarRX: header checksum ok"); + // DEBUG1("DStarRX: header checksum ok"); io.setDecode(true); serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); @@ -382,7 +382,7 @@ void CDStarRX::processHeader(bool bit) m_rxState = DSRXS_DATA; m_dataBits = MAX_SYNC_BITS; } else { - DEBUG1("DStarRX: header checksum failed"); + // DEBUG1("DStarRX: header checksum failed"); // The checksum failed, return to looking for syncs m_rxState = DSRXS_NONE; @@ -401,7 +401,7 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the end frame sequences if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { - DEBUG1("DStarRX: Found end sync in Data"); + // DEBUG1("DStarRX: Found end sync in Data"); io.setDecode(false); serial.writeDStarEOT(); @@ -440,7 +440,7 @@ void CDStarRX::processData(bool bit) // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE m_dataBits--; if (m_dataBits == 0U) { - DEBUG1("DStarRX: data sync timed out, lost lock"); + // DEBUG1("DStarRX: data sync timed out, lost lock"); io.setDecode(false); serial.writeDStarLost(); diff --git a/SerialPort.cpp b/SerialPort.cpp index e9c4fc1..31508bf 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160303 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160308 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; @@ -255,31 +255,31 @@ void CSerialPort::setMode(MMDVM_STATE modemState) { switch (modemState) { case STATE_DMR: - DEBUG1("Mode set to DMR"); + // DEBUG1("Mode set to DMR"); dstarRX.reset(); ysfRX.reset(); break; case STATE_DSTAR: - DEBUG1("Mode set to D-Star"); + // DEBUG1("Mode set to D-Star"); dmrIdleRX.reset(); dmrRX.reset(); ysfRX.reset(); break; case STATE_YSF: - DEBUG1("Mode set to System Fusion"); + // DEBUG1("Mode set to System Fusion"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); break; case STATE_CALIBRATE: - DEBUG1("Mode set to Calibrate"); + // DEBUG1("Mode set to Calibrate"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); break; default: - DEBUG1("Mode set to Idle"); + // DEBUG1("Mode set to Idle"); // STATE_IDLE break; } diff --git a/YSFRX.cpp b/YSFRX.cpp index 33452f7..f10dea0 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -503,7 +503,7 @@ void CYSFRX::processData(q15_t sample) // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE m_lostCount--; if (m_lostCount == 0U) { - DEBUG1("YSFRX: sync timed out, lost lock"); + // DEBUG1("YSFRX: sync timed out, lost lock"); io.setDecode(false); serial.writeYSFLost(); @@ -528,7 +528,7 @@ void CYSFRX::processData(q15_t sample) serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); if (ok && (FICH[0U] & 0xC0U) == 0x80U) { - DEBUG1("YSFRX: end of transmission"); + // DEBUG1("YSFRX: end of transmission"); io.setDecode(false); m_state = YSFRXS_NONE; } else { From a4814bf351349e0c73de85782ef5e8ca459a4666 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 9 Mar 2016 07:01:08 +0000 Subject: [PATCH 013/329] Reduce the C4FSK filter length significantly. --- Config.h | 2 +- IO.cpp | 6 ++---- SerialPort.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Config.h b/Config.h index 83adc12..9189105 100644 --- a/Config.h +++ b/Config.h @@ -19,7 +19,7 @@ #if !defined(CONFIG_H) #define CONFIG_H -#define WANT_DEBUG +// #define WANT_DEBUG // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT diff --git a/IO.cpp b/IO.cpp index 42cedb6..779a3f7 100644 --- a/IO.cpp +++ b/IO.cpp @@ -21,10 +21,8 @@ #include "IO.h" // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, - 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, - -553, -847, -731, -340, 104, 401, 0}; -const uint16_t C4FSK_FILTER_LEN = 42U; +static q15_t C4FSK_FILTER[] = {2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, 0}; +const uint16_t C4FSK_FILTER_LEN = 10U; // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/SerialPort.cpp b/SerialPort.cpp index 31508bf..b6f3357 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160308 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160309 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From c2ca15efdf3a3b340580e3a401a65f7b9c372d6c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 9 Mar 2016 15:40:16 +0000 Subject: [PATCH 014/329] Increase size of the C4FSK filter slightly for efficiency. --- IO.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IO.cpp b/IO.cpp index 779a3f7..60496bd 100644 --- a/IO.cpp +++ b/IO.cpp @@ -21,8 +21,8 @@ #include "IO.h" // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, 0}; -const uint16_t C4FSK_FILTER_LEN = 10U; +static q15_t C4FSK_FILTER[] = {-770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, 0}; +const uint16_t C4FSK_FILTER_LEN = 12U; // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; From ef58f7ed36ea0886827573209ab7b210b0cc04e0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Mar 2016 09:14:20 +0000 Subject: [PATCH 015/329] Add Phoenix (UK) as an allowed network. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e7328a..26bd3b7 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,4 @@ In order to build this software you will need to edit a file within the Arduino This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden. -It is only to be used on the main DMR+ and main BrandMeister networks. If you wish to use it on any other network, you must get written permission from myself, G4KLX. Each such request will be dealt with on a case-by-case basis. +It is only to be used on the main DMR+, the main BrandMeister, and the Phoenix (UK) networks. If you wish to use it on any other network, you must get written permission from myself, G4KLX. Each such request will be dealt with on a case-by-case basis. From 7d77f20ee964160fd01e887a7bc37354f8fd09ee Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Mar 2016 18:16:01 +0000 Subject: [PATCH 016/329] Restore previous C4FSK filter. --- IO.cpp | 6 ++++-- SerialPort.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/IO.cpp b/IO.cpp index 60496bd..9981773 100644 --- a/IO.cpp +++ b/IO.cpp @@ -21,8 +21,10 @@ #include "IO.h" // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {-770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, 0}; -const uint16_t C4FSK_FILTER_LEN = 12U; +static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t C4FSK_FILTER_LEN = 42U; // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/SerialPort.cpp b/SerialPort.cpp index b6f3357..97cb463 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160309 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160310 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 037f60ea06a08418ca6f3fdb29a8a17ad90694dd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 14 Mar 2016 20:24:51 +0000 Subject: [PATCH 017/329] Set debugging on a per-file basis. --- Config.h | 4 +--- DMRIdleRX.cpp | 2 ++ DMRSlotRX.cpp | 16 +++++++++------- DStarRX.cpp | 13 ++++++------- IO.cpp | 2 ++ SampleRB.cpp | 1 - SerialPort.cpp | 16 +++++++--------- SerialPort.h | 5 +++-- SerialRB.cpp | 1 - YSFRX.cpp | 8 +++++--- 10 files changed, 35 insertions(+), 33 deletions(-) diff --git a/Config.h b/Config.h index 9189105..5b7a4b1 100644 --- a/Config.h +++ b/Config.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 @@ -19,8 +19,6 @@ #if !defined(CONFIG_H) #define CONFIG_H -// #define WANT_DEBUG - // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 5b4adbd..44a596e 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +// #define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "DMRIdleRX.h" diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index c266ad2..163ffe8 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "DMRSlotRX.h" @@ -119,25 +121,25 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - // DEBUG3("DMRSlotRX: data header for slot/data type", m_slot ? 2U : 1U, dataType); + DEBUG3("DMRSlotRX: data header for slot/data type", m_slot ? 2U : 1U, dataType); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_VOICE_LC_HEADER: - // DEBUG3("DMRSlotRX: voice header for slot/data type", m_slot ? 2U : 1U, dataType); + DEBUG3("DMRSlotRX: voice header for slot/data type", m_slot ? 2U : 1U, dataType); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_VOICE_PI_HEADER: - // DEBUG3("DMRSlotRX: pi header for slot/data type", m_slot ? 2U : 1U, dataType); + DEBUG3("DMRSlotRX: pi header for slot/data type", m_slot ? 2U : 1U, dataType); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; case DT_TERMINATOR_WITH_LC: - // DEBUG2("DMRSlotRX: terminator for slot", m_slot ? 2U : 1U); + DEBUG2("DMRSlotRX: terminator for slot", m_slot ? 2U : 1U); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; default: - // DEBUG3("DMRSlotRX: data sync for slot/data type", m_slot ? 2U : 1U, dataType); + DEBUG3("DMRSlotRX: data sync for slot/data type", m_slot ? 2U : 1U, dataType); m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); break; @@ -145,14 +147,14 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == 0x20U) { // Voice sync - // DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); + DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_syncCount = 0U; m_n = 0U; } else { m_syncCount++; if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { - // DEBUG2("DMRSlotRX: lost for slot", m_slot ? 2U : 1U); + DEBUG2("DMRSlotRX: lost for slot", m_slot ? 2U : 1U); serial.writeDMRLost(m_slot); m_syncCount = 0U; m_threshold = 0; diff --git a/DStarRX.cpp b/DStarRX.cpp index b77ddd6..d0cb104 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +// #define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "DStarRX.h" @@ -319,7 +321,7 @@ void CDStarRX::processNone(bool bit) // Exact matching of the frame sync sequence if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) == 0U) { - // DEBUG1("DStarRX: found frame sync in None"); + DEBUG1("DStarRX: found frame sync in None"); ::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES); m_rxBufferBits = 0U; @@ -371,7 +373,6 @@ void CDStarRX::processHeader(bool bit) unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; bool ok = rxHeader(m_rxBuffer, header); if (ok) { - // DEBUG1("DStarRX: header checksum ok"); io.setDecode(true); serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); @@ -382,8 +383,6 @@ void CDStarRX::processHeader(bool bit) m_rxState = DSRXS_DATA; m_dataBits = MAX_SYNC_BITS; } else { - // DEBUG1("DStarRX: header checksum failed"); - // The checksum failed, return to looking for syncs m_rxState = DSRXS_NONE; } @@ -401,7 +400,7 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the end frame sequences if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { - // DEBUG1("DStarRX: Found end sync in Data"); + DEBUG1("DStarRX: Found end sync in Data"); io.setDecode(false); serial.writeDStarEOT(); @@ -440,7 +439,7 @@ void CDStarRX::processData(bool bit) // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE m_dataBits--; if (m_dataBits == 0U) { - // DEBUG1("DStarRX: data sync timed out, lost lock"); + DEBUG1("DStarRX: data sync timed out, lost lock"); io.setDecode(false); serial.writeDStarLost(); diff --git a/IO.cpp b/IO.cpp index 9981773..d1dab5e 100644 --- a/IO.cpp +++ b/IO.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +// #define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "IO.h" diff --git a/SampleRB.cpp b/SampleRB.cpp index 1d1f9e6..6494a99 100644 --- a/SampleRB.cpp +++ b/SampleRB.cpp @@ -19,7 +19,6 @@ Boston, MA 02110-1301, USA. */ #include "SampleRB.h" -#include "Debug.h" CSampleRB::CSampleRB(uint16_t length) : m_length(length), diff --git a/SerialPort.cpp b/SerialPort.cpp index 97cb463..72d5cb7 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +// #define WANT_DEBUG + #include "Config.h" #include "Globals.h" @@ -255,31 +257,31 @@ void CSerialPort::setMode(MMDVM_STATE modemState) { switch (modemState) { case STATE_DMR: - // DEBUG1("Mode set to DMR"); + DEBUG1("Mode set to DMR"); dstarRX.reset(); ysfRX.reset(); break; case STATE_DSTAR: - // DEBUG1("Mode set to D-Star"); + DEBUG1("Mode set to D-Star"); dmrIdleRX.reset(); dmrRX.reset(); ysfRX.reset(); break; case STATE_YSF: - // DEBUG1("Mode set to System Fusion"); + DEBUG1("Mode set to System Fusion"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); break; case STATE_CALIBRATE: - // DEBUG1("Mode set to Calibrate"); + DEBUG1("Mode set to Calibrate"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); break; default: - // DEBUG1("Mode set to Idle"); + DEBUG1("Mode set to Idle"); // STATE_IDLE break; } @@ -689,8 +691,6 @@ void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) #endif } -#if defined(WANT_DEBUG) - void CSerialPort::writeDump(const uint8_t* data, uint8_t length) { ASSERT(length <= 252U); @@ -870,5 +870,3 @@ void CSerialPort::writeAssert(bool cond, const char* text, const char* file, lon write(reply, count, true); } -#endif - diff --git a/SerialPort.h b/SerialPort.h index 0d8ce7c..c6cb0a7 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -44,16 +44,17 @@ public: void writeCalData(const uint8_t* data, uint8_t length); -#if defined(WANT_DEBUG) void writeDump(const uint8_t* data, uint8_t length); + void writeSamples(const q15_t* data, uint8_t length); + void writeDebug(const char* text); void writeDebug(const char* text, int16_t n1); void writeDebug(const char* text, int16_t n1, int16_t n2); void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3); void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4); + void writeAssert(bool cond, const char* text, const char* file, long line); -#endif private: #if defined(__MBED__) diff --git a/SerialRB.cpp b/SerialRB.cpp index 97912c2..ed11711 100644 --- a/SerialRB.cpp +++ b/SerialRB.cpp @@ -19,7 +19,6 @@ Boston, MA 02110-1301, USA. */ #include "SerialRB.h" -#include "Debug.h" CSerialRB::CSerialRB(uint16_t length) : m_length(length), diff --git a/YSFRX.cpp b/YSFRX.cpp index f10dea0..d343ef5 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +// #define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "YSFRX.h" @@ -503,7 +505,7 @@ void CYSFRX::processData(q15_t sample) // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE m_lostCount--; if (m_lostCount == 0U) { - // DEBUG1("YSFRX: sync timed out, lost lock"); + DEBUG1("YSFRX: sync timed out, lost lock"); io.setDecode(false); serial.writeYSFLost(); @@ -528,7 +530,7 @@ void CYSFRX::processData(q15_t sample) serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); if (ok && (FICH[0U] & 0xC0U) == 0x80U) { - // DEBUG1("YSFRX: end of transmission"); + DEBUG1("YSFRX: end of transmission"); io.setDecode(false); m_state = YSFRXS_NONE; } else { From 3fbb6148271d75f3d55cc1219743d0ac37dfa62c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Mar 2016 19:17:44 +0000 Subject: [PATCH 018/329] Switch debugging off in the DMR Slot RX. --- DMRSlotRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 163ffe8..63157f3 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" From c7ea8a68c6335860cbcbd2ca9b6b1e2e07326e4d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Mar 2016 19:18:09 +0000 Subject: [PATCH 019/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 72d5cb7..b16ebe0 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -59,7 +59,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160310 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160315 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From da34f26c55ae8dc646b1cf2274c60f49892bad19 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 17 Mar 2016 19:31:12 +0000 Subject: [PATCH 020/329] Allow for a delay before processing a DMR slot. --- DMRRX.cpp | 6 ++++++ DMRRX.h | 1 + DMRSlotRX.cpp | 31 +++++++++++++++++++++---------- DMRSlotRX.h | 7 +++++-- SerialPort.cpp | 5 ++++- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/DMRRX.cpp b/DMRRX.cpp index 36923cb..9137b94 100644 --- a/DMRRX.cpp +++ b/DMRRX.cpp @@ -56,6 +56,12 @@ void CDMRRX::setColorCode(uint8_t colorCode) m_slot2RX.setColorCode(colorCode); } +void CDMRRX::setDelay(uint8_t delay) +{ + m_slot1RX.setDelay(delay); + m_slot2RX.setDelay(delay); +} + void CDMRRX::reset() { m_slot1RX.reset(); diff --git a/DMRRX.h b/DMRRX.h index f31f8ab..2f8810d 100644 --- a/DMRRX.h +++ b/DMRRX.h @@ -29,6 +29,7 @@ public: void samples(const q15_t* samples, const uint8_t* control, uint8_t length); void setColorCode(uint8_t colorCode); + void setDelay(uint8_t delay); void reset(); diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 63157f3..bc7c40f 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -45,28 +45,32 @@ m_bitPtr(0U), m_dataPtr(0U), m_syncPtr(0U), m_endPtr(NOENDPTR), +m_delayPtr(0U), m_maxCorr(0), m_centre(0), m_threshold(0), m_control(0x00U), m_syncCount(0U), m_colorCode(0U), +m_delay(0U), m_n(0U) { } void CDMRSlotRX::start() { - m_dataPtr = 0U; - m_bitPtr = 0U; - m_maxCorr = 0; - m_control = 0x00U; + m_dataPtr = 0U; + m_delayPtr = 0U; + m_bitPtr = 0U; + m_maxCorr = 0; + m_control = 0x00U; } void CDMRSlotRX::reset() { m_syncPtr = 0U; m_dataPtr = 0U; + m_delayPtr = 0U; m_bitPtr = 0U; m_maxCorr = 0; m_control = 0x00U; @@ -78,6 +82,10 @@ void CDMRSlotRX::reset() bool CDMRSlotRX::processSample(q15_t sample) { + m_delayPtr++; + if (m_delayPtr < m_delay) + return m_endPtr != NOENDPTR; + // Ensure that the buffer doesn't overflow if (m_dataPtr > m_endPtr || m_dataPtr >= 900U) return m_endPtr != NOENDPTR; @@ -95,7 +103,7 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(sample); } else { - if (m_dataPtr >= 390U && m_dataPtr <= 500U) + if (m_dataPtr >= 420U && m_dataPtr <= 500U) correlateSync(sample); } @@ -226,10 +234,9 @@ void CDMRSlotRX::correlateSync(q15_t sample) errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - // DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); #if defined(WANT_DEBUG) if (m_endPtr == NOENDPTR) - DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); else DEBUG3("DMRSlotRX: data sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); #endif @@ -246,10 +253,9 @@ void CDMRSlotRX::correlateSync(q15_t sample) errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - // DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); #if defined(WANT_DEBUG) if (m_endPtr == NOENDPTR) - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_dataPtr, centre, threshold); + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); else DEBUG3("DMRSlotRX: voice sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); #endif @@ -299,3 +305,8 @@ void CDMRSlotRX::setColorCode(uint8_t colorCode) m_colorCode = colorCode; } +void CDMRSlotRX::setDelay(uint8_t delay) +{ + m_delay = delay; +} + diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 0ac8d92..aacbe2a 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -31,6 +31,7 @@ public: bool processSample(q15_t sample); void setColorCode(uint8_t colorCode); + void setDelay(uint8_t delay); void reset(); @@ -42,16 +43,18 @@ private: uint16_t m_dataPtr; uint16_t m_syncPtr; uint16_t m_endPtr; + uint16_t m_delayPtr; q31_t m_maxCorr; q15_t m_centre; q15_t m_threshold; uint8_t m_control; uint8_t m_syncCount; uint8_t m_colorCode; + uint16_t m_delay; uint8_t m_n; - void correlateSync(q15_t sample); - void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); + void correlateSync(q15_t sample); + void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; #endif diff --git a/SerialPort.cpp b/SerialPort.cpp index b16ebe0..d97dceb 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -176,7 +176,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 7U) + if (length < 8U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -209,6 +209,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) if (colorCode > 15U) return 4U; + uint8_t dmrDelay = data[7U]; + m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -220,6 +222,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrTX.setColorCode(colorCode); dmrRX.setColorCode(colorCode); + dmrRX.setDelay(dmrDelay); dmrIdleRX.setColorCode(colorCode); io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, txLevel); From d957ec6e36ed043795cc6f84ba4a751154dc436f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 17 Mar 2016 19:34:40 +0000 Subject: [PATCH 021/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index d97dceb..9be0ad0 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -59,7 +59,7 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; const uint8_t MMDVM_SAMPLES = 0xF8U; -const uint8_t HARDWARE[] = "MMDVM 20160315 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160317 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 4d9f8d19e2b6ebe1dac20ffa6d7af52e62a2538b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 17 Mar 2016 22:45:26 +0000 Subject: [PATCH 022/329] Rationalisation of debugging messages. --- Debug.h | 6 +----- SerialPort.cpp | 38 -------------------------------------- SerialPort.h | 4 ---- 3 files changed, 1 insertion(+), 47 deletions(-) diff --git a/Debug.h b/Debug.h index bb16563..667856d 100644 --- a/Debug.h +++ b/Debug.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 @@ -31,8 +31,6 @@ #define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d)) #define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e)) #define ASSERT(a) serial.writeAssert((a),#a,__FILE__,__LINE__) -#define DUMP(a,b) serial.writeDump((a),(b)) -#define SAMPLES(a,b) serial.writeSamples((a),(b)) #else @@ -42,8 +40,6 @@ #define DEBUG4(a,b,c,d) #define DEBUG5(a,b,c,d,e) #define ASSERT(a) -#define DUMP(a,b) -#define SAMPLES(a,b) #endif diff --git a/SerialPort.cpp b/SerialPort.cpp index 9be0ad0..2c73ef2 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -51,13 +51,11 @@ const uint8_t MMDVM_YSF_LOST = 0x21U; const uint8_t MMDVM_ACK = 0x70U; const uint8_t MMDVM_NAK = 0x7FU; -const uint8_t MMDVM_DUMP = 0xF0U; const uint8_t MMDVM_DEBUG1 = 0xF1U; const uint8_t MMDVM_DEBUG2 = 0xF2U; const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t MMDVM_SAMPLES = 0xF8U; const uint8_t HARDWARE[] = "MMDVM 20160317 (D-Star/DMR/System Fusion)"; @@ -694,42 +692,6 @@ void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) #endif } -void CSerialPort::writeDump(const uint8_t* data, uint8_t length) -{ - ASSERT(length <= 252U); - - uint8_t reply[255U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 0U; - reply[2U] = MMDVM_DUMP; - - uint8_t count = length * sizeof(uint8_t) + 3U; - ::memcpy(reply + 3U, data, length * sizeof(uint8_t)); - - reply[1U] = count; - - write(reply, count, true); -} - -void CSerialPort::writeSamples(const q15_t* data, uint8_t length) -{ - ASSERT(length <= 126U); - - uint8_t reply[255U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 0U; - reply[2U] = MMDVM_SAMPLES; - - uint8_t count = length * sizeof(q15_t) + 3U; - ::memcpy(reply + 3U, data, length * sizeof(q15_t)); - - reply[1U] = count; - - write(reply, count, true); -} - void CSerialPort::writeDebug(const char* text) { uint8_t reply[130U]; diff --git a/SerialPort.h b/SerialPort.h index c6cb0a7..bcf4d05 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -44,10 +44,6 @@ public: void writeCalData(const uint8_t* data, uint8_t length); - void writeDump(const uint8_t* data, uint8_t length); - - void writeSamples(const q15_t* data, uint8_t length); - void writeDebug(const char* text); void writeDebug(const char* text, int16_t n1); void writeDebug(const char* text, int16_t n1, int16_t n2); From 89d9dd9a7bc7106e20e06b9f55be2ddabe29f7c9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Mar 2016 21:49:50 +0000 Subject: [PATCH 023/329] Add or remove samples to handle oscillator offsets. --- DMRTX.cpp | 38 +++++++++++++++++++++++------ DMRTX.h | 3 ++- DStarTX.cpp | 29 ++++++++++++++++++---- DStarTX.h | 3 ++- Globals.h | 3 +++ IO.cpp | 66 ++++++++++++++++++++++++++++++++------------------ IO.h | 2 ++ MMDVM.cpp | 5 +++- MMDVM.ino | 5 +++- SerialPort.cpp | 14 ++++++++++- YSFTX.cpp | 31 +++++++++++++++++++----- YSFTX.h | 3 ++- 12 files changed, 154 insertions(+), 48 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index d6b7c04..9f3142f 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -63,7 +63,8 @@ m_newShortLC(), m_markBuffer(), m_poBuffer(), m_poLen(0U), -m_poPtr(0U) +m_poPtr(0U), +m_count(0U) { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); @@ -192,8 +193,8 @@ void CDMRTX::setStart(bool start) void CDMRTX::writeByte(uint8_t c, uint8_t control) { - q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U]; - q15_t outBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U]; + q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; + q15_t outBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; const uint8_t MASK = 0xC0U; @@ -215,13 +216,34 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) } } - uint8_t controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U]; - ::memset(controlBuffer, MARK_NONE, DMR_RADIO_SYMBOL_LENGTH * 4U * sizeof(uint8_t)); - controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U] = control; + uint8_t blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U; - ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, DMR_RADIO_SYMBOL_LENGTH * 4U); + uint8_t controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; + ::memset(controlBuffer, MARK_NONE, (DMR_RADIO_SYMBOL_LENGTH * 4U + 1U) * sizeof(uint8_t)); - io.write(outBuffer, DMR_RADIO_SYMBOL_LENGTH * 4U, controlBuffer); + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += DMR_RADIO_SYMBOL_LENGTH * 4U; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U - 1U]; + blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U + 1U; + controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U + 1U] = control; + } else { + blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U - 1U; + controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U - 1U] = control; + } + + m_count -= m_sampleCount; + } + } else { + controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U] = control; + } + + ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + + io.write(outBuffer, blockSize, controlBuffer); } uint16_t CDMRTX::getSpace1() const diff --git a/DMRTX.h b/DMRTX.h index 3cae45e..7fc499d 100644 --- a/DMRTX.h +++ b/DMRTX.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 @@ -62,6 +62,7 @@ private: uint8_t m_poBuffer[40U]; uint16_t m_poLen; uint16_t m_poPtr; + uint32_t m_count; void createData(uint8_t slotIndex); void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex); diff --git a/DStarTX.cpp b/DStarTX.cpp index ce704a1..236f333 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -193,7 +193,8 @@ m_modState(), m_poBuffer(), m_poLen(0U), m_poPtr(0U), -m_txDelay(60U) // 100ms +m_txDelay(60U), // 100ms +m_count(0U) { ::memset(m_modState, 0x00U, 60U * sizeof(q15_t)); @@ -403,8 +404,8 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const void CDStarTX::writeByte(uint8_t c) { - q15_t inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U]; - q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U]; + q15_t inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U + 1U]; + q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U + 1U]; uint8_t mask = 0x01U; @@ -418,9 +419,27 @@ void CDStarTX::writeByte(uint8_t c) mask <<= 1; } - ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U); + uint8_t blockSize = DSTAR_RADIO_BIT_LENGTH * 8U; - io.write(outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U); + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += DSTAR_RADIO_BIT_LENGTH * 8U; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U] = inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U - 1U]; + blockSize = DSTAR_RADIO_BIT_LENGTH * 8U + 1U; + } else { + blockSize = DSTAR_RADIO_BIT_LENGTH * 8U - 1U; + } + + m_count -= m_sampleCount; + } + } + + ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + + io.write(outBuffer, blockSize); } void CDStarTX::setTXDelay(uint8_t delay) diff --git a/DStarTX.h b/DStarTX.h index 22e3fd0..b2f72ff 100644 --- a/DStarTX.h +++ b/DStarTX.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,6 +45,7 @@ private: uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; // In bytes + uint32_t m_count; void txHeader(const uint8_t* in, uint8_t* out) const; void writeByte(uint8_t c); diff --git a/Globals.h b/Globals.h index 8a7509e..a97c2c3 100644 --- a/Globals.h +++ b/Globals.h @@ -69,6 +69,9 @@ extern bool m_ysfEnable; extern bool m_tx; +extern uint32_t m_sampleCount; +extern bool m_sampleInsert; + extern CSerialPort serial; extern CIO io; diff --git a/IO.cpp b/IO.cpp index d1dab5e..5cdeed9 100644 --- a/IO.cpp +++ b/IO.cpp @@ -117,6 +117,7 @@ m_ledValue(true), m_dcd(false), m_overflow(0U), m_overcount(0U), +m_count(0U), m_watchdog(0U), m_lockout(false) { @@ -256,10 +257,12 @@ void CIO::process() } if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { - q15_t samples[RX_BLOCK_SIZE]; - uint8_t control[RX_BLOCK_SIZE]; + q15_t samples[RX_BLOCK_SIZE + 1U]; + uint8_t control[RX_BLOCK_SIZE + 1U]; - for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + uint8_t blockSize = RX_BLOCK_SIZE; + + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { uint16_t sample; m_rxBuffer.get(sample, control[i]); @@ -273,57 +276,74 @@ void CIO::process() samples[i] = q15_t(__SSAT((res2 >> 15), 16)); } + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += RX_BLOCK_SIZE; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + control[RX_BLOCK_SIZE] = control[RX_BLOCK_SIZE - 1U]; + samples[RX_BLOCK_SIZE] = 0; + blockSize = RX_BLOCK_SIZE + 1U; + } else { + blockSize = RX_BLOCK_SIZE - 1U; + } + + m_count -= m_sampleCount; + } + } + if (m_lockout) return; if (m_modemState == STATE_IDLE) { if (m_dstarEnable) { - q15_t GMSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, RX_BLOCK_SIZE); + q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - dstarRX.samples(GMSKVals, RX_BLOCK_SIZE); + dstarRX.samples(GMSKVals, blockSize); } if (m_dmrEnable || m_ysfEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, RX_BLOCK_SIZE); + q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); if (m_dmrEnable) - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); + dmrIdleRX.samples(C4FSKVals, blockSize); if (m_ysfEnable) - ysfRX.samples(C4FSKVals, RX_BLOCK_SIZE); + ysfRX.samples(C4FSKVals, blockSize); } } else if (m_modemState == STATE_DSTAR) { if (m_dstarEnable) { - q15_t GMSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, RX_BLOCK_SIZE); + q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - dstarRX.samples(GMSKVals, RX_BLOCK_SIZE); + dstarRX.samples(GMSKVals, blockSize); } } else if (m_modemState == STATE_DMR) { if (m_dmrEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, RX_BLOCK_SIZE); + q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs if (m_tx) - dmrRX.samples(C4FSKVals, control, RX_BLOCK_SIZE); + dmrRX.samples(C4FSKVals, control, blockSize); else - dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE); + dmrIdleRX.samples(C4FSKVals, blockSize); } } else if (m_modemState == STATE_YSF) { if (m_ysfEnable) { - q15_t C4FSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, RX_BLOCK_SIZE); + q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); - ysfRX.samples(C4FSKVals, RX_BLOCK_SIZE); + ysfRX.samples(C4FSKVals, blockSize); } } else if (m_modemState == STATE_CALIBRATE) { - q15_t GMSKVals[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, RX_BLOCK_SIZE); + q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; + ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - calRX.samples(GMSKVals, RX_BLOCK_SIZE); + calRX.samples(GMSKVals, blockSize); } } } diff --git a/IO.h b/IO.h index 962f6f4..4878d8d 100644 --- a/IO.h +++ b/IO.h @@ -85,6 +85,8 @@ private: uint16_t m_overflow; uint16_t m_overcount; + uint32_t m_count; + volatile uint32_t m_watchdog; bool m_lockout; diff --git a/MMDVM.cpp b/MMDVM.cpp index 134e949..734b20e 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2016 by Mathis Schmieder DB9MAT * * This program is free software; you can redistribute it and/or modify @@ -31,6 +31,9 @@ bool m_ysfEnable = true; bool m_tx = false; +uint32_t m_sampleCount = 0U; +bool m_sampleInsert = false; + CDStarRX dstarRX; CDStarTX dstarTX; diff --git a/MMDVM.ino b/MMDVM.ino index 773a660..d9c2041 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -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 @@ -28,6 +28,9 @@ bool m_ysfEnable = true; bool m_tx = false; +uint32_t m_sampleCount = 0U; +bool m_sampleInsert = false; + CDStarRX dstarRX; CDStarTX dstarTX; diff --git a/SerialPort.cpp b/SerialPort.cpp index 2c73ef2..4457bf2 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -174,7 +174,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 8U) + if (length < 9U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -209,6 +209,18 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t dmrDelay = data[7U]; + int8_t oscOffset = int8_t(data[8U]) - 128; + if (oscOffset < 0) { + m_sampleCount = 1000000U / uint32_t(-oscOffset); + m_sampleInsert = true; + } else if (oscOffset > 0) { + m_sampleCount = 1000000U / uint32_t(oscOffset); + m_sampleInsert = false; + } else { + m_sampleCount = 0U; + m_sampleInsert = false; + } + m_modemState = modemState; m_dstarEnable = dstarEnable; diff --git a/YSFTX.cpp b/YSFTX.cpp index 5af85fa..f72ab98 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -44,7 +44,8 @@ m_modState(), m_poBuffer(), m_poLen(0U), m_poPtr(0U), -m_txDelay(120U) // 100ms +m_txDelay(120U), // 100ms +m_count(0U) { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); @@ -107,8 +108,8 @@ uint8_t CYSFTX::writeData(const uint8_t* data, uint8_t length) void CYSFTX::writeByte(uint8_t c) { - q15_t inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U]; - q15_t outBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U]; + q15_t inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U + 1U]; + q15_t outBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U + 1U]; const uint8_t MASK = 0xC0U; @@ -130,9 +131,27 @@ void CYSFTX::writeByte(uint8_t c) } } - ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, YSF_RADIO_SYMBOL_LENGTH * 4U); + uint8_t blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U; - io.write(outBuffer, YSF_RADIO_SYMBOL_LENGTH * 4U); + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += YSF_RADIO_SYMBOL_LENGTH * 4U; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U - 1U]; + blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U + 1U; + } else { + blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U - 1U; + } + + m_count -= m_sampleCount; + } + } + + ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + + io.write(outBuffer, blockSize); } void CYSFTX::setTXDelay(uint8_t delay) diff --git a/YSFTX.h b/YSFTX.h index bcaba20..9235a9c 100644 --- a/YSFTX.h +++ b/YSFTX.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 @@ -43,6 +43,7 @@ private: uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; + uint32_t m_count; void writeByte(uint8_t c); }; From 96091c84242aad22b624521f9383fc321c6f1e2d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Mar 2016 22:03:00 +0000 Subject: [PATCH 024/329] Make the D-Star demodulator stiffer when locked. --- DStarRX.cpp | 28 +++++++++++++++++++--------- DStarRX.h | 4 +++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index d0cb104..12ed043 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -25,9 +25,10 @@ const unsigned int BUFFER_LENGTH = 200U; -const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; -const uint32_t INC = PLLINC / 32U; +const uint32_t PLLMAX = 0x10000U; +const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; +const uint32_t INC_LOCK = PLLINC / 64U; +const uint32_t INC_UNLOCK = PLLINC / 32U; const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; @@ -243,6 +244,7 @@ const uint16_t CCITT_TABLE[] = { CDStarRX::CDStarRX() : m_pll(0U), m_prev(false), +m_inc(INC_UNLOCK), m_rxState(DSRXS_NONE), m_patternBuffer(0x00U), m_rxBuffer(), @@ -264,6 +266,7 @@ void CDStarRX::reset() { m_pll = 0U; m_prev = false; + m_inc = INC_UNLOCK; m_rxState = DSRXS_NONE; m_patternBuffer = 0x00U; m_rxBufferBits = 0U; @@ -280,9 +283,9 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length) if (bit != m_prev) { if (m_pll < (PLLMAX / 2U)) - m_pll += INC; + m_pll += m_inc; else - m_pll -= INC; + m_pll -= m_inc; } m_prev = bit; @@ -333,7 +336,7 @@ void CDStarRX::processNone(bool bit) // Exact matching of the data sync bit sequence if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) { DEBUG1("DStarRX: found data sync in None"); - io.setDecode(true); + locked(true); #if defined(WANT_DEBUG) q15_t min = 16000; @@ -373,7 +376,7 @@ void CDStarRX::processHeader(bool bit) unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; bool ok = rxHeader(m_rxBuffer, header); if (ok) { - io.setDecode(true); + locked(true); serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); @@ -401,7 +404,7 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the end frame sequences if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { DEBUG1("DStarRX: Found end sync in Data"); - io.setDecode(false); + locked(false); serial.writeDStarEOT(); @@ -440,7 +443,7 @@ void CDStarRX::processData(bool bit) m_dataBits--; if (m_dataBits == 0U) { DEBUG1("DStarRX: data sync timed out, lost lock"); - io.setDecode(false); + locked(false); serial.writeDStarLost(); @@ -693,3 +696,10 @@ 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]; } +void CDStarRX::locked(bool lock) +{ + io.setDecode(lock); + + m_inc = lock ? INC_LOCK : INC_UNLOCK; +} + diff --git a/DStarRX.h b/DStarRX.h index ee5c2a9..da24e93 100644 --- a/DStarRX.h +++ b/DStarRX.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 @@ -39,6 +39,7 @@ public: private: uint32_t m_pll; bool m_prev; + uint32_t m_inc; DSRX_STATE m_rxState; uint32_t m_patternBuffer; uint8_t m_rxBuffer[100U]; @@ -62,6 +63,7 @@ private: void viterbiDecode(int* data); void traceBack(); bool checksum(const uint8_t* header) const; + void locked(bool lock); }; #endif From 3665d02fe78f42d9f67504ff213066c902460f4e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Mar 2016 22:07:33 +0000 Subject: [PATCH 025/329] Make the YSF demodulator stiffer when locked. --- YSFRX.cpp | 26 ++++++++++++++++++-------- YSFRX.h | 4 +++- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index d343ef5..bfe82d4 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -27,9 +27,10 @@ const unsigned int BUFFER_LENGTH = 200U; const q15_t SCALING_FACTOR = 19505; // Q15(0.60) -const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; -const uint32_t INC = PLLINC / 32U; +const uint32_t PLLMAX = 0x10000U; +const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; +const uint32_t INC_UNLOCK = PLLINC / 32U; +const uint32_t INC_LOCK = PLLINC / 64U; const uint8_t SYNC_SYMBOL_ERRS = 2U; const uint8_t SYNC_BIT_ERRS = 4U; @@ -311,6 +312,7 @@ static const unsigned short CCITT_TABLE[] = { CYSFRX::CYSFRX() : m_pll(0U), m_prev(false), +m_inc(INC_UNLOCK), m_state(YSFRXS_NONE), m_bitBuffer(0x00U), m_symbols(), @@ -335,6 +337,7 @@ void CYSFRX::reset() { m_pll = 0U; m_prev = false; + m_inc = INC_UNLOCK; m_state = YSFRXS_NONE; m_bitBuffer = 0x00U; m_bufferPtr = 0U; @@ -351,9 +354,9 @@ void CYSFRX::samples(const q15_t* samples, uint8_t length) if (bit != m_prev) { if (m_pll < (PLLMAX / 2U)) - m_pll += INC; + m_pll += m_inc; else - m_pll -= INC; + m_pll -= m_inc; } m_prev = bit; @@ -440,7 +443,7 @@ void CYSFRX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; m_state = YSFRXS_DATA; - io.setDecode(true); + locked(true); } } @@ -506,7 +509,7 @@ void CYSFRX::processData(q15_t sample) m_lostCount--; if (m_lostCount == 0U) { DEBUG1("YSFRX: sync timed out, lost lock"); - io.setDecode(false); + locked(false); serial.writeYSFLost(); @@ -531,7 +534,7 @@ void CYSFRX::processData(q15_t sample) if (ok && (FICH[0U] & 0xC0U) == 0x80U) { DEBUG1("YSFRX: end of transmission"); - io.setDecode(false); + locked(false); m_state = YSFRXS_NONE; } else { // Start the next frame @@ -696,3 +699,10 @@ bool CYSFRX::checksum(const uint8_t* fich) const return crc8[0U] == fich[5U] && crc8[1U] == fich[4U]; } +void CYSFRX::locked(bool lock) +{ + io.setDecode(lock); + + m_inc = lock ? INC_LOCK : INC_UNLOCK; +} + diff --git a/YSFRX.h b/YSFRX.h index 46950c0..cf2e172 100644 --- a/YSFRX.h +++ b/YSFRX.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 @@ -38,6 +38,7 @@ public: private: uint32_t m_pll; bool m_prev; + uint32_t m_inc; YSFRX_STATE m_state; uint32_t m_symbolBuffer; uint64_t m_bitBuffer; @@ -64,6 +65,7 @@ private: uint32_t getSyndrome23127(uint32_t pattern) const; uint32_t golay24128(const uint8_t* bytes) const; bool checksum(const uint8_t* fich) const; + void locked(bool lock); }; #endif From 7907ce69113d4ad9d67ac7b4fae252c27f8c6d8d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Mar 2016 06:36:47 +0000 Subject: [PATCH 026/329] Reset the sample count at the beginning of each transmission. --- DMRTX.cpp | 2 ++ DStarTX.cpp | 5 +++++ YSFTX.cpp | 2 ++ 3 files changed, 9 insertions(+) diff --git a/DMRTX.cpp b/DMRTX.cpp index 9f3142f..a3b9e7c 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -189,6 +189,8 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length) void CDMRTX::setStart(bool start) { m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE; + + m_count = 0U; } void CDMRTX::writeByte(uint8_t c, uint8_t control) diff --git a/DStarTX.cpp b/DStarTX.cpp index 236f333..1bbf95c 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -212,6 +212,8 @@ void CDStarTX::process() if (type == DSTAR_HEADER && m_poLen == 0U) { if (!m_tx) { + m_count = 0U; + for (uint16_t i = 0U; i < m_txDelay; i++) m_poBuffer[m_poLen++] = BIT_SYNC; } else { @@ -237,6 +239,9 @@ void CDStarTX::process() } if (type == DSTAR_DATA && m_poLen == 0U) { + if (!m_tx) + m_count = 0U; + // Pop the type byte off m_buffer.get(); diff --git a/YSFTX.cpp b/YSFTX.cpp index f72ab98..74bc398 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -61,6 +61,8 @@ void CYSFTX::process() if (m_poLen == 0U) { if (!m_tx) { + m_count = 0U; + for (uint16_t i = 0U; i < m_txDelay; i++) m_poBuffer[m_poLen++] = YSF_START_SYNC; } else { From 414fd9f779caa2cbfc1d1db4bcbdf7d4c4201600 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Mar 2016 06:44:08 +0000 Subject: [PATCH 027/329] Shift the control information in line with the samples. --- IO.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/IO.cpp b/IO.cpp index 5cdeed9..16eb272 100644 --- a/IO.cpp +++ b/IO.cpp @@ -198,6 +198,7 @@ void CIO::start() m_pinLED.write(1); #endif + m_count = 0U; m_started = true; } @@ -260,9 +261,9 @@ void CIO::process() q15_t samples[RX_BLOCK_SIZE + 1U]; uint8_t control[RX_BLOCK_SIZE + 1U]; - uint8_t blockSize = RX_BLOCK_SIZE; + uint8_t blockSize = RX_BLOCK_SIZE; - for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { + for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { uint16_t sample; m_rxBuffer.get(sample, control[i]); @@ -282,11 +283,14 @@ void CIO::process() if (m_count >= m_sampleCount) { if (m_sampleInsert) { - control[RX_BLOCK_SIZE] = control[RX_BLOCK_SIZE - 1U]; - samples[RX_BLOCK_SIZE] = 0; blockSize = RX_BLOCK_SIZE + 1U; + samples[RX_BLOCK_SIZE] = 0; + for (int8_t i = RX_BLOCK_SIZE - 1; i >= 0; i--) + control[i + 1] = control[i]; } else { blockSize = RX_BLOCK_SIZE - 1U; + for (uint8_t i = 0U; i < (RX_BLOCK_SIZE - 1U); i++) + control[i] = control[i + 1U]; } m_count -= m_sampleCount; From f656baf64ec17c8ed2385a3dfb5d18f8358b46fd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Mar 2016 06:45:59 +0000 Subject: [PATCH 028/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 4457bf2..394ed9f 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160317 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160322 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 8d3ede9160998cf5b1ff801ffa584741dd5ba4b2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 23 Mar 2016 17:46:21 +0000 Subject: [PATCH 029/329] Fix DMR timing bug with OscOffset. --- DMRTX.cpp | 14 ++++++++------ DStarTX.cpp | 6 +++--- IO.cpp | 4 ++-- SerialPort.cpp | 8 ++++---- YSFTX.cpp | 6 +++--- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index a3b9e7c..1588dfd 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -218,10 +218,11 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) } } - uint8_t blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U; + uint16_t blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U; uint8_t controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; ::memset(controlBuffer, MARK_NONE, (DMR_RADIO_SYMBOL_LENGTH * 4U + 1U) * sizeof(uint8_t)); + controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U] = control; // Handle the case of the oscillator not being accurate enough if (m_sampleCount > 0U) { @@ -230,17 +231,18 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) if (m_count >= m_sampleCount) { if (m_sampleInsert) { inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U - 1U]; - blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U + 1U; - controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U + 1U] = control; + for (int8_t i = DMR_RADIO_SYMBOL_LENGTH * 4U - 1; i >= 0; i--) + controlBuffer[i + 1] = controlBuffer[i]; + blockSize++; } else { - blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U - 1U; controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U - 1U] = control; + for (uint8_t i = 0U; i < (DMR_RADIO_SYMBOL_LENGTH * 4U - 1U); i++) + controlBuffer[i] = controlBuffer[i + 1U]; + blockSize--; } m_count -= m_sampleCount; } - } else { - controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U] = control; } ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); diff --git a/DStarTX.cpp b/DStarTX.cpp index 1bbf95c..6338773 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -424,7 +424,7 @@ void CDStarTX::writeByte(uint8_t c) mask <<= 1; } - uint8_t blockSize = DSTAR_RADIO_BIT_LENGTH * 8U; + uint16_t blockSize = DSTAR_RADIO_BIT_LENGTH * 8U; // Handle the case of the oscillator not being accurate enough if (m_sampleCount > 0U) { @@ -433,9 +433,9 @@ void CDStarTX::writeByte(uint8_t c) if (m_count >= m_sampleCount) { if (m_sampleInsert) { inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U] = inBuffer[DSTAR_RADIO_BIT_LENGTH * 8U - 1U]; - blockSize = DSTAR_RADIO_BIT_LENGTH * 8U + 1U; + blockSize++; } else { - blockSize = DSTAR_RADIO_BIT_LENGTH * 8U - 1U; + blockSize--; } m_count -= m_sampleCount; diff --git a/IO.cpp b/IO.cpp index 16eb272..57bf777 100644 --- a/IO.cpp +++ b/IO.cpp @@ -283,12 +283,12 @@ void CIO::process() if (m_count >= m_sampleCount) { if (m_sampleInsert) { - blockSize = RX_BLOCK_SIZE + 1U; + blockSize++; samples[RX_BLOCK_SIZE] = 0; for (int8_t i = RX_BLOCK_SIZE - 1; i >= 0; i--) control[i + 1] = control[i]; } else { - blockSize = RX_BLOCK_SIZE - 1U; + blockSize--; for (uint8_t i = 0U; i < (RX_BLOCK_SIZE - 1U); i++) control[i] = control[i + 1U]; } diff --git a/SerialPort.cpp b/SerialPort.cpp index 394ed9f..5536a68 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -210,11 +210,11 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t dmrDelay = data[7U]; int8_t oscOffset = int8_t(data[8U]) - 128; - if (oscOffset < 0) { - m_sampleCount = 1000000U / uint32_t(-oscOffset); - m_sampleInsert = true; - } else if (oscOffset > 0) { + if (oscOffset > 0) { m_sampleCount = 1000000U / uint32_t(oscOffset); + m_sampleInsert = true; + } else if (oscOffset < 0) { + m_sampleCount = 1000000U / uint32_t(-oscOffset); m_sampleInsert = false; } else { m_sampleCount = 0U; diff --git a/YSFTX.cpp b/YSFTX.cpp index 74bc398..34c9299 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -133,7 +133,7 @@ void CYSFTX::writeByte(uint8_t c) } } - uint8_t blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U; + uint16_t blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U; // Handle the case of the oscillator not being accurate enough if (m_sampleCount > 0U) { @@ -142,9 +142,9 @@ void CYSFTX::writeByte(uint8_t c) if (m_count >= m_sampleCount) { if (m_sampleInsert) { inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[YSF_RADIO_SYMBOL_LENGTH * 4U - 1U]; - blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U + 1U; + blockSize++; } else { - blockSize = YSF_RADIO_SYMBOL_LENGTH * 4U - 1U; + blockSize--; } m_count -= m_sampleCount; From 9e91a527930f4dbb972ba2cb9d6d8cc3936b8acf Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 23 Mar 2016 17:51:11 +0000 Subject: [PATCH 030/329] Bump the version date. --- SerialPort.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 5536a68..e2722a8 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160322 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160323 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; @@ -210,12 +210,12 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t dmrDelay = data[7U]; int8_t oscOffset = int8_t(data[8U]) - 128; - if (oscOffset > 0) { - m_sampleCount = 1000000U / uint32_t(oscOffset); - m_sampleInsert = true; - } else if (oscOffset < 0) { + if (oscOffset < 0) { m_sampleCount = 1000000U / uint32_t(-oscOffset); m_sampleInsert = false; + } else if (oscOffset > 0) { + m_sampleCount = 1000000U / uint32_t(oscOffset); + m_sampleInsert = true; } else { m_sampleCount = 0U; m_sampleInsert = false; From 17f212db3bff71830e121298c4077002ddeac225 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 23 Mar 2016 18:51:52 +0000 Subject: [PATCH 031/329] Add the EMB correlator for DMR. --- DMRDefines.h | 4 +- DMRSlotRX.cpp | 105 +++++++++++++++++++++++++++++++++++++------------- DMRSlotRX.h | 42 ++++++++++++-------- 3 files changed, 107 insertions(+), 44 deletions(-) diff --git a/DMRDefines.h b/DMRDefines.h index 2592500..23de540 100644 --- a/DMRDefines.h +++ b/DMRDefines.h @@ -76,8 +76,10 @@ const uint8_t DT_VOICE_LC_HEADER = 1U; const uint8_t DT_TERMINATOR_WITH_LC = 2U; const uint8_t DT_CSBK = 3U; const uint8_t DT_DATA_HEADER = 6U; +const uint8_t DT_RATE_12_DATA = 7U; +const uint8_t DT_RATE_34_DATA = 8U; const uint8_t DT_IDLE = 9U; -// All others are for data transfer +const uint8_t DT_RATE_1_DATA = 10U; #endif diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index bc7c40f..9eef38a 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -35,6 +35,24 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +const int8_t EMB_SYMBOLS[16U][5U][DMR_EMB_LENGTH_SYMBOLS] = { + {{+1, +1, +1, -1, +3, -3, +1, -3}, {+1, +1, +3, -1, -1, +3, +3, -1}, {+1, +1, +3, -1, -1, +3, +3, -1}, {+1, +1, +3, +1, -3, -1, +3, +3}, {+1, +1, +1, +1, +1, +1, +1, +1}}, + {{+1, +3, +1, -3, -1, +3, +1, +3}, {+1, +3, +3, -3, +3, -3, +3, +1}, {+1, +3, +3, -3, +3, -3, +3, +1}, {+1, +3, +3, +3, +1, +1, +3, -3}, {+1, +3, +1, +3, -3, -1, +1, -1}}, + {{+1, -1, +1, -3, -3, +1, +3, +1}, {+1, -1, +3, -3, +1, -1, +1, +3}, {+1, -1, +3, -3, +1, -1, +1, +3}, {+1, -1, +3, +3, +3, +3, +1, -1}, {+1, -1, +1, +3, -1, -3, +3, -3}}, + {{+1, -3, +1, -1, +1, -1, +3, -1}, {+1, -3, +3, -1, -3, +1, +1, -3}, {+1, -3, +3, -1, -3, +1, +1, -3}, {+1, -3, +3, +1, -1, -3, +1, +1}, {+1, -3, +1, +1, +3, +3, +3, +3}}, + {{+3, +1, +1, -3, +3, -1, -3, +3}, {+3, +1, +3, -3, -1, +1, -1, +1}, {+3, +1, +3, -3, -1, +1, -1, +1}, {+3, +1, +3, +3, -3, -3, -1, -3}, {+3, +1, +1, +3, +1, +3, -3, -1}}, + {{+3, +3, +1, -1, -1, +1, -3, -3}, {+3, +3, +3, -1, +3, -1, -1, -1}, {+3, +3, +3, -1, +3, -1, -1, -1}, {+3, +3, +3, +1, +1, +3, -1, +3}, {+3, +3, +1, +1, -3, -3, -3, +1}}, + {{+3, -1, +1, -1, -3, +3, -1, -1}, {+3, -1, +3, -1, +1, -3, -3, -3}, {+3, -1, +3, -1, +1, -3, -3, -3}, {+3, -1, +3, +1, +3, +1, -3, +1}, {+3, -1, +1, +1, -1, -1, -1, +3}}, + {{+3, -3, +1, -3, +1, -3, -1, +1}, {+3, -3, +3, -3, -3, +3, -3, +3}, {+3, -3, +3, -3, -3, +3, -3, +3}, {+3, -3, +3, +3, -1, -1, -3, -1}, {+3, -3, +1, +3, +3, +1, -1, -3}}, + {{-1, +1, +1, -1, +1, -3, -3, +1}, {-1, +1, +3, -1, -3, +3, -1, +3}, {-1, +1, +3, -1, -3, +3, -1, +3}, {-1, +1, +3, +1, -1, -1, -1, -1}, {-1, +1, +1, +1, +3, +1, -3, -3}}, + {{-1, +3, +1, -3, -3, +3, -3, -1}, {-1, +3, +3, -3, +1, -3, -1, -3}, {-1, +3, +3, -3, +1, -3, -1, -3}, {-1, +3, +3, +3, +3, +1, -1, +1}, {-1, +3, +1, +3, -1, -1, -3, +3}}, + {{-1, -1, +1, -3, -1, +1, -1, -3}, {-1, -1, +3, -3, +3, -1, -3, -1}, {-1, -1, +3, -3, +3, -1, -3, -1}, {-1, -1, +3, +3, +1, +3, -3, +3}, {-1, -1, +1, +3, -3, -3, -1, +1}}, + {{-1, -3, +1, -1, +3, -1, -1, +3}, {-1, -3, +3, -1, -1, +1, -3, +1}, {-1, -3, +3, -1, -1, +1, -3, +1}, {-1, -3, +3, +1, -3, -3, -3, -3}, {-1, -3, +1, +1, +1, +3, -1, -1}}, + {{-3, +1, +1, -3, +1, -1, +1, -1}, {-3, +1, +3, -3, -3, +1, +3, -3}, {-3, +1, +3, -3, -3, +1, +3, -3}, {-3, +1, +3, +3, -1, -3, +3, +1}, {-3, +1, +1, +3, +3, +3, +1, +3}}, + {{-3, +3, +1, -1, -3, +1, +1, +1}, {-3, +3, +3, -1, +1, -1, +3, +3}, {-3, +3, +3, -1, +1, -1, +3, +3}, {-3, +3, +3, +1, +3, +3, +3, -1}, {-3, +3, +1, +1, -1, -3, +1, -3}}, + {{-3, -1, +1, -1, -1, +3, +3, +3}, {-3, -1, +3, -1, +3, -3, +1, +1}, {-3, -1, +3, -1, +3, -3, +1, +1}, {-3, -1, +3, +1, +1, +1, +1, -3}, {-3, -1, +1, +1, -3, -1, +3, -1}}, + {{-3, -3, +1, -3, +3, -3, +3, -3}, {-3, -3, +3, -3, -1, +3, +1, -1}, {-3, -3, +3, -3, -1, +3, +1, -1}, {-3, -3, +3, +3, -3, -1, +1, +3}, {-3, -3, +1, +3, +1, +1, +3, +1}}}; + const uint16_t NOENDPTR = 9999U; CDMRSlotRX::CDMRSlotRX(bool slot) : @@ -53,6 +71,7 @@ m_control(0x00U), m_syncCount(0U), m_colorCode(0U), m_delay(0U), +m_state(DMRRXS_NONE), m_n(0U) { } @@ -77,6 +96,7 @@ void CDMRSlotRX::reset() m_syncCount = 0U; m_threshold = 0; m_centre = 0; + m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } @@ -84,11 +104,11 @@ bool CDMRSlotRX::processSample(q15_t sample) { m_delayPtr++; if (m_delayPtr < m_delay) - return m_endPtr != NOENDPTR; + return m_state != DMRRXS_NONE; // Ensure that the buffer doesn't overflow if (m_dataPtr > m_endPtr || m_dataPtr >= 900U) - return m_endPtr != NOENDPTR; + return m_state != DMRRXS_NONE; m_buffer[m_dataPtr] = sample; @@ -96,15 +116,23 @@ bool CDMRSlotRX::processSample(q15_t sample) if (sample < 0) m_bitBuffer[m_bitPtr] |= 0x01U; - // The approximate position of the sync samples - if (m_endPtr != NOENDPTR) { - uint16_t min = m_syncPtr - 5U; - uint16_t max = m_syncPtr + 5U; + if (m_state == DMRRXS_VOICE) { + uint16_t min = m_syncPtr - 2U; + uint16_t max = m_syncPtr + 2U; + if (m_dataPtr >= min && m_dataPtr <= max) { + if (m_n >= 5U) + correlateSync(); + else + correlateEMB(); + } + } else if (m_state == DMRRXS_DATA) { + uint16_t min = m_syncPtr - 2U; + uint16_t max = m_syncPtr + 2U; if (m_dataPtr >= min && m_dataPtr <= max) - correlateSync(sample); + correlateSync(); } else { if (m_dataPtr >= 420U && m_dataPtr <= 500U) - correlateSync(sample); + correlateSync(); } if (m_dataPtr == m_endPtr) { @@ -129,27 +157,21 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - DEBUG3("DMRSlotRX: data header for slot/data type", m_slot ? 2U : 1U, dataType); - m_endPtr = NOENDPTR; + case DT_RATE_12_DATA: + case DT_RATE_34_DATA: + case DT_RATE_1_DATA: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_DATA; break; case DT_VOICE_LC_HEADER: - DEBUG3("DMRSlotRX: voice header for slot/data type", m_slot ? 2U : 1U, dataType); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - break; case DT_VOICE_PI_HEADER: - DEBUG3("DMRSlotRX: pi header for slot/data type", m_slot ? 2U : 1U, dataType); - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - break; - case DT_TERMINATOR_WITH_LC: - DEBUG2("DMRSlotRX: terminator for slot", m_slot ? 2U : 1U); - m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_VOICE; break; default: - DEBUG3("DMRSlotRX: data sync for slot/data type", m_slot ? 2U : 1U, dataType); - m_endPtr = NOENDPTR; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; break; } } @@ -157,23 +179,26 @@ bool CDMRSlotRX::processSample(q15_t sample) // Voice sync DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_VOICE; m_syncCount = 0U; m_n = 0U; } else { m_syncCount++; if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { - DEBUG2("DMRSlotRX: lost for slot", m_slot ? 2U : 1U); serial.writeDMRLost(m_slot); m_syncCount = 0U; m_threshold = 0; m_centre = 0; + m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; return false; } // Voice data - frame[0U] |= ++m_n; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + if (m_state == DMRRXS_VOICE) { + frame[0U] |= ++m_n; + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + } } } @@ -183,10 +208,10 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_bitPtr >= DMR_RADIO_SYMBOL_LENGTH) m_bitPtr = 0U; - return m_endPtr != NOENDPTR; + return m_state != DMRRXS_NONE; } -void CDMRSlotRX::correlateSync(q15_t sample) +void CDMRSlotRX::correlateSync() { uint8_t errs = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_MS_DATA_SYNC_SYMBOLS); @@ -271,6 +296,34 @@ void CDMRSlotRX::correlateSync(q15_t sample) } } +void CDMRSlotRX::correlateEMB() +{ + uint8_t n = 0U; + q31_t corr = 0; + + // The beginning of the first section of the EMB is at the same place as the beginning of the sync + uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + for (uint8_t i = 0U; i < (DMR_EMB_LENGTH_SYMBOLS / 2U); i++, n++) { + corr += EMB_SYMBOLS[m_colorCode][m_n][n] * m_buffer[ptr]; + ptr += DMR_RADIO_SYMBOL_LENGTH; + } + + ptr = m_dataPtr - (DMR_EMB_LENGTH_SAMPLES / 2U) + DMR_RADIO_SYMBOL_LENGTH; + for (uint8_t i = 0U; i < (DMR_EMB_LENGTH_SYMBOLS / 2U); i++, n++) { + corr += EMB_SYMBOLS[m_colorCode][m_n][n] * m_buffer[ptr]; + ptr += DMR_RADIO_SYMBOL_LENGTH; + } + + if (corr > m_maxCorr) { +#if defined(WANT_DEBUG) + DEBUG3("DMRSlotRX: emb found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); +#endif + m_maxCorr = corr; + m_syncPtr = m_dataPtr; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + } +} + 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) { diff --git a/DMRSlotRX.h b/DMRSlotRX.h index aacbe2a..dbbfc59 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -22,6 +22,12 @@ #include "Config.h" #include "DMRDefines.h" +enum DMRRX_STATE { + DMRRXS_NONE, + DMRRXS_VOICE, + DMRRXS_DATA +}; + class CDMRSlotRX { public: CDMRSlotRX(bool slot); @@ -36,24 +42,26 @@ public: void reset(); private: - bool m_slot; - uint32_t m_bitBuffer[DMR_RADIO_SYMBOL_LENGTH]; - q15_t m_buffer[900U]; - uint16_t m_bitPtr; - uint16_t m_dataPtr; - uint16_t m_syncPtr; - uint16_t m_endPtr; - uint16_t m_delayPtr; - q31_t m_maxCorr; - q15_t m_centre; - q15_t m_threshold; - uint8_t m_control; - uint8_t m_syncCount; - uint8_t m_colorCode; - uint16_t m_delay; - uint8_t m_n; + bool m_slot; + uint32_t m_bitBuffer[DMR_RADIO_SYMBOL_LENGTH]; + q15_t m_buffer[900U]; + uint16_t m_bitPtr; + uint16_t m_dataPtr; + uint16_t m_syncPtr; + uint16_t m_endPtr; + uint16_t m_delayPtr; + q31_t m_maxCorr; + q15_t m_centre; + q15_t m_threshold; + uint8_t m_control; + uint8_t m_syncCount; + uint8_t m_colorCode; + uint16_t m_delay; + DMRRX_STATE m_state; + uint8_t m_n; - void correlateSync(q15_t sample); + void correlateSync(); + void correlateEMB(); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; From dee0020e11ca4cb2f760e88fca1e5ec77ac77ffe Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Mar 2016 06:56:02 +0000 Subject: [PATCH 032/329] More intelligent use of the m_n field. --- DMRSlotRX.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 9eef38a..68b42e9 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -177,7 +177,6 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == 0x20U) { // Voice sync - DEBUG2("DMRSlotRX: voice sync for slot", m_slot ? 2U : 1U); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; m_syncCount = 0U; @@ -196,8 +195,14 @@ bool CDMRSlotRX::processSample(q15_t sample) // Voice data if (m_state == DMRRXS_VOICE) { - frame[0U] |= ++m_n; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + if (m_n >= 5U) { + frame[0U] = 0x20U; + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_n = 0U; + } else { + frame[0U] |= ++m_n; + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + } } } } From 65c639a3c56d84ec1b568bbc7587a4819849bb46 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Mar 2016 12:55:48 +0000 Subject: [PATCH 033/329] Return control buffer initialisation to previous. --- DMRTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 1588dfd..380d390 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -221,7 +221,7 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) uint16_t blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U; uint8_t controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; - ::memset(controlBuffer, MARK_NONE, (DMR_RADIO_SYMBOL_LENGTH * 4U + 1U) * sizeof(uint8_t)); + ::memset(controlBuffer, MARK_NONE, DMR_RADIO_SYMBOL_LENGTH * 4U * sizeof(uint8_t)); controlBuffer[DMR_RADIO_SYMBOL_LENGTH * 2U] = control; // Handle the case of the oscillator not being accurate enough From c0c12bdb676d82c5e9f6408d1e2c81c4e5536ee8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Mar 2016 12:57:11 +0000 Subject: [PATCH 034/329] Remove excessive logging which slows the modem down. --- DMRSlotRX.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 68b42e9..3e461e3 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -320,9 +320,6 @@ void CDMRSlotRX::correlateEMB() } if (corr > m_maxCorr) { -#if defined(WANT_DEBUG) - DEBUG3("DMRSlotRX: emb found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); -#endif m_maxCorr = corr; m_syncPtr = m_dataPtr; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; From 01578235a865a5b8f3791c9f2e29c6a10bf1b631 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 25 Mar 2016 21:07:47 +0000 Subject: [PATCH 035/329] Remove EMB synchronisation (for now). --- DMRSlotRX.cpp | 24 ++++++++++-------------- DMRSlotRX.h | 1 + 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 3e461e3..eefc7d3 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -72,7 +72,8 @@ m_syncCount(0U), m_colorCode(0U), m_delay(0U), m_state(DMRRXS_NONE), -m_n(0U) +m_n(0U), +m_type(0U) { } @@ -116,23 +117,14 @@ bool CDMRSlotRX::processSample(q15_t sample) if (sample < 0) m_bitBuffer[m_bitPtr] |= 0x01U; - if (m_state == DMRRXS_VOICE) { - uint16_t min = m_syncPtr - 2U; - uint16_t max = m_syncPtr + 2U; - if (m_dataPtr >= min && m_dataPtr <= max) { - if (m_n >= 5U) - correlateSync(); - else - correlateEMB(); - } - } else if (m_state == DMRRXS_DATA) { + if (m_state == DMRRXS_NONE) { + if (m_dataPtr >= 420U && m_dataPtr <= 500U) + correlateSync(); + } else { uint16_t min = m_syncPtr - 2U; uint16_t max = m_syncPtr + 2U; if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(); - } else { - if (m_dataPtr >= 420U && m_dataPtr <= 500U) - correlateSync(); } if (m_dataPtr == m_endPtr) { @@ -162,6 +154,7 @@ bool CDMRSlotRX::processSample(q15_t sample) case DT_RATE_1_DATA: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_DATA; + m_type = dataType; break; case DT_VOICE_LC_HEADER: case DT_VOICE_PI_HEADER: @@ -203,6 +196,9 @@ bool CDMRSlotRX::processSample(q15_t sample) frame[0U] |= ++m_n; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } + } else if (m_state == DMRRXS_DATA) { + frame[0U] = 0x40U | m_type; + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } } } diff --git a/DMRSlotRX.h b/DMRSlotRX.h index dbbfc59..82918e6 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -59,6 +59,7 @@ private: uint16_t m_delay; DMRRX_STATE m_state; uint8_t m_n; + uint8_t m_type; void correlateSync(); void correlateEMB(); From 10345e52cccdece1ac94f0b5c06b766497160b20 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 26 Mar 2016 21:19:51 +0000 Subject: [PATCH 036/329] Remove the EMB correlator. --- DMRSlotRX.cpp | 43 ------------------------------------------- DMRSlotRX.h | 1 - 2 files changed, 44 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index eefc7d3..cb3de4a 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -35,24 +35,6 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) -const int8_t EMB_SYMBOLS[16U][5U][DMR_EMB_LENGTH_SYMBOLS] = { - {{+1, +1, +1, -1, +3, -3, +1, -3}, {+1, +1, +3, -1, -1, +3, +3, -1}, {+1, +1, +3, -1, -1, +3, +3, -1}, {+1, +1, +3, +1, -3, -1, +3, +3}, {+1, +1, +1, +1, +1, +1, +1, +1}}, - {{+1, +3, +1, -3, -1, +3, +1, +3}, {+1, +3, +3, -3, +3, -3, +3, +1}, {+1, +3, +3, -3, +3, -3, +3, +1}, {+1, +3, +3, +3, +1, +1, +3, -3}, {+1, +3, +1, +3, -3, -1, +1, -1}}, - {{+1, -1, +1, -3, -3, +1, +3, +1}, {+1, -1, +3, -3, +1, -1, +1, +3}, {+1, -1, +3, -3, +1, -1, +1, +3}, {+1, -1, +3, +3, +3, +3, +1, -1}, {+1, -1, +1, +3, -1, -3, +3, -3}}, - {{+1, -3, +1, -1, +1, -1, +3, -1}, {+1, -3, +3, -1, -3, +1, +1, -3}, {+1, -3, +3, -1, -3, +1, +1, -3}, {+1, -3, +3, +1, -1, -3, +1, +1}, {+1, -3, +1, +1, +3, +3, +3, +3}}, - {{+3, +1, +1, -3, +3, -1, -3, +3}, {+3, +1, +3, -3, -1, +1, -1, +1}, {+3, +1, +3, -3, -1, +1, -1, +1}, {+3, +1, +3, +3, -3, -3, -1, -3}, {+3, +1, +1, +3, +1, +3, -3, -1}}, - {{+3, +3, +1, -1, -1, +1, -3, -3}, {+3, +3, +3, -1, +3, -1, -1, -1}, {+3, +3, +3, -1, +3, -1, -1, -1}, {+3, +3, +3, +1, +1, +3, -1, +3}, {+3, +3, +1, +1, -3, -3, -3, +1}}, - {{+3, -1, +1, -1, -3, +3, -1, -1}, {+3, -1, +3, -1, +1, -3, -3, -3}, {+3, -1, +3, -1, +1, -3, -3, -3}, {+3, -1, +3, +1, +3, +1, -3, +1}, {+3, -1, +1, +1, -1, -1, -1, +3}}, - {{+3, -3, +1, -3, +1, -3, -1, +1}, {+3, -3, +3, -3, -3, +3, -3, +3}, {+3, -3, +3, -3, -3, +3, -3, +3}, {+3, -3, +3, +3, -1, -1, -3, -1}, {+3, -3, +1, +3, +3, +1, -1, -3}}, - {{-1, +1, +1, -1, +1, -3, -3, +1}, {-1, +1, +3, -1, -3, +3, -1, +3}, {-1, +1, +3, -1, -3, +3, -1, +3}, {-1, +1, +3, +1, -1, -1, -1, -1}, {-1, +1, +1, +1, +3, +1, -3, -3}}, - {{-1, +3, +1, -3, -3, +3, -3, -1}, {-1, +3, +3, -3, +1, -3, -1, -3}, {-1, +3, +3, -3, +1, -3, -1, -3}, {-1, +3, +3, +3, +3, +1, -1, +1}, {-1, +3, +1, +3, -1, -1, -3, +3}}, - {{-1, -1, +1, -3, -1, +1, -1, -3}, {-1, -1, +3, -3, +3, -1, -3, -1}, {-1, -1, +3, -3, +3, -1, -3, -1}, {-1, -1, +3, +3, +1, +3, -3, +3}, {-1, -1, +1, +3, -3, -3, -1, +1}}, - {{-1, -3, +1, -1, +3, -1, -1, +3}, {-1, -3, +3, -1, -1, +1, -3, +1}, {-1, -3, +3, -1, -1, +1, -3, +1}, {-1, -3, +3, +1, -3, -3, -3, -3}, {-1, -3, +1, +1, +1, +3, -1, -1}}, - {{-3, +1, +1, -3, +1, -1, +1, -1}, {-3, +1, +3, -3, -3, +1, +3, -3}, {-3, +1, +3, -3, -3, +1, +3, -3}, {-3, +1, +3, +3, -1, -3, +3, +1}, {-3, +1, +1, +3, +3, +3, +1, +3}}, - {{-3, +3, +1, -1, -3, +1, +1, +1}, {-3, +3, +3, -1, +1, -1, +3, +3}, {-3, +3, +3, -1, +1, -1, +3, +3}, {-3, +3, +3, +1, +3, +3, +3, -1}, {-3, +3, +1, +1, -1, -3, +1, -3}}, - {{-3, -1, +1, -1, -1, +3, +3, +3}, {-3, -1, +3, -1, +3, -3, +1, +1}, {-3, -1, +3, -1, +3, -3, +1, +1}, {-3, -1, +3, +1, +1, +1, +1, -3}, {-3, -1, +1, +1, -3, -1, +3, -1}}, - {{-3, -3, +1, -3, +3, -3, +3, -3}, {-3, -3, +3, -3, -1, +3, +1, -1}, {-3, -3, +3, -3, -1, +3, +1, -1}, {-3, -3, +3, +3, -3, -1, +1, +3}, {-3, -3, +1, +3, +1, +1, +3, +1}}}; - const uint16_t NOENDPTR = 9999U; CDMRSlotRX::CDMRSlotRX(bool slot) : @@ -297,31 +279,6 @@ void CDMRSlotRX::correlateSync() } } -void CDMRSlotRX::correlateEMB() -{ - uint8_t n = 0U; - q31_t corr = 0; - - // The beginning of the first section of the EMB is at the same place as the beginning of the sync - uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; - for (uint8_t i = 0U; i < (DMR_EMB_LENGTH_SYMBOLS / 2U); i++, n++) { - corr += EMB_SYMBOLS[m_colorCode][m_n][n] * m_buffer[ptr]; - ptr += DMR_RADIO_SYMBOL_LENGTH; - } - - ptr = m_dataPtr - (DMR_EMB_LENGTH_SAMPLES / 2U) + DMR_RADIO_SYMBOL_LENGTH; - for (uint8_t i = 0U; i < (DMR_EMB_LENGTH_SYMBOLS / 2U); i++, n++) { - corr += EMB_SYMBOLS[m_colorCode][m_n][n] * m_buffer[ptr]; - ptr += DMR_RADIO_SYMBOL_LENGTH; - } - - if (corr > m_maxCorr) { - m_maxCorr = corr; - m_syncPtr = m_dataPtr; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; - } -} - 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) { diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 82918e6..d924e40 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -62,7 +62,6 @@ private: uint8_t m_type; void correlateSync(); - void correlateEMB(); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; From da28bb373336ca4557e6eaea5af3af9c9efbc59d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 26 Mar 2016 21:37:34 +0000 Subject: [PATCH 037/329] Add external high stability oscillator support. --- Config.h | 5 +++++ IO.cpp | 25 +++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Config.h b/Config.h index 5b7a4b1..91e21c9 100644 --- a/Config.h +++ b/Config.h @@ -19,6 +19,11 @@ #if !defined(CONFIG_H) #define CONFIG_H +// Allow for the use of high quality external clock oscillators +// There is one entry for 12 MHz and another for 14.4 MHz +// #define EXTERNAL_OSC_12_MHZ +// #define EXTERNAL_OSC_14_4_MHZ + // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT diff --git a/IO.cpp b/IO.cpp index 57bf777..9cce0e9 100644 --- a/IO.cpp +++ b/IO.cpp @@ -1,5 +1,7 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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 @@ -160,20 +162,39 @@ void CIO::start() ADC->ADC_COR = 0x00000000; // All offsets off ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 +#if defined(EXTERNAL_OSC_12_MHZ) || defined(EXTERNAL_OSC_14_4_MHZ) + // Set up the external clock input on PA4 = AI5 + REG_PIOA_ODR = 0x10; // Set Pin As Input + REG_PIOA_PDR = 0x10; // Disable PIO A Bit 4 + REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input +#endif + // Set up the timer pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0 TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0 t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs t->TC_IDR = 0xFFFFFFFF; // Disable interrupts t->TC_SR; // Read int status reg to clear pending +#if defined(EXTERNAL_OSC_12_MHZ) || defined(EXTERNAL_OSC_14_4_MHZ) + t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 External clock +#else t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) +#endif TC_CMR_WAVE | // Waveform mode TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; - t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz clock (was 875) - t->TC_RA = 880; // Roughly square wave (was 440) +#if defined(EXTERNAL_OSC_14_4_MHZ) + t->TC_RC = 600; // Counter resets on RC, so sets period in terms of 14.4MHz External clock + t->TC_RA = 300; // Roughly square wave +#elif defined(EXTERNAL_OSC_12_MHZ) + t->TC_RC = 500; // Counter resets on RC, so sets period in terms of 12MHz External clock + t->TC_RA = 250; // Roughly square wave +#else + t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz Internal clock + t->TC_RA = 880; // Roughly square wave +#endif t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source. From 591ed534b58b727dea410e47742dd3b3ad544211 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 26 Mar 2016 21:38:37 +0000 Subject: [PATCH 038/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index e2722a8..192baa1 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160323 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160326 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From e6f86052ccaefaf0a0acb12b531ffd2ecfd1d92b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 27 Mar 2016 11:16:54 +0100 Subject: [PATCH 039/329] Rationalise the external clock compilation. --- Config.h | 10 +++++++--- IO.cpp | 21 +++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Config.h b/Config.h index 91e21c9..603b0a1 100644 --- a/Config.h +++ b/Config.h @@ -20,9 +20,13 @@ #define CONFIG_H // Allow for the use of high quality external clock oscillators -// There is one entry for 12 MHz and another for 14.4 MHz -// #define EXTERNAL_OSC_12_MHZ -// #define EXTERNAL_OSC_14_4_MHZ +// The number is the frequency of the oscillator in Hertz. +// For 12 MHz +// #define EXTERNAL_OSC 12000000 +// For 14.4 MHz +// #define EXTERNAL_OSC 14400000 +// For 19.2 MHz +// #define EXTERNAL_OSC 19200000 // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT diff --git a/IO.cpp b/IO.cpp index 9cce0e9..fae1e9e 100644 --- a/IO.cpp +++ b/IO.cpp @@ -162,10 +162,10 @@ void CIO::start() ADC->ADC_COR = 0x00000000; // All offsets off ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 -#if defined(EXTERNAL_OSC_12_MHZ) || defined(EXTERNAL_OSC_14_4_MHZ) +#if defined(EXTERNAL_OSC) // Set up the external clock input on PA4 = AI5 - REG_PIOA_ODR = 0x10; // Set Pin As Input - REG_PIOA_PDR = 0x10; // Disable PIO A Bit 4 + REG_PIOA_ODR = 0x10; // Set pin as input + REG_PIOA_PDR = 0x10; // Disable PIO A bit 4 REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input #endif @@ -175,8 +175,8 @@ void CIO::start() t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs t->TC_IDR = 0xFFFFFFFF; // Disable interrupts t->TC_SR; // Read int status reg to clear pending -#if defined(EXTERNAL_OSC_12_MHZ) || defined(EXTERNAL_OSC_14_4_MHZ) - t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 External clock +#if defined(EXTERNAL_OSC) + t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock #else t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) #endif @@ -185,14 +185,11 @@ void CIO::start() TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; -#if defined(EXTERNAL_OSC_14_4_MHZ) - t->TC_RC = 600; // Counter resets on RC, so sets period in terms of 14.4MHz External clock - t->TC_RA = 300; // Roughly square wave -#elif defined(EXTERNAL_OSC_12_MHZ) - t->TC_RC = 500; // Counter resets on RC, so sets period in terms of 12MHz External clock - t->TC_RA = 250; // Roughly square wave +#if defined(EXTERNAL_OSC) + t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock + t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave #else - t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz Internal clock + t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock t->TC_RA = 880; // Roughly square wave #endif t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares From e5f778b1c2773253e79b51edd278e15e381a8b98 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 27 Mar 2016 11:25:53 +0100 Subject: [PATCH 040/329] Rationalisation of the DMR slot demodulator. --- DMRSlotRX.cpp | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index cb3de4a..941d1ec 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -35,7 +35,9 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) -const uint16_t NOENDPTR = 9999U; +const unsigned char CONTROL_NONE = 0x00U; +const unsigned char CONTROL_VOICE = 0x20U; +const unsigned char CONTROL_DATA = 0x40U; CDMRSlotRX::CDMRSlotRX(bool slot) : m_slot(slot), @@ -44,12 +46,12 @@ m_buffer(), m_bitPtr(0U), m_dataPtr(0U), m_syncPtr(0U), -m_endPtr(NOENDPTR), +m_endPtr(0U), m_delayPtr(0U), m_maxCorr(0), m_centre(0), m_threshold(0), -m_control(0x00U), +m_control(CONTROL_NONE), m_syncCount(0U), m_colorCode(0U), m_delay(0U), @@ -65,7 +67,7 @@ void CDMRSlotRX::start() m_delayPtr = 0U; m_bitPtr = 0U; m_maxCorr = 0; - m_control = 0x00U; + m_control = CONTROL_NONE; } void CDMRSlotRX::reset() @@ -75,12 +77,11 @@ void CDMRSlotRX::reset() m_delayPtr = 0U; m_bitPtr = 0U; m_maxCorr = 0; - m_control = 0x00U; + m_control = CONTROL_NONE; m_syncCount = 0U; m_threshold = 0; m_centre = 0; m_state = DMRRXS_NONE; - m_endPtr = NOENDPTR; } bool CDMRSlotRX::processSample(q15_t sample) @@ -116,7 +117,7 @@ bool CDMRSlotRX::processSample(q15_t sample) uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centre, m_threshold); - if (m_control == 0x40U) { + if (m_control == CONTROL_DATA) { // Data sync uint8_t colorCode; uint8_t dataType; @@ -124,6 +125,8 @@ bool CDMRSlotRX::processSample(q15_t sample) slotType.decode(frame + 1U, colorCode, dataType); if (colorCode == m_colorCode) { + DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + m_syncCount = 0U; m_n = 0U; @@ -146,12 +149,12 @@ bool CDMRSlotRX::processSample(q15_t sample) default: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; - m_endPtr = NOENDPTR; break; } } - } else if (m_control == 0x20U) { + } else if (m_control == CONTROL_VOICE) { // Voice sync + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; m_syncCount = 0U; @@ -164,22 +167,21 @@ bool CDMRSlotRX::processSample(q15_t sample) m_threshold = 0; m_centre = 0; m_state = DMRRXS_NONE; - m_endPtr = NOENDPTR; return false; } // Voice data if (m_state == DMRRXS_VOICE) { if (m_n >= 5U) { - frame[0U] = 0x20U; + frame[0U] = CONTROL_VOICE; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_n = 0U; } else { - frame[0U] |= ++m_n; + frame[0U] = ++m_n; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } } else if (m_state == DMRRXS_DATA) { - frame[0U] = 0x40U | m_type; + frame[0U] = CONTROL_DATA | m_type; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } } @@ -242,16 +244,10 @@ void CDMRSlotRX::correlateSync() errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { -#if defined(WANT_DEBUG) - if (m_endPtr == NOENDPTR) - DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); - else - DEBUG3("DMRSlotRX: data sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); -#endif m_maxCorr = corr; m_centre = centre; m_threshold = threshold; - m_control = 0x40U; + m_control = CONTROL_DATA; m_syncPtr = m_dataPtr; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } @@ -261,16 +257,10 @@ void CDMRSlotRX::correlateSync() errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { -#if defined(WANT_DEBUG) - if (m_endPtr == NOENDPTR) - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); - else - DEBUG3("DMRSlotRX: voice sync found slot/rel pos", m_slot ? 2U : 1U, int16_t(m_dataPtr) - int16_t(m_syncPtr)); -#endif m_maxCorr = corr; m_centre = centre; m_threshold = threshold; - m_control = 0x20U; + m_control = CONTROL_VOICE; m_syncPtr = m_dataPtr; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } From 95f661a5810781a5ca7374a92fcbb3b9381f1489 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 27 Mar 2016 11:32:42 +0100 Subject: [PATCH 041/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 192baa1..03591af 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160326 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160327 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 2c11137d274fa15cb8cc0f3d9af13c4d2ae4eff0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 17:39:27 +0100 Subject: [PATCH 042/329] Restore the NOENDPTR for DMR. --- DMRSlotRX.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 941d1ec..b444ca1 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -35,6 +35,8 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +const uint16_t NOENDPTR = 9999U; + const unsigned char CONTROL_NONE = 0x00U; const unsigned char CONTROL_VOICE = 0x20U; const unsigned char CONTROL_DATA = 0x40U; @@ -46,7 +48,7 @@ m_buffer(), m_bitPtr(0U), m_dataPtr(0U), m_syncPtr(0U), -m_endPtr(0U), +m_endPtr(NOENDPTR), m_delayPtr(0U), m_maxCorr(0), m_centre(0), @@ -82,6 +84,7 @@ void CDMRSlotRX::reset() m_threshold = 0; m_centre = 0; m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; } bool CDMRSlotRX::processSample(q15_t sample) @@ -148,7 +151,8 @@ bool CDMRSlotRX::processSample(q15_t sample) break; default: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - m_state = DMRRXS_NONE; + m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; break; } } @@ -167,6 +171,7 @@ bool CDMRSlotRX::processSample(q15_t sample) m_threshold = 0; m_centre = 0; m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; return false; } From 428dcaa7d638eae893e5991247459b36902b9cb7 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 17:49:52 +0100 Subject: [PATCH 043/329] Revert the demodulator lock stiffening for D-Star and System Fusion. --- DStarRX.cpp | 28 +++++++++------------------- DStarRX.h | 2 -- YSFRX.cpp | 26 ++++++++------------------ YSFRX.h | 2 -- 4 files changed, 17 insertions(+), 41 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 12ed043..d0cb104 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -25,10 +25,9 @@ const unsigned int BUFFER_LENGTH = 200U; -const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; -const uint32_t INC_LOCK = PLLINC / 64U; -const uint32_t INC_UNLOCK = PLLINC / 32U; +const uint32_t PLLMAX = 0x10000U; +const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; +const uint32_t INC = PLLINC / 32U; const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; @@ -244,7 +243,6 @@ const uint16_t CCITT_TABLE[] = { CDStarRX::CDStarRX() : m_pll(0U), m_prev(false), -m_inc(INC_UNLOCK), m_rxState(DSRXS_NONE), m_patternBuffer(0x00U), m_rxBuffer(), @@ -266,7 +264,6 @@ void CDStarRX::reset() { m_pll = 0U; m_prev = false; - m_inc = INC_UNLOCK; m_rxState = DSRXS_NONE; m_patternBuffer = 0x00U; m_rxBufferBits = 0U; @@ -283,9 +280,9 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length) if (bit != m_prev) { if (m_pll < (PLLMAX / 2U)) - m_pll += m_inc; + m_pll += INC; else - m_pll -= m_inc; + m_pll -= INC; } m_prev = bit; @@ -336,7 +333,7 @@ void CDStarRX::processNone(bool bit) // Exact matching of the data sync bit sequence if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) { DEBUG1("DStarRX: found data sync in None"); - locked(true); + io.setDecode(true); #if defined(WANT_DEBUG) q15_t min = 16000; @@ -376,7 +373,7 @@ void CDStarRX::processHeader(bool bit) unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; bool ok = rxHeader(m_rxBuffer, header); if (ok) { - locked(true); + io.setDecode(true); serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); @@ -404,7 +401,7 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the end frame sequences if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { DEBUG1("DStarRX: Found end sync in Data"); - locked(false); + io.setDecode(false); serial.writeDStarEOT(); @@ -443,7 +440,7 @@ void CDStarRX::processData(bool bit) m_dataBits--; if (m_dataBits == 0U) { DEBUG1("DStarRX: data sync timed out, lost lock"); - locked(false); + io.setDecode(false); serial.writeDStarLost(); @@ -696,10 +693,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]; } -void CDStarRX::locked(bool lock) -{ - io.setDecode(lock); - - m_inc = lock ? INC_LOCK : INC_UNLOCK; -} - diff --git a/DStarRX.h b/DStarRX.h index da24e93..dd63ed3 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -39,7 +39,6 @@ public: private: uint32_t m_pll; bool m_prev; - uint32_t m_inc; DSRX_STATE m_rxState; uint32_t m_patternBuffer; uint8_t m_rxBuffer[100U]; @@ -63,7 +62,6 @@ private: void viterbiDecode(int* data); void traceBack(); bool checksum(const uint8_t* header) const; - void locked(bool lock); }; #endif diff --git a/YSFRX.cpp b/YSFRX.cpp index bfe82d4..d343ef5 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -27,10 +27,9 @@ const unsigned int BUFFER_LENGTH = 200U; const q15_t SCALING_FACTOR = 19505; // Q15(0.60) -const uint32_t PLLMAX = 0x10000U; -const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; -const uint32_t INC_UNLOCK = PLLINC / 32U; -const uint32_t INC_LOCK = PLLINC / 64U; +const uint32_t PLLMAX = 0x10000U; +const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; +const uint32_t INC = PLLINC / 32U; const uint8_t SYNC_SYMBOL_ERRS = 2U; const uint8_t SYNC_BIT_ERRS = 4U; @@ -312,7 +311,6 @@ static const unsigned short CCITT_TABLE[] = { CYSFRX::CYSFRX() : m_pll(0U), m_prev(false), -m_inc(INC_UNLOCK), m_state(YSFRXS_NONE), m_bitBuffer(0x00U), m_symbols(), @@ -337,7 +335,6 @@ void CYSFRX::reset() { m_pll = 0U; m_prev = false; - m_inc = INC_UNLOCK; m_state = YSFRXS_NONE; m_bitBuffer = 0x00U; m_bufferPtr = 0U; @@ -354,9 +351,9 @@ void CYSFRX::samples(const q15_t* samples, uint8_t length) if (bit != m_prev) { if (m_pll < (PLLMAX / 2U)) - m_pll += m_inc; + m_pll += INC; else - m_pll -= m_inc; + m_pll -= INC; } m_prev = bit; @@ -443,7 +440,7 @@ void CYSFRX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; m_state = YSFRXS_DATA; - locked(true); + io.setDecode(true); } } @@ -509,7 +506,7 @@ void CYSFRX::processData(q15_t sample) m_lostCount--; if (m_lostCount == 0U) { DEBUG1("YSFRX: sync timed out, lost lock"); - locked(false); + io.setDecode(false); serial.writeYSFLost(); @@ -534,7 +531,7 @@ void CYSFRX::processData(q15_t sample) if (ok && (FICH[0U] & 0xC0U) == 0x80U) { DEBUG1("YSFRX: end of transmission"); - locked(false); + io.setDecode(false); m_state = YSFRXS_NONE; } else { // Start the next frame @@ -699,10 +696,3 @@ bool CYSFRX::checksum(const uint8_t* fich) const return crc8[0U] == fich[5U] && crc8[1U] == fich[4U]; } -void CYSFRX::locked(bool lock) -{ - io.setDecode(lock); - - m_inc = lock ? INC_LOCK : INC_UNLOCK; -} - diff --git a/YSFRX.h b/YSFRX.h index cf2e172..785f4d7 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -38,7 +38,6 @@ public: private: uint32_t m_pll; bool m_prev; - uint32_t m_inc; YSFRX_STATE m_state; uint32_t m_symbolBuffer; uint64_t m_bitBuffer; @@ -65,7 +64,6 @@ private: uint32_t getSyndrome23127(uint32_t pattern) const; uint32_t golay24128(const uint8_t* bytes) const; bool checksum(const uint8_t* fich) const; - void locked(bool lock); }; #endif From e0a7ab66729b7cc744598121e85da0e8ee7615a0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 17:54:33 +0100 Subject: [PATCH 044/329] DMR start does not change the mode. --- SerialPort.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 03591af..2e98eee 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -459,13 +459,11 @@ void CSerialPort::process() if (m_dmrEnable) { err = 4U; if (m_len == 4U) { - if (m_buffer[3U] == 0x01U && m_modemState == STATE_IDLE) { + if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR) { dmrTX.setStart(true); - setMode(STATE_DMR); err = 0U; } else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR) { dmrTX.setStart(false); - setMode(STATE_IDLE); err = 0U; } } From c565a505a0fa377f59abaecccc91d5e6e7ef11a0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 18:11:46 +0100 Subject: [PATCH 045/329] Increase the minimum TX Delay for D-Star and System Fusion. --- DStarTX.cpp | 2 +- YSFTX.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DStarTX.cpp b/DStarTX.cpp index 6338773..c077b20 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -449,7 +449,7 @@ void CDStarTX::writeByte(uint8_t c) void CDStarTX::setTXDelay(uint8_t delay) { - m_txDelay = 60U + uint16_t(delay) * 6U; // 100ms + tx delay + m_txDelay = 120U + uint16_t(delay) * 6U; // 200ms + tx delay } uint16_t CDStarTX::getSpace() const diff --git a/YSFTX.cpp b/YSFTX.cpp index 34c9299..e3a06cb 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -158,7 +158,7 @@ void CYSFTX::writeByte(uint8_t c) void CYSFTX::setTXDelay(uint8_t delay) { - m_txDelay = 120U + uint16_t(delay) * 12U; // 100ms + tx delay + m_txDelay = 240U + uint16_t(delay) * 12U; // 200ms + tx delay } uint16_t CYSFTX::getSpace() const From fa1a1daa453365037815f6ccf682a4912eff4118 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 20:12:37 +0100 Subject: [PATCH 046/329] Only pass on relevent frame types. --- DMRSlotRX.cpp | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index b444ca1..c95b0aa 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -137,19 +137,35 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - case DT_RATE_12_DATA: - case DT_RATE_34_DATA: - case DT_RATE_1_DATA: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_DATA; m_type = dataType; break; + case DT_RATE_12_DATA: + case DT_RATE_34_DATA: + case DT_RATE_1_DATA: + if (m_state == DMRRXS_DATA) { + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_type = dataType; + } + break; case DT_VOICE_LC_HEADER: - case DT_VOICE_PI_HEADER: serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; break; - default: + case DT_VOICE_PI_HEADER: + if (m_state == DMRRXS_VOICE) + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_VOICE; + break; + case DT_TERMINATOR_WITH_LC: + if (m_state == DMRRXS_VOICE) { + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; + } + break; + default: // DT_CSBK serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; @@ -164,18 +180,18 @@ bool CDMRSlotRX::processSample(q15_t sample) m_syncCount = 0U; m_n = 0U; } else { - m_syncCount++; - if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { - serial.writeDMRLost(m_slot); - m_syncCount = 0U; - m_threshold = 0; - m_centre = 0; - m_state = DMRRXS_NONE; - m_endPtr = NOENDPTR; - return false; + if (m_state != DMRRXS_NONE) { + m_syncCount++; + if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { + serial.writeDMRLost(m_slot); + m_syncCount = 0U; + m_threshold = 0; + m_centre = 0; + m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; + } } - // Voice data if (m_state == DMRRXS_VOICE) { if (m_n >= 5U) { frame[0U] = CONTROL_VOICE; From f7395a5a22c3e3473c61ec4a1c14304364751e76 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Mar 2016 20:13:04 +0100 Subject: [PATCH 047/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 2e98eee..53be263 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160327 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160329 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 90186cbf90f816d06cc16d0436e7613b759e14d3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 30 Mar 2016 07:48:56 +0100 Subject: [PATCH 048/329] Handle being in DMR mode with no transmitter on. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index fae1e9e..1f60ad5 100644 --- a/IO.cpp +++ b/IO.cpp @@ -227,7 +227,7 @@ void CIO::process() // Two seconds timeout if (m_watchdog >= 48000U) { if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF) { - if (m_modemState == STATE_DMR) + if (m_modemState == STATE_DMR && m_tx) dmrTX.setStart(false); m_modemState = STATE_IDLE; } From d6e5b031418848c9cc2aba3ba8f186453e45cc47 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 30 Mar 2016 15:28:31 +0100 Subject: [PATCH 049/329] More checking for the DMR Start command. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 53be263..13346d4 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -459,10 +459,10 @@ void CSerialPort::process() if (m_dmrEnable) { err = 4U; if (m_len == 4U) { - if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR) { + if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR && !m_tx) { dmrTX.setStart(true); err = 0U; - } else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR) { + } else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR && m_tx) { dmrTX.setStart(false); err = 0U; } From 25bfeef5a39f08452919dc4db86f750138f2582d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 31 Mar 2016 11:29:30 +0100 Subject: [PATCH 050/329] More intelligent DMR Start command. --- SerialPort.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 13346d4..b806cef 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -459,11 +459,13 @@ void CSerialPort::process() if (m_dmrEnable) { err = 4U; if (m_len == 4U) { - if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR && !m_tx) { - dmrTX.setStart(true); + if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR) { + if (!m_tx) + dmrTX.setStart(true); err = 0U; - } else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR && m_tx) { - dmrTX.setStart(false); + } else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR) { + if (m_tx) + dmrTX.setStart(false); err = 0U; } } From d5f065d89be752f49dbc0df5b8d0701f8bfecb87 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 1 Apr 2016 09:06:08 +0100 Subject: [PATCH 051/329] Reduce the size of the RX_BLOCK_SIZE. --- Globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Globals.h b/Globals.h index a97c2c3..d64a64f 100644 --- a/Globals.h +++ b/Globals.h @@ -59,7 +59,7 @@ const uint8_t MARK_SLOT1 = 0x08U; const uint8_t MARK_SLOT2 = 0x04U; const uint8_t MARK_NONE = 0x00U; -const uint16_t RX_BLOCK_SIZE = 20U; +const uint16_t RX_BLOCK_SIZE = 2U; extern MMDVM_STATE m_modemState; From 2e67f92f678e0160c2e43ad74d20bf5d4e3dff61 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 1 Apr 2016 09:06:47 +0100 Subject: [PATCH 052/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index b806cef..85a368f 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160329 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160401 (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From d2b858e51f157be1c6e2ee1a823c25a49e249a18 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 3 Apr 2016 19:21:24 +0100 Subject: [PATCH 053/329] Align with 48kHz branch. --- DMRSlotRX.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index c95b0aa..35b48d6 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -104,11 +104,11 @@ bool CDMRSlotRX::processSample(q15_t sample) m_bitBuffer[m_bitPtr] |= 0x01U; if (m_state == DMRRXS_NONE) { - if (m_dataPtr >= 420U && m_dataPtr <= 500U) + if (m_dataPtr >= 420U && m_dataPtr <= 455U) correlateSync(); } else { - uint16_t min = m_syncPtr - 2U; - uint16_t max = m_syncPtr + 2U; + uint16_t min = m_syncPtr - 1U; + uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(); } @@ -128,8 +128,6 @@ bool CDMRSlotRX::processSample(q15_t sample) slotType.decode(frame + 1U, colorCode, dataType); if (colorCode == m_colorCode) { - DEBUG5("DMRSlotRX: data sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); - m_syncCount = 0U; m_n = 0U; @@ -137,6 +135,7 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: + DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_DATA; m_type = dataType; @@ -145,27 +144,33 @@ bool CDMRSlotRX::processSample(q15_t sample) case DT_RATE_34_DATA: case DT_RATE_1_DATA: if (m_state == DMRRXS_DATA) { - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - m_type = dataType; + DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_type = dataType; } break; case DT_VOICE_LC_HEADER: + DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; break; case DT_VOICE_PI_HEADER: - if (m_state == DMRRXS_VOICE) + if (m_state == DMRRXS_VOICE) { + DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + } 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, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } break; default: // DT_CSBK + DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; From b155e72c546ed2be605ba3cd4e384e2552c90a46 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 3 Apr 2016 19:23:13 +0100 Subject: [PATCH 054/329] Match the 48kHz modem message. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 85a368f..3505b45 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160401 (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160401 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From bbf8b0dbbcc09c1ad9e8cbf529b34eceec7ba354 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 4 Apr 2016 19:22:04 +0100 Subject: [PATCH 055/329] Clean up the DMR Idle RX. --- DMRIdleRX.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 44a596e..2121a47 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -33,12 +33,17 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +const uint16_t NOENDPTR = 9999U; + +const uint8_t CONTROL_IDLE = 0x80U; +const uint8_t CONTROL_DATA = 0x40U; + CDMRIdleRX::CDMRIdleRX() : m_bitBuffer(), m_buffer(), m_bitPtr(0U), m_dataPtr(0U), -m_endPtr(999U), +m_endPtr(NOENDPTR), m_maxCorr(0), m_centre(0), m_threshold(0), @@ -53,7 +58,7 @@ void CDMRIdleRX::reset() m_maxCorr = 0; m_threshold = 0; m_centre = 0; - m_endPtr = 999U; + m_endPtr = NOENDPTR; } void CDMRIdleRX::samples(const q15_t* samples, uint8_t length) @@ -140,15 +145,11 @@ void CDMRIdleRX::processSample(q15_t sample) slotType.decode(frame + 1U, colorCode, dataType); if (colorCode == m_colorCode && dataType == DT_CSBK) { - frame[0U] = 0x80U | 0x40U | DT_CSBK; // Idle RX, Data Sync, CSBK + frame[0U] = CONTROL_IDLE | CONTROL_DATA | DT_CSBK; serial.writeDMRData(false, frame, DMR_FRAME_LENGTH_BYTES + 1U); -#if defined(WANT_DEBUG) - } else { - DEBUG5("DMRIdleRX: invalid color code or data type", colorCode, m_colorCode, dataType, DT_CSBK); -#endif } - m_endPtr = 999U; + m_endPtr = NOENDPTR; m_maxCorr = 0U; } From 48fb023f1de07c946fd6fde6a8356f8465b18b54 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 4 Apr 2016 19:29:15 +0100 Subject: [PATCH 056/329] Clean up the DMR Slot RX. --- DMRSlotRX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 35b48d6..8bb56bc 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -37,9 +37,9 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 const uint16_t NOENDPTR = 9999U; -const unsigned char CONTROL_NONE = 0x00U; -const unsigned char CONTROL_VOICE = 0x20U; -const unsigned char CONTROL_DATA = 0x40U; +const uint8_t CONTROL_NONE = 0x00U; +const uint8_t CONTROL_VOICE = 0x20U; +const uint8_t CONTROL_DATA = 0x40U; CDMRSlotRX::CDMRSlotRX(bool slot) : m_slot(slot), From a6fd81bae4190d5fff6fd8d89930dfe10e7fa621 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 11 Apr 2016 11:06:52 +0100 Subject: [PATCH 057/329] Add level averaging to the DMR slot receiver. --- DMRSlotRX.cpp | 96 ++++++++++++++++++++++++++++++++------------------- DMRSlotRX.h | 7 ++-- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 8bb56bc..c99c0d5 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -51,8 +51,9 @@ m_syncPtr(0U), m_endPtr(NOENDPTR), m_delayPtr(0U), m_maxCorr(0), -m_centre(0), -m_threshold(0), +m_centre(), +m_threshold(), +m_averagePtr(0U), m_control(CONTROL_NONE), m_syncCount(0U), m_colorCode(0U), @@ -81,8 +82,6 @@ void CDMRSlotRX::reset() m_maxCorr = 0; m_control = CONTROL_NONE; m_syncCount = 0U; - m_threshold = 0; - m_centre = 0; m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } @@ -105,20 +104,24 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_state == DMRRXS_NONE) { if (m_dataPtr >= 420U && m_dataPtr <= 455U) - correlateSync(); + correlateSync(true); } else { uint16_t min = m_syncPtr - 1U; uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) - correlateSync(); + correlateSync(false); } if (m_dataPtr == m_endPtr) { + // Find the average centre and threshold values + q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; + q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + uint8_t frame[DMR_FRAME_LENGTH_BYTES + 1U]; frame[0U] = m_control; uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; - samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centre, m_threshold); + samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, centre, threshold); if (m_control == CONTROL_DATA) { // Data sync @@ -135,42 +138,42 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_DATA; - m_type = dataType; + m_type = 0x00U; break; case DT_RATE_12_DATA: case DT_RATE_34_DATA: case DT_RATE_1_DATA: if (m_state == DMRRXS_DATA) { - DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); - m_type = dataType; + m_type = dataType; } break; case DT_VOICE_LC_HEADER: - DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); 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, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } 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, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } break; default: // DT_CSBK - DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; @@ -179,7 +182,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == CONTROL_VOICE) { // Voice sync - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, m_centre, m_threshold); + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; m_syncCount = 0U; @@ -189,11 +192,8 @@ bool CDMRSlotRX::processSample(q15_t sample) m_syncCount++; if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { serial.writeDMRLost(m_slot); - m_syncCount = 0U; - m_threshold = 0; - m_centre = 0; - m_state = DMRRXS_NONE; - m_endPtr = NOENDPTR; + m_state = DMRRXS_NONE; + m_endPtr = NOENDPTR; } } @@ -207,8 +207,10 @@ bool CDMRSlotRX::processSample(q15_t sample) serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } } else if (m_state == DMRRXS_DATA) { - frame[0U] = CONTROL_DATA | m_type; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + if (m_type != 0x00U) { + frame[0U] = CONTROL_DATA | m_type; + serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); + } } } } @@ -222,7 +224,7 @@ bool CDMRSlotRX::processSample(q15_t sample) return m_state != DMRRXS_NONE; } -void CDMRSlotRX::correlateSync() +void CDMRSlotRX::correlateSync(bool first) { uint8_t errs = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_MS_DATA_SYNC_SYMBOLS); @@ -270,12 +272,23 @@ void CDMRSlotRX::correlateSync() errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - m_maxCorr = corr; - m_centre = centre; - m_threshold = threshold; - m_control = CONTROL_DATA; - m_syncPtr = m_dataPtr; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + if (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; + } else { + m_threshold[m_averagePtr] = threshold; + m_centre[m_averagePtr] = centre; + + m_averagePtr++; + if (m_averagePtr >= 4U) + m_averagePtr = 0U; + } + + m_maxCorr = corr; + m_control = CONTROL_DATA; + m_syncPtr = m_dataPtr; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } else { // if (voice) uint8_t errs = 0U; @@ -283,12 +296,23 @@ void CDMRSlotRX::correlateSync() errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]); if (errs <= MAX_SYNC_BYTES_ERRS) { - m_maxCorr = corr; - m_centre = centre; - m_threshold = threshold; - m_control = CONTROL_VOICE; - m_syncPtr = m_dataPtr; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + if (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; + } else { + m_threshold[m_averagePtr] = threshold; + m_centre[m_averagePtr] = centre; + + m_averagePtr++; + if (m_averagePtr >= 4U) + m_averagePtr = 0U; + } + + m_maxCorr = corr; + m_control = CONTROL_VOICE; + m_syncPtr = m_dataPtr; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } } diff --git a/DMRSlotRX.h b/DMRSlotRX.h index d924e40..6c3c446 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -51,8 +51,9 @@ private: uint16_t m_endPtr; uint16_t m_delayPtr; q31_t m_maxCorr; - q15_t m_centre; - q15_t m_threshold; + q15_t m_centre[4U]; + q15_t m_threshold[4U]; + uint8_t m_averagePtr; uint8_t m_control; uint8_t m_syncCount; uint8_t m_colorCode; @@ -61,7 +62,7 @@ private: uint8_t m_n; uint8_t m_type; - void correlateSync(); + void correlateSync(bool first); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; From 76846d53ed046ea3e3fee997377de3718c920243 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 11 Apr 2016 11:12:03 +0100 Subject: [PATCH 058/329] Open up the DMR sync window a little. --- DMRSlotRX.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index c99c0d5..7a4c77b 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -103,7 +103,7 @@ bool CDMRSlotRX::processSample(q15_t sample) m_bitBuffer[m_bitPtr] |= 0x01U; if (m_state == DMRRXS_NONE) { - if (m_dataPtr >= 420U && m_dataPtr <= 455U) + if (m_dataPtr >= 415U && m_dataPtr <= 455U) correlateSync(true); } else { uint16_t min = m_syncPtr - 1U; @@ -138,7 +138,7 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_DATA; m_type = 0x00U; @@ -147,33 +147,33 @@ bool CDMRSlotRX::processSample(q15_t sample) case DT_RATE_34_DATA: case DT_RATE_1_DATA: if (m_state == DMRRXS_DATA) { - DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_type = dataType; } break; case DT_VOICE_LC_HEADER: - DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); 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, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); } 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, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } break; default: // DT_CSBK - DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; @@ -182,7 +182,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == CONTROL_VOICE) { // Voice sync - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 420, centre, threshold); + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; m_syncCount = 0U; From c69066c59170060e93ad3dce20c88b4df0cdd64a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 11 Apr 2016 11:12:59 +0100 Subject: [PATCH 059/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 3505b45..e752f4a 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160401 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160411 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 81596b754dd23cb2feb56e3c34c1d99849ab4d01 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 12 Apr 2016 18:41:02 +0100 Subject: [PATCH 060/329] Remove the YSF FICH decoding. --- YSFRX.cpp | 458 +----------------------------------------------------- YSFRX.h | 12 -- 2 files changed, 8 insertions(+), 462 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index d343ef5..17e9009 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -41,273 +41,6 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -const uint8_t INTERLEAVE_TABLE_RX[] = { - 0U, 40U, 80U, 120U, 160U, - 2U, 42U, 82U, 122U, 162U, - 4U, 44U, 84U, 124U, 164U, - 6U, 46U, 86U, 126U, 166U, - 8U, 48U, 88U, 128U, 168U, - 10U, 50U, 90U, 130U, 170U, - 12U, 52U, 92U, 132U, 172U, - 14U, 54U, 94U, 134U, 174U, - 16U, 56U, 96U, 136U, 176U, - 18U, 58U, 98U, 138U, 178U, - 20U, 60U, 100U, 140U, 180U, - 22U, 62U, 102U, 142U, 182U, - 24U, 64U, 104U, 144U, 184U, - 26U, 66U, 106U, 146U, 186U, - 28U, 68U, 108U, 148U, 188U, - 30U, 70U, 110U, 150U, 190U, - 32U, 72U, 112U, 152U, 192U, - 34U, 74U, 114U, 154U, 194U, - 36U, 76U, 116U, 156U, 196U, - 38U, 78U, 118U, 158U, 198U}; - -const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U}; - -const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U}; - -const uint32_t DECODING_TABLE_23127[] = { - 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, - 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, - 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, - 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, - 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, - 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, - 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, - 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, - 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, - 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, - 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, - 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, - 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, - 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, - 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, - 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, - 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, - 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, - 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, - 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, - 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, - 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, - 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, - 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, - 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, - 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, - 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, - 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, - 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, - 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, - 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, - 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, - 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, - 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, - 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, - 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, - 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, - 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, - 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, - 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, - 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, - 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, - 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, - 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, - 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, - 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, - 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, - 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, - 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, - 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, - 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, - 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, - 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, - 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, - 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, - 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, - 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, - 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, - 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, - 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, - 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, - 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, - 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, - 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, - 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, - 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, - 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, - 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, - 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, - 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, - 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, - 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, - 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, - 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, - 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, - 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, - 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, - 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, - 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, - 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, - 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, - 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, - 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, - 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, - 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, - 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, - 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, - 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, - 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, - 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, - 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, - 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, - 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, - 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, - 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, - 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, - 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, - 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, - 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, - 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, - 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, - 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, - 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, - 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, - 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, - 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, - 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, - 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, - 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, - 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, - 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, - 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, - 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, - 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, - 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, - 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, - 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, - 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, - 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, - 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, - 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, - 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, - 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, - 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, - 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, - 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, - 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, - 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, - 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, - 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, - 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, - 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, - 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, - 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, - 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, - 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, - 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, - 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, - 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, - 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, - 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, - 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, - 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, - 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, - 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, - 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, - 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, - 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, - 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, - 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, - 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, - 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, - 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, - 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, - 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, - 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, - 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, - 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, - 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, - 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, - 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, - 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, - 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, - 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, - 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, - 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, - 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, - 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, - 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, - 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, - 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, - 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, - 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, - 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, - 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, - 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, - 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, - 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, - 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, - 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, - 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, - 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, - 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, - 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, - 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, - 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, - 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, - 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, - 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, - 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, - 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, - 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, - 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, - 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, - 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, - 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, - 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, - 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, - 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, - 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, - 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, - 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, - 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, - 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, - 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U}; - -static const unsigned short CCITT_TABLE[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; - CYSFRX::CYSFRX() : m_pll(0U), m_prev(false), @@ -320,13 +53,7 @@ m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), m_centre(0), -m_threshold(0), -m_metrics1(), -m_metrics2(), -m_oldMetrics(NULL), -m_newMetrics(NULL), -m_decisions(), -m_dp(NULL) +m_threshold(0) { m_buffer = m_outBuffer + 1U; } @@ -483,6 +210,8 @@ void CYSFRX::processData(q15_t sample) m_bufferPtr++; } + bool found = false; + // Only search for a sync in the right place +-1 symbol if (m_bufferPtr >= (YSF_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (YSF_SYNC_LENGTH_BITS + 2U)) { // Fuzzy matching of the data sync bit sequence @@ -497,6 +226,7 @@ void CYSFRX::processData(q15_t sample) #endif m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; + found = true; } } @@ -513,186 +243,14 @@ void CYSFRX::processData(q15_t sample) m_state = YSFRXS_NONE; return; } else { - uint8_t FICH[6U]; - bool ok = rxFICH(m_buffer + YSF_SYNC_LENGTH_BYTES, FICH); - -#if defined(WANT_DEBUG) - if (ok) - DEBUG5("YSFRX: Valid FICH", FICH[0U], FICH[1U], FICH[2U], FICH[3U]); - else - DEBUG5("YSFRX: Invalid FICH", FICH[0U], FICH[1U], FICH[2U], FICH[3U]); -#endif - - m_outBuffer[0U] = (FICH[0U] & 0xC0U) << 0; // FI - m_outBuffer[0U] |= (FICH[2U] & 0x03U) << 4; // DT - m_outBuffer[0U] |= ok ? 0x01U : 0x00U; + m_outBuffer[0U] = found ? 0x01U : 0x00U; serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); - if (ok && (FICH[0U] & 0xC0U) == 0x80U) { - DEBUG1("YSFRX: end of transmission"); - io.setDecode(false); - m_state = YSFRXS_NONE; - } else { - // Start the next frame - ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 1U); - m_bufferPtr = 0U; - } + // Start the next frame + ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 1U); + m_bufferPtr = 0U; } } } -const unsigned int NUM_OF_STATES_D2 = 8U; -const unsigned int NUM_OF_STATES = 16U; -const uint32_t M = 3U; -const unsigned int K = 5U; - -bool CYSFRX::rxFICH(uint8_t* data, uint8_t* FICH) -{ - ::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); - ::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); - m_oldMetrics = m_metrics1; - m_newMetrics = m_metrics2; - m_dp = m_decisions; - - // Deinterleave the FICH and send bits to the Viterbi decoder - for (uint8_t i = 0U; i < 100U; i++) { - uint8_t n = INTERLEAVE_TABLE_RX[i]; - uint8_t s0 = READ_BIT1(data, n) ? 1U : 0U; - - n++; - uint8_t s1 = READ_BIT1(data, n) ? 1U : 0U; - - viterbiDecode(s0, s1); - } - - uint8_t output[13U]; - chainback(output); - - uint32_t b0 = golay24128(output + 0U); - uint32_t b1 = golay24128(output + 3U); - uint32_t b2 = golay24128(output + 6U); - uint32_t b3 = golay24128(output + 9U); - - FICH[0U] = (b0 >> 16) & 0xFFU; - FICH[1U] = ((b0 >> 8) & 0xF0U) | ((b1 >> 20) & 0x0FU); - FICH[2U] = (b1 >> 12) & 0xFFU; - FICH[3U] = (b2 >> 16) & 0xFFU; - FICH[4U] = ((b2 >> 8) & 0xF0U) | ((b3 >> 20) & 0x0FU); - FICH[5U] = (b3 >> 12) & 0xFFU; - - return checksum(FICH); -} - -void CYSFRX::viterbiDecode(uint8_t s0, uint8_t s1) -{ - *m_dp = 0U; - - for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) { - uint8_t j = i * 2U; - - uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1); - - uint16_t m0 = m_oldMetrics[i] + metric; - uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric); - uint8_t decision0 = (m0 >= m1) ? 1U : 0U; - m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0; - - m0 = m_oldMetrics[i] + (M - metric); - m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric; - uint8_t decision1 = (m0 >= m1) ? 1U : 0U; - m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0; - - *m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U)); - } - - ++m_dp; - - uint16_t* tmp = m_oldMetrics; - m_oldMetrics = m_newMetrics; - m_newMetrics = tmp; -} - -void CYSFRX::chainback(uint8_t *out) -{ - uint32_t state = 0U; - - uint8_t nbits = 96U; - while (nbits-- > 0) { - --m_dp; - - uint32_t i = state >> (9 - K); - uint8_t bit = uint8_t(*m_dp >> i) & 1; - state = (bit << 7) | (state >> 1); - - WRITE_BIT1(out, nbits, bit != 0U); - } -} - -#define X22 0x00400000 /* vector representation of X^{22} */ -#define X11 0x00000800 /* vector representation of X^{11} */ -#define MASK12 0xfffff800 /* auxiliary vector for testing */ -#define GENPOL 0x00000c75 /* generator polinomial, g(x) */ - -uint32_t CYSFRX::getSyndrome23127(uint32_t pattern) const -/* - * Compute the syndrome corresponding to the given pattern, i.e., the - * remainder after dividing the pattern (when considering it as the vector - * representation of a polynomial) by the generator polynomial, GENPOL. - * In the program this pattern has several meanings: (1) pattern = infomation - * bits, when constructing the encoding table; (2) pattern = error pattern, - * when constructing the decoding table; and (3) pattern = received vector, to - * obtain its syndrome in decoding. - */ -{ - uint32_t aux = X22; - - if (pattern >= X11) { - while (pattern & MASK12) { - while (!(aux & pattern)) - aux = aux >> 1; - - pattern ^= (aux / X11) * GENPOL; - } - } - - return pattern; -} - -uint32_t CYSFRX::golay24128(const uint8_t* bytes) const -{ - uint32_t code = bytes[0U]; - code <<= 8; - code |= bytes[1U]; - code <<= 8; - code |= bytes[2U]; - - code >>= 1; - - uint32_t syndrome = getSyndrome23127(code); - uint32_t error_pattern = DECODING_TABLE_23127[syndrome]; - - code ^= error_pattern; - code <<= 1; - - return code; -} - -bool CYSFRX::checksum(const uint8_t* fich) const -{ - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; - - crc16 = 0U; - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT_TABLE[crc8[1U] ^ fich[0U]]; - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT_TABLE[crc8[1U] ^ fich[1U]]; - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT_TABLE[crc8[1U] ^ fich[2U]]; - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT_TABLE[crc8[1U] ^ fich[3U]]; - - crc16 = ~crc16; - - return crc8[0U] == fich[5U] && crc8[1U] == fich[4U]; -} - diff --git a/YSFRX.h b/YSFRX.h index 785f4d7..22228ce 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -49,21 +49,9 @@ private: uint16_t m_lostCount; q15_t m_centre; q15_t m_threshold; - uint16_t m_metrics1[16U]; - uint16_t m_metrics2[16U]; - uint16_t* m_oldMetrics; - uint16_t* m_newMetrics; - uint64_t m_decisions[100U]; - uint64_t* m_dp; void processNone(q15_t sample); void processData(q15_t sample); - bool rxFICH(uint8_t* data, uint8_t* FICH); - void viterbiDecode(uint8_t s0, uint8_t s1); - void chainback(uint8_t* out); - uint32_t getSyndrome23127(uint32_t pattern) const; - uint32_t golay24128(const uint8_t* bytes) const; - bool checksum(const uint8_t* fich) const; }; #endif From fadef361c1beb41c678d5d96f354fbb7a0cd9d4f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 12 Apr 2016 19:37:00 +0100 Subject: [PATCH 061/329] Clean up the YSF RX. --- YSFRX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index 17e9009..e9c8796 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -230,7 +230,7 @@ void CYSFRX::processData(q15_t sample) } } - // Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen + // Send a data frame to the host if the required number of bits have been received if (m_bufferPtr == YSF_FRAME_LENGTH_BITS) { // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE m_lostCount--; @@ -241,7 +241,6 @@ void CYSFRX::processData(q15_t sample) serial.writeYSFLost(); m_state = YSFRXS_NONE; - return; } else { m_outBuffer[0U] = found ? 0x01U : 0x00U; From 154a9049f47789a47ca45fc2ebdcc286dbdd66d2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 12 Apr 2016 19:38:59 +0100 Subject: [PATCH 062/329] Clean up the YSF RX. --- YSFRX.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index e9c8796..66f37dc 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -216,14 +216,7 @@ void CYSFRX::processData(q15_t sample) if (m_bufferPtr >= (YSF_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (YSF_SYNC_LENGTH_BITS + 2U)) { // Fuzzy matching of the data sync bit sequence if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_ERRS) { -#if defined(WANT_DEBUG) - if (m_bufferPtr < YSF_SYNC_LENGTH_BITS) - DEBUG2("YSFRX: found sync in Data, early", YSF_SYNC_LENGTH_BITS - m_bufferPtr); - else if (m_bufferPtr > YSF_SYNC_LENGTH_BITS) - DEBUG2("YSFRX: found sync in Data, late", m_bufferPtr - YSF_SYNC_LENGTH_BITS); - else - DEBUG1("YSFRX: found sync in Data"); -#endif + DEBUG2("YSFRX: found sync in Data, pos", m_bufferPtr - YSF_SYNC_LENGTH_BITS); m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; found = true; From c054ea925916b1ac2bb0c55fa77ad90393ba125d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 12 Apr 2016 20:10:44 +0100 Subject: [PATCH 063/329] Small mistake in the YSF RX. --- YSFRX.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index 66f37dc..0ccaccd 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -210,8 +210,6 @@ void CYSFRX::processData(q15_t sample) m_bufferPtr++; } - bool found = false; - // Only search for a sync in the right place +-1 symbol if (m_bufferPtr >= (YSF_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (YSF_SYNC_LENGTH_BITS + 2U)) { // Fuzzy matching of the data sync bit sequence @@ -219,7 +217,6 @@ void CYSFRX::processData(q15_t sample) DEBUG2("YSFRX: found sync in Data, pos", m_bufferPtr - YSF_SYNC_LENGTH_BITS); m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; - found = true; } } @@ -235,7 +232,7 @@ void CYSFRX::processData(q15_t sample) m_state = YSFRXS_NONE; } else { - m_outBuffer[0U] = found ? 0x01U : 0x00U; + m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); From 275c63368b0f3e32c79dfd717d21aa81fdcd8dea Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 12 Apr 2016 21:47:06 +0100 Subject: [PATCH 064/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index e752f4a..c4adc3f 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -57,7 +57,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160411 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160412 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 8bfff17ace46044cd15d9db3828bc749c829dc55 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 13 Apr 2016 08:01:01 +0100 Subject: [PATCH 065/329] Increase the YSF TX buffer. --- YSFTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YSFTX.cpp b/YSFTX.cpp index e3a06cb..7c669eb 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -38,7 +38,7 @@ q15_t YSF_D[] = {-1408, -1408, -1408, -1408, -1408}; CYSFTX::CYSFTX() : -m_buffer(), +m_buffer(1500U), m_modFilter(), m_modState(), m_poBuffer(), From 51f26b133008337a939e010d0299402e82f37ab3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 17:42:38 +0100 Subject: [PATCH 066/329] Add DMR calibration. --- CalDMR.cpp | 49 +++++++++++++++++++++++++++++++++++++ CalDMR.h | 39 +++++++++++++++++++++++++++++ CalRX.cpp => CalDStarRX.cpp | 10 ++++---- CalRX.h => CalDStarRX.h | 10 ++++---- CalTX.cpp => CalDStarTX.cpp | 10 ++++---- CalTX.h => CalDStarTX.h | 10 ++++---- DMRTX.cpp | 25 ++++++++++++++++++- DMRTX.h | 6 ++++- Globals.h | 15 +++++++----- IO.cpp | 4 +-- MMDVM.cpp | 13 +++++++--- MMDVM.ino | 13 +++++++--- SerialPort.cpp | 26 ++++++++++++++------ 13 files changed, 184 insertions(+), 46 deletions(-) create mode 100644 CalDMR.cpp create mode 100644 CalDMR.h rename CalRX.cpp => CalDStarRX.cpp (93%) rename CalRX.h => CalDStarRX.h (87%) rename CalTX.cpp => CalDStarTX.cpp (97%) rename CalTX.h => CalDStarTX.h (86%) diff --git a/CalDMR.cpp b/CalDMR.cpp new file mode 100644 index 0000000..5622c1d --- /dev/null +++ b/CalDMR.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" +#include "CalDMR.h" + + +CCalDMR::CCalDMR() : +m_transmit(false) +{ +} + +void CCalDMR::process() +{ + if (m_transmit) { + dmrTX.setCal(true); + dmrTX.process(); + } else { + dmrTX.setCal(false); + } +} + +uint8_t CCalDMR::write(const uint8_t* data, uint8_t length) +{ + if (length != 1U) + return 4U; + + m_transmit = data[0U] == 1U; + + return 0U; +} + diff --git a/CalDMR.h b/CalDMR.h new file mode 100644 index 0000000..c3231c5 --- /dev/null +++ b/CalDMR.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(CALDMR_H) +#define CALDMR_H + +#include "Config.h" +#include "DMRDefines.h" + +class CCalDMR { +public: + CCalDMR(); + + void process(); + + uint8_t write(const uint8_t* data, uint8_t length); + +private: + bool m_transmit; +}; + +#endif + diff --git a/CalRX.cpp b/CalDStarRX.cpp similarity index 93% rename from CalRX.cpp rename to CalDStarRX.cpp index c37f191..32b6345 100644 --- a/CalRX.cpp +++ b/CalDStarRX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -18,7 +18,7 @@ #include "Config.h" #include "Globals.h" -#include "CalRX.h" +#include "CalDStarRX.h" #include "Utils.h" const unsigned int BUFFER_LENGTH = 200U; @@ -33,7 +33,7 @@ const uint32_t DATA_SYNC_DATA2 = 0x00554B97U; const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU; const uint8_t DATA_SYNC_ERRS = 2U; -CCalRX::CCalRX() : +CCalDStarRX::CCalDStarRX() : m_pll(0U), m_prev(false), m_patternBuffer(0x00U), @@ -42,7 +42,7 @@ m_ptr(0U) { } -void CCalRX::samples(const q15_t* samples, uint8_t length) +void CCalDStarRX::samples(const q15_t* samples, uint8_t length) { for (uint16_t i = 0U; i < length; i++) { bool bit = samples[i] < 0; @@ -65,7 +65,7 @@ void CCalRX::samples(const q15_t* samples, uint8_t length) } } -void CCalRX::process(q15_t value) +void CCalDStarRX::process(q15_t value) { m_patternBuffer <<= 1; if (value < 0) diff --git a/CalRX.h b/CalDStarRX.h similarity index 87% rename from CalRX.h rename to CalDStarRX.h index cc1ba67..9b2c067 100644 --- a/CalRX.h +++ b/CalDStarRX.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 @@ -16,15 +16,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(CALRX_H) -#define CALRX_H +#if !defined(CALDSTARRX_H) +#define CALDSTARRX_H #include "Config.h" #include "DStarDefines.h" -class CCalRX { +class CCalDStarRX { public: - CCalRX(); + CCalDStarRX(); void samples(const q15_t* samples, uint8_t length); diff --git a/CalTX.cpp b/CalDStarTX.cpp similarity index 97% rename from CalTX.cpp rename to CalDStarTX.cpp index 4534d1e..1c1a3a4 100644 --- a/CalTX.cpp +++ b/CalDStarTX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2009-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 @@ -18,7 +18,7 @@ #include "Config.h" #include "Globals.h" -#include "CalTX.h" +#include "CalDStarTX.h" const uint8_t HEADER[] = {0x00U, 0x00U, 0x00U, 'D', 'I', 'R', 'E', 'C', 'T', ' ', ' ', 'D', 'I', 'R', 'E', 'C', 'T', ' ', ' ', @@ -28,13 +28,13 @@ const uint8_t HEADER[] = {0x00U, 0x00U, 0x00U, 'D', 'I', 'R', 'E', 'C', 'T', ' ' const uint8_t SLOW_DATA_TEXT[] = {'M', 'M', 'D', 'V', 'M', ' ', 'M', 'o', 'd', 'e', 'm', ' ', 'T', 'e', 's', 't', ' ', ' ', ' ', ' '}; -CCalTX::CCalTX() : +CCalDStarTX::CCalDStarTX() : m_transmit(false), m_count(0U) { } -void CCalTX::process() +void CCalDStarTX::process() { dstarTX.process(); @@ -162,7 +162,7 @@ void CCalTX::process() m_count = (m_count + 1U) % (30U * 21U); } -uint8_t CCalTX::write(const uint8_t* data, uint8_t length) +uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length) { if (length != 1U) return 4U; diff --git a/CalTX.h b/CalDStarTX.h similarity index 86% rename from CalTX.h rename to CalDStarTX.h index cd6a374..c411317 100644 --- a/CalTX.h +++ b/CalDStarTX.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 @@ -16,15 +16,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(CALTX_H) -#define CALTX_H +#if !defined(CALDSTARTX_H) +#define CALDSTARTX_H #include "Config.h" #include "DStarDefines.h" -class CCalTX { +class CCalDStarTX { public: - CCalTX(); + CCalDStarTX(); uint8_t write(const uint8_t* data, uint8_t length); diff --git a/DMRTX.cpp b/DMRTX.cpp index 380d390..031d15e 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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 @@ -97,7 +98,11 @@ void CDMRTX::process() createData(1U); m_state = DMRTXSTATE_CACH1; break; - + + case DMRTXSTATE_CAL: + createCal(); + break; + default: createCACH(0U, 1U); m_state = DMRTXSTATE_SLOT1; @@ -193,6 +198,13 @@ void CDMRTX::setStart(bool start) m_count = 0U; } +void CDMRTX::setCal(bool start) +{ + m_state = start ? DMRTXSTATE_CAL : DMRTXSTATE_IDLE; + + m_count = 0U; +} + void CDMRTX::writeByte(uint8_t c, uint8_t control) { q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; @@ -279,6 +291,17 @@ void CDMRTX::createData(uint8_t slotIndex) m_poPtr = 0U; } +void CDMRTX::createCal() +{ + for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) { + m_poBuffer[i] = 0x5FU; // +3, +3, -3, -3 pattern for deviation cal. + m_markBuffer[i] = MARK_NONE; + } + + m_poLen = DMR_FRAME_LENGTH_BYTES; + m_poPtr = 0U; +} + void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex) { if (m_cachPtr >= 12U) diff --git a/DMRTX.h b/DMRTX.h index 7fc499d..2db5f3f 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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 @@ -29,7 +30,8 @@ enum DMRTXSTATE { DMRTXSTATE_SLOT1, DMRTXSTATE_CACH1, DMRTXSTATE_SLOT2, - DMRTXSTATE_CACH2 + DMRTXSTATE_CACH2, + DMRTXSTATE_CAL }; class CDMRTX { @@ -41,6 +43,7 @@ public: uint8_t writeShortLC(const uint8_t* data, uint8_t length); void setStart(bool start); + void setCal(bool start); void process(); @@ -66,6 +69,7 @@ private: void createData(uint8_t slotIndex); void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex); + void createCal(); void writeByte(uint8_t c, uint8_t control); }; diff --git a/Globals.h b/Globals.h index d64a64f..0e7116f 100644 --- a/Globals.h +++ b/Globals.h @@ -39,7 +39,8 @@ enum MMDVM_STATE { STATE_DSTAR = 1, STATE_DMR = 2, STATE_YSF = 3, - STATE_CALIBRATE = 99 + STATE_DMRCAL = 98, + STATE_DSTARCAL = 99 }; #include "SerialPort.h" @@ -50,8 +51,9 @@ enum MMDVM_STATE { #include "DMRTX.h" #include "YSFRX.h" #include "YSFTX.h" -#include "CalRX.h" -#include "CalTX.h" +#include "CalDStarRX.h" +#include "CalDStarTX.h" +#include "CalDMR.h" #include "Debug.h" #include "IO.h" @@ -70,7 +72,7 @@ extern bool m_ysfEnable; extern bool m_tx; extern uint32_t m_sampleCount; -extern bool m_sampleInsert; +extern bool m_sampleInsert; extern CSerialPort serial; extern CIO io; @@ -85,8 +87,9 @@ extern CDMRTX dmrTX; extern CYSFRX ysfRX; extern CYSFTX ysfTX; -extern CCalRX calRX; -extern CCalTX calTX; +extern CCalDStarRX calDStarRX; +extern CCalDStarTX calDStarTX; +extern CCalDMR calDMR; #endif diff --git a/IO.cpp b/IO.cpp index 1f60ad5..1c9bac7 100644 --- a/IO.cpp +++ b/IO.cpp @@ -361,11 +361,11 @@ void CIO::process() ysfRX.samples(C4FSKVals, blockSize); } - } else if (m_modemState == STATE_CALIBRATE) { + } else if (m_modemState == STATE_DSTARCAL) { q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); - calRX.samples(GMSKVals, blockSize); + calDStarRX.samples(GMSKVals, blockSize); } } } diff --git a/MMDVM.cpp b/MMDVM.cpp index 734b20e..1f14e88 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2016 by Mathis Schmieder DB9MAT + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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 @@ -44,8 +45,9 @@ CDMRTX dmrTX; CYSFRX ysfRX; CYSFTX ysfTX; -CCalRX calRX; -CCalTX calTX; +CCalDStarRX calDStarRX; +CCalDStarTX calDStarTX; +CCalDMR calDMR; CSerialPort serial; CIO io; @@ -71,8 +73,11 @@ void loop() if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); - if (m_modemState == STATE_CALIBRATE) - calTX.process(); + if (m_modemState == STATE_DSTARCAL) + calDStarTX.process(); + + if (m_modemState == STATE_DMRCAL) + calDMR.process(); } int main() diff --git a/MMDVM.ino b/MMDVM.ino index d9c2041..f84c25f 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -1,5 +1,6 @@ /* * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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,8 +42,9 @@ CDMRTX dmrTX; CYSFRX ysfRX; CYSFTX ysfTX; -CCalRX calRX; -CCalTX calTX; +CCalDStarRX calDStarRX; +CCalDStarTX calDStarTX; +CCalDMR calDMR; CSerialPort serial; CIO io; @@ -68,7 +70,10 @@ void loop() if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); - if (m_modemState == STATE_CALIBRATE) - calTX.process(); + if (m_modemState == STATE_DSTARCAL) + calDStarTX.process(); + + if (m_modemState == STATE_DMRCAL) + calDMR.process(); } diff --git a/SerialPort.cpp b/SerialPort.cpp index c4adc3f..e8bc328 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013,2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML * * 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 @@ -57,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160412 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160413 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; @@ -191,7 +192,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) MMDVM_STATE modemState = MMDVM_STATE(data[3U]); - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_CALIBRATE) + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) return 4U; if (modemState == STATE_DSTAR && !dstarEnable) return 4U; @@ -252,7 +253,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length) if (modemState == m_modemState) return 0U; - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_CALIBRATE) + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) return 4U; if (modemState == STATE_DSTAR && !m_dstarEnable) return 4U; @@ -286,8 +287,15 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrRX.reset(); dstarRX.reset(); break; - case STATE_CALIBRATE: - DEBUG1("Mode set to Calibrate"); + case STATE_DSTARCAL: + DEBUG1("Mode set to D-Star Calibrate"); + dmrIdleRX.reset(); + dmrRX.reset(); + dstarRX.reset(); + ysfRX.reset(); + break; + case STATE_DMRCAL: + DEBUG1("Mode set to DMR Calibrate"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); @@ -375,8 +383,10 @@ void CSerialPort::process() break; case MMDVM_CAL_DATA: - if (m_modemState == STATE_CALIBRATE) - err = calTX.write(m_buffer + 3U, m_len - 3U); + if (m_modemState == STATE_DSTARCAL) + err = calDStarTX.write(m_buffer + 3U, m_len - 3U); + if (m_modemState == STATE_DMRCAL) + err = calDMR.write(m_buffer + 3U, m_len - 3U); if (err == 0U) { sendACK(); } else { @@ -673,7 +683,7 @@ void CSerialPort::writeYSFLost() void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) { - if (m_modemState != STATE_CALIBRATE) + if (m_modemState != STATE_DSTARCAL) return; uint8_t reply[130U]; From 67aec1907eef749e69edfdd36d6e53bc3e691c85 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 18:38:02 +0100 Subject: [PATCH 067/329] Reduce the transmit levels by half. --- DMRTX.cpp | 8 ++++---- DStarTX.cpp | 4 ++-- YSFTX.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 031d15e..dcd1397 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -27,10 +27,10 @@ static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1 -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; -q15_t DMR_A[] = { 1280, 1280, 1280, 1280, 1280}; -q15_t DMR_B[] = { 427, 427, 427, 427, 427}; -q15_t DMR_C[] = { -427, -427, -427, -427, -427}; -q15_t DMR_D[] = {-1280, -1280, -1280, -1280, -1280}; +q15_t DMR_A[] = { 640, 640, 640, 640, 640}; +q15_t DMR_B[] = { 213, 213, 213, 213, 213}; +q15_t DMR_C[] = {-213, -213, -213, -213, -213}; +q15_t DMR_D[] = {-640, -640, -640, -640, -640}; // The PR FILL and Data Sync pattern. const uint8_t IDLE_DATA[] = diff --git a/DStarTX.cpp b/DStarTX.cpp index c077b20..7b4bf66 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -30,8 +30,8 @@ const uint8_t FRAME_SYNC[] = {0xEAU, 0xA6U, 0x00U}; static q15_t DSTAR_GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; const uint16_t DSTAR_GMSK_FILTER_LEN = 12U; -q15_t DSTAR_1[] = { 1600, 1600, 1600, 1600, 1600}; -q15_t DSTAR_0[] = {-1600, -1600, -1600, -1600, -1600}; +q15_t DSTAR_1[] = { 800, 800, 800, 800, 800}; +q15_t DSTAR_0[] = {-800, -800, -800, -800, -800}; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; diff --git a/YSFTX.cpp b/YSFTX.cpp index 7c669eb..7fc1561 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -31,10 +31,10 @@ const uint16_t YSF_C4FSK_FILTER_LEN = 42U; const uint8_t YSF_START_SYNC = 0x77U; const uint8_t YSF_END_SYNC = 0xFFU; -q15_t YSF_A[] = { 1408, 1408, 1408, 1408, 1408}; -q15_t YSF_B[] = { 470, 470, 470, 470, 470}; -q15_t YSF_C[] = { -470, -470, -470, -470, -470}; -q15_t YSF_D[] = {-1408, -1408, -1408, -1408, -1408}; +q15_t YSF_A[] = { 704, 704, 704, 704, 704}; +q15_t YSF_B[] = { 235, 235, 235, 235, 235}; +q15_t YSF_C[] = {-235, -235, -235, -235, -235}; +q15_t YSF_D[] = {-704, -704, -704, -704, -704}; CYSFTX::CYSFTX() : From ca2c7c34187bdd34c47e52a7cf4002b71026772a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 18:38:39 +0100 Subject: [PATCH 068/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index e8bc328..24353b6 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -58,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160413 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160414 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 114f720ccce74dd9aa87303561214b706e10b570 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 21:27:28 +0100 Subject: [PATCH 069/329] Small tweak to the CACH. --- DMRTX.cpp | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index dcd1397..851b7df 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -45,7 +45,7 @@ const uint8_t CACH_INTERLEAVE[] = 73U, 74U, 75U, 77U, 78U, 79U, 81U, 82U, 83U, 85U, 87U, 88U, 89U, 91U, 92U, 93U, 95U}; const uint8_t EMPTY_SHORT_LC[] = - {0x00U, 0x08U, 0x44U, 0x00U, 0x88U, 0x18U, 0x63U, 0x89U, 0x18U, 0x64U, 0x80U, 0x00U}; + {0x00U, 0x00U, 0x44U, 0x00U, 0x00U, 0x18U, 0x63U, 0x01U, 0x18U, 0x64U, 0x00U, 0x00U}; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -182,12 +182,6 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length) WRITE_BIT1(m_newShortLC, n, b); } - // Set the LCSS bits - m_newShortLC[1U] |= 0x08U; - m_newShortLC[4U] |= 0x88U; - m_newShortLC[7U] |= 0x88U; - m_newShortLC[10U] |= 0x80U; - return 0U; } @@ -321,23 +315,25 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex) bool at = m_fifo[rxSlotIndex].getData() > 0U; bool tc = txSlotIndex == 1U; - bool lcss0 = true; // For 1 and 2 - bool lcss1 = true; + bool ls0 = true; // For 1 and 2 + bool ls1 = true; if (m_cachPtr == 0U) // For 0 - lcss0 = false; + ls0 = false; else if (m_cachPtr == 9U) // For 3 - lcss1 = false; + ls1 = false; - bool h0 = at ^ tc ^ lcss0; - bool h1 = tc ^ lcss0 ^ lcss1; - bool h2 = at ^ tc ^ lcss1; + bool h0 = at ^ tc ^ ls0; + bool h1 = tc ^ ls0 ^ ls1; + bool h2 = at ^ tc ^ ls1; - m_poBuffer[0U] |= at ? 0x80U : 0x00U; - m_poBuffer[0U] |= tc ? 0x08U : 0x00U; - m_poBuffer[1U] |= h0 ? 0x02U : 0x00U; - m_poBuffer[2U] |= h1 ? 0x20U : 0x00U; - m_poBuffer[2U] |= h2 ? 0x02U : 0x00U; + m_poBuffer[0U] |= at ? 0x80U : 0x00U; + m_poBuffer[0U] |= tc ? 0x08U : 0x00U; + m_poBuffer[1U] |= ls0 ? 0x80U : 0x00U; + m_poBuffer[1U] |= ls1 ? 0x08U : 0x00U; + m_poBuffer[1U] |= h0 ? 0x02U : 0x00U; + m_poBuffer[2U] |= h1 ? 0x20U : 0x00U; + m_poBuffer[2U] |= h2 ? 0x02U : 0x00U; m_poLen = DMR_CACH_LENGTH_BYTES; m_poPtr = 0U; From fba27219f2b17dbf1b83c3fce21e34f0a226e310 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 21:50:48 +0100 Subject: [PATCH 070/329] Update the empty short LC. --- DMRTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 851b7df..8eedae1 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -45,7 +45,7 @@ const uint8_t CACH_INTERLEAVE[] = 73U, 74U, 75U, 77U, 78U, 79U, 81U, 82U, 83U, 85U, 87U, 88U, 89U, 91U, 92U, 93U, 95U}; const uint8_t EMPTY_SHORT_LC[] = - {0x00U, 0x00U, 0x44U, 0x00U, 0x00U, 0x18U, 0x63U, 0x01U, 0x18U, 0x64U, 0x00U, 0x00U}; + {0x00U, 0x00U, 0x44U, 0x00U, 0x00U, 0x18U, 0x03U, 0x14U, 0x08U, 0x63U, 0x20U, 0x00U}; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; From 9d9bba49020d46f435d5e589acb13aa81166a0c3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Apr 2016 22:05:01 +0100 Subject: [PATCH 071/329] Swap LS1 and LS0 over to match the DMR specification. --- DMRTX.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 8eedae1..dd918f1 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -319,18 +319,18 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex) bool ls1 = true; if (m_cachPtr == 0U) // For 0 - ls0 = false; - else if (m_cachPtr == 9U) // For 3 ls1 = false; + else if (m_cachPtr == 9U) // For 3 + ls0 = false; - bool h0 = at ^ tc ^ ls0; - bool h1 = tc ^ ls0 ^ ls1; - bool h2 = at ^ tc ^ ls1; + bool h0 = at ^ tc ^ ls1; + bool h1 = tc ^ ls1 ^ ls0; + bool h2 = at ^ tc ^ ls0; m_poBuffer[0U] |= at ? 0x80U : 0x00U; m_poBuffer[0U] |= tc ? 0x08U : 0x00U; - m_poBuffer[1U] |= ls0 ? 0x80U : 0x00U; - m_poBuffer[1U] |= ls1 ? 0x08U : 0x00U; + m_poBuffer[1U] |= ls1 ? 0x80U : 0x00U; + m_poBuffer[1U] |= ls0 ? 0x08U : 0x00U; m_poBuffer[1U] |= h0 ? 0x02U : 0x00U; m_poBuffer[2U] |= h1 ? 0x20U : 0x00U; m_poBuffer[2U] |= h2 ? 0x02U : 0x00U; From ca3f07b8d39bcab035196badfce8f09e217922a6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 18 Apr 2016 21:45:52 +0100 Subject: [PATCH 072/329] Switch off debugging. --- YSFRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index 0ccaccd..b1d2c5a 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" From 8dd97c02cffb09865112d3560e44e11b19c19dbf Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 19 Apr 2016 19:53:20 +0100 Subject: [PATCH 073/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 24353b6..a9646d3 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -58,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160414 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160419 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From c711bfe858dba2385250b0ae2b6382eb9997f8fd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 20 Apr 2016 07:26:01 +0100 Subject: [PATCH 074/329] Modify the threshold for YSF. --- YSFRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index b1d2c5a..4a6849d 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -25,7 +25,7 @@ const unsigned int BUFFER_LENGTH = 200U; -const q15_t SCALING_FACTOR = 19505; // Q15(0.60) +const q15_t SCALING_FACTOR = 18750; // Q15(0.55) const uint32_t PLLMAX = 0x10000U; const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; From fb2581d2e765409f2138896dcd0d0f273ce19bef Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 26 Apr 2016 18:47:37 +0100 Subject: [PATCH 075/329] Switch off DMR receive debugging. --- DMRSlotRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 7a4c77b..3100b2f 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" From fe59e4191558a0861511034cbf3950659f0ce963 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 26 Apr 2016 18:48:07 +0100 Subject: [PATCH 076/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index a9646d3..a6d5851 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -58,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160419 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160426 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 731a33aef87420ef4def0110c0b53e596addbc54 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 28 Apr 2016 18:39:25 +0100 Subject: [PATCH 077/329] Open up the sync search range. --- DMRSlotRX.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 3100b2f..81b8c26 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -103,7 +103,7 @@ bool CDMRSlotRX::processSample(q15_t sample) m_bitBuffer[m_bitPtr] |= 0x01U; if (m_state == DMRRXS_NONE) { - if (m_dataPtr >= 415U && m_dataPtr <= 455U) + if (m_dataPtr >= 400U && m_dataPtr <= 490U) correlateSync(true); } else { uint16_t min = m_syncPtr - 1U; @@ -138,7 +138,7 @@ bool CDMRSlotRX::processSample(q15_t sample) switch (dataType) { case DT_DATA_HEADER: - DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); + 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); m_state = DMRRXS_DATA; m_type = 0x00U; @@ -147,33 +147,33 @@ bool CDMRSlotRX::processSample(q15_t sample) case DT_RATE_34_DATA: case DT_RATE_1_DATA: if (m_state == DMRRXS_DATA) { - DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); + 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); m_type = dataType; } break; case DT_VOICE_LC_HEADER: - DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); + 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); 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, int16_t(m_dataPtr) - 415, centre, threshold); + 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); } 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, int16_t(m_dataPtr) - 415, centre, threshold); + 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); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; } break; default: // DT_CSBK - DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); + 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); m_state = DMRRXS_NONE; m_endPtr = NOENDPTR; @@ -182,7 +182,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } } else if (m_control == CONTROL_VOICE) { // Voice sync - DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, int16_t(m_dataPtr) - 415, centre, threshold); + DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_state = DMRRXS_VOICE; m_syncCount = 0U; From b8497a869a7fa2cceb4060dd28830075b567e0cc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 28 Apr 2016 18:39:44 +0100 Subject: [PATCH 078/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index a6d5851..612fdd7 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -58,7 +58,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160426 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160428 24kHz (D-Star/DMR/System Fusion)"; const uint8_t PROTOCOL_VERSION = 1U; From 24e68639ae407d64f9a1b7a5613782092e82c569 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 2 May 2016 11:49:15 +0100 Subject: [PATCH 079/329] Re-enable DMR levels debugging. --- DMRSlotRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 81b8c26..eee9088 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" From 7f49e715f8e246bcb647cf94f3b6699a286a56e1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 9 May 2016 21:57:14 +0100 Subject: [PATCH 080/329] Add the CW Id. --- CWIdTX.cpp | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ CWIdTX.h | 41 +++++++++++++ Globals.h | 3 + MMDVM.cpp | 5 ++ MMDVM.ino | 5 ++ SerialPort.cpp | 11 ++++ 6 files changed, 228 insertions(+) create mode 100644 CWIdTX.cpp create mode 100644 CWIdTX.h diff --git a/CWIdTX.cpp b/CWIdTX.cpp new file mode 100644 index 0000000..a5433ee --- /dev/null +++ b/CWIdTX.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// #define WANT_DEBUG + +#include "Config.h" +#include "Globals.h" +#include "CWIdTX.h" + +q15_t TONE[] = { + 0, 2588, 5000, 7071, 8660, 9659, 10000, 9659, 8660, 7071, 5000, 2588, 0, -2588, -5000, -7071, -8660, -9659, -10000, -9659, -8660, -7071, -5000, -2588}; + +q15_t SILENCE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +const uint8_t CYCLE_LENGTH = 24U; + +const uint8_t DOT_LENGTH = 80U; + +const struct { + uint8_t c; + uint32_t pattern; + uint8_t length; +} SYMBOL_LIST[] = { + {'A', 0xB8000000U, 8U}, + {'B', 0xEA800000U, 12U}, + {'C', 0xEBA00000U, 14U}, + {'D', 0xEA000000U, 10U}, + {'E', 0x80000000U, 4U}, + {'F', 0xAE800000U, 12U}, + {'G', 0xEE800000U, 12U}, + {'H', 0xAA000000U, 10U}, + {'I', 0xA0000000U, 6U}, + {'J', 0xBBB80000U, 16U}, + {'K', 0xEB800000U, 12U}, + {'L', 0xBA800000U, 12U}, + {'M', 0xEE000000U, 10U}, + {'N', 0xE8000000U, 8U}, + {'O', 0xEEE00000U, 14U}, + {'P', 0xBBA00000U, 14U}, + {'Q', 0xEEB80000U, 16U}, + {'R', 0xBA000000U, 10U}, + {'S', 0xA8000000U, 8U}, + {'T', 0xE0000000U, 6U}, + {'U', 0xAE000000U, 10U}, + {'V', 0xAB800000U, 12U}, + {'W', 0xBB800000U, 12U}, + {'X', 0xEAE00000U, 14U}, + {'Y', 0xEBB80000U, 16U}, + {'Z', 0xEEA00000U, 14U}, + {'1', 0xBBBB8000U, 20U}, + {'2', 0xAEEE0000U, 18U}, + {'3', 0xABB80000U, 16U}, + {'4', 0xAAE00000U, 14U}, + {'5', 0xAA800000U, 12U}, + {'6', 0xEAA00000U, 14U}, + {'7', 0xEEA80000U, 16U}, + {'8', 0xEEEA0000U, 18U}, + {'9', 0xEEEE8000U, 20U}, + {'0', 0xEEEEE000U, 22U}, + {'/', 0xEAE80000U, 16U}, + {'?', 0xAEEA0000U, 18U}, + {',', 0xEEAEE000U, 22U}, + {' ', 0x00000000U, 4U}, + {0U, 0x00000000U, 0U} +}; + +const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +CCWIdTX::CCWIdTX() : +m_poBuffer(), +m_poLen(0U), +m_poPtr(0U), +m_n(0U) +{ +} + +void CCWIdTX::process() +{ + if (m_poLen == 0U) + return; + + uint16_t space = io.getSpace(); + + while (space > CYCLE_LENGTH && space < 1000U) { + bool b = READ_BIT1(m_poBuffer, m_poPtr); + if (b) + io.write(TONE, CYCLE_LENGTH); + else + io.write(SILENCE, CYCLE_LENGTH); + + space -= CYCLE_LENGTH; + + m_n++; + if (m_n >= DOT_LENGTH) { + m_poPtr++; + m_n = 0U; + } + + if (m_poPtr >= m_poLen) { + m_poPtr = 0U; + m_poLen = 0U; + return; + } + } +} + +uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length) +{ + ::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t)); + + m_poLen = 8U; + m_poPtr = 0U; + m_n = 0U; + + for (uint8_t i = 0U; i < length; i++) { + for (uint8_t j = 0U; SYMBOL_LIST[j].c != 0U; j++) { + if (SYMBOL_LIST[j].c == data[i]) { + uint32_t MASK = 0x80000000U; + for (uint8_t k = 0U; k < SYMBOL_LIST[j].length; k++, m_poLen++, MASK >>= 1) { + bool b = (SYMBOL_LIST[j].pattern & MASK) == MASK; + WRITE_BIT1(m_poBuffer, m_poLen, b); + + if (m_poLen >= 1000U) { + m_poLen = 0U; + return 4U; + } + } + + break; + } + } + } + + if (m_poLen == 8U) + m_poLen = 0U; + else + m_poLen += 5U; + + DEBUG2("Message created with length", m_poLen); + + return 0U; +} + diff --git a/CWIdTX.h b/CWIdTX.h new file mode 100644 index 0000000..4722dfa --- /dev/null +++ b/CWIdTX.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2009-2015 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(CWIDTX_H) +#define CWIDTX_H + +#include "Config.h" + +class CCWIdTX { +public: + CCWIdTX(); + + void process(); + + uint8_t write(const uint8_t* data, uint8_t length); + +private: + uint8_t m_poBuffer[1000U]; + uint16_t m_poLen; + uint16_t m_poPtr; + uint8_t m_n; +}; + +#endif + diff --git a/Globals.h b/Globals.h index 0e7116f..9199e60 100644 --- a/Globals.h +++ b/Globals.h @@ -54,6 +54,7 @@ enum MMDVM_STATE { #include "CalDStarRX.h" #include "CalDStarTX.h" #include "CalDMR.h" +#include "CWIdTX.h" #include "Debug.h" #include "IO.h" @@ -91,5 +92,7 @@ extern CCalDStarRX calDStarRX; extern CCalDStarTX calDStarTX; extern CCalDMR calDMR; +extern CCWIdTX cwIdTX; + #endif diff --git a/MMDVM.cpp b/MMDVM.cpp index 1f14e88..432678b 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -49,6 +49,8 @@ CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; CCalDMR calDMR; +CCWIdTX cwIdTX; + CSerialPort serial; CIO io; @@ -78,6 +80,9 @@ void loop() if (m_modemState == STATE_DMRCAL) calDMR.process(); + + if (m_modemState == STATE_IDLE) + cwIdTX.process(); } int main() diff --git a/MMDVM.ino b/MMDVM.ino index f84c25f..ef84aa0 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -46,6 +46,8 @@ CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; CCalDMR calDMR; +CCWIdTX cwIdTX; + CSerialPort serial; CIO io; @@ -75,5 +77,8 @@ void loop() if (m_modemState == STATE_DMRCAL) calDMR.process(); + + if (m_modemState == STATE_IDLE) + cwIdTX.process(); } diff --git a/SerialPort.cpp b/SerialPort.cpp index 612fdd7..3ea8515 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -34,6 +34,8 @@ const uint8_t MMDVM_SET_FREQ = 0x04U; const uint8_t MMDVM_CAL_DATA = 0x08U; +const uint8_t MMDVM_SEND_CWID = 0x0AU; + const uint8_t MMDVM_DSTAR_HEADER = 0x10U; const uint8_t MMDVM_DSTAR_DATA = 0x11U; const uint8_t MMDVM_DSTAR_LOST = 0x12U; @@ -395,6 +397,15 @@ void CSerialPort::process() } break; + case MMDVM_SEND_CWID: + if (m_modemState == STATE_IDLE) + err = cwIdTX.write(m_buffer + 3U, m_len - 3U); + if (err != 0U) { + DEBUG2("Invalid CW Id data", err); + sendNAK(err); + } + break; + case MMDVM_DSTAR_HEADER: if (m_dstarEnable) { if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR) From 61cacc40b979d0daca52f5db6652b8c7189e818b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 9 May 2016 21:58:44 +0100 Subject: [PATCH 081/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 3ea8515..22d5767 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -60,7 +60,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160428 24kHz (D-Star/DMR/System Fusion)"; +const uint8_t HARDWARE[] = "MMDVM 20160509 24kHz (D-Star/DMR/System Fusion/CW Id)"; const uint8_t PROTOCOL_VERSION = 1U; From 90ff130c5138a761076dc68538e186571b092982 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 10 May 2016 06:35:53 +0100 Subject: [PATCH 082/329] Small CW Id cleanups. --- CWIdTX.cpp | 18 ++++++++++++++---- CWIdTX.h | 2 ++ SerialPort.cpp | 5 +++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index a5433ee..c75196f 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -140,7 +140,7 @@ uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length) bool b = (SYMBOL_LIST[j].pattern & MASK) == MASK; WRITE_BIT1(m_poBuffer, m_poLen, b); - if (m_poLen >= 1000U) { + if (m_poLen >= 995U) { m_poLen = 0U; return 4U; } @@ -151,13 +151,23 @@ uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length) } } - if (m_poLen == 8U) + // An empty message + if (m_poLen == 8U) { m_poLen = 0U; - else - m_poLen += 5U; + return 4U; + } + + m_poLen += 5U; DEBUG2("Message created with length", m_poLen); return 0U; } +void CCWIdTX::reset() +{ + m_poLen = 0U; + m_poPtr = 0U; + m_n = 0U; +} + diff --git a/CWIdTX.h b/CWIdTX.h index 4722dfa..70f67ea 100644 --- a/CWIdTX.h +++ b/CWIdTX.h @@ -30,6 +30,8 @@ public: uint8_t write(const uint8_t* data, uint8_t length); + void reset(); + private: uint8_t m_poBuffer[1000U]; uint16_t m_poLen; diff --git a/SerialPort.cpp b/SerialPort.cpp index 22d5767..b2b2fcb 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -276,18 +276,21 @@ void CSerialPort::setMode(MMDVM_STATE modemState) DEBUG1("Mode set to DMR"); dstarRX.reset(); ysfRX.reset(); + cwIdTX.reset(); break; case STATE_DSTAR: DEBUG1("Mode set to D-Star"); dmrIdleRX.reset(); dmrRX.reset(); ysfRX.reset(); + cwIdTX.reset(); break; case STATE_YSF: DEBUG1("Mode set to System Fusion"); dmrIdleRX.reset(); dmrRX.reset(); dstarRX.reset(); + cwIdTX.reset(); break; case STATE_DSTARCAL: DEBUG1("Mode set to D-Star Calibrate"); @@ -295,6 +298,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); + cwIdTX.reset(); break; case STATE_DMRCAL: DEBUG1("Mode set to DMR Calibrate"); @@ -302,6 +306,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); + cwIdTX.reset(); break; default: DEBUG1("Mode set to Idle"); From c509f11c2a96abea9ea2a0a2b52f003a3e48b7a6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 10 May 2016 18:11:31 +0100 Subject: [PATCH 083/329] Stop TX buffer overflows. --- CWIdTX.cpp | 2 +- DMRTX.cpp | 2 +- DStarTX.cpp | 2 +- Globals.h | 3 +++ IO.cpp | 7 ++----- YSFTX.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index c75196f..d03af8d 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -101,7 +101,7 @@ void CCWIdTX::process() uint16_t space = io.getSpace(); - while (space > CYCLE_LENGTH && space < 1000U) { + while (space > CYCLE_LENGTH && space <= TX_RINGBUFFER_SIZE) { bool b = READ_BIT1(m_poBuffer, m_poPtr); if (b) io.write(TONE, CYCLE_LENGTH); diff --git a/DMRTX.cpp b/DMRTX.cpp index dd918f1..a78a966 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -113,7 +113,7 @@ void CDMRTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (4U * DMR_RADIO_SYMBOL_LENGTH) && space < 1000U) { + while (space > (4U * DMR_RADIO_SYMBOL_LENGTH) && space <= TX_RINGBUFFER_SIZE) { uint8_t c = m_poBuffer[m_poPtr]; uint8_t m = m_markBuffer[m_poPtr]; m_poPtr++; diff --git a/DStarTX.cpp b/DStarTX.cpp index 7b4bf66..c719e97 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -266,7 +266,7 @@ void CDStarTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (8U * DSTAR_RADIO_BIT_LENGTH) && space < 1000U) { + while (space > (8U * DSTAR_RADIO_BIT_LENGTH) && space <= TX_RINGBUFFER_SIZE) { uint8_t c = m_poBuffer[m_poPtr++]; writeByte(c); diff --git a/Globals.h b/Globals.h index 9199e60..b4d2dbb 100644 --- a/Globals.h +++ b/Globals.h @@ -64,6 +64,9 @@ const uint8_t MARK_NONE = 0x00U; const uint16_t RX_BLOCK_SIZE = 2U; +const uint16_t TX_RINGBUFFER_SIZE = 500U; +const uint16_t RX_RINGBUFFER_SIZE = 600U; + extern MMDVM_STATE m_modemState; extern bool m_dstarEnable; diff --git a/IO.cpp b/IO.cpp index 1c9bac7..2eb6d40 100644 --- a/IO.cpp +++ b/IO.cpp @@ -36,9 +36,6 @@ const uint16_t GMSK_FILTER_LEN = 12U; const uint16_t DC_OFFSET = 2048U; -const uint16_t TX_BUFFER_SIZE = 501U; -const uint16_t RX_BUFFER_SIZE = 601U; - #if defined(__SAM3X8E__) // An Arduino Due #if defined(ARDUINO_DUE_PAPA) @@ -105,8 +102,8 @@ m_pinDAC(PIN_DAC), m_ticker(), #endif m_started(false), -m_rxBuffer(RX_BUFFER_SIZE), -m_txBuffer(TX_BUFFER_SIZE), +m_rxBuffer(RX_RINGBUFFER_SIZE), +m_txBuffer(TX_RINGBUFFER_SIZE), m_C4FSKFilter(), m_GMSKFilter(), m_C4FSKState(), diff --git a/YSFTX.cpp b/YSFTX.cpp index 7fc1561..2ff596f 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -78,7 +78,7 @@ void CYSFTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (4U * YSF_RADIO_SYMBOL_LENGTH) && space < 1000U) { + while (space > (4U * YSF_RADIO_SYMBOL_LENGTH) && space <= TX_RINGBUFFER_SIZE) { uint8_t c = m_poBuffer[m_poPtr++]; writeByte(c); From e0fc2a50d124b5e773b8516b6190a825dad4e627 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 10 May 2016 21:29:02 +0100 Subject: [PATCH 084/329] Speed up the CW Id. --- CWIdTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index d03af8d..8786f24 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -31,7 +31,7 @@ q15_t SILENCE[] = { const uint8_t CYCLE_LENGTH = 24U; -const uint8_t DOT_LENGTH = 80U; +const uint8_t DOT_LENGTH = 60U; const struct { uint8_t c; From b36ed70b0c0eefc8f35e5dedcaf8532013999923 Mon Sep 17 00:00:00 2001 From: phl0 Date: Thu, 12 May 2016 12:52:02 +0200 Subject: [PATCH 085/329] Add information for MMDVM build on Ubuntu 14.04 with latest Arduino IDE --- BUILD.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/BUILD.txt b/BUILD.txt index b9dc4e0..f8e83ba 100644 --- a/BUILD.txt +++ b/BUILD.txt @@ -99,3 +99,21 @@ On Linux, the path was found to differ slightly (GCC instead of ARM): Which is the CMSIS AMR3 DSP library for little-endian operation. 4. Save the file and start up the Arduino GUI and build MMDVM. + +For Arduino 1.6.9 with SAM 1.6.8 +-------------------------------- + +1. Locate platform.txt. On Ubuntu 14.04 LTS x86_64 OS it is in: + +/home/$user/.arduino15/packages/arduino/hardware/sam/1.6.8/ + +2. Open the file in a text editor and change the line: + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc + +to + +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc + +3. Save the file, open the Arduino IDE and build MMDVM From fe9b4d230581d4e7e2000a3225b8073364d9196b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 12 May 2016 18:03:12 +0100 Subject: [PATCH 086/329] Increase the speed of the CW Id. --- CWIdTX.cpp | 2 +- SerialPort.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index 8786f24..c4bc40c 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -31,7 +31,7 @@ q15_t SILENCE[] = { const uint8_t CYCLE_LENGTH = 24U; -const uint8_t DOT_LENGTH = 60U; +const uint8_t DOT_LENGTH = 50U; const struct { uint8_t c; diff --git a/SerialPort.cpp b/SerialPort.cpp index b2b2fcb..13eaf9c 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -403,6 +403,7 @@ void CSerialPort::process() break; case MMDVM_SEND_CWID: + err = 5U; if (m_modemState == STATE_IDLE) err = cwIdTX.write(m_buffer + 3U, m_len - 3U); if (err != 0U) { From e4462ced3f0d74d4c0e75bfa28407d54de08dfa9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 17 May 2016 19:59:59 +0100 Subject: [PATCH 087/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 13eaf9c..fe16f81 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -60,7 +60,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160509 24kHz (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160517 24kHz (D-Star/DMR/System Fusion/CW Id)"; const uint8_t PROTOCOL_VERSION = 1U; From bcd63e7a341699d23928f328d2c606608272e6e0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 23 May 2016 18:49:02 +0100 Subject: [PATCH 088/329] Make the high stability 12 MHz oscillator the default. --- Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.h b/Config.h index 603b0a1..55cc547 100644 --- a/Config.h +++ b/Config.h @@ -22,7 +22,7 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // For 12 MHz -// #define EXTERNAL_OSC 12000000 +#define EXTERNAL_OSC 12000000 // For 14.4 MHz // #define EXTERNAL_OSC 14400000 // For 19.2 MHz From 2e0d0c027c3ef3c4749ec65ab78c184d20665fdf Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 25 May 2016 07:26:50 +0100 Subject: [PATCH 089/329] Revert "Make the high stability 12 MHz oscillator the default." This reverts commit bcd63e7a341699d23928f328d2c606608272e6e0. --- Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.h b/Config.h index 55cc547..603b0a1 100644 --- a/Config.h +++ b/Config.h @@ -22,7 +22,7 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // For 12 MHz -#define EXTERNAL_OSC 12000000 +// #define EXTERNAL_OSC 12000000 // For 14.4 MHz // #define EXTERNAL_OSC 14400000 // For 19.2 MHz From e9ba2e896ae136a4742f9c7110e12966353dde0d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 1 Jun 2016 09:23:09 +0100 Subject: [PATCH 090/329] Assert optional output pins on mode change. --- Config.h | 3 +++ IO.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- IO.h | 3 ++- SerialPort.cpp | 2 ++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Config.h b/Config.h index 603b0a1..148fea1 100644 --- a/Config.h +++ b/Config.h @@ -31,6 +31,9 @@ // Allow the use of the COS line to lockout the modem // #define USE_COS_AS_LOCKOUT +// Use pins to output the current mode +// #define ARDUINO_MODE_PINS + // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA diff --git a/IO.cpp b/IO.cpp index 2eb6d40..e4e2012 100644 --- a/IO.cpp +++ b/IO.cpp @@ -51,6 +51,9 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 +#define PIN_DSTAR 132 +#define PIN_DMR 133 +#define PIN_YSF 134 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -137,6 +140,13 @@ m_lockout(false) pinMode(PIN_COSLED, OUTPUT); pinMode(PIN_LED, OUTPUT); pinMode(PIN_COS, INPUT); + +#if defined(ARDUINO_MODE_PINS) + // Set up the mode output pins + pinMode(PIN_DSTAR, OUTPUT); + pinMode(PIN_DMR, OUTPUT); + pinMode(PIN_YSF, OUTPUT); +#endif #endif } @@ -204,7 +214,7 @@ void CIO::start() digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); - digitalWrite(PIN_LED, HIGH); + digitalWrite(PIN_LED, HIGH); #elif defined(__MBED__) m_ticker.attach(&ADC_Handler, 1.0 / 24000.0); @@ -215,6 +225,8 @@ void CIO::start() m_count = 0U; m_started = true; + + setMode(); } void CIO::process() @@ -227,6 +239,7 @@ void CIO::process() if (m_modemState == STATE_DMR && m_tx) dmrTX.setStart(false); m_modemState = STATE_IDLE; + setMode(); } m_watchdog = 0U; @@ -433,6 +446,36 @@ void CIO::setDecode(bool dcd) m_dcd = dcd; } +void CIO::setMode() +{ +#if !defined(__MBED__) +#if defined(ARDUINO_MODE_PINS) +switch (m_modemState) { + case STATE_DSTAR: + digitalWrite(PIN_DSTAR, HIGH); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + break; + case STATE_DMR: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, HIGH); + digitalWrite(PIN_YSF, LOW); + break; + case STATE_YSF: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, HIGH); + break; + default: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + break; +} +#endif +#endif +} + void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t txLevel) { m_pttInvert = pttInvert; diff --git a/IO.h b/IO.h index 4878d8d..bd8d985 100644 --- a/IO.h +++ b/IO.h @@ -36,7 +36,8 @@ public: uint16_t getSpace() const; void setDecode(bool dcd); - + void setMode(); + void interrupt(); void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t txLevel); diff --git a/SerialPort.cpp b/SerialPort.cpp index fe16f81..4747a5a 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -315,6 +315,8 @@ void CSerialPort::setMode(MMDVM_STATE modemState) } m_modemState = modemState; + + io.setMode(); } void CSerialPort::start() From 8daa53dc3ee431ce2cb9c9f6096960bec308f224 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 2 Jun 2016 12:55:50 +0100 Subject: [PATCH 091/329] Add output definition for the NTH board. --- IO.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/IO.cpp b/IO.cpp index e4e2012..f4ee849 100644 --- a/IO.cpp +++ b/IO.cpp @@ -63,6 +63,9 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS A7 #define PIN_PTT A8 #define PIN_COSLED A11 +#define PIN_DSTAR 132 +#define PIN_DMR 133 +#define PIN_YSF 134 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 From 19ea52ed218c7dac7a0984cf5a984b3de22607b7 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 2 Jun 2016 12:58:00 +0100 Subject: [PATCH 092/329] Increase the level of the YSF TX. --- YSFTX.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/YSFTX.cpp b/YSFTX.cpp index 2ff596f..9f8774e 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -31,11 +31,10 @@ const uint16_t YSF_C4FSK_FILTER_LEN = 42U; const uint8_t YSF_START_SYNC = 0x77U; const uint8_t YSF_END_SYNC = 0xFFU; -q15_t YSF_A[] = { 704, 704, 704, 704, 704}; -q15_t YSF_B[] = { 235, 235, 235, 235, 235}; -q15_t YSF_C[] = {-235, -235, -235, -235, -235}; -q15_t YSF_D[] = {-704, -704, -704, -704, -704}; - +q15_t YSF_A[] = { 809, 809, 809, 809, 809}; +q15_t YSF_B[] = { 269, 269, 269, 269, 269}; +q15_t YSF_C[] = {-269, -269, -269, -269, -269}; +q15_t YSF_D[] = {-809, -809, -809, -809, -809}; CYSFTX::CYSFTX() : m_buffer(1500U), From cd5849ad695e2bb65c454f94f71709fe0b9d7561 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 2 Jun 2016 18:55:21 +0100 Subject: [PATCH 093/329] Alter pin definitions for mode outputs. --- IO.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/IO.cpp b/IO.cpp index f4ee849..17aa528 100644 --- a/IO.cpp +++ b/IO.cpp @@ -51,9 +51,9 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 -#define PIN_DSTAR 132 -#define PIN_DMR 133 -#define PIN_YSF 134 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -63,9 +63,9 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS A7 #define PIN_PTT A8 #define PIN_COSLED A11 -#define PIN_DSTAR 132 -#define PIN_DMR 133 -#define PIN_YSF 134 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 From d4e56965dab4c99779999fb61301545c3ca2864b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 6 Jun 2016 17:44:34 +0100 Subject: [PATCH 094/329] Reduce the CW Id transmit level considerably. --- CWIdTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index c4bc40c..fd980e8 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -24,7 +24,7 @@ #include "CWIdTX.h" q15_t TONE[] = { - 0, 2588, 5000, 7071, 8660, 9659, 10000, 9659, 8660, 7071, 5000, 2588, 0, -2588, -5000, -7071, -8660, -9659, -10000, -9659, -8660, -7071, -5000, -2588}; + 0, 259, 500, 707, 866, 966, 1000, 966, 866, 707, 500, 259, 0, -259, -500, -707, -866, -966, -1000, -966, -866, -707, -500, -259}; q15_t SILENCE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; From b8457aed4c6f3432ac19e750f05c7b42a5a46930 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 6 Jun 2016 18:04:03 +0100 Subject: [PATCH 095/329] Disassociate the ADC overload detection from the DCD LED. --- DMRSlotRX.cpp | 29 +++++++++++++++++++++-------- DMRSlotRX.h | 1 + DStarRX.cpp | 7 +++++++ IO.cpp | 8 +++++++- IO.h | 2 ++ YSFRX.cpp | 4 ++++ 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index eee9088..353b489 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -48,6 +48,7 @@ m_buffer(), m_bitPtr(0U), m_dataPtr(0U), m_syncPtr(0U), +m_startPtr(0U), m_endPtr(NOENDPTR), m_delayPtr(0U), m_maxCorr(0), @@ -83,6 +84,7 @@ void CDMRSlotRX::reset() m_control = CONTROL_NONE; m_syncCount = 0U; m_state = DMRRXS_NONE; + m_startPtr = 0U; m_endPtr = NOENDPTR; } @@ -92,6 +94,15 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_delayPtr < m_delay) return m_state != DMRRXS_NONE; + if (m_state != DMRRXS_NONE) { + if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) + io.setADCDetection(true); + else + io.setADCDetection(false); + } else { + io.setADCDetection(false); + } + // Ensure that the buffer doesn't overflow if (m_dataPtr > m_endPtr || m_dataPtr >= 900U) return m_state != DMRRXS_NONE; @@ -285,10 +296,11 @@ void CDMRSlotRX::correlateSync(bool first) m_averagePtr = 0U; } - m_maxCorr = corr; - m_control = CONTROL_DATA; - m_syncPtr = m_dataPtr; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + m_maxCorr = corr; + m_control = CONTROL_DATA; + m_syncPtr = m_dataPtr; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } else { // if (voice) uint8_t errs = 0U; @@ -309,10 +321,11 @@ void CDMRSlotRX::correlateSync(bool first) m_averagePtr = 0U; } - m_maxCorr = corr; - m_control = CONTROL_VOICE; - m_syncPtr = m_dataPtr; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + m_maxCorr = corr; + m_control = CONTROL_VOICE; + m_syncPtr = m_dataPtr; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } } diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 6c3c446..994839f 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -48,6 +48,7 @@ private: uint16_t m_bitPtr; uint16_t m_dataPtr; uint16_t m_syncPtr; + uint16_t m_startPtr; uint16_t m_endPtr; uint16_t m_delayPtr; q31_t m_maxCorr; diff --git a/DStarRX.cpp b/DStarRX.cpp index d0cb104..e2ebc60 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -333,7 +333,9 @@ void CDStarRX::processNone(bool bit) // Exact matching of the data sync bit sequence if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) { DEBUG1("DStarRX: found data sync in None"); + io.setDecode(true); + io.setADCDetection(true); #if defined(WANT_DEBUG) q15_t min = 16000; @@ -374,6 +376,7 @@ void CDStarRX::processHeader(bool bit) bool ok = rxHeader(m_rxBuffer, header); if (ok) { io.setDecode(true); + io.setADCDetection(true); serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); @@ -401,7 +404,9 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the end frame sequences if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { DEBUG1("DStarRX: Found end sync in Data"); + io.setDecode(false); + io.setADCDetection(false); serial.writeDStarEOT(); @@ -440,7 +445,9 @@ void CDStarRX::processData(bool bit) m_dataBits--; if (m_dataBits == 0U) { DEBUG1("DStarRX: data sync timed out, lost lock"); + io.setDecode(false); + io.setADCDetection(false); serial.writeDStarLost(); diff --git a/IO.cpp b/IO.cpp index 17aa528..c0343c6 100644 --- a/IO.cpp +++ b/IO.cpp @@ -120,6 +120,7 @@ m_txLevel(128 * 128), m_ledCount(0U), m_ledValue(true), m_dcd(false), +m_detect(false), m_overflow(0U), m_overcount(0U), m_count(0U), @@ -299,7 +300,7 @@ void CIO::process() m_rxBuffer.get(sample, control[i]); // Detect ADC overflow - if (m_dcd && (sample == 0U || sample == 4095U)) + if (m_detect && (sample == 0U || sample == 4095U)) m_overflow++; m_overcount++; @@ -449,6 +450,11 @@ void CIO::setDecode(bool dcd) m_dcd = dcd; } +void CIO::setADCDetection(bool detect) +{ + m_detect = detect; +} + void CIO::setMode() { #if !defined(__MBED__) diff --git a/IO.h b/IO.h index bd8d985..43f0a2d 100644 --- a/IO.h +++ b/IO.h @@ -36,6 +36,7 @@ public: uint16_t getSpace() const; void setDecode(bool dcd); + void setADCDetection(bool detect); void setMode(); void interrupt(); @@ -82,6 +83,7 @@ private: bool m_ledValue; bool m_dcd; + bool m_detect; uint16_t m_overflow; uint16_t m_overcount; diff --git a/YSFRX.cpp b/YSFRX.cpp index 4a6849d..4c1b0a1 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -167,7 +167,9 @@ void CYSFRX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; m_state = YSFRXS_DATA; + io.setDecode(true); + io.setADCDetection(true); } } @@ -226,7 +228,9 @@ void CYSFRX::processData(q15_t sample) m_lostCount--; if (m_lostCount == 0U) { DEBUG1("YSFRX: sync timed out, lost lock"); + io.setDecode(false); + io.setADCDetection(false); serial.writeYSFLost(); From 6c66f56e54a55b8c94a6a1cc4ce86e6184913bc3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 6 Jun 2016 18:07:33 +0100 Subject: [PATCH 096/329] Tighter sync detection for YSF. --- YSFRX.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index 4c1b0a1..2ee5a02 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -31,8 +31,10 @@ const uint32_t PLLMAX = 0x10000U; const uint32_t PLLINC = PLLMAX / YSF_RADIO_SYMBOL_LENGTH; const uint32_t INC = PLLINC / 32U; -const uint8_t SYNC_SYMBOL_ERRS = 2U; -const uint8_t SYNC_BIT_ERRS = 4U; +const uint8_t SYNC_SYMBOL_ERRS = 0U; + +const uint8_t SYNC_BIT_START_ERRS = 2U; +const uint8_t SYNC_BIT_RUN_ERRS = 4U; const unsigned int MAX_SYNC_FRAMES = 4U + 1U; @@ -158,7 +160,7 @@ void CYSFRX::processNone(q15_t sample) } // Fuzzy matching of the data sync bit sequence - if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_ERRS) { + if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_START_ERRS) { DEBUG5("YSFRX: sync found in None min/max/centre/threshold", min, max, centre, threshold); for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_BYTES; i++) m_buffer[i] = YSF_SYNC_BYTES[i]; @@ -212,10 +214,10 @@ void CYSFRX::processData(q15_t sample) m_bufferPtr++; } - // Only search for a sync in the right place +-1 symbol + // Only search for a sync in the right place +-2 symbols if (m_bufferPtr >= (YSF_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (YSF_SYNC_LENGTH_BITS + 2U)) { // Fuzzy matching of the data sync bit sequence - if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_ERRS) { + if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) { DEBUG2("YSFRX: found sync in Data, pos", m_bufferPtr - YSF_SYNC_LENGTH_BITS); m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; From 961d1000f52fe171d8a93950e9dd0f11d45723d0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 6 Jun 2016 18:31:55 +0100 Subject: [PATCH 097/329] Correct the start pointer calculation. --- DMRSlotRX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 353b489..be2ec48 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -299,7 +299,7 @@ void CDMRSlotRX::correlateSync(bool first) m_maxCorr = corr; m_control = CONTROL_DATA; m_syncPtr = m_dataPtr; - m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } else { // if (voice) @@ -324,7 +324,7 @@ void CDMRSlotRX::correlateSync(bool first) m_maxCorr = corr; m_control = CONTROL_VOICE; m_syncPtr = m_dataPtr; - m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; } } From 0d07dd78ebd6bd43061dbe2b7960ff585eb20deb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 9 Jun 2016 19:50:34 +0100 Subject: [PATCH 098/329] Detect DAC overflows. --- IO.cpp | 33 ++++++++++++++++++--------------- IO.h | 6 +++--- SerialPort.cpp | 9 ++++++++- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/IO.cpp b/IO.cpp index c0343c6..a834c0c 100644 --- a/IO.cpp +++ b/IO.cpp @@ -121,8 +121,8 @@ m_ledCount(0U), m_ledValue(true), m_dcd(false), m_detect(false), -m_overflow(0U), -m_overcount(0U), +m_adcOverflow(0U), +m_dacOverflow(0U), m_count(0U), m_watchdog(0U), m_lockout(false) @@ -301,8 +301,7 @@ void CIO::process() // Detect ADC overflow if (m_detect && (sample == 0U || sample == 4095U)) - m_overflow++; - m_overcount++; + m_adcOverflow++; q15_t res1 = q15_t(sample) - DC_OFFSET; q31_t res2 = res1 * m_rxLevel; @@ -405,11 +404,16 @@ void CIO::write(q15_t* samples, uint16_t length, const uint8_t* control) for (uint16_t i = 0U; i < length; i++) { q31_t res1 = samples[i] * m_txLevel; q15_t res2 = q15_t(__SSAT((res1 >> 15), 16)); - + uint16_t res3 = uint16_t(res2 + DC_OFFSET); + + // Detect DAC overflow + if (res3 == 0U || res3 >= 4095U) + m_dacOverflow++; + if (control == NULL) - m_txBuffer.put(uint16_t(res2 + DC_OFFSET), MARK_NONE); + m_txBuffer.put(res3, MARK_NONE); else - m_txBuffer.put(uint16_t(res2 + DC_OFFSET), control[i]); + m_txBuffer.put(res3, control[i]); } } @@ -499,19 +503,18 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_txLevel = -m_txLevel; } -bool CIO::hasADCOverflow() +void CIO::getOverflow(bool& adcOverflow, bool& dacOverflow) { - bool overflow = m_overflow > 0U; + adcOverflow = m_adcOverflow > 0U; + dacOverflow = m_dacOverflow > 0U; #if defined(WANT_DEBUG) - if (m_overflow > 0U) - DEBUG3("IO: Overflow, n/count", m_overflow, m_overcount); + if (m_adcOverflow > 0U || m_dacOverflow > 0U) + DEBUG3("IO: adc/dac", m_adcOverflow, m_dacOverflow); #endif - m_overflow = 0U; - m_overcount = 0U; - - return overflow; + m_adcOverflow = 0U; + m_dacOverflow = 0U; } bool CIO::hasTXOverflow() diff --git a/IO.h b/IO.h index 43f0a2d..bf047e2 100644 --- a/IO.h +++ b/IO.h @@ -43,7 +43,7 @@ public: void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t txLevel); - bool hasADCOverflow(); + void getOverflow(bool& adcOverflow, bool& dacOverflow); bool hasTXOverflow(); bool hasRXOverflow(); @@ -85,8 +85,8 @@ private: bool m_dcd; bool m_detect; - uint16_t m_overflow; - uint16_t m_overcount; + uint16_t m_adcOverflow; + uint16_t m_dacOverflow; uint32_t m_count; diff --git a/SerialPort.cpp b/SerialPort.cpp index 4747a5a..0efbbfe 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -123,7 +123,11 @@ void CSerialPort::getStatus() reply[5U] = m_tx ? 0x01U : 0x00U; - if (io.hasADCOverflow()) + bool adcOverflow; + bool dacOverflow; + io.getOverflow(adcOverflow, dacOverflow); + + if (adcOverflow) reply[5U] |= 0x02U; if (io.hasRXOverflow()) @@ -135,6 +139,9 @@ void CSerialPort::getStatus() if (io.hasLockout()) reply[5U] |= 0x10U; + if (dacOverflow) + reply[5U] |= 0x20U; + if (m_dstarEnable) reply[6U] = dstarTX.getSpace(); else From 3d49de190d0cf280bf22cb4849e6987f13fbb450 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 9 Jun 2016 19:57:32 +0100 Subject: [PATCH 099/329] Increase the level of the CW id. --- CWIdTX.cpp | 2 +- YSFTX.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index fd980e8..e6db1eb 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -24,7 +24,7 @@ #include "CWIdTX.h" q15_t TONE[] = { - 0, 259, 500, 707, 866, 966, 1000, 966, 866, 707, 500, 259, 0, -259, -500, -707, -866, -966, -1000, -966, -866, -707, -500, -259}; + 0, 1294, 2500, 3535, 4330, 4830, 5000, 4830, 4330, 3535, 2500, 1294, 0, -1294, -2500, -3535, -4330, -4830, -5000, -4830, -4330, -3535, -2500, -1294}; q15_t SILENCE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/YSFTX.cpp b/YSFTX.cpp index 9f8774e..a45c8cf 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -43,7 +43,7 @@ m_modState(), m_poBuffer(), m_poLen(0U), m_poPtr(0U), -m_txDelay(120U), // 100ms +m_txDelay(240U), // 200ms m_count(0U) { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); From 3521aa6994f6472285e1ebee3b83933a3ae9aaa9 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Jun 2016 19:31:16 +0100 Subject: [PATCH 100/329] Change DAC overflow threshold. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index a834c0c..9803040 100644 --- a/IO.cpp +++ b/IO.cpp @@ -407,7 +407,7 @@ void CIO::write(q15_t* samples, uint16_t length, const uint8_t* control) uint16_t res3 = uint16_t(res2 + DC_OFFSET); // Detect DAC overflow - if (res3 == 0U || res3 >= 4095U) + if (res3 > 4095U) m_dacOverflow++; if (control == NULL) From a381387c5c713e957d11c30ea55934e9e879d013 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Jun 2016 19:41:12 +0100 Subject: [PATCH 101/329] Reduce the CW Id level again. --- CWIdTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index e6db1eb..de666ec 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -24,7 +24,7 @@ #include "CWIdTX.h" q15_t TONE[] = { - 0, 1294, 2500, 3535, 4330, 4830, 5000, 4830, 4330, 3535, 2500, 1294, 0, -1294, -2500, -3535, -4330, -4830, -5000, -4830, -4330, -3535, -2500, -1294}; + 0, 647, 1250, 1767, 2165, 2415, 2500, 2415, 2165, 1767, 1250, 647, 0, -647, -1250, -1767, -2165, -2415, -2500, -2415, -2165, -1767, -1250, -647}; q15_t SILENCE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; From 0c635f5132d30f938b424aa30a33a7c8a26d8b5a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 13 Jun 2016 19:47:45 +0100 Subject: [PATCH 102/329] Sanity check the ring buffers. --- CWIdTX.cpp | 2 +- DMRTX.cpp | 2 +- DStarTX.cpp | 2 +- SampleRB.cpp | 13 ++++++++++--- SerialRB.cpp | 13 ++++++++++--- YSFTX.cpp | 2 +- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index de666ec..185d72e 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -101,7 +101,7 @@ void CCWIdTX::process() uint16_t space = io.getSpace(); - while (space > CYCLE_LENGTH && space <= TX_RINGBUFFER_SIZE) { + while (space > CYCLE_LENGTH) { bool b = READ_BIT1(m_poBuffer, m_poPtr); if (b) io.write(TONE, CYCLE_LENGTH); diff --git a/DMRTX.cpp b/DMRTX.cpp index a78a966..3406ff6 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -113,7 +113,7 @@ void CDMRTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (4U * DMR_RADIO_SYMBOL_LENGTH) && space <= TX_RINGBUFFER_SIZE) { + while (space > (4U * DMR_RADIO_SYMBOL_LENGTH)) { uint8_t c = m_poBuffer[m_poPtr]; uint8_t m = m_markBuffer[m_poPtr]; m_poPtr++; diff --git a/DStarTX.cpp b/DStarTX.cpp index c719e97..a319651 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -266,7 +266,7 @@ void CDStarTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (8U * DSTAR_RADIO_BIT_LENGTH) && space <= TX_RINGBUFFER_SIZE) { + while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) { uint8_t c = m_poBuffer[m_poPtr++]; writeByte(c); diff --git a/SampleRB.cpp b/SampleRB.cpp index 6494a99..dd9154f 100644 --- a/SampleRB.cpp +++ b/SampleRB.cpp @@ -35,12 +35,19 @@ m_overflow(false) uint16_t CSampleRB::getSpace() const { + uint16_t n = 0U; + if (m_tail == m_head) - return m_full ? 0U : m_length; + n = m_full ? 0U : m_length; else if (m_tail < m_head) - return m_length - m_head + m_tail; + n = m_length - m_head + m_tail; else - return m_tail - m_head; + n = m_tail - m_head; + + if (n > m_length) + n = 0U; + + return n; } uint16_t CSampleRB::getData() const diff --git a/SerialRB.cpp b/SerialRB.cpp index ed11711..5f917d5 100644 --- a/SerialRB.cpp +++ b/SerialRB.cpp @@ -39,12 +39,19 @@ void CSerialRB::reset() uint16_t CSerialRB::getSpace() const { + uint16_t n = 0U; + if (m_tail == m_head) - return m_full ? 0U : m_length; + n = m_full ? 0U : m_length; else if (m_tail < m_head) - return m_length - m_head + m_tail; + n = m_length - m_head + m_tail; else - return m_tail - m_head; + n = m_tail - m_head; + + if (n > m_length) + n = 0U; + + return n; } uint16_t CSerialRB::getData() const diff --git a/YSFTX.cpp b/YSFTX.cpp index a45c8cf..92984a7 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -77,7 +77,7 @@ void CYSFTX::process() if (m_poLen > 0U) { uint16_t space = io.getSpace(); - while (space > (4U * YSF_RADIO_SYMBOL_LENGTH) && space <= TX_RINGBUFFER_SIZE) { + while (space > (4U * YSF_RADIO_SYMBOL_LENGTH)) { uint8_t c = m_poBuffer[m_poPtr++]; writeByte(c); From ea68dcb89c7123dad074b3c64471a9bed5d29cdc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 14 Jun 2016 19:17:40 +0100 Subject: [PATCH 103/329] Optimise the min/max calculation. --- YSFRX.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/YSFRX.cpp b/YSFRX.cpp index 2ee5a02..37826af 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -110,22 +110,15 @@ void CYSFRX::processNone(q15_t sample) // Fuzzy matching of the data sync bit sequence if (countBits32((m_symbolBuffer & YSF_SYNC_SYMBOLS_MASK) ^ YSF_SYNC_SYMBOLS) <= SYNC_SYMBOL_ERRS) { - uint16_t ptr = m_symbolPtr + 1U; - if (ptr >= YSF_SYNC_LENGTH_SYMBOLS) - ptr = 0U; - q15_t max = -16000; q15_t min = 16000; for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_SYMBOLS; i++) { - if (m_symbols[ptr] > max) - max = m_symbols[ptr]; - if (m_symbols[ptr] < min) - min = m_symbols[ptr]; - - ptr++; - if (ptr >= YSF_SYNC_LENGTH_SYMBOLS) - ptr = 0U; + q15_t val = m_symbols[i]; + if (val > max) + max = val; + if (val < min) + min = val; } q15_t centre = (max + min) >> 1; @@ -133,7 +126,7 @@ void CYSFRX::processNone(q15_t sample) q31_t v1 = (max - centre) * SCALING_FACTOR; q15_t threshold = q15_t(v1 >> 15); - ptr = m_symbolPtr + 1U; + uint16_t ptr = m_symbolPtr + 1U; if (ptr >= YSF_SYNC_LENGTH_SYMBOLS) ptr = 0U; From 195f94c3683730df7c55988ccf138822e562796b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 14 Jun 2016 19:18:49 +0100 Subject: [PATCH 104/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 0efbbfe..d11e7e3 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -60,7 +60,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160517 24kHz (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160614 24kHz (D-Star/DMR/System Fusion/CW Id)"; const uint8_t PROTOCOL_VERSION = 1U; From 4dbcfd6b049cd78ac17ee5785b704be659e36093 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 17 Jun 2016 07:47:11 +0100 Subject: [PATCH 105/329] Add the DMR Abort command. --- DMRTX.cpp | 19 +++++++++++++++++++ DMRTX.h | 2 ++ SerialPort.cpp | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/DMRTX.cpp b/DMRTX.cpp index 3406ff6..7800490 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -185,6 +185,25 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length) return 0U; } +uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length) +{ + if (length != 1U) + return 4U; + + switch (data[0U]) { + case 1U: + m_fifo[0U].reset(); + return 0U; + + case 2U: + m_fifo[1U].reset(); + return 0U; + + default: + return 4U; + } +} + void CDMRTX::setStart(bool start) { m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE; diff --git a/DMRTX.h b/DMRTX.h index 2db5f3f..ea404d0 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -40,7 +40,9 @@ public: uint8_t writeData1(const uint8_t* data, uint8_t length); uint8_t writeData2(const uint8_t* data, uint8_t length); + uint8_t writeShortLC(const uint8_t* data, uint8_t length); + uint8_t writeAbort(const uint8_t* data, uint8_t length); void setStart(bool start); void setCal(bool start); diff --git a/SerialPort.cpp b/SerialPort.cpp index d11e7e3..a29fec2 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -47,6 +47,7 @@ const uint8_t MMDVM_DMR_DATA2 = 0x1AU; const uint8_t MMDVM_DMR_LOST2 = 0x1BU; const uint8_t MMDVM_DMR_SHORTLC = 0x1CU; const uint8_t MMDVM_DMR_START = 0x1DU; +const uint8_t MMDVM_DMR_ABORT = 0x1EU; const uint8_t MMDVM_YSF_DATA = 0x20U; const uint8_t MMDVM_YSF_LOST = 0x21U; @@ -521,6 +522,15 @@ void CSerialPort::process() } break; + case MMDVM_DMR_ABORT: + if (m_dmrEnable) + err = dmrTX.writeAbort(m_buffer + 3U, m_len - 3U); + if (err != 0U) { + DEBUG2("Received invalid DMR Abort", err); + sendNAK(err); + } + break; + case MMDVM_YSF_DATA: if (m_ysfEnable) { if (m_modemState == STATE_IDLE || m_modemState == STATE_YSF) From 1c70de5aee8f03c1c762d34b8f4fca2948f76125 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 20 Jun 2016 19:34:25 +0100 Subject: [PATCH 106/329] Change the empty activity short LC to the null short LC. --- DMRTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 7800490..f204f51 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -45,7 +45,7 @@ const uint8_t CACH_INTERLEAVE[] = 73U, 74U, 75U, 77U, 78U, 79U, 81U, 82U, 83U, 85U, 87U, 88U, 89U, 91U, 92U, 93U, 95U}; const uint8_t EMPTY_SHORT_LC[] = - {0x00U, 0x00U, 0x44U, 0x00U, 0x00U, 0x18U, 0x03U, 0x14U, 0x08U, 0x63U, 0x20U, 0x00U}; + {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; From a3ea870b521916c8fd65ae6d784cee04a8ae9c86 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 20 Jun 2016 22:03:54 +0100 Subject: [PATCH 107/329] Allow for the fine adjustment of levels. --- DMRTX.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++------- DMRTX.h | 5 +++++ DStarTX.cpp | 38 +++++++++++++++++++++++++++---- DStarTX.h | 3 +++ SerialPort.cpp | 14 +++++++++++- YSFTX.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++------- YSFTX.h | 5 +++++ 7 files changed, 166 insertions(+), 21 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index f204f51..a396ebb 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -17,6 +17,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "DMRSlotType.h" @@ -27,10 +29,8 @@ static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1 -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; -q15_t DMR_A[] = { 640, 640, 640, 640, 640}; -q15_t DMR_B[] = { 213, 213, 213, 213, 213}; -q15_t DMR_C[] = {-213, -213, -213, -213, -213}; -q15_t DMR_D[] = {-640, -640, -640, -640, -640}; +const q15_t DMR_LEVEL3 = 640; +const q15_t DMR_LEVEL1 = 213; // The PR FILL and Data Sync pattern. const uint8_t IDLE_DATA[] = @@ -54,6 +54,10 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 CDMRTX::CDMRTX() : m_fifo(), +m_levelA(), +m_levelB(), +m_levelC(), +m_levelD(), m_modFilter(), m_modState(), m_state(DMRTXSTATE_IDLE), @@ -75,6 +79,13 @@ m_count(0U) ::memcpy(m_newShortLC, EMPTY_SHORT_LC, 12U); ::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U); + + for (uint8_t i = 0U; i < 5U; i++) { + m_levelA[i] = DMR_LEVEL3; + m_levelB[i] = DMR_LEVEL1; + m_levelC[i] = -DMR_LEVEL1; + m_levelD[i] = -DMR_LEVEL3; + } } void CDMRTX::process() @@ -229,16 +240,16 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += DMR_RADIO_SYMBOL_LENGTH) { switch (c & MASK) { case 0xC0U: - ::memcpy(p, DMR_A, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelA, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x80U: - ::memcpy(p, DMR_B, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelB, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x00U: - ::memcpy(p, DMR_C, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelC, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; default: - ::memcpy(p, DMR_D, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelD, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; } } @@ -368,3 +379,37 @@ void CDMRTX::setColorCode(uint8_t colorCode) slotType.encode(colorCode, DT_IDLE, m_idle); } +void CDMRTX::setLevels(int8_t percent1, int8_t percent3) +{ + q31_t res1 = DMR_LEVEL1 * 1000; + q31_t res3 = DMR_LEVEL3 * 1000; + + if (percent1 > 0) { + for (int8_t i = 0; i < percent1; i++) + res1 += DMR_LEVEL1; + } else if (percent1 < 0) { + for (int8_t i = 0; i < -percent1; i++) + res1 -= DMR_LEVEL1; + } + + if (percent3 > 0) { + for (int8_t i = 0; i < percent3; i++) + res3 += DMR_LEVEL3; + } else if (percent3 < 0) { + for (int8_t i = 0; i < -percent3; i++) + res3 -= DMR_LEVEL3; + } + + q15_t level1 = res1 / 1000; + q15_t level3 = res3 / 1000; + + for (uint8_t i = 0U; i < 5U; i++) { + m_levelA[i] = level3; + m_levelB[i] = level1; + m_levelC[i] = -level1; + m_levelD[i] = -level3; + } + + DEBUG3("DMR, Levels 1/3", level1, level3); +} + diff --git a/DMRTX.h b/DMRTX.h index ea404d0..7cb3c0b 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -53,9 +53,14 @@ public: uint16_t getSpace2() const; void setColorCode(uint8_t colorCode); + void setLevels(int8_t level1, int8_t level3); private: CSerialRB m_fifo[2U]; + q15_t m_levelA[5U]; + q15_t m_levelB[5U]; + q15_t m_levelC[5U]; + q15_t m_levelD[5U]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare DMRTXSTATE m_state; diff --git a/DStarTX.cpp b/DStarTX.cpp index a319651..f07ee87 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "DStarTX.h" @@ -30,8 +32,7 @@ const uint8_t FRAME_SYNC[] = {0xEAU, 0xA6U, 0x00U}; static q15_t DSTAR_GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; const uint16_t DSTAR_GMSK_FILTER_LEN = 12U; -q15_t DSTAR_1[] = { 800, 800, 800, 800, 800}; -q15_t DSTAR_0[] = {-800, -800, -800, -800, -800}; +const q15_t DSTAR_LEVEL = 800; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -188,6 +189,8 @@ const uint8_t DSTAR_EOT = 0x02U; CDStarTX::CDStarTX() : m_buffer(), +m_level0(), +m_level1(), m_modFilter(), m_modState(), m_poBuffer(), @@ -201,6 +204,11 @@ m_count(0U) m_modFilter.numTaps = DSTAR_GMSK_FILTER_LEN; m_modFilter.pState = m_modState; m_modFilter.pCoeffs = DSTAR_GMSK_FILTER; + + for (uint8_t i = 0U; i < 5U; i++) { + m_level0[i] = -DSTAR_LEVEL; + m_level1[i] = DSTAR_LEVEL; + } } void CDStarTX::process() @@ -417,9 +425,9 @@ void CDStarTX::writeByte(uint8_t c) q15_t* p = inBuffer; for (uint8_t i = 0U; i < 8U; i++, p += DSTAR_RADIO_BIT_LENGTH) { if ((c & mask) == mask) - ::memcpy(p, DSTAR_0, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_level0, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); else - ::memcpy(p, DSTAR_1, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_level1, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); mask <<= 1; } @@ -457,3 +465,25 @@ uint16_t CDStarTX::getSpace() const return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U); } +void CDStarTX::setLevels(int8_t percent) +{ + q31_t res = DSTAR_LEVEL * 1000; + + if (percent > 0) { + for (int8_t i = 0; i < percent; i++) + res += DSTAR_LEVEL; + } else if (percent < 0) { + for (int8_t i = 0; i < -percent; i++) + res -= DSTAR_LEVEL; + } + + q15_t level = res / 1000; + + for (uint8_t i = 0U; i < 5U; i++) { + m_level0[i] = -level; + m_level1[i] = level; + } + + DEBUG2("D-Star, Level", level); +} + diff --git a/DStarTX.h b/DStarTX.h index b2f72ff..c3cb177 100644 --- a/DStarTX.h +++ b/DStarTX.h @@ -34,11 +34,14 @@ public: void process(); void setTXDelay(uint8_t delay); + void setLevels(int8_t level); uint16_t getSpace() const; private: CSerialRB m_buffer; + q15_t m_level0[5U]; + q15_t m_level1[5U]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare uint8_t m_poBuffer[400U]; diff --git a/SerialPort.cpp b/SerialPort.cpp index a29fec2..e688b00 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -185,7 +185,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 9U) + if (length < 14U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -232,6 +232,14 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_sampleInsert = false; } + int8_t dstarLevel = int8_t(data[9U]) - 128; + + int8_t dmrLevel1 = int8_t(data[10U]) - 128; + int8_t dmrLevel3 = int8_t(data[11U]) - 128; + + int8_t ysfLevel1 = int8_t(data[12U]) - 128; + int8_t ysfLevel3 = int8_t(data[13U]) - 128; + m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -246,6 +254,10 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrRX.setDelay(dmrDelay); dmrIdleRX.setColorCode(colorCode); + dstarTX.setLevels(dstarLevel); + dmrTX.setLevels(dmrLevel1, dmrLevel3); + ysfTX.setLevels(ysfLevel1, ysfLevel3); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, txLevel); io.start(); diff --git a/YSFTX.cpp b/YSFTX.cpp index 92984a7..3b37372 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define WANT_DEBUG + #include "Config.h" #include "Globals.h" #include "YSFTX.h" @@ -31,13 +33,15 @@ const uint16_t YSF_C4FSK_FILTER_LEN = 42U; const uint8_t YSF_START_SYNC = 0x77U; const uint8_t YSF_END_SYNC = 0xFFU; -q15_t YSF_A[] = { 809, 809, 809, 809, 809}; -q15_t YSF_B[] = { 269, 269, 269, 269, 269}; -q15_t YSF_C[] = {-269, -269, -269, -269, -269}; -q15_t YSF_D[] = {-809, -809, -809, -809, -809}; +const q15_t YSF_LEVEL3 = 809; +const q15_t YSF_LEVEL1 = 269; CYSFTX::CYSFTX() : m_buffer(1500U), +m_levelA(), +m_levelB(), +m_levelC(), +m_levelD(), m_modFilter(), m_modState(), m_poBuffer(), @@ -51,6 +55,13 @@ m_count(0U) m_modFilter.numTaps = YSF_C4FSK_FILTER_LEN; m_modFilter.pState = m_modState; m_modFilter.pCoeffs = YSF_C4FSK_FILTER; + + for (uint8_t i = 0U; i < 5U; i++) { + m_levelA[i] = YSF_LEVEL3; + m_levelB[i] = YSF_LEVEL1; + m_levelC[i] = -YSF_LEVEL1; + m_levelD[i] = -YSF_LEVEL3; + } } void CYSFTX::process() @@ -118,16 +129,16 @@ void CYSFTX::writeByte(uint8_t c) for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += YSF_RADIO_SYMBOL_LENGTH) { switch (c & MASK) { case 0xC0U: - ::memcpy(p, YSF_A, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelA, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x80U: - ::memcpy(p, YSF_B, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelB, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x00U: - ::memcpy(p, YSF_C, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelC, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; default: - ::memcpy(p, YSF_D, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, m_levelD, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; } } @@ -165,3 +176,37 @@ uint16_t CYSFTX::getSpace() const return m_buffer.getSpace() / YSF_FRAME_LENGTH_BYTES; } +void CYSFTX::setLevels(int8_t percent1, int8_t percent3) +{ + q31_t res1 = YSF_LEVEL1 * 1000; + q31_t res3 = YSF_LEVEL3 * 1000; + + if (percent1 > 0) { + for (int8_t i = 0; i < percent1; i++) + res1 += YSF_LEVEL1; + } else if (percent1 < 0) { + for (int8_t i = 0; i < -percent1; i++) + res1 -= YSF_LEVEL1; + } + + if (percent3 > 0) { + for (int8_t i = 0; i < percent3; i++) + res3 += YSF_LEVEL3; + } else if (percent3 < 0) { + for (int8_t i = 0; i < -percent3; i++) + res3 -= YSF_LEVEL3; + } + + q15_t level1 = res1 / 1000; + q15_t level3 = res3 / 1000; + + for (uint8_t i = 0U; i < 5U; i++) { + m_levelA[i] = level3; + m_levelB[i] = level1; + m_levelC[i] = -level1; + m_levelD[i] = -level3; + } + + DEBUG3("YSF, Levels 1/3", level1, level3); +} + diff --git a/YSFTX.h b/YSFTX.h index 9235a9c..9ae8cef 100644 --- a/YSFTX.h +++ b/YSFTX.h @@ -32,11 +32,16 @@ public: void process(); void setTXDelay(uint8_t delay); + void setLevels(int8_t level1, int8_t level3); uint16_t getSpace() const; private: CSerialRB m_buffer; + q15_t m_levelA[5U]; + q15_t m_levelB[5U]; + q15_t m_levelC[5U]; + q15_t m_levelD[5U]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare uint8_t m_poBuffer[720U]; From 17f6314f906b96d5829f6db26fbdc8bafe12704f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Jun 2016 07:25:25 +0100 Subject: [PATCH 108/329] Add fine adjustment to the DMR/YSF thresholds. --- DMRIdleRX.cpp | 24 +++++++++++++++++++++--- DMRIdleRX.h | 2 ++ DMRRX.cpp | 6 ++++++ DMRRX.h | 1 + DMRSlotRX.cpp | 22 ++++++++++++++++++++-- DMRSlotRX.h | 2 ++ SerialPort.cpp | 9 ++++++++- YSFRX.cpp | 22 ++++++++++++++++++++-- YSFRX.h | 3 +++ 9 files changed, 83 insertions(+), 8 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 2121a47..28b716f 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -47,7 +47,8 @@ m_endPtr(NOENDPTR), m_maxCorr(0), m_centre(0), m_threshold(0), -m_colorCode(0U) +m_colorCode(0U), +m_scale(SCALING_FACTOR) { } @@ -103,7 +104,7 @@ void CDMRIdleRX::processSample(q15_t sample) if (corr > m_maxCorr) { q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * SCALING_FACTOR; + q31_t v1 = (max - centre) * m_scale; q15_t threshold = q15_t(v1 >> 15); uint8_t sync[DMR_SYNC_BYTES_LENGTH]; @@ -200,3 +201,20 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode) m_colorCode = colorCode; } +void CDMRIdleRX::setThreshold(int8_t percent) +{ + q31_t res = SCALING_FACTOR * 1000; + + if (percent > 0) { + for (int8_t i = 0; i < percent; i++) + res += SCALING_FACTOR; + } else if (percent < 0) { + for (int8_t i = 0; i < -percent; i++) + res -= SCALING_FACTOR; + } + + m_scale = res / 1000; + + DEBUG2("DMR, Scale", m_scale); +} + diff --git a/DMRIdleRX.h b/DMRIdleRX.h index fbb82fa..72b251f 100644 --- a/DMRIdleRX.h +++ b/DMRIdleRX.h @@ -28,6 +28,7 @@ public: void samples(const q15_t* samples, uint8_t length); + void setThreshold(int8_t threshold); void setColorCode(uint8_t colorCode); void reset(); @@ -42,6 +43,7 @@ private: q15_t m_centre; q15_t m_threshold; uint8_t m_colorCode; + q15_t m_scale; void processSample(q15_t sample); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); diff --git a/DMRRX.cpp b/DMRRX.cpp index 9137b94..3c93b3c 100644 --- a/DMRRX.cpp +++ b/DMRRX.cpp @@ -56,6 +56,12 @@ void CDMRRX::setColorCode(uint8_t colorCode) m_slot2RX.setColorCode(colorCode); } +void CDMRRX::setThreshold(int8_t threshold) +{ + m_slot1RX.setThreshold(threshold); + m_slot2RX.setThreshold(threshold); +} + void CDMRRX::setDelay(uint8_t delay) { m_slot1RX.setDelay(delay); diff --git a/DMRRX.h b/DMRRX.h index 2f8810d..b3584de 100644 --- a/DMRRX.h +++ b/DMRRX.h @@ -29,6 +29,7 @@ public: void samples(const q15_t* samples, const uint8_t* control, uint8_t length); void setColorCode(uint8_t colorCode); + void setThreshold(int8_t threshold); void setDelay(uint8_t delay); void reset(); diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index be2ec48..fc67529 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -61,7 +61,8 @@ m_colorCode(0U), m_delay(0U), m_state(DMRRXS_NONE), m_n(0U), -m_type(0U) +m_type(0U), +m_scale(SCALING_FACTOR) { } @@ -270,7 +271,7 @@ void CDMRSlotRX::correlateSync(bool first) if (corr > m_maxCorr) { q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * SCALING_FACTOR; + q31_t v1 = (max - centre) * m_scale; q15_t threshold = q15_t(v1 >> 15); uint8_t sync[DMR_SYNC_BYTES_LENGTH]; @@ -371,3 +372,20 @@ void CDMRSlotRX::setDelay(uint8_t delay) m_delay = delay; } +void CDMRSlotRX::setThreshold(int8_t percent) +{ + q31_t res = SCALING_FACTOR * 1000; + + if (percent > 0) { + for (int8_t i = 0; i < percent; i++) + res += SCALING_FACTOR; + } else if (percent < 0) { + for (int8_t i = 0; i < -percent; i++) + res -= SCALING_FACTOR; + } + + m_scale = res / 1000; + + DEBUG2("DMR, Scale", m_scale); +} + diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 994839f..023b97c 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -37,6 +37,7 @@ public: bool processSample(q15_t sample); void setColorCode(uint8_t colorCode); + void setThreshold(int8_t threshold); void setDelay(uint8_t delay); void reset(); @@ -62,6 +63,7 @@ private: DMRRX_STATE m_state; uint8_t m_n; uint8_t m_type; + q15_t m_scale; void correlateSync(bool first); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); diff --git a/SerialPort.cpp b/SerialPort.cpp index e688b00..b9a6e57 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -185,7 +185,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 14U) + if (length < 16U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -240,6 +240,9 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) int8_t ysfLevel1 = int8_t(data[12U]) - 128; int8_t ysfLevel3 = int8_t(data[13U]) - 128; + int8_t dmrThreshold = int8_t(data[14U]) - 128; + int8_t ysfThreshold = int8_t(data[15U]) - 128; + m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -258,6 +261,10 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrTX.setLevels(dmrLevel1, dmrLevel3); ysfTX.setLevels(ysfLevel1, ysfLevel3); + dmrIdleRX.setThreshold(dmrThreshold); + dmrRX.setThreshold(dmrThreshold); + ysfRX.setThreshold(ysfThreshold); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, txLevel); io.start(); diff --git a/YSFRX.cpp b/YSFRX.cpp index 37826af..477c3b2 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -55,7 +55,8 @@ m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), m_centre(0), -m_threshold(0) +m_threshold(0), +m_scale(SCALING_FACTOR) { m_buffer = m_outBuffer + 1U; } @@ -123,7 +124,7 @@ void CYSFRX::processNone(q15_t sample) q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * SCALING_FACTOR; + q31_t v1 = (max - centre) * m_scale; q15_t threshold = q15_t(v1 >> 15); uint16_t ptr = m_symbolPtr + 1U; @@ -242,3 +243,20 @@ void CYSFRX::processData(q15_t sample) } } +void CYSFRX::setThreshold(int8_t percent) +{ + q31_t res = SCALING_FACTOR * 1000; + + if (percent > 0) { + for (int8_t i = 0; i < percent; i++) + res += SCALING_FACTOR; + } else if (percent < 0) { + for (int8_t i = 0; i < -percent; i++) + res -= SCALING_FACTOR; + } + + m_scale = res / 1000; + + DEBUG2("YSF, Scale", m_scale); +} + diff --git a/YSFRX.h b/YSFRX.h index 22228ce..32a8c9e 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -35,6 +35,8 @@ public: void reset(); + void setThreshold(int8_t threshold); + private: uint32_t m_pll; bool m_prev; @@ -49,6 +51,7 @@ private: uint16_t m_lostCount; q15_t m_centre; q15_t m_threshold; + q15_t m_scale; void processNone(q15_t sample); void processData(q15_t sample); From 2d656b0126549b237d7f7bbc7a2f58d589b3e9e0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 22 Jun 2016 18:06:49 +0100 Subject: [PATCH 109/329] Alter levels and threshold logging slightly. --- DMRIdleRX.cpp | 2 +- DMRSlotRX.cpp | 2 +- DMRTX.cpp | 2 +- DStarTX.cpp | 2 +- YSFRX.cpp | 2 +- YSFTX.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 28b716f..bc0570b 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -215,6 +215,6 @@ void CDMRIdleRX::setThreshold(int8_t percent) m_scale = res / 1000; - DEBUG2("DMR, Scale", m_scale); + DEBUG2("DMRIdleRX: Scale", m_scale); } diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index fc67529..d312266 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -386,6 +386,6 @@ void CDMRSlotRX::setThreshold(int8_t percent) m_scale = res / 1000; - DEBUG2("DMR, Scale", m_scale); + DEBUG2("DMRSlotRX: Scale", m_scale); } diff --git a/DMRTX.cpp b/DMRTX.cpp index a396ebb..af6173f 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -410,6 +410,6 @@ void CDMRTX::setLevels(int8_t percent1, int8_t percent3) m_levelD[i] = -level3; } - DEBUG3("DMR, Levels 1/3", level1, level3); + DEBUG3("DMRTX: Levels 1/3", level1, level3); } diff --git a/DStarTX.cpp b/DStarTX.cpp index f07ee87..14bd713 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -484,6 +484,6 @@ void CDStarTX::setLevels(int8_t percent) m_level1[i] = level; } - DEBUG2("D-Star, Level", level); + DEBUG2("DStarTX: Level", level); } diff --git a/YSFRX.cpp b/YSFRX.cpp index 477c3b2..b3ffa46 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -257,6 +257,6 @@ void CYSFRX::setThreshold(int8_t percent) m_scale = res / 1000; - DEBUG2("YSF, Scale", m_scale); + DEBUG2("YSFRX: Scale", m_scale); } diff --git a/YSFTX.cpp b/YSFTX.cpp index 3b37372..e433ab4 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -207,6 +207,6 @@ void CYSFTX::setLevels(int8_t percent1, int8_t percent3) m_levelD[i] = -level3; } - DEBUG3("YSF, Levels 1/3", level1, level3); + DEBUG3("YSFTX: Levels 1/3", level1, level3); } From 01d40782caa6a8117a51b5fbf4b3385c1ec97c3c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 22 Jun 2016 20:51:35 +0100 Subject: [PATCH 110/329] Use symbolic names instead of magic numbers. --- DMRTX.cpp | 4 ++-- DMRTX.h | 8 ++++---- DStarTX.cpp | 4 ++-- DStarTX.h | 4 ++-- YSFTX.cpp | 4 ++-- YSFTX.h | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index af6173f..e73d6d6 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -80,7 +80,7 @@ m_count(0U) ::memcpy(m_newShortLC, EMPTY_SHORT_LC, 12U); ::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U); - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < DMR_RADIO_SYMBOL_LENGTH; i++) { m_levelA[i] = DMR_LEVEL3; m_levelB[i] = DMR_LEVEL1; m_levelC[i] = -DMR_LEVEL1; @@ -403,7 +403,7 @@ void CDMRTX::setLevels(int8_t percent1, int8_t percent3) q15_t level1 = res1 / 1000; q15_t level3 = res3 / 1000; - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < DMR_RADIO_SYMBOL_LENGTH; i++) { m_levelA[i] = level3; m_levelB[i] = level1; m_levelC[i] = -level1; diff --git a/DMRTX.h b/DMRTX.h index 7cb3c0b..a42c850 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -57,10 +57,10 @@ public: private: CSerialRB m_fifo[2U]; - q15_t m_levelA[5U]; - q15_t m_levelB[5U]; - q15_t m_levelC[5U]; - q15_t m_levelD[5U]; + q15_t m_levelA[DMR_RADIO_SYMBOL_LENGTH]; + q15_t m_levelB[DMR_RADIO_SYMBOL_LENGTH]; + q15_t m_levelC[DMR_RADIO_SYMBOL_LENGTH]; + q15_t m_levelD[DMR_RADIO_SYMBOL_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare DMRTXSTATE m_state; diff --git a/DStarTX.cpp b/DStarTX.cpp index 14bd713..b80c4be 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -205,7 +205,7 @@ m_count(0U) m_modFilter.pState = m_modState; m_modFilter.pCoeffs = DSTAR_GMSK_FILTER; - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < DSTAR_RADIO_BIT_LENGTH; i++) { m_level0[i] = -DSTAR_LEVEL; m_level1[i] = DSTAR_LEVEL; } @@ -479,7 +479,7 @@ void CDStarTX::setLevels(int8_t percent) q15_t level = res / 1000; - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < DSTAR_RADIO_BIT_LENGTH; i++) { m_level0[i] = -level; m_level1[i] = level; } diff --git a/DStarTX.h b/DStarTX.h index c3cb177..ab9ae17 100644 --- a/DStarTX.h +++ b/DStarTX.h @@ -40,8 +40,8 @@ public: private: CSerialRB m_buffer; - q15_t m_level0[5U]; - q15_t m_level1[5U]; + q15_t m_level0[DSTAR_RADIO_BIT_LENGTH]; + q15_t m_level1[DSTAR_RADIO_BIT_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare uint8_t m_poBuffer[400U]; diff --git a/YSFTX.cpp b/YSFTX.cpp index e433ab4..f2652dc 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -56,7 +56,7 @@ m_count(0U) m_modFilter.pState = m_modState; m_modFilter.pCoeffs = YSF_C4FSK_FILTER; - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < YSF_RADIO_SYMBOL_LENGTH; i++) { m_levelA[i] = YSF_LEVEL3; m_levelB[i] = YSF_LEVEL1; m_levelC[i] = -YSF_LEVEL1; @@ -200,7 +200,7 @@ void CYSFTX::setLevels(int8_t percent1, int8_t percent3) q15_t level1 = res1 / 1000; q15_t level3 = res3 / 1000; - for (uint8_t i = 0U; i < 5U; i++) { + for (uint8_t i = 0U; i < YSF_RADIO_SYMBOL_LENGTH; i++) { m_levelA[i] = level3; m_levelB[i] = level1; m_levelC[i] = -level1; diff --git a/YSFTX.h b/YSFTX.h index 9ae8cef..0e5cb18 100644 --- a/YSFTX.h +++ b/YSFTX.h @@ -38,10 +38,10 @@ public: private: CSerialRB m_buffer; - q15_t m_levelA[5U]; - q15_t m_levelB[5U]; - q15_t m_levelC[5U]; - q15_t m_levelD[5U]; + q15_t m_levelA[YSF_RADIO_SYMBOL_LENGTH]; + q15_t m_levelB[YSF_RADIO_SYMBOL_LENGTH]; + q15_t m_levelC[YSF_RADIO_SYMBOL_LENGTH]; + q15_t m_levelD[YSF_RADIO_SYMBOL_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare uint8_t m_poBuffer[720U]; From 723c7fe12ac05669b497cb050a6fc72c8d3d45eb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 24 Jun 2016 10:40:25 +0100 Subject: [PATCH 111/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index b9a6e57..c55eed3 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -61,7 +61,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160614 24kHz (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160624 24kHz (D-Star/DMR/System Fusion/CW Id)"; const uint8_t PROTOCOL_VERSION = 1U; From 5500975b5e84f9d7b1e2a6d7880a2e8adc29fbe7 Mon Sep 17 00:00:00 2001 From: kc2vrj Date: Wed, 29 Jun 2016 00:09:07 -0400 Subject: [PATCH 112/329] Create mmdvmmenu.sh This is a simple menu for editing the Config.c in the MMDVM --- mmdvmmenu.sh | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 mmdvmmenu.sh diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh new file mode 100644 index 0000000..390919b --- /dev/null +++ b/mmdvmmenu.sh @@ -0,0 +1,84 @@ +#! /bin/bash + +############################################################################### +# +# mmdvmmenu.sh +# +# Copyright (C) 2016 by Paul Nannery KC2VRJ +# +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +############################################################################### +# +# On a Linux based system, such as a Raspberry Pi, this script will perform +# Modafacation to the Config.c file for most options. It makes a Back up when +# you staet the script if none is present. You must recompile and load firmwhare +# on Due if changes are made. +# +############################################################################### +# +# CONFIGURATION +# +# Location of Config.h +conf=Config.h +#Location of backup file +confbak=Config.h.bak + +################################################################################ +# +# Do not edit below here +# +############################################################################### + + + +# Check for backup file and make one if not present + +if [ ! -f $confbak ];then + +cp -f $conf $confbak + +fi + +while : +do + clear + cat< $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; + "2") sudo sed -e 's/\/\/ #define EXTERNAL_OSC 14/ #define EXTERNAL_OSC 14/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; + "3") sudo sed -e 's/\/\/ #define EXTERNAL_OSC 19/ #define EXTERNAL_OSC 19/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; + "4") sudo sed -e 's/\/\/ #define USE/ #define USE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; + "5") sudo sed -e 's/\/\/ #define ARDUINO_MODE/ #define ARDUINO_MODE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; + "6") MV -f $confbak $conf ;; + "Q") echo "If any changes are made you need to upload to MMDVM" && exit;; + "q") echo "If any changes are made you need to upload to MMDVM" && exit;; + * ) echo "invalid option" ;; + esac + sleep 1 +done From d38ae029fe48b1fca48412d1b3fa7cf8e6161bb7 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:21:27 +0200 Subject: [PATCH 113/329] Removal of sudo and some minor code cleanups --- mmdvmmenu.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 390919b..b272e3f 100644 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash ############################################################################### # @@ -57,25 +57,25 @@ do clear cat< $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; - "2") sudo sed -e 's/\/\/ #define EXTERNAL_OSC 14/ #define EXTERNAL_OSC 14/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; - "3") sudo sed -e 's/\/\/ #define EXTERNAL_OSC 19/ #define EXTERNAL_OSC 19/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; - "4") sudo sed -e 's/\/\/ #define USE/ #define USE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; - "5") sudo sed -e 's/\/\/ #define ARDUINO_MODE/ #define ARDUINO_MODE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; - "6") MV -f $confbak $conf ;; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12/ #define EXTERNAL_OSC 12/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14/ #define EXTERNAL_OSC 14/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19/ #define EXTERNAL_OSC 19/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; + "4") sed -e 's/\/\/ #define USE/ #define USE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; + "5") sed -e 's/\/\/ #define ARDUINO_MODE/ #define ARDUINO_MODE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; + "6") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to upload to MMDVM" && exit;; "q") echo "If any changes are made you need to upload to MMDVM" && exit;; * ) echo "invalid option" ;; From d15e5532ae1bdeb8b621c863094d8ec1fdaf5d76 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:22:18 +0200 Subject: [PATCH 114/329] Make mmdvmmenu.sh executable --- mmdvmmenu.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 mmdvmmenu.sh diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh old mode 100644 new mode 100755 From 2b148904af95f9c6bac28074a4bb6518366fd780 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:31:46 +0200 Subject: [PATCH 115/329] Typo correction --- mmdvmmenu.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index b272e3f..7d53760 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -61,7 +61,7 @@ do -------------------------------------------------------------- Please enter your choice: - (1) Enable 12.0 MHZ CLock (4) Use the COS to lockout the modem + (1) Enable 12.0 MHZ Clock (4) Use the COS to lockout the modem (2) Enable 14.4 MHz Clock (5) Use pins to output the current mode (3) Enable 19.2 MHz Clock (6) Return to Default From 70df22ef8157a351b3eef78c15a08b528d3fb430 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:40:45 +0200 Subject: [PATCH 116/329] Make sed commands more specific --- mmdvmmenu.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 7d53760..fb61f58 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -10,23 +10,23 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # ############################################################################### # -# On a Linux based system, such as a Raspberry Pi, this script will perform -# Modafacation to the Config.c file for most options. It makes a Back up when +# On a Linux based system, such as a Raspberry Pi, this script will perform +# Modafacation to the Config.c file for most options. It makes a Back up when # you staet the script if none is present. You must recompile and load firmwhare # on Due if changes are made. -# +# ############################################################################### # # CONFIGURATION @@ -44,7 +44,7 @@ confbak=Config.h.bak -# Check for backup file and make one if not present +# Check for backup file and make one if not present if [ ! -f $confbak ];then @@ -70,14 +70,14 @@ do EOF read -n1 -s case "$REPLY" in - "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12/ #define EXTERNAL_OSC 12/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; - "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14/ #define EXTERNAL_OSC 14/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; - "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19/ #define EXTERNAL_OSC 19/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; - "4") sed -e 's/\/\/ #define USE/ #define USE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; - "5") sed -e 's/\/\/ #define ARDUINO_MODE/ #define ARDUINO_MODE/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; + "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; + "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; "6") mv -f $confbak $conf ;; - "Q") echo "If any changes are made you need to upload to MMDVM" && exit;; - "q") echo "If any changes are made you need to upload to MMDVM" && exit;; + "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; + "q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; * ) echo "invalid option" ;; esac sleep 1 From 701732a72437bef07afd993b9e552088fdcd46ec Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:46:47 +0200 Subject: [PATCH 117/329] Add options to change board layout --- mmdvmmenu.sh | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index fb61f58..556e5b7 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -61,21 +61,30 @@ do -------------------------------------------------------------- Please enter your choice: - (1) Enable 12.0 MHZ Clock (4) Use the COS to lockout the modem - (2) Enable 14.4 MHz Clock (5) Use pins to output the current mode - (3) Enable 19.2 MHz Clock (6) Return to Default + (1) Enable 12.0 MHZ Clock + (2) Enable 14.4 MHz Clock + (3) Enable 19.2 MHz Clock + (4) Use the COS to lockout the modem + (5) Use pins to output the current mode + (6) Use original Arduino Due layout + (7) Use new Arduino Due layout + (8) Use layout for SP8NTH board + (9) Return to Default (Q)uit --------------------------------------------------------------- EOF read -n1 -s case "$REPLY" in - "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; - "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; - "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; - "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; - "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/g' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; - "6") mv -f $confbak $conf ;; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; + "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; + "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; + "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Original Arduino Due layout enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM/#define ARDUINO_DUE_ZUM/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "New Arduino Due layout enabled";; + "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; + "9") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; "q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; * ) echo "invalid option" ;; From abfb777c696a3af6fea0b4f72019c913aa8b6b47 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 29 Jun 2016 12:48:11 +0200 Subject: [PATCH 118/329] Some typo correction --- mmdvmmenu.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 556e5b7..9434669 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -76,11 +76,11 @@ do EOF read -n1 -s case "$REPLY" in - "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHZ CLock Enabled";; - "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHZ CLock Enabled";; - "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHZ CLock Enabled";; - "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS As Lockout Enabled";; - "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode Pins Enabled";; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHz clock enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHz clock enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; + "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; + "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Original Arduino Due layout enabled";; "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM/#define ARDUINO_DUE_ZUM/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "New Arduino Due layout enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; From 8135f8a57d17f73375aff0e2083a71c327a4f000 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 5 Jul 2016 07:09:01 +0100 Subject: [PATCH 119/329] New transmit filters for DMR and YSF. --- Config.h | 2 +- DMRTX.cpp | 9 +++++++++ IO.cpp | 4 ++-- YSFTX.cpp | 15 ++++++++++++--- mmdvmmenu.sh | 8 ++++---- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Config.h b/Config.h index 148fea1..16ed653 100644 --- a/Config.h +++ b/Config.h @@ -38,7 +38,7 @@ // #define ARDUINO_DUE_PAPA // For the new Arduino Due pin layout -#define ARDUINO_DUE_ZUM +#define ARDUINO_DUE_ZUM_V10 // For the SP8NTH board // #define ARDUINO_DUE_NTH diff --git a/DMRTX.cpp b/DMRTX.cpp index e73d6d6..43a14ad 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -23,11 +23,20 @@ #include "Globals.h" #include "DMRSlotType.h" +#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, + -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. + -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, + 2, 1, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 60U; +#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; +#endif const q15_t DMR_LEVEL3 = 640; const q15_t DMR_LEVEL1 = 213; diff --git a/IO.cpp b/IO.cpp index 9803040..3540f10 100644 --- a/IO.cpp +++ b/IO.cpp @@ -47,7 +47,7 @@ const uint16_t DC_OFFSET = 2048U; #define ADC_CDR_Chan 7 #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 -#elif defined(ARDUINO_DUE_ZUM) +#elif defined(ARDUINO_DUE_ZUM_V10) #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -72,7 +72,7 @@ const uint16_t DC_OFFSET = 2048U; #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 #else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM, or ARDUINO_DUE_NTH need to be defined" +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" #endif #elif defined(__MBED__) // A generic MBED platform diff --git a/YSFTX.cpp b/YSFTX.cpp index f2652dc..7e0465d 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -24,18 +24,27 @@ #include "YSFDefines.h" +#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB +static q15_t YSF_C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, + -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. + -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, + 2, 1, 0}; +const uint16_t YSF_C4FSK_FILTER_LEN = 60U; +#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 42U; - -const uint8_t YSF_START_SYNC = 0x77U; -const uint8_t YSF_END_SYNC = 0xFFU; +#endif const q15_t YSF_LEVEL3 = 809; const q15_t YSF_LEVEL1 = 269; +const uint8_t YSF_START_SYNC = 0x77U; +const uint8_t YSF_END_SYNC = 0xFFU; + CYSFTX::CYSFTX() : m_buffer(1500U), m_levelA(), diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 9434669..aa56151 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -66,8 +66,8 @@ do (3) Enable 19.2 MHz Clock (4) Use the COS to lockout the modem (5) Use pins to output the current mode - (6) Use original Arduino Due layout - (7) Use new Arduino Due layout + (6) Use layout for the PAPA board + (7) Use layout for ZUM board V1.0 (8) Use layout for SP8NTH board (9) Return to Default @@ -81,8 +81,8 @@ EOF "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; - "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Original Arduino Due layout enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM/#define ARDUINO_DUE_ZUM/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "New Arduino Due layout enabled";; + "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; "9") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; From 5725e3babeee23d7c11626811fa38d525cf50fa3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 5 Jul 2016 07:31:29 +0100 Subject: [PATCH 120/329] New receive filter for DMR and YSF. --- DMRSlotRX.cpp | 10 +++++++++- IO.cpp | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index d312266..157280b 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -24,6 +24,14 @@ #include "DMRSlotType.h" #include "Utils.h" +#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) +const uint16_t SCAN_START = 420U; +const uint16_t SCAN_END = 510U; +#else +const uint16_t SCAN_START = 400U; +const uint16_t SCAN_END = 490U; +#endif + const q15_t SCALING_FACTOR = 19505; // Q15(0.60) const uint8_t MAX_SYNC_SYMBOLS_ERRS = 2U; @@ -115,7 +123,7 @@ bool CDMRSlotRX::processSample(q15_t sample) m_bitBuffer[m_bitPtr] |= 0x01U; if (m_state == DMRRXS_NONE) { - if (m_dataPtr >= 400U && m_dataPtr <= 490U) + if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END) correlateSync(true); } else { uint16_t min = m_syncPtr - 1U; diff --git a/IO.cpp b/IO.cpp index 3540f10..01adede 100644 --- a/IO.cpp +++ b/IO.cpp @@ -24,11 +24,20 @@ #include "Globals.h" #include "IO.h" +#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB +static q15_t C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, + -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. + -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, + 2, 1, 0}; +const uint16_t C4FSK_FILTER_LEN = 60U; +#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t C4FSK_FILTER_LEN = 42U; +#endif // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; From dcc52ca479ad99cb6cc34c86cdb728a2296d4b22 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 5 Jul 2016 18:16:47 +0100 Subject: [PATCH 121/329] Remove new filters and remove extra debugging. --- DMRIdleRX.cpp | 2 +- DMRSlotRX.cpp | 7 +------ DMRTX.cpp | 11 +---------- DStarTX.cpp | 4 ++-- DStarTX.h | 2 +- IO.cpp | 9 --------- YSFTX.cpp | 13 ++----------- YSFTX.h | 2 +- 8 files changed, 9 insertions(+), 41 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index bc0570b..63859ef 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 157280b..d964ef3 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -24,13 +24,8 @@ #include "DMRSlotType.h" #include "Utils.h" -#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) -const uint16_t SCAN_START = 420U; -const uint16_t SCAN_END = 510U; -#else const uint16_t SCAN_START = 400U; const uint16_t SCAN_END = 490U; -#endif const q15_t SCALING_FACTOR = 19505; // Q15(0.60) diff --git a/DMRTX.cpp b/DMRTX.cpp index 43a14ad..49277d2 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -17,26 +17,17 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" #include "DMRSlotType.h" -#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB -static q15_t DMR_C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, - -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. - -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, - 2, 1, 0}; -const uint16_t DMR_C4FSK_FILTER_LEN = 60U; -#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; -#endif const q15_t DMR_LEVEL3 = 640; const q15_t DMR_LEVEL1 = 213; diff --git a/DStarTX.cpp b/DStarTX.cpp index b80c4be..c71b1d2 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -457,7 +457,7 @@ void CDStarTX::writeByte(uint8_t c) void CDStarTX::setTXDelay(uint8_t delay) { - m_txDelay = 120U + uint16_t(delay) * 6U; // 200ms + tx delay + m_txDelay = 150U + uint16_t(delay) * 6U; // 250ms + tx delay } uint16_t CDStarTX::getSpace() const diff --git a/DStarTX.h b/DStarTX.h index ab9ae17..eb43a5f 100644 --- a/DStarTX.h +++ b/DStarTX.h @@ -44,7 +44,7 @@ private: q15_t m_level1[DSTAR_RADIO_BIT_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare - uint8_t m_poBuffer[400U]; + uint8_t m_poBuffer[500U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; // In bytes diff --git a/IO.cpp b/IO.cpp index 01adede..3540f10 100644 --- a/IO.cpp +++ b/IO.cpp @@ -24,20 +24,11 @@ #include "Globals.h" #include "IO.h" -#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB -static q15_t C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, - -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. - -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, - 2, 1, 0}; -const uint16_t C4FSK_FILTER_LEN = 60U; -#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t C4FSK_FILTER_LEN = 42U; -#endif // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/YSFTX.cpp b/YSFTX.cpp index 7e0465d..b0b947a 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -24,20 +24,11 @@ #include "YSFDefines.h" -#if defined(ARDUINO_DUE_ZUM_V10) || defined(ARDUINO_DUE_NTH) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') plus a custom filter in MATLAB -static q15_t YSF_C4FSK_FILTER[] = {1, 2, 1, -5, -17, -28, -17, 37, 121, 175, 105, -137, -475, -690, -518, 166, 1197, 2114, 2346, 1516, -309, - -2550, -4280, -4565, -2827, 885, 5849, 10850, 14549, 15911, 14549, 10850, 5849, 885, -2827, -4565, -4280. - -2550, -309, 1516, 2346, 2114, 1197, 166, -518, -690, -475, -137, 105, 175, 121, 37, -17, -28, -17, -5, 1, - 2, 1, 0}; -const uint16_t YSF_C4FSK_FILTER_LEN = 60U; -#else // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 42U; -#endif const q15_t YSF_LEVEL3 = 809; const q15_t YSF_LEVEL1 = 269; @@ -177,7 +168,7 @@ void CYSFTX::writeByte(uint8_t c) void CYSFTX::setTXDelay(uint8_t delay) { - m_txDelay = 240U + uint16_t(delay) * 12U; // 200ms + tx delay + m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay } uint16_t CYSFTX::getSpace() const diff --git a/YSFTX.h b/YSFTX.h index 0e5cb18..d5b0b2a 100644 --- a/YSFTX.h +++ b/YSFTX.h @@ -44,7 +44,7 @@ private: q15_t m_levelD[YSF_RADIO_SYMBOL_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare - uint8_t m_poBuffer[720U]; + uint8_t m_poBuffer[920U]; uint16_t m_poLen; uint16_t m_poPtr; uint16_t m_txDelay; From 87b6688f8fc321256885caf5570d69d42753c55f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 7 Jul 2016 17:37:06 +0100 Subject: [PATCH 122/329] Remove the level tweaking functionality. --- DMRIdleRX.cpp | 22 ++----------------- DMRIdleRX.h | 2 -- DMRRX.cpp | 6 ----- DMRRX.h | 1 - DMRSlotRX.cpp | 22 ++----------------- DMRSlotRX.h | 2 -- DMRTX.cpp | 59 +++++++------------------------------------------- DMRTX.h | 5 ----- DStarTX.cpp | 36 ++++-------------------------- DStarTX.h | 3 --- SerialPort.cpp | 21 +----------------- YSFRX.cpp | 22 ++----------------- YSFRX.h | 3 --- YSFTX.cpp | 59 +++++++------------------------------------------- YSFTX.h | 5 ----- 15 files changed, 27 insertions(+), 241 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 63859ef..2121a47 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -47,8 +47,7 @@ m_endPtr(NOENDPTR), m_maxCorr(0), m_centre(0), m_threshold(0), -m_colorCode(0U), -m_scale(SCALING_FACTOR) +m_colorCode(0U) { } @@ -104,7 +103,7 @@ void CDMRIdleRX::processSample(q15_t sample) if (corr > m_maxCorr) { q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * m_scale; + q31_t v1 = (max - centre) * SCALING_FACTOR; q15_t threshold = q15_t(v1 >> 15); uint8_t sync[DMR_SYNC_BYTES_LENGTH]; @@ -201,20 +200,3 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode) m_colorCode = colorCode; } -void CDMRIdleRX::setThreshold(int8_t percent) -{ - q31_t res = SCALING_FACTOR * 1000; - - if (percent > 0) { - for (int8_t i = 0; i < percent; i++) - res += SCALING_FACTOR; - } else if (percent < 0) { - for (int8_t i = 0; i < -percent; i++) - res -= SCALING_FACTOR; - } - - m_scale = res / 1000; - - DEBUG2("DMRIdleRX: Scale", m_scale); -} - diff --git a/DMRIdleRX.h b/DMRIdleRX.h index 72b251f..fbb82fa 100644 --- a/DMRIdleRX.h +++ b/DMRIdleRX.h @@ -28,7 +28,6 @@ public: void samples(const q15_t* samples, uint8_t length); - void setThreshold(int8_t threshold); void setColorCode(uint8_t colorCode); void reset(); @@ -43,7 +42,6 @@ private: q15_t m_centre; q15_t m_threshold; uint8_t m_colorCode; - q15_t m_scale; void processSample(q15_t sample); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); diff --git a/DMRRX.cpp b/DMRRX.cpp index 3c93b3c..9137b94 100644 --- a/DMRRX.cpp +++ b/DMRRX.cpp @@ -56,12 +56,6 @@ void CDMRRX::setColorCode(uint8_t colorCode) m_slot2RX.setColorCode(colorCode); } -void CDMRRX::setThreshold(int8_t threshold) -{ - m_slot1RX.setThreshold(threshold); - m_slot2RX.setThreshold(threshold); -} - void CDMRRX::setDelay(uint8_t delay) { m_slot1RX.setDelay(delay); diff --git a/DMRRX.h b/DMRRX.h index b3584de..2f8810d 100644 --- a/DMRRX.h +++ b/DMRRX.h @@ -29,7 +29,6 @@ public: void samples(const q15_t* samples, const uint8_t* control, uint8_t length); void setColorCode(uint8_t colorCode); - void setThreshold(int8_t threshold); void setDelay(uint8_t delay); void reset(); diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index d964ef3..3218381 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -64,8 +64,7 @@ m_colorCode(0U), m_delay(0U), m_state(DMRRXS_NONE), m_n(0U), -m_type(0U), -m_scale(SCALING_FACTOR) +m_type(0U) { } @@ -274,7 +273,7 @@ void CDMRSlotRX::correlateSync(bool first) if (corr > m_maxCorr) { q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * m_scale; + q31_t v1 = (max - centre) * SCALING_FACTOR; q15_t threshold = q15_t(v1 >> 15); uint8_t sync[DMR_SYNC_BYTES_LENGTH]; @@ -375,20 +374,3 @@ void CDMRSlotRX::setDelay(uint8_t delay) m_delay = delay; } -void CDMRSlotRX::setThreshold(int8_t percent) -{ - q31_t res = SCALING_FACTOR * 1000; - - if (percent > 0) { - for (int8_t i = 0; i < percent; i++) - res += SCALING_FACTOR; - } else if (percent < 0) { - for (int8_t i = 0; i < -percent; i++) - res -= SCALING_FACTOR; - } - - m_scale = res / 1000; - - DEBUG2("DMRSlotRX: Scale", m_scale); -} - diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 023b97c..994839f 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -37,7 +37,6 @@ public: bool processSample(q15_t sample); void setColorCode(uint8_t colorCode); - void setThreshold(int8_t threshold); void setDelay(uint8_t delay); void reset(); @@ -63,7 +62,6 @@ private: DMRRX_STATE m_state; uint8_t m_n; uint8_t m_type; - q15_t m_scale; void correlateSync(bool first); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); diff --git a/DMRTX.cpp b/DMRTX.cpp index 49277d2..9b937d6 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -29,8 +29,10 @@ static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1 -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; -const q15_t DMR_LEVEL3 = 640; -const q15_t DMR_LEVEL1 = 213; +const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; +const q15_t DMR_LEVELB[] = { 213, 213, 213, 213, 213}; +const q15_t DMR_LEVELC[] = {-213, -213, -213, -213, -213}; +const q15_t DMR_LEVELD[] = {-640, -640, -640, -640, -640}; // The PR FILL and Data Sync pattern. const uint8_t IDLE_DATA[] = @@ -54,10 +56,6 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02 CDMRTX::CDMRTX() : m_fifo(), -m_levelA(), -m_levelB(), -m_levelC(), -m_levelD(), m_modFilter(), m_modState(), m_state(DMRTXSTATE_IDLE), @@ -79,13 +77,6 @@ m_count(0U) ::memcpy(m_newShortLC, EMPTY_SHORT_LC, 12U); ::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U); - - for (uint8_t i = 0U; i < DMR_RADIO_SYMBOL_LENGTH; i++) { - m_levelA[i] = DMR_LEVEL3; - m_levelB[i] = DMR_LEVEL1; - m_levelC[i] = -DMR_LEVEL1; - m_levelD[i] = -DMR_LEVEL3; - } } void CDMRTX::process() @@ -240,16 +231,16 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += DMR_RADIO_SYMBOL_LENGTH) { switch (c & MASK) { case 0xC0U: - ::memcpy(p, m_levelA, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, DMR_LEVELA, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x80U: - ::memcpy(p, m_levelB, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, DMR_LEVELB, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x00U: - ::memcpy(p, m_levelC, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, DMR_LEVELC, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; default: - ::memcpy(p, m_levelD, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, DMR_LEVELD, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; } } @@ -379,37 +370,3 @@ void CDMRTX::setColorCode(uint8_t colorCode) slotType.encode(colorCode, DT_IDLE, m_idle); } -void CDMRTX::setLevels(int8_t percent1, int8_t percent3) -{ - q31_t res1 = DMR_LEVEL1 * 1000; - q31_t res3 = DMR_LEVEL3 * 1000; - - if (percent1 > 0) { - for (int8_t i = 0; i < percent1; i++) - res1 += DMR_LEVEL1; - } else if (percent1 < 0) { - for (int8_t i = 0; i < -percent1; i++) - res1 -= DMR_LEVEL1; - } - - if (percent3 > 0) { - for (int8_t i = 0; i < percent3; i++) - res3 += DMR_LEVEL3; - } else if (percent3 < 0) { - for (int8_t i = 0; i < -percent3; i++) - res3 -= DMR_LEVEL3; - } - - q15_t level1 = res1 / 1000; - q15_t level3 = res3 / 1000; - - for (uint8_t i = 0U; i < DMR_RADIO_SYMBOL_LENGTH; i++) { - m_levelA[i] = level3; - m_levelB[i] = level1; - m_levelC[i] = -level1; - m_levelD[i] = -level3; - } - - DEBUG3("DMRTX: Levels 1/3", level1, level3); -} - diff --git a/DMRTX.h b/DMRTX.h index a42c850..ea404d0 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -53,14 +53,9 @@ public: uint16_t getSpace2() const; void setColorCode(uint8_t colorCode); - void setLevels(int8_t level1, int8_t level3); private: CSerialRB m_fifo[2U]; - q15_t m_levelA[DMR_RADIO_SYMBOL_LENGTH]; - q15_t m_levelB[DMR_RADIO_SYMBOL_LENGTH]; - q15_t m_levelC[DMR_RADIO_SYMBOL_LENGTH]; - q15_t m_levelD[DMR_RADIO_SYMBOL_LENGTH]; arm_fir_instance_q15 m_modFilter; q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare DMRTXSTATE m_state; diff --git a/DStarTX.cpp b/DStarTX.cpp index c71b1d2..6fee338 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -32,7 +32,8 @@ const uint8_t FRAME_SYNC[] = {0xEAU, 0xA6U, 0x00U}; static q15_t DSTAR_GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; const uint16_t DSTAR_GMSK_FILTER_LEN = 12U; -const q15_t DSTAR_LEVEL = 800; +const q15_t DSTAR_LEVEL0[] = {-800, -800, -800, -800, -800}; +const q15_t DSTAR_LEVEL1[] = { 800, 800, 800, 800, 800}; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -189,8 +190,6 @@ const uint8_t DSTAR_EOT = 0x02U; CDStarTX::CDStarTX() : m_buffer(), -m_level0(), -m_level1(), m_modFilter(), m_modState(), m_poBuffer(), @@ -204,11 +203,6 @@ m_count(0U) m_modFilter.numTaps = DSTAR_GMSK_FILTER_LEN; m_modFilter.pState = m_modState; m_modFilter.pCoeffs = DSTAR_GMSK_FILTER; - - for (uint8_t i = 0U; i < DSTAR_RADIO_BIT_LENGTH; i++) { - m_level0[i] = -DSTAR_LEVEL; - m_level1[i] = DSTAR_LEVEL; - } } void CDStarTX::process() @@ -425,9 +419,9 @@ void CDStarTX::writeByte(uint8_t c) q15_t* p = inBuffer; for (uint8_t i = 0U; i < 8U; i++, p += DSTAR_RADIO_BIT_LENGTH) { if ((c & mask) == mask) - ::memcpy(p, m_level0, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); + ::memcpy(p, DSTAR_LEVEL0, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); else - ::memcpy(p, m_level1, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); + ::memcpy(p, DSTAR_LEVEL1, DSTAR_RADIO_BIT_LENGTH * sizeof(q15_t)); mask <<= 1; } @@ -465,25 +459,3 @@ uint16_t CDStarTX::getSpace() const return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U); } -void CDStarTX::setLevels(int8_t percent) -{ - q31_t res = DSTAR_LEVEL * 1000; - - if (percent > 0) { - for (int8_t i = 0; i < percent; i++) - res += DSTAR_LEVEL; - } else if (percent < 0) { - for (int8_t i = 0; i < -percent; i++) - res -= DSTAR_LEVEL; - } - - q15_t level = res / 1000; - - for (uint8_t i = 0U; i < DSTAR_RADIO_BIT_LENGTH; i++) { - m_level0[i] = -level; - m_level1[i] = level; - } - - DEBUG2("DStarTX: Level", level); -} - diff --git a/DStarTX.h b/DStarTX.h index eb43a5f..828974c 100644 --- a/DStarTX.h +++ b/DStarTX.h @@ -34,14 +34,11 @@ public: void process(); void setTXDelay(uint8_t delay); - void setLevels(int8_t level); uint16_t getSpace() const; private: CSerialRB m_buffer; - q15_t m_level0[DSTAR_RADIO_BIT_LENGTH]; - q15_t m_level1[DSTAR_RADIO_BIT_LENGTH]; 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]; diff --git a/SerialPort.cpp b/SerialPort.cpp index c55eed3..a881c99 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -185,7 +185,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 16U) + if (length < 9U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -232,17 +232,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_sampleInsert = false; } - int8_t dstarLevel = int8_t(data[9U]) - 128; - - int8_t dmrLevel1 = int8_t(data[10U]) - 128; - int8_t dmrLevel3 = int8_t(data[11U]) - 128; - - int8_t ysfLevel1 = int8_t(data[12U]) - 128; - int8_t ysfLevel3 = int8_t(data[13U]) - 128; - - int8_t dmrThreshold = int8_t(data[14U]) - 128; - int8_t ysfThreshold = int8_t(data[15U]) - 128; - m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -257,14 +246,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrRX.setDelay(dmrDelay); dmrIdleRX.setColorCode(colorCode); - dstarTX.setLevels(dstarLevel); - dmrTX.setLevels(dmrLevel1, dmrLevel3); - ysfTX.setLevels(ysfLevel1, ysfLevel3); - - dmrIdleRX.setThreshold(dmrThreshold); - dmrRX.setThreshold(dmrThreshold); - ysfRX.setThreshold(ysfThreshold); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, txLevel); io.start(); diff --git a/YSFRX.cpp b/YSFRX.cpp index b3ffa46..37826af 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -55,8 +55,7 @@ m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), m_centre(0), -m_threshold(0), -m_scale(SCALING_FACTOR) +m_threshold(0) { m_buffer = m_outBuffer + 1U; } @@ -124,7 +123,7 @@ void CYSFRX::processNone(q15_t sample) q15_t centre = (max + min) >> 1; - q31_t v1 = (max - centre) * m_scale; + q31_t v1 = (max - centre) * SCALING_FACTOR; q15_t threshold = q15_t(v1 >> 15); uint16_t ptr = m_symbolPtr + 1U; @@ -243,20 +242,3 @@ void CYSFRX::processData(q15_t sample) } } -void CYSFRX::setThreshold(int8_t percent) -{ - q31_t res = SCALING_FACTOR * 1000; - - if (percent > 0) { - for (int8_t i = 0; i < percent; i++) - res += SCALING_FACTOR; - } else if (percent < 0) { - for (int8_t i = 0; i < -percent; i++) - res -= SCALING_FACTOR; - } - - m_scale = res / 1000; - - DEBUG2("YSFRX: Scale", m_scale); -} - diff --git a/YSFRX.h b/YSFRX.h index 32a8c9e..22228ce 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -35,8 +35,6 @@ public: void reset(); - void setThreshold(int8_t threshold); - private: uint32_t m_pll; bool m_prev; @@ -51,7 +49,6 @@ private: uint16_t m_lostCount; q15_t m_centre; q15_t m_threshold; - q15_t m_scale; void processNone(q15_t sample); void processData(q15_t sample); diff --git a/YSFTX.cpp b/YSFTX.cpp index b0b947a..0457b65 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -30,18 +30,16 @@ static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1 -553, -847, -731, -340, 104, 401, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 42U; -const q15_t YSF_LEVEL3 = 809; -const q15_t YSF_LEVEL1 = 269; +const q15_t YSF_LEVELA[] = { 809, 809, 809, 809, 809}; +const q15_t YSF_LEVELB[] = { 269, 269, 269, 269, 269}; +const q15_t YSF_LEVELC[] = {-269, -269, -269, -269, -269}; +const q15_t YSF_LEVELD[] = {-809, -809, -809, -809, -809}; const uint8_t YSF_START_SYNC = 0x77U; const uint8_t YSF_END_SYNC = 0xFFU; CYSFTX::CYSFTX() : m_buffer(1500U), -m_levelA(), -m_levelB(), -m_levelC(), -m_levelD(), m_modFilter(), m_modState(), m_poBuffer(), @@ -55,13 +53,6 @@ m_count(0U) m_modFilter.numTaps = YSF_C4FSK_FILTER_LEN; m_modFilter.pState = m_modState; m_modFilter.pCoeffs = YSF_C4FSK_FILTER; - - for (uint8_t i = 0U; i < YSF_RADIO_SYMBOL_LENGTH; i++) { - m_levelA[i] = YSF_LEVEL3; - m_levelB[i] = YSF_LEVEL1; - m_levelC[i] = -YSF_LEVEL1; - m_levelD[i] = -YSF_LEVEL3; - } } void CYSFTX::process() @@ -129,16 +120,16 @@ void CYSFTX::writeByte(uint8_t c) for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += YSF_RADIO_SYMBOL_LENGTH) { switch (c & MASK) { case 0xC0U: - ::memcpy(p, m_levelA, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, YSF_LEVELA, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x80U: - ::memcpy(p, m_levelB, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, YSF_LEVELB, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; case 0x00U: - ::memcpy(p, m_levelC, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, YSF_LEVELC, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; default: - ::memcpy(p, m_levelD, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + ::memcpy(p, YSF_LEVELD, YSF_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); break; } } @@ -176,37 +167,3 @@ uint16_t CYSFTX::getSpace() const return m_buffer.getSpace() / YSF_FRAME_LENGTH_BYTES; } -void CYSFTX::setLevels(int8_t percent1, int8_t percent3) -{ - q31_t res1 = YSF_LEVEL1 * 1000; - q31_t res3 = YSF_LEVEL3 * 1000; - - if (percent1 > 0) { - for (int8_t i = 0; i < percent1; i++) - res1 += YSF_LEVEL1; - } else if (percent1 < 0) { - for (int8_t i = 0; i < -percent1; i++) - res1 -= YSF_LEVEL1; - } - - if (percent3 > 0) { - for (int8_t i = 0; i < percent3; i++) - res3 += YSF_LEVEL3; - } else if (percent3 < 0) { - for (int8_t i = 0; i < -percent3; i++) - res3 -= YSF_LEVEL3; - } - - q15_t level1 = res1 / 1000; - q15_t level3 = res3 / 1000; - - for (uint8_t i = 0U; i < YSF_RADIO_SYMBOL_LENGTH; i++) { - m_levelA[i] = level3; - m_levelB[i] = level1; - m_levelC[i] = -level1; - m_levelD[i] = -level3; - } - - DEBUG3("YSFTX: Levels 1/3", level1, level3); -} - diff --git a/YSFTX.h b/YSFTX.h index d5b0b2a..309cacc 100644 --- a/YSFTX.h +++ b/YSFTX.h @@ -32,16 +32,11 @@ public: void process(); void setTXDelay(uint8_t delay); - void setLevels(int8_t level1, int8_t level3); uint16_t getSpace() const; private: CSerialRB m_buffer; - q15_t m_levelA[YSF_RADIO_SYMBOL_LENGTH]; - q15_t m_levelB[YSF_RADIO_SYMBOL_LENGTH]; - q15_t m_levelC[YSF_RADIO_SYMBOL_LENGTH]; - q15_t m_levelD[YSF_RADIO_SYMBOL_LENGTH]; 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]; From 57b90920feace95b08b4eadc1986ebba41764869 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 7 Jul 2016 21:46:54 +0100 Subject: [PATCH 123/329] Add additional filters. --- DMRTX.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/DMRTX.cpp b/DMRTX.cpp index 9b937d6..e6238dd 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -23,11 +23,31 @@ #include "Globals.h" #include "DMRSlotType.h" +// Uncomment one of the following to change the filter +#define USE8 +// #define USE6 +// #define USE4 + +#if defined(USE8) // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 42U; +#elif defined(USE6) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, + 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, + 684, 1452, 1474, 911, 112, -554, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 32U; +#elif defined(USE4) +// Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, + 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 22U; +#else +#error "Must define one of USE8, USE6, or USE4." +#endif const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; const q15_t DMR_LEVELB[] = { 213, 213, 213, 213, 213}; From 2f648b3f79992cbbd18088115c69e79ab460c53c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 11 Jul 2016 18:02:53 +0100 Subject: [PATCH 124/329] Add a choice of C4FSK filters. --- DMRTX.cpp | 7 ++++++- IO.cpp | 27 ++++++++++++++++++++++++++- YSFTX.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index e6238dd..69fa3eb 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -27,6 +27,7 @@ #define USE8 // #define USE6 // #define USE4 +// #define USE2 #if defined(USE8) // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB @@ -45,8 +46,12 @@ const uint16_t DMR_C4FSK_FILTER_LEN = 32U; static q15_t DMR_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 22U; +#elif defined(USE2) +// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 12U; #else -#error "Must define one of USE8, USE6, or USE4." +#error "Must define one of USE8, USE6, USE4, or USE2." #endif const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; diff --git a/IO.cpp b/IO.cpp index 3540f10..836c04c 100644 --- a/IO.cpp +++ b/IO.cpp @@ -24,11 +24,36 @@ #include "Globals.h" #include "IO.h" +// Uncomment one of the following to change the filter +#define USE8 +// #define USE6 +// #define USE4 +// #define USE2 + +#if defined(USE8) // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, +static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t C4FSK_FILTER_LEN = 42U; +#elif defined(USE6) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB +static q15_t C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, + 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, + 684, 1452, 1474, 911, 112, -554, 0}; +const uint16_t C4FSK_FILTER_LEN = 32U; +#elif defined(USE4) +// Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB +static q15_t C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, + 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; +const uint16_t C4FSK_FILTER_LEN = 22U; +#elif defined(USE2) +// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB +static q15_t C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; +const uint16_t C4FSK_FILTER_LEN = 12U; +#else +#error "Must define one of USE8, USE6, USE4, or USE2." +#endif // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/YSFTX.cpp b/YSFTX.cpp index 0457b65..df230e6 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -24,11 +24,36 @@ #include "YSFDefines.h" +// Uncomment one of the following to change the filter +#define USE8 +// #define USE6 +// #define USE4 +// #define USE2 + +#if defined(USE8) // Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, -553, -847, -731, -340, 104, 401, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 42U; +#elif defined(USE6) +// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB +static q15_t YSF_C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, + 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, + 684, 1452, 1474, 911, 112, -554, 0}; +const uint16_t YSF_C4FSK_FILTER_LEN = 32U; +#elif defined(USE4) +// Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB +static q15_t YSF_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, + 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; +const uint16_t YSF_C4FSK_FILTER_LEN = 22U; +#elif defined(USE2) +// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB +static q15_t YSF_C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; +const uint16_t YSF_C4FSK_FILTER_LEN = 12U; +#else +#error "Must define one of USE8, USE6, USE4, or USE2." +#endif const q15_t YSF_LEVELA[] = { 809, 809, 809, 809, 809}; const q15_t YSF_LEVELB[] = { 269, 269, 269, 269, 269}; From 8278415572ef96848b962e2c3c1d876e13724b44 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 11 Jul 2016 20:33:16 +0100 Subject: [PATCH 125/329] Improve the synchronisation. --- DStarRX.cpp | 77 +++++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index e2ebc60..15edfcc 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -31,6 +31,10 @@ const uint32_t INC = PLLINC / 32U; const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS; +const unsigned int SYNC_POS = 21U * DSTAR_DATA_LENGTH_BITS; +const unsigned int SYNC_SCAN_START = SYNC_POS - 3U; +const unsigned int SYNC_SCAN_END = SYNC_POS + 3U; + const q15_t THRESHOLD = 0; // D-Star bit order version of 0x55 0x55 0x6E 0x0A @@ -337,25 +341,13 @@ void CDStarRX::processNone(bool bit) io.setDecode(true); io.setADCDetection(true); -#if defined(WANT_DEBUG) - q15_t min = 16000; - q15_t max = -16000; - for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_BITS; i++) { - if (m_samples[i] > max) - max = m_samples[i]; - if (m_samples[i] < min) - min = m_samples[i]; - } - DEBUG3("DStarRX: data sync found min/max", min, max); -#endif - serial.writeDStarData(DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES); ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES); m_rxBufferBits = 0U; - m_dataBits = MAX_SYNC_BITS; - m_rxState = DSRXS_DATA; + m_dataBits = 0U; + m_rxState = DSRXS_DATA; return; } } @@ -383,8 +375,8 @@ void CDStarRX::processHeader(bool bit) ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES); m_rxBufferBits = 0U; - m_rxState = DSRXS_DATA; - m_dataBits = MAX_SYNC_BITS; + m_rxState = DSRXS_DATA; + m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; } else { // The checksum failed, return to looking for syncs m_rxState = DSRXS_NONE; @@ -416,34 +408,38 @@ void CDStarRX::processData(bool bit) // Fuzzy matching of the data sync bit sequence bool syncSeen = false; - if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) { + if (m_dataBits >= SYNC_SCAN_START && m_dataBits <= (SYNC_POS + 1U)) { if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) { #if defined(WANT_DEBUG) - if (m_rxBufferBits < DSTAR_DATA_LENGTH_BITS) - DEBUG2("DStarRX: found data sync in Data, early", DSTAR_DATA_LENGTH_BITS - m_rxBufferBits); + if (m_dataBits < SYNC_POS) + DEBUG2("DStarRX: found data sync in Data, early", SYNC_POS - m_dataBits); else DEBUG1("DStarRX: found data sync in Data"); - - q15_t min = 16000; - q15_t max = -16000; - for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_BITS; i++) { - if (m_samples[i] > max) - max = m_samples[i]; - if (m_samples[i] < min) - min = m_samples[i]; - } - - DEBUG3("DStarRX: data sync found min/max", min, max); #endif m_rxBufferBits = DSTAR_DATA_LENGTH_BITS; - m_dataBits = MAX_SYNC_BITS; - syncSeen = true; + m_dataBits = 0U; + syncSeen = true; } } + // Check to see if the sync is arriving late + if (m_dataBits == SYNC_POS) { + for (uint8_t i = 1U; i <= 3U; i++) { + uint32_t syncMask = DATA_SYNC_MASK >> i; + uint32_t syncData = DATA_SYNC_DATA >> i; + if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) { + DEBUG2("DStarRX: found data sync in Data, late", i); + m_rxBufferBits -= i; + m_dataBits -= i; + break; + } + } + } + + m_dataBits++; + // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE - m_dataBits--; - if (m_dataBits == 0U) { + if (m_dataBits >= MAX_SYNC_BITS) { DEBUG1("DStarRX: data sync timed out, lost lock"); io.setDecode(false); @@ -455,19 +451,6 @@ void CDStarRX::processData(bool bit) return; } - // Check to see if the sync is arriving late - if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) { - for (uint8_t i = 1U; i <= 3U; i++) { - uint32_t syncMask = DATA_SYNC_MASK >> i; - uint32_t syncData = DATA_SYNC_DATA >> i; - if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) { - DEBUG2("DStarRX: found data sync in Data, late", i); - m_rxBufferBits -= i; - break; - } - } - } - // Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) { if (syncSeen) { From 87422228cd8b5f444adcf6b0e6c47fc21aac2836 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 13 Jul 2016 07:19:50 +0100 Subject: [PATCH 126/329] Add extra debugging. --- DStarTX.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DStarTX.cpp b/DStarTX.cpp index 6fee338..1456bc0 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -306,8 +306,10 @@ uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length) return 4U; uint16_t space = m_buffer.getSpace(); - if (space < (DSTAR_DATA_LENGTH_BYTES + 1U)) + if (space < (DSTAR_DATA_LENGTH_BYTES + 1U)) { + DEBUG2("D-Star, space available", space); return 5U; + } m_buffer.put(DSTAR_DATA); From f92587dbbfae72079eb280f0e194f75e4e764180 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 14 Jul 2016 19:53:59 +0100 Subject: [PATCH 127/329] Use the wider C4FSK filters fot TX and RX. --- Config.h | 2 +- DMRTX.cpp | 26 -------------------------- IO.cpp | 26 -------------------------- YSFTX.cpp | 26 -------------------------- 4 files changed, 1 insertion(+), 79 deletions(-) diff --git a/Config.h b/Config.h index 16ed653..9c3809c 100644 --- a/Config.h +++ b/Config.h @@ -37,7 +37,7 @@ // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA -// For the new Arduino Due pin layout +// For the ZUM Board V1.0 pin layout #define ARDUINO_DUE_ZUM_V10 // For the SP8NTH board diff --git a/DMRTX.cpp b/DMRTX.cpp index 69fa3eb..7430d68 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -23,36 +23,10 @@ #include "Globals.h" #include "DMRSlotType.h" -// Uncomment one of the following to change the filter -#define USE8 -// #define USE6 -// #define USE4 -// #define USE2 - -#if defined(USE8) -// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, - 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, - -553, -847, -731, -340, 104, 401, 0}; -const uint16_t DMR_C4FSK_FILTER_LEN = 42U; -#elif defined(USE6) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB -static q15_t DMR_C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, - 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, - 684, 1452, 1474, 911, 112, -554, 0}; -const uint16_t DMR_C4FSK_FILTER_LEN = 32U; -#elif defined(USE4) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t DMR_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 22U; -#elif defined(USE2) -// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB -static q15_t DMR_C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; -const uint16_t DMR_C4FSK_FILTER_LEN = 12U; -#else -#error "Must define one of USE8, USE6, USE4, or USE2." -#endif const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; const q15_t DMR_LEVELB[] = { 213, 213, 213, 213, 213}; diff --git a/IO.cpp b/IO.cpp index 836c04c..d3b61fc 100644 --- a/IO.cpp +++ b/IO.cpp @@ -24,36 +24,10 @@ #include "Globals.h" #include "IO.h" -// Uncomment one of the following to change the filter -#define USE8 -// #define USE6 -// #define USE4 -// #define USE2 - -#if defined(USE8) -// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, - 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, - -553, -847, -731, -340, 104, 401, 0}; -const uint16_t C4FSK_FILTER_LEN = 42U; -#elif defined(USE6) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, - 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, - 684, 1452, 1474, 911, 112, -554, 0}; -const uint16_t C4FSK_FILTER_LEN = 32U; -#elif defined(USE4) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t C4FSK_FILTER_LEN = 22U; -#elif defined(USE2) -// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB -static q15_t C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; -const uint16_t C4FSK_FILTER_LEN = 12U; -#else -#error "Must define one of USE8, USE6, USE4, or USE2." -#endif // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/YSFTX.cpp b/YSFTX.cpp index df230e6..cb56672 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -24,36 +24,10 @@ #include "YSFDefines.h" -// Uncomment one of the following to change the filter -#define USE8 -// #define USE6 -// #define USE4 -// #define USE2 - -#if defined(USE8) -// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB -static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, - 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, - -553, -847, -731, -340, 104, 401, 0}; -const uint16_t YSF_C4FSK_FILTER_LEN = 42U; -#elif defined(USE6) -// Generated using rcosdesign(0.2, 6, 5, 'sqrt') in MATLAB -static q15_t YSF_C4FSK_FILTER[] = {-554, 112, 911, 1474, 1452, 684, -676, -2147, -3045, -2710, -772, 2671, 7005, - 11253, 14352, 15486, 14352, 11253, 7005, 2671, -772, -2710, -3045, -2147, -676, - 684, 1452, 1474, 911, 112, -554, 0}; -const uint16_t YSF_C4FSK_FILTER_LEN = 32U; -#elif defined(USE4) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t YSF_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 22U; -#elif defined(USE2) -// Generated using rcosdesign(0.2, 2, 5, 'sqrt') in MATLAB -static q15_t YSF_C4FSK_FILTER[] = {-792, 2742, 7192, 11553, 14735, 15900, 14735, 11553, 7192, 2742, -792, 0}; -const uint16_t YSF_C4FSK_FILTER_LEN = 12U; -#else -#error "Must define one of USE8, USE6, USE4, or USE2." -#endif const q15_t YSF_LEVELA[] = { 809, 809, 809, 809, 809}; const q15_t YSF_LEVELB[] = { 269, 269, 269, 269, 269}; From f7cae15aba788d224ead9b6a724076d5b2ec5341 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 18 Jul 2016 17:39:31 +0100 Subject: [PATCH 128/329] Make wider TX and RX C4FSK filters optional from Config.h --- Config.h | 5 +++++ DMRTX.cpp | 8 ++++++++ DStarTX.cpp | 10 +++++++--- IO.cpp | 8 ++++++++ YSFTX.cpp | 8 ++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Config.h b/Config.h index 9c3809c..f594cf0 100644 --- a/Config.h +++ b/Config.h @@ -43,5 +43,10 @@ // For the SP8NTH board // #define ARDUINO_DUE_NTH +// To use wider C4FSK filters for DMR and System Fusion on transmit +// #define WIDE_C4FSK_FILTERS_TX +// To use wider C4FSK filters for DMR and System Fusion on receive +// #define WIDE_C4FSK_FILTERS_RX + #endif diff --git a/DMRTX.cpp b/DMRTX.cpp index 7430d68..9151341 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -23,10 +23,18 @@ #include "Globals.h" #include "DMRSlotType.h" +#if defined(WIDE_C4FSK_FILTERS_TX) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t DMR_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t DMR_C4FSK_FILTER_LEN = 22U; +#else +// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 42U; +#endif const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; const q15_t DMR_LEVELB[] = { 213, 213, 213, 213, 213}; diff --git a/DStarTX.cpp b/DStarTX.cpp index 1456bc0..7411b81 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -289,8 +289,10 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length) return 4U; uint16_t space = m_buffer.getSpace(); - if (space < (DSTAR_HEADER_LENGTH_BYTES + 1U)) + if (space < (DSTAR_HEADER_LENGTH_BYTES + 1U)) { + DEBUG2("D-Star, header space available", space); return 5U; + } m_buffer.put(DSTAR_HEADER); @@ -307,7 +309,7 @@ uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length) uint16_t space = m_buffer.getSpace(); if (space < (DSTAR_DATA_LENGTH_BYTES + 1U)) { - DEBUG2("D-Star, space available", space); + DEBUG2("D-Star, data space available", space); return 5U; } @@ -322,8 +324,10 @@ uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length) uint8_t CDStarTX::writeEOT() { uint16_t space = m_buffer.getSpace(); - if (space < 1U) + if (space < 1U) { + DEBUG2("D-Star, EOT space available", space); return 5U; + } m_buffer.put(DSTAR_EOT); diff --git a/IO.cpp b/IO.cpp index d3b61fc..ce98e1b 100644 --- a/IO.cpp +++ b/IO.cpp @@ -24,10 +24,18 @@ #include "Globals.h" #include "IO.h" +#if defined(WIDE_C4FSK_FILTERS_RX) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t C4FSK_FILTER_LEN = 22U; +#else +// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB +static q15_t C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t C4FSK_FILTER_LEN = 42U; +#endif // Generated using gaussfir(0.5, 4, 5) in MATLAB static q15_t GMSK_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0}; diff --git a/YSFTX.cpp b/YSFTX.cpp index cb56672..fa616a4 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -24,10 +24,18 @@ #include "YSFDefines.h" +#if defined(WIDE_C4FSK_FILTERS_TX) // Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB static q15_t YSF_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; const uint16_t YSF_C4FSK_FILTER_LEN = 22U; +#else +// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB +static q15_t YSF_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t YSF_C4FSK_FILTER_LEN = 42U; +#endif const q15_t YSF_LEVELA[] = { 809, 809, 809, 809, 809}; const q15_t YSF_LEVELB[] = { 269, 269, 269, 269, 269}; From 66ca69b02e75d8e44a7cfb959aecf9697b1b36bc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 19 Jul 2016 17:34:55 +0100 Subject: [PATCH 129/329] Remove small gap when data comes in while sending terminators. --- DMRTX.cpp | 24 +++++++++++++++++++++--- DMRTX.h | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/DMRTX.cpp b/DMRTX.cpp index 9151341..4976a5d 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -74,7 +74,8 @@ m_markBuffer(), m_poBuffer(), m_poLen(0U), m_poPtr(0U), -m_count(0U) +m_count(0U), +m_abort() { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); @@ -84,6 +85,9 @@ m_count(0U) ::memcpy(m_newShortLC, EMPTY_SHORT_LC, 12U); ::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U); + + m_abort[0U] = false; + m_abort[1U] = false; } void CDMRTX::process() @@ -149,6 +153,11 @@ uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; + if (m_abort[0U]) { + m_fifo[0U].reset(); + m_abort[0U] = false; + } + for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) m_fifo[0U].put(data[i + 1U]); @@ -168,6 +177,11 @@ uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; + if (m_abort[1U]) { + m_fifo[1U].reset(); + m_abort[1U] = false; + } + for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) m_fifo[1U].put(data[i + 1U]); @@ -201,11 +215,11 @@ uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length) switch (data[0U]) { case 1U: - m_fifo[0U].reset(); + m_abort[0U] = true; return 0U; case 2U: - m_fifo[1U].reset(); + m_abort[1U] = true; return 0U; default: @@ -218,6 +232,9 @@ void CDMRTX::setStart(bool start) m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE; m_count = 0U; + + m_abort[0U] = false; + m_abort[1U] = false; } void CDMRTX::setCal(bool start) @@ -302,6 +319,7 @@ void CDMRTX::createData(uint8_t slotIndex) m_markBuffer[i] = MARK_NONE; } } else { + m_abort[slotIndex] = false; // Transmit an idle message for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) { m_poBuffer[i] = m_idle[i]; diff --git a/DMRTX.h b/DMRTX.h index ea404d0..599b8fe 100644 --- a/DMRTX.h +++ b/DMRTX.h @@ -68,6 +68,7 @@ private: uint16_t m_poLen; uint16_t m_poPtr; uint32_t m_count; + bool m_abort[2U]; void createData(uint8_t slotIndex); void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex); From e4391eb4ab69417ccb229a33cb1565cbd9332513 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 20 Jul 2016 07:28:36 +0100 Subject: [PATCH 130/329] Update the logging messages. --- DStarTX.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DStarTX.cpp b/DStarTX.cpp index 7411b81..6081b69 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -290,7 +290,7 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length) uint16_t space = m_buffer.getSpace(); if (space < (DSTAR_HEADER_LENGTH_BYTES + 1U)) { - DEBUG2("D-Star, header space available", space); + DEBUG2("DStarTX: header space available", space); return 5U; } @@ -309,7 +309,7 @@ uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length) uint16_t space = m_buffer.getSpace(); if (space < (DSTAR_DATA_LENGTH_BYTES + 1U)) { - DEBUG2("D-Star, data space available", space); + DEBUG2("DStarTX: data space available", space); return 5U; } @@ -325,7 +325,7 @@ uint8_t CDStarTX::writeEOT() { uint16_t space = m_buffer.getSpace(); if (space < 1U) { - DEBUG2("D-Star, EOT space available", space); + DEBUG2("DStarTX: EOT space available", space); return 5U; } From b96413c5af66b6c9929936ba49416d747062154a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 21 Jul 2016 17:08:00 +0100 Subject: [PATCH 131/329] Restore DMR level reporting. --- DMRIdleRX.cpp | 2 +- DMRSlotRX.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index 2121a47..8205150 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 3218381..05af4b5 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +#define WANT_DEBUG #include "Config.h" #include "Globals.h" From eafc329cc9c40dd2ddaa47ef1766699135f02979 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 8 Aug 2016 20:38:58 +0100 Subject: [PATCH 132/329] Add an optional RSSI input. --- Config.h | 3 +++ DMRSlotRX.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--- DMRSlotRX.h | 2 ++ DStarRX.cpp | 36 ++++++++++++++++++++++++++++-------- DStarRX.h | 1 + IO.cpp | 13 +++++++++++++ IO.h | 4 ++++ YSFRX.cpp | 21 ++++++++++++++++++++- YSFRX.h | 3 ++- 9 files changed, 115 insertions(+), 13 deletions(-) diff --git a/Config.h b/Config.h index f594cf0..27f7290 100644 --- a/Config.h +++ b/Config.h @@ -48,5 +48,8 @@ // To use wider C4FSK filters for DMR and System Fusion on receive // #define WIDE_C4FSK_FILTERS_RX +// Pass RSSI information to the host +// #define SEND_RSSI_DATA + #endif diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 05af4b5..5ad4070 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -64,7 +64,9 @@ m_colorCode(0U), m_delay(0U), m_state(DMRRXS_NONE), m_n(0U), -m_type(0U) +m_type(0U), +m_rssiCount(0U), +m_rssi(0U) { } @@ -89,6 +91,7 @@ void CDMRSlotRX::reset() m_state = DMRRXS_NONE; m_startPtr = 0U; m_endPtr = NOENDPTR; + m_rssiCount = 0U; } bool CDMRSlotRX::processSample(q15_t sample) @@ -120,6 +123,11 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END) correlateSync(true); } else { +#if defined(SEND_RSSI_DATA) + // Grab the RSSI data near the centre of the frame + if (m_state == DMRRXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 0U) + m_rssi = io.getRSSIValue(); +#endif uint16_t min = m_syncPtr - 1U; uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) @@ -131,7 +139,7 @@ bool CDMRSlotRX::processSample(q15_t sample) q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; - uint8_t frame[DMR_FRAME_LENGTH_BYTES + 1U]; + uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U]; frame[0U] = m_control; uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; @@ -197,7 +205,22 @@ bool CDMRSlotRX::processSample(q15_t sample) } 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 0.5 seconds + if (m_rssiCount == 0U) { + frame[34U] = (m_rssi >> 8) & 0xFFU; + frame[35U] = (m_rssi >> 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 >= 8U) + m_rssiCount = 0U; +#else serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); +#endif m_state = DMRRXS_VOICE; m_syncCount = 0U; m_n = 0U; @@ -214,12 +237,26 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_state == DMRRXS_VOICE) { if (m_n >= 5U) { frame[0U] = CONTROL_VOICE; - serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); m_n = 0U; } else { frame[0U] = ++m_n; + } +#if defined(SEND_RSSI_DATA) + // Send RSSI data approximately every 0.5 seconds + if (m_rssiCount == 0U) { + frame[34U] = (m_rssi >> 8) & 0xFFU; + frame[35U] = (m_rssi >> 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 >= 8U) + 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; @@ -290,6 +327,7 @@ 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; @@ -315,6 +353,7 @@ 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; diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 994839f..12482d0 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -62,6 +62,8 @@ private: DMRRX_STATE m_state; uint8_t m_n; uint8_t m_type; + uint16_t m_rssiCount; + uint16_t m_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); diff --git a/DStarRX.cpp b/DStarRX.cpp index 15edfcc..9a2eb61 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -260,7 +260,8 @@ m_pathMemory2(), m_pathMemory3(), m_fecOutput(), m_samples(), -m_samplesPtr(0U) +m_samplesPtr(0U), +m_rssiCount(0U) { } @@ -273,6 +274,7 @@ void CDStarRX::reset() m_rxBufferBits = 0U; m_dataBits = 0U; m_samplesPtr = 0U; + m_rssiCount = 0U; } void CDStarRX::samples(const q15_t* samples, uint8_t length) @@ -343,11 +345,12 @@ void CDStarRX::processNone(bool bit) serial.writeDStarData(DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES); - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES); + ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); m_rxBufferBits = 0U; - m_dataBits = 0U; - m_rxState = DSRXS_DATA; + m_dataBits = 0U; + m_rssiCount = 0U; + m_rxState = DSRXS_DATA; return; } } @@ -372,11 +375,12 @@ void CDStarRX::processHeader(bool bit) serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES); + ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); m_rxBufferBits = 0U; - m_rxState = DSRXS_DATA; - m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; + m_rxState = DSRXS_DATA; + m_rssiCount = 0U; + m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; } else { // The checksum failed, return to looking for syncs m_rxState = DSRXS_NONE; @@ -459,10 +463,26 @@ void CDStarRX::processData(bool bit) m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; } +#if defined(SEND_RSSI_DATA) + // Send RSSI data every 0.5 seconds + if (m_rssiCount == 0U) { + uint16_t rssi = io.getRSSIValue(); + m_rxBuffer[12U] = (rssi >> 8) & 0xFFU; + m_rxBuffer[13U] = (rssi >> 0) & 0xFFU; + serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES + 2U); + } else { + serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); + } + + m_rssiCount++; + if (m_rssiCount >= 25U) + m_rssiCount = 0U; +#else serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); +#endif // Start the next frame - ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES); + ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); m_rxBufferBits = 0U; } } diff --git a/DStarRX.h b/DStarRX.h index dd63ed3..a9252a8 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -53,6 +53,7 @@ private: uint8_t m_fecOutput[42U]; q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS]; uint8_t m_samplesPtr; + uint16_t m_rssiCount; void processNone(bool bit); void processHeader(bool bit); diff --git a/IO.cpp b/IO.cpp index ce98e1b..1b79b47 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,6 +61,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 +#define PIN_RSSI 88 // ADC on Due pin A8 - Due AD10 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -158,6 +159,11 @@ m_lockout(false) pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); #endif + +#if defined(SEND_RSSI_DATA) + pinMode(PIN_RSSI, INPUT); + analogReadResolution(12); +#endif #endif } @@ -544,3 +550,10 @@ bool CIO::hasLockout() const return m_lockout; } +#if defined(SEND_RSSI_DATA) +uint16_t CIO::getRSSIValue() +{ + return analogRead(PIN_RSSI); +} +#endif + diff --git a/IO.h b/IO.h index bf047e2..5fa529d 100644 --- a/IO.h +++ b/IO.h @@ -52,6 +52,10 @@ public: void resetWatchdog(); +#if defined(SEND_RSSI_DATA) + uint16_t getRSSIValue(); +#endif + private: #if defined(__MBED__) DigitalOut m_pinPTT; diff --git a/YSFRX.cpp b/YSFRX.cpp index 37826af..579334a 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -54,6 +54,7 @@ m_buffer(NULL), m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), +m_rssiCount(0U), m_centre(0), m_threshold(0) { @@ -69,6 +70,7 @@ void CYSFRX::reset() m_bufferPtr = 0U; m_symbolPtr = 0U; m_lostCount = 0U; + m_rssiCount = 0U; m_centre = 0; m_threshold = 0; } @@ -162,6 +164,7 @@ void CYSFRX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; m_state = YSFRXS_DATA; + m_rssiCount = 0U; io.setDecode(true); io.setADCDetection(true); @@ -233,10 +236,26 @@ void CYSFRX::processData(q15_t sample) } else { m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; +#if defined(SEND_RSSI_DATA) + // Send RSSI data every 0.5 seconds + if (m_rssiCount == 0U) { + uint16_t rssi = io.getRSSIValue(); + m_outBuffer[121U] = (rssi >> 8) & 0xFFU; + m_outBuffer[122U] = (rssi >> 0) & 0xFFU; + serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 3U); + } else { + serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); + } + + m_rssiCount++; + if (m_rssiCount >= 5U) + m_rssiCount = 0U; +#else serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); +#endif // Start the next frame - ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 1U); + ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); m_bufferPtr = 0U; } } diff --git a/YSFRX.h b/YSFRX.h index 22228ce..41a8b71 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -42,11 +42,12 @@ private: uint32_t m_symbolBuffer; uint64_t m_bitBuffer; q15_t m_symbols[YSF_SYNC_LENGTH_SYMBOLS]; - uint8_t m_outBuffer[YSF_FRAME_LENGTH_BYTES + 1U]; + uint8_t m_outBuffer[YSF_FRAME_LENGTH_BYTES + 3U]; uint8_t* m_buffer; uint16_t m_bufferPtr; uint16_t m_symbolPtr; uint16_t m_lostCount; + uint16_t m_rssiCount; q15_t m_centre; q15_t m_threshold; From 8c96a48b2bb1de456b17255e842da23a83e644d1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 8 Aug 2016 21:43:00 +0100 Subject: [PATCH 133/329] Change the sampling poistion and rate for the RSSI. --- DMRSlotRX.cpp | 14 +++++++------- DStarRX.cpp | 4 ++-- YSFRX.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 5ad4070..424b78f 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -125,7 +125,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } else { #if defined(SEND_RSSI_DATA) // Grab the RSSI data near the centre of the frame - if (m_state == DMRRXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 0U) + if (m_state == DMRRXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) m_rssi = io.getRSSIValue(); #endif uint16_t min = m_syncPtr - 1U; @@ -206,8 +206,8 @@ bool CDMRSlotRX::processSample(q15_t sample) // 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 0.5 seconds - if (m_rssiCount == 0U) { + // Send RSSI data approximately every second + if (m_rssiCount == 2U) { frame[34U] = (m_rssi >> 8) & 0xFFU; frame[35U] = (m_rssi >> 0) & 0xFFU; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U); @@ -216,7 +216,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } m_rssiCount++; - if (m_rssiCount >= 8U) + if (m_rssiCount >= 16U) m_rssiCount = 0U; #else serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); @@ -242,8 +242,8 @@ bool CDMRSlotRX::processSample(q15_t sample) frame[0U] = ++m_n; } #if defined(SEND_RSSI_DATA) - // Send RSSI data approximately every 0.5 seconds - if (m_rssiCount == 0U) { + // Send RSSI data approximately every second + if (m_rssiCount == 2U) { frame[34U] = (m_rssi >> 8) & 0xFFU; frame[35U] = (m_rssi >> 0) & 0xFFU; serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U); @@ -252,7 +252,7 @@ bool CDMRSlotRX::processSample(q15_t sample) } m_rssiCount++; - if (m_rssiCount >= 8U) + if (m_rssiCount >= 16U) m_rssiCount = 0U; #else serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U); diff --git a/DStarRX.cpp b/DStarRX.cpp index 9a2eb61..12fac7a 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -464,7 +464,7 @@ void CDStarRX::processData(bool bit) } #if defined(SEND_RSSI_DATA) - // Send RSSI data every 0.5 seconds + // Send RSSI data every second if (m_rssiCount == 0U) { uint16_t rssi = io.getRSSIValue(); m_rxBuffer[12U] = (rssi >> 8) & 0xFFU; @@ -475,7 +475,7 @@ void CDStarRX::processData(bool bit) } m_rssiCount++; - if (m_rssiCount >= 25U) + if (m_rssiCount >= 50U) m_rssiCount = 0U; #else serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); diff --git a/YSFRX.cpp b/YSFRX.cpp index 579334a..f820078 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -237,7 +237,7 @@ void CYSFRX::processData(q15_t sample) m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; #if defined(SEND_RSSI_DATA) - // Send RSSI data every 0.5 seconds + // Send RSSI data every second if (m_rssiCount == 0U) { uint16_t rssi = io.getRSSIValue(); m_outBuffer[121U] = (rssi >> 8) & 0xFFU; @@ -248,7 +248,7 @@ void CYSFRX::processData(q15_t sample) } m_rssiCount++; - if (m_rssiCount >= 5U) + if (m_rssiCount >= 10U) m_rssiCount = 0U; #else serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); From 62743345a4dffd987e89fd7349cd6577dcafe7cd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 9 Aug 2016 07:11:10 +0100 Subject: [PATCH 134/329] Add independent transmit levels. --- CWIdTX.cpp | 4 ++-- DMRTX.cpp | 2 +- DStarTX.cpp | 2 +- IO.cpp | 36 ++++++++++++++++++++++++++++-------- IO.h | 8 +++++--- SerialPort.cpp | 9 ++++++--- YSFTX.cpp | 2 +- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index 185d72e..8f69311 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -104,9 +104,9 @@ void CCWIdTX::process() while (space > CYCLE_LENGTH) { bool b = READ_BIT1(m_poBuffer, m_poPtr); if (b) - io.write(TONE, CYCLE_LENGTH); + io.write(STATE_DSTAR, TONE, CYCLE_LENGTH); else - io.write(SILENCE, CYCLE_LENGTH); + io.write(STATE_DSTAR, SILENCE, CYCLE_LENGTH); space -= CYCLE_LENGTH; diff --git a/DMRTX.cpp b/DMRTX.cpp index 4976a5d..684f659 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -298,7 +298,7 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); - io.write(outBuffer, blockSize, controlBuffer); + io.write(STATE_DMR, outBuffer, blockSize, controlBuffer); } uint16_t CDMRTX::getSpace1() const diff --git a/DStarTX.cpp b/DStarTX.cpp index 6081b69..03caa31 100644 --- a/DStarTX.cpp +++ b/DStarTX.cpp @@ -452,7 +452,7 @@ void CDStarTX::writeByte(uint8_t c) ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); - io.write(outBuffer, blockSize); + io.write(STATE_DSTAR, outBuffer, blockSize); } void CDStarTX::setTXDelay(uint8_t delay) diff --git a/IO.cpp b/IO.cpp index 1b79b47..982ca92 100644 --- a/IO.cpp +++ b/IO.cpp @@ -124,7 +124,9 @@ m_C4FSKState(), m_GMSKState(), m_pttInvert(false), m_rxLevel(128 * 128), -m_txLevel(128 * 128), +m_dstarTXLevel(128 * 128), +m_dmrTXLevel(128 * 128), +m_ysfTXLevel(128 * 128), m_ledCount(0U), m_ledValue(true), m_dcd(false), @@ -396,7 +398,7 @@ void CIO::process() } } -void CIO::write(q15_t* samples, uint16_t length, const uint8_t* control) +void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t* control) { if (!m_started) return; @@ -414,8 +416,21 @@ void CIO::write(q15_t* samples, uint16_t length, const uint8_t* control) #endif } + q15_t txLevel = 0; + switch (mode) { + case STATE_DMR: + txLevel = m_dmrTXLevel; + break; + case STATE_YSF: + txLevel = m_ysfTXLevel; + break; + default: + txLevel = m_dstarTXLevel; + break; + } + for (uint16_t i = 0U; i < length; i++) { - q31_t res1 = samples[i] * m_txLevel; + q31_t res1 = samples[i] * txLevel; q15_t res2 = q15_t(__SSAT((res1 >> 15), 16)); uint16_t res3 = uint16_t(res2 + DC_OFFSET); @@ -502,18 +517,23 @@ switch (m_modemState) { #endif } -void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t txLevel) +void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel) { m_pttInvert = pttInvert; - m_rxLevel = q15_t(rxLevel * 128); - m_txLevel = q15_t(txLevel * 128); + m_rxLevel = q15_t(rxLevel * 128); + m_dstarTXLevel = q15_t(dstarTXLevel * 128); + m_dmrTXLevel = q15_t(dmrTXLevel * 128); + m_ysfTXLevel = q15_t(ysfTXLevel * 128); if (rxInvert) m_rxLevel = -m_rxLevel; - if (txInvert) - m_txLevel = -m_txLevel; + if (txInvert) { + m_dstarTXLevel = -m_dstarTXLevel; + m_dmrTXLevel = -m_dmrTXLevel; + m_ysfTXLevel = -m_ysfTXLevel; + } } void CIO::getOverflow(bool& adcOverflow, bool& dacOverflow) diff --git a/IO.h b/IO.h index 5fa529d..b7befcb 100644 --- a/IO.h +++ b/IO.h @@ -31,7 +31,7 @@ public: void process(); - void write(q15_t* samples, uint16_t length, const uint8_t* control = NULL); + void write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t* control = NULL); uint16_t getSpace() const; @@ -41,7 +41,7 @@ public: void interrupt(); - void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t txLevel); + void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -81,7 +81,9 @@ private: bool m_pttInvert; q15_t m_rxLevel; - q15_t m_txLevel; + q15_t m_dstarTXLevel; + q15_t m_dmrTXLevel; + q15_t m_ysfTXLevel; uint32_t m_ledCount; bool m_ledValue; diff --git a/SerialPort.cpp b/SerialPort.cpp index a881c99..575512a 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -185,7 +185,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 9U) + if (length < 12U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -212,7 +212,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) return 4U; uint8_t rxLevel = data[4U]; - uint8_t txLevel = data[5U]; uint8_t colorCode = data[6U]; if (colorCode > 15U) @@ -232,6 +231,10 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_sampleInsert = false; } + uint8_t dstarTXLevel = data[9U]; + uint8_t dmrTXLevel = data[10U]; + uint8_t ysfTXLevel = data[11U]; + m_modemState = modemState; m_dstarEnable = dstarEnable; @@ -246,7 +249,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrRX.setDelay(dmrDelay); dmrIdleRX.setColorCode(colorCode); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, txLevel); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel); io.start(); diff --git a/YSFTX.cpp b/YSFTX.cpp index fa616a4..d3e20a3 100644 --- a/YSFTX.cpp +++ b/YSFTX.cpp @@ -161,7 +161,7 @@ void CYSFTX::writeByte(uint8_t c) ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); - io.write(outBuffer, blockSize); + io.write(STATE_YSF, outBuffer, blockSize); } void CYSFTX::setTXDelay(uint8_t delay) From e13b7ad6da867fd83c99c67734cb3b0c9eaae0d6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 9 Aug 2016 10:00:38 +0100 Subject: [PATCH 135/329] Change the RSSI input pin to A7. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index 1b79b47..53cb68b 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,7 +61,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 88 // ADC on Due pin A8 - Due AD10 +#define PIN_RSSI 85 // ADC on Due pin A7 - Due AD0 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 From 6b771a44c633eb80733d2626e5e047e76cfe2a41 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 9 Aug 2016 11:26:38 +0100 Subject: [PATCH 136/329] Change the RSSI input pin to A6. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index 53cb68b..145b7bb 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,7 +61,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 85 // ADC on Due pin A7 - Due AD0 +#define PIN_RSSI 84 // ADC on Due pin A6 - Due AD1 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 From f1ed511bcb076eff034e7ce828cf7b300ab3422c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 9 Aug 2016 17:32:18 +0100 Subject: [PATCH 137/329] Remove the network restrictions from the licence. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 26bd3b7..cb145fc 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,3 @@ Currently it only runs on the Arduino Due, but other platforms are planned. In order to build this software you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden. - -It is only to be used on the main DMR+, the main BrandMeister, and the Phoenix (UK) networks. If you wish to use it on any other network, you must get written permission from myself, G4KLX. Each such request will be dealt with on a case-by-case basis. From a34b69a4dc6c2009a43c3c5d2930ab0b9e7743cc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 11 Aug 2016 09:41:38 +0100 Subject: [PATCH 138/329] Remove RSSI code. --- IO.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/IO.cpp b/IO.cpp index 36aa2aa..0851918 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,7 +61,6 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 84 // ADC on Due pin A6 - Due AD1 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -161,11 +160,6 @@ m_lockout(false) pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); #endif - -#if defined(SEND_RSSI_DATA) - pinMode(PIN_RSSI, INPUT); - analogReadResolution(12); -#endif #endif } @@ -206,11 +200,11 @@ void CIO::start() #else t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) #endif - TC_CMR_WAVE | // Waveform mode - TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold - TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) - TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | - TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; + TC_CMR_WAVE | // Waveform mode + TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold + TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) + TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | + TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; #if defined(EXTERNAL_OSC) t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave @@ -219,13 +213,13 @@ void CIO::start() t->TC_RA = 880; // Roughly square wave #endif t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares - t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source. + t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source. // Set up the DAC pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC DACC->DACC_MR = - DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 + DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 DACC_MR_USER_SEL_Chan | // Select channel (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts @@ -573,7 +567,7 @@ bool CIO::hasLockout() const #if defined(SEND_RSSI_DATA) uint16_t CIO::getRSSIValue() { - return analogRead(PIN_RSSI); + return 0U; } #endif From 0bfecf72a9e0b8c9022cac7eaa3c85e60cb88d5d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 11 Aug 2016 10:59:49 +0100 Subject: [PATCH 139/329] Re-add the RSSI code with a different RSSI pin number. --- IO.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/IO.cpp b/IO.cpp index 0851918..f64178c 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,6 +61,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 +#define PIN_RSSI 60 // ADC on Due pin A6 - Due AD1 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -160,6 +161,11 @@ m_lockout(false) pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); #endif + +#if defined(SEND_RSSI_DATA) + pinMode(PIN_RSSI, INPUT); + analogReadResolution(12); +#endif #endif } @@ -213,7 +219,7 @@ void CIO::start() t->TC_RA = 880; // Roughly square wave #endif t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares - t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; // re-enable local clocking and switch to hardware trigger source. + t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. // Set up the DAC pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC @@ -567,7 +573,6 @@ bool CIO::hasLockout() const #if defined(SEND_RSSI_DATA) uint16_t CIO::getRSSIValue() { - return 0U; + return analogRead(PIN_RSSI); } #endif - From 7c34cdb6f8e0c9ace12e28847b7427a3f74591e4 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 11 Aug 2016 20:19:31 +0100 Subject: [PATCH 140/329] Move the RSSI sampling point. --- DMRSlotRX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 424b78f..4772d8f 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -124,8 +124,8 @@ bool CDMRSlotRX::processSample(q15_t sample) correlateSync(true); } else { #if defined(SEND_RSSI_DATA) - // Grab the RSSI data near the centre of the frame - if (m_state == DMRRXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) + // Grab the RSSI data during the frame + if (m_state == DMRRXS_VOICE && m_dataPtr == m_startPtr && m_rssiCount == 2U) m_rssi = io.getRSSIValue(); #endif uint16_t min = m_syncPtr - 1U; From f5b2d185fdffe7e020cc48c5c34737f0986fc336 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 16 Aug 2016 17:03:27 +0100 Subject: [PATCH 141/329] Bump the version date. --- SerialPort.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 575512a..c3777b7 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -61,7 +61,7 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160624 24kHz (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz (D-Star/DMR/System Fusion/CW Id)"; const uint8_t PROTOCOL_VERSION = 1U; From f9fd1de2ed3ef3d7b760557e97813e7247d95d23 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 07:30:25 +0100 Subject: [PATCH 142/329] Add duplex flag. --- Globals.h | 2 ++ MMDVM.cpp | 2 ++ SerialPort.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Globals.h b/Globals.h index b4d2dbb..6ea1d22 100644 --- a/Globals.h +++ b/Globals.h @@ -73,6 +73,8 @@ extern bool m_dstarEnable; extern bool m_dmrEnable; extern bool m_ysfEnable; +extern bool m_duplex; + extern bool m_tx; extern uint32_t m_sampleCount; diff --git a/MMDVM.cpp b/MMDVM.cpp index 432678b..669506c 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -30,6 +30,8 @@ bool m_dstarEnable = true; bool m_dmrEnable = true; bool m_ysfEnable = true; +bool m_duplex = true; + bool m_tx = false; uint32_t m_sampleCount = 0U; diff --git a/SerialPort.cpp b/SerialPort.cpp index c3777b7..3ed94d2 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -191,6 +191,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) bool rxInvert = (data[0U] & 0x01U) == 0x01U; bool txInvert = (data[0U] & 0x02U) == 0x02U; bool pttInvert = (data[0U] & 0x04U) == 0x04U; + bool duplex = (data[0U] & 0x80U) == 0x80U; bool dstarEnable = (data[1U] & 0x01U) == 0x01U; bool dmrEnable = (data[1U] & 0x02U) == 0x02U; @@ -240,6 +241,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_dstarEnable = dstarEnable; m_dmrEnable = dmrEnable; m_ysfEnable = ysfEnable; + m_duplex = duplex; dstarTX.setTXDelay(txDelay); ysfTX.setTXDelay(txDelay); From a866d04078ff626f31ee1051804571f0bff01455 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 07:32:49 +0100 Subject: [PATCH 143/329] Don't forget the ino file! --- MMDVM.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MMDVM.ino b/MMDVM.ino index ef84aa0..8fa1608 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -27,6 +27,8 @@ bool m_dstarEnable = true; bool m_dmrEnable = true; bool m_ysfEnable = true; +bool m_duplex = true; + bool m_tx = false; uint32_t m_sampleCount = 0U; From 69f02f6649d397cc37c894a8cb8d407aceea5031 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 08:16:49 +0100 Subject: [PATCH 144/329] Put the scaffolding in for DMR DMO mode. --- Globals.h | 5 +++++ IO.cpp | 22 +++++++++++++++------- MMDVM.cpp | 11 +++++++++-- MMDVM.ino | 11 +++++++++-- SerialPort.cpp | 24 ++++++++++++++++++------ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/Globals.h b/Globals.h index 6ea1d22..161641a 100644 --- a/Globals.h +++ b/Globals.h @@ -45,6 +45,8 @@ enum MMDVM_STATE { #include "SerialPort.h" #include "DMRIdleRX.h" +#include "DMRDMORX.h" +#include "DMRDMOTX.h" #include "DStarRX.h" #include "DStarTX.h" #include "DMRRX.h" @@ -90,6 +92,9 @@ extern CDMRIdleRX dmrIdleRX; extern CDMRRX dmrRX; extern CDMRTX dmrTX; +extern CDMRDMORX dmrDMORX; +extern CDMRDMOTX dmrDMOTX; + extern CYSFRX ysfRX; extern CYSFTX ysfTX; diff --git a/IO.cpp b/IO.cpp index f64178c..46a4dd0 100644 --- a/IO.cpp +++ b/IO.cpp @@ -358,8 +358,12 @@ void CIO::process() q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); - if (m_dmrEnable) - dmrIdleRX.samples(C4FSKVals, blockSize); + if (m_dmrEnable) { + if (m_duplex) + dmrIdleRX.samples(C4FSKVals, blockSize); + else + dmrDMORX.samples(C4FSKVals, blockSize); + } if (m_ysfEnable) ysfRX.samples(C4FSKVals, blockSize); @@ -376,11 +380,15 @@ void CIO::process() q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); - // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs - if (m_tx) - dmrRX.samples(C4FSKVals, control, blockSize); - else - dmrIdleRX.samples(C4FSKVals, blockSize); + if (m_duplex) { + // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs + if (m_tx) + dmrRX.samples(C4FSKVals, control, blockSize); + else + dmrIdleRX.samples(C4FSKVals, blockSize); + } else { + dmrDMORX.samples(c4FSKVals, blockSize); + } } } else if (m_modemState == STATE_YSF) { if (m_ysfEnable) { diff --git a/MMDVM.cpp b/MMDVM.cpp index 669506c..49ab79a 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -44,6 +44,9 @@ CDMRIdleRX dmrIdleRX; CDMRRX dmrRX; CDMRTX dmrTX; +CDMRDMORX dmrDMORX; +CDMRDMOTX dmrDMOTX; + CYSFRX ysfRX; CYSFTX ysfTX; @@ -71,8 +74,12 @@ void loop() if (m_dstarEnable && m_modemState == STATE_DSTAR) dstarTX.process(); - if (m_dmrEnable && m_modemState == STATE_DMR) - dmrTX.process(); + if (m_dmrEnable && m_modemState == STATE_DMR) { + if (m_duplex) + dmrTX.process(); + else + dmrDMOTX.process(); + } if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); diff --git a/MMDVM.ino b/MMDVM.ino index 8fa1608..2bfac98 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -41,6 +41,9 @@ CDMRIdleRX dmrIdleRX; CDMRRX dmrRX; CDMRTX dmrTX; +CDMRDMORX dmrDMORX; +CDMRDMOTX dmrDMOTX; + CYSFRX ysfRX; CYSFTX ysfTX; @@ -68,8 +71,12 @@ void loop() if (m_dstarEnable && m_modemState == STATE_DSTAR) dstarTX.process(); - if (m_dmrEnable && m_modemState == STATE_DMR) - dmrTX.process(); + if (m_dmrEnable && m_modemState == STATE_DMR) { + if (m_duplex) + dmrTX.process(); + else + dmrDMOTX.process(); + } if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); diff --git a/SerialPort.cpp b/SerialPort.cpp index 3ed94d2..4983c5b 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -149,8 +149,13 @@ void CSerialPort::getStatus() reply[6U] = 0U; if (m_dmrEnable) { - reply[7U] = dmrTX.getSpace1(); - reply[8U] = dmrTX.getSpace2(); + if (m_duplex) { + reply[7U] = dmrTX.getSpace1(); + reply[8U] = dmrTX.getSpace2(); + } else { + reply[7U] = 0U; + reply[8U] = dmrDMOTX.getSpace(); + } } else { reply[7U] = 0U; reply[8U] = 0U; @@ -249,6 +254,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrTX.setColorCode(colorCode); dmrRX.setColorCode(colorCode); dmrRX.setDelay(dmrDelay); + dmrDMORX.setColorCode(colorCode); dmrIdleRX.setColorCode(colorCode); io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel); @@ -471,8 +477,10 @@ void CSerialPort::process() case MMDVM_DMR_DATA1: if (m_dmrEnable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) - err = dmrTX.writeData1(m_buffer + 3U, m_len - 3U); + if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) { + if (m_duplex) + err = dmrTX.writeData1(m_buffer + 3U, m_len - 3U); + } } if (err == 0U) { if (m_modemState == STATE_IDLE) @@ -485,8 +493,12 @@ void CSerialPort::process() case MMDVM_DMR_DATA2: if (m_dmrEnable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) - err = dmrTX.writeData2(m_buffer + 3U, m_len - 3U); + if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) { + if (m_duplex) + err = dmrTX.writeData2(m_buffer + 3U, m_len - 3U); + else + err = dmrDMOTX.writeData(m_buffer + 3U, m_len - 3U); + } } if (err == 0U) { if (m_modemState == STATE_IDLE) From d477796903c4b656401443ee3ec041199cfca7c8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 08:17:15 +0100 Subject: [PATCH 145/329] The beginnings of the DMR DMO transmitter. --- DMRDMOTX.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++ DMRDMOTX.h | 50 ++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 DMRDMOTX.cpp create mode 100644 DMRDMOTX.h diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp new file mode 100644 index 0000000..ac5df61 --- /dev/null +++ b/DMRDMOTX.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2009-2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// #define WANT_DEBUG + +#include "Config.h" +#include "Globals.h" +#include "DMRSlotType.h" + +#if defined(WIDE_C4FSK_FILTERS_TX) +// Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, + 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 22U; +#else +// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB +static q15_t DMR_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t DMR_C4FSK_FILTER_LEN = 42U; +#endif + +const q15_t DMR_LEVELA[] = { 640, 640 , 640, 640, 640}; +const q15_t DMR_LEVELB[] = { 213, 213, 213, 213, 213}; +const q15_t DMR_LEVELC[] = {-213, -213, -213, -213, -213}; +const q15_t DMR_LEVELD[] = {-640, -640, -640, -640, -640}; + + +CDMRDMOTX::CDMRDMOTX() : +m_fifo(), +m_modFilter(), +m_modState(), +m_poBuffer(), +m_poLen(0U), +m_poPtr(0U) +{ + ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); + + m_modFilter.numTaps = DMR_C4FSK_FILTER_LEN; + m_modFilter.pState = m_modState; + m_modFilter.pCoeffs = DMR_C4FSK_FILTER; +} + +void CDMRTX::process() +{ + if (m_poLen == 0U && m_fifo.getData() > 0U) { + for (unsigned int i = 0U; i < 72U; i++) + m_poBuffer[i] = 0x00U; + + for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) + m_poBuffer[i] = m_fifo.get(); + + m_poLen = 72U; + m_poPtr = 0U; + } + + if (m_poLen > 0U) { + uint16_t space = io.getSpace(); + + while (space > (4U * DMR_RADIO_SYMBOL_LENGTH)) { + uint8_t c = m_poBuffer[m_poPtr++]; + + writeByte(c); + + space -= 4U * DMR_RADIO_SYMBOL_LENGTH; + + if (m_poPtr >= m_poLen) { + m_poPtr = 0U; + m_poLen = 0U; + return; + } + } + } +} + +uint8_t CDMRTX::writeData(const uint8_t* data, uint8_t length) +{ + if (length != (DMR_FRAME_LENGTH_BYTES + 1U)) + return 4U; + + uint16_t space = m_fifo.getSpace(); + if (space < DMR_FRAME_LENGTH_BYTES) + return 5U; + + for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) + m_fifo.put(data[i + 1U]); + + return 0U; +} + +void CDMRTX::writeByte(uint8_t c) +{ + q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; + q15_t outBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; + + const uint8_t MASK = 0xC0U; + + q15_t* p = inBuffer; + for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += DMR_RADIO_SYMBOL_LENGTH) { + switch (c & MASK) { + case 0xC0U: + ::memcpy(p, DMR_LEVELA, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + case 0x80U: + ::memcpy(p, DMR_LEVELB, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + case 0x00U: + ::memcpy(p, DMR_LEVELC, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + default: + ::memcpy(p, DMR_LEVELD, DMR_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + } + } + + uint16_t blockSize = DMR_RADIO_SYMBOL_LENGTH * 4U; + + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += DMR_RADIO_SYMBOL_LENGTH * 4U; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U - 1U]; + blockSize++; + } else { + blockSize--; + } + + m_count -= m_sampleCount; + } + } + + ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + + io.write(STATE_DMR, outBuffer, blockSize); +} + +uint16_t CDMRTX::getSpace() const +{ + return m_fifo.getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U); +} + diff --git a/DMRDMOTX.h b/DMRDMOTX.h new file mode 100644 index 0000000..a081f22 --- /dev/null +++ b/DMRDMOTX.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(DMRDMOTX_H) +#define DMRDMOTX_H + +#include "Config.h" +#include "DMRDefines.h" + +#include "SerialRB.h" + +class CDMRDMOTX { +public: + CDMRDMOTX(); + + uint8_t writeData(const uint8_t* data, uint8_t length); + + void process(); + + uint16_t getSpace() const; + +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]; + uint16_t m_poLen; + uint16_t m_poPtr; + + void writeByte(uint8_t c); +}; + +#endif + From 35ae6b002d60e3b2d07539ed585d84b8388ec1e5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 20:16:46 +0100 Subject: [PATCH 146/329] First compiling version of DMO code, untested. --- DMRDMORX.cpp | 405 +++++++++++++++++++++++++++++++++++++++++++++++++ DMRDMORX.h | 72 +++++++++ DMRDMOTX.cpp | 31 ++-- DMRDMOTX.h | 4 + DMRDefines.h | 12 ++ IO.cpp | 2 +- SerialPort.cpp | 11 +- 7 files changed, 523 insertions(+), 14 deletions(-) create mode 100644 DMRDMORX.cpp create mode 100644 DMRDMORX.h diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp new file mode 100644 index 0000000..c81b37b --- /dev/null +++ b/DMRDMORX.cpp @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2009-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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WANT_DEBUG + +#include "Config.h" +#include "Globals.h" +#include "DMRDMORX.h" +#include "DMRSlotType.h" +#include "Utils.h" + +const q15_t SCALING_FACTOR = 19505; // Q15(0.60) + +const uint8_t MAX_SYNC_SYMBOLS_ERRS = 2U; +const uint8_t MAX_SYNC_BYTES_ERRS = 3U; + +const uint8_t MAX_SYNC_LOST_FRAMES = 13U; + +const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) + +const uint16_t NOENDPTR = 9999U; + +const uint8_t CONTROL_NONE = 0x00U; +const uint8_t CONTROL_VOICE = 0x20U; +const uint8_t CONTROL_DATA = 0x40U; + +CDMRDMORX::CDMRDMORX() : +m_bitBuffer(), +m_buffer(), +m_bitPtr(0U), +m_dataPtr(0U), +m_syncPtr(0U), +m_startPtr(0U), +m_endPtr(NOENDPTR), +m_maxCorr(0), +m_centre(), +m_threshold(), +m_averagePtr(0U), +m_control(CONTROL_NONE), +m_syncCount(0U), +m_colorCode(0U), +m_state(DMORXS_NONE), +m_n(0U), +m_type(0U), +m_rssiCount(0U), +m_rssi(0U) +{ +} + +void CDMRDMORX::start() +{ + m_dataPtr = 0U; + m_bitPtr = 0U; + m_maxCorr = 0; + m_control = CONTROL_NONE; +} + +void CDMRDMORX::reset() +{ + m_syncPtr = 0U; + m_dataPtr = 0U; + m_bitPtr = 0U; + m_maxCorr = 0; + m_control = CONTROL_NONE; + m_syncCount = 0U; + m_state = DMORXS_NONE; + m_startPtr = 0U; + m_endPtr = NOENDPTR; + m_rssiCount = 0U; +} + +void CDMRDMORX::samples(const q15_t* samples, uint8_t length) +{ + bool dcd = false; + + for (uint8_t i = 0U; i < length; i++) + dcd = processSample(samples[i]); + + io.setDecode(dcd); +} + +bool CDMRDMORX::processSample(q15_t sample) +{ + if (m_state != DMORXS_NONE) { + if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) + io.setADCDetection(true); + else + io.setADCDetection(false); + } else { + io.setADCDetection(false); + } + + m_buffer[m_dataPtr] = sample; + + m_bitBuffer[m_bitPtr] <<= 1; + if (sample < 0) + m_bitBuffer[m_bitPtr] |= 0x01U; + + if (m_state == DMORXS_NONE) { + correlateSync(true); + } else { +#if defined(SEND_RSSI_DATA) + // Grab the RSSI data during the frame + if (m_state == DMORXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) + m_rssi = io.getRSSIValue(); +#endif + uint16_t min = m_syncPtr - 1U; + uint16_t max = m_syncPtr + 1U; + if (m_dataPtr >= min && m_dataPtr <= max) + correlateSync(false); + } + + if (m_dataPtr == m_endPtr) { + // Find the average centre and threshold values + q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; + q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + + uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U]; + frame[0U] = m_control; + + uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; + samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, centre, threshold); + + if (m_control == CONTROL_DATA) { + // Data sync + uint8_t colorCode; + uint8_t dataType; + CDMRSlotType slotType; + slotType.decode(frame + 1U, colorCode, dataType); + + if (colorCode == m_colorCode) { + m_syncCount = 0U; + m_n = 0U; + + frame[0U] |= dataType; + + 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); + m_state = DMORXS_DATA; + m_type = 0x00U; + break; + case DT_RATE_12_DATA: + case DT_RATE_34_DATA: + 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); + 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); + 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); + } + 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); + m_state = DMORXS_NONE; + m_endPtr = NOENDPTR; + } + break; + default: // DT_CSBK + DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold); + serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); + m_state = DMORXS_NONE; + m_endPtr = NOENDPTR; + break; + } + } + } 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) { + frame[34U] = (m_rssi >> 8) & 0xFFU; + frame[35U] = (m_rssi >> 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 + m_state = DMORXS_VOICE; + m_syncCount = 0U; + m_n = 0U; + } else { + if (m_state != DMORXS_NONE) { + m_syncCount++; + if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { + serial.writeDMRLost(true); + m_state = DMORXS_NONE; + m_endPtr = NOENDPTR; + } + } + + if (m_state == DMORXS_VOICE) { + if (m_n >= 5U) { + frame[0U] = CONTROL_VOICE; + m_n = 0U; + } else { + frame[0U] = ++m_n; + } +#if defined(SEND_RSSI_DATA) + // Send RSSI data approximately every second + if (m_rssiCount == 2U) { + frame[34U] = (m_rssi >> 8) & 0xFFU; + frame[35U] = (m_rssi >> 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); + } + } + } + } + + m_dataPtr++; + if (m_dataPtr >= DMO_BUFFER_SIZE) + m_dataPtr = 0U; + + m_bitPtr++; + if (m_bitPtr >= DMR_RADIO_SYMBOL_LENGTH) + m_bitPtr = 0U; + + return m_state != DMORXS_NONE; +} + +void CDMRDMORX::correlateSync(bool first) +{ + uint8_t errs = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_S2_DATA_SYNC_SYMBOLS); + + // The voice sync is the complement of the data sync + bool data = (errs <= MAX_SYNC_SYMBOLS_ERRS); + bool voice = (errs >= (DMR_SYNC_LENGTH_SYMBOLS - MAX_SYNC_SYMBOLS_ERRS)); + + if (data || voice) { + uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + + q31_t corr = 0; + q15_t min = 16000; + q15_t max = -16000; + + uint32_t mask = 0x00800000U; + for (uint8_t i = 0U; i < DMR_SYNC_LENGTH_SYMBOLS; i++, mask >>= 1) { + bool b = (DMR_MS_DATA_SYNC_SYMBOLS & mask) == mask; + + if (m_buffer[ptr] > max) + max = m_buffer[ptr]; + if (m_buffer[ptr] < min) + min = m_buffer[ptr]; + + if (data) + corr += b ? -m_buffer[ptr] : m_buffer[ptr]; + else // if (voice) + corr += b ? m_buffer[ptr] : -m_buffer[ptr]; + + ptr += DMR_RADIO_SYMBOL_LENGTH; + } + + if (corr > m_maxCorr) { + q15_t centre = (max + min) >> 1; + + q31_t v1 = (max - centre) * SCALING_FACTOR; + q15_t threshold = q15_t(v1 >> 15); + + uint8_t sync[DMR_SYNC_BYTES_LENGTH]; + uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + samplesToBits(ptr, DMR_SYNC_LENGTH_SYMBOLS, sync, 4U, centre, threshold); + + if (data) { + uint8_t errs = 0U; + for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_DATA_SYNC_BYTES[i]); + + if (errs <= MAX_SYNC_BYTES_ERRS) { + if (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; + + m_averagePtr++; + if (m_averagePtr >= 4U) + m_averagePtr = 0U; + } + + m_maxCorr = corr; + m_control = CONTROL_DATA; + m_syncPtr = m_dataPtr; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + } + } else { // if (voice) + uint8_t errs = 0U; + for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_VOICE_SYNC_BYTES[i]); + + if (errs <= MAX_SYNC_BYTES_ERRS) { + if (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; + + m_averagePtr++; + if (m_averagePtr >= 4U) + m_averagePtr = 0U; + } + + m_maxCorr = corr; + m_control = CONTROL_VOICE; + m_syncPtr = m_dataPtr; + m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + } + } + } + } +} + +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++, start += DMR_RADIO_SYMBOL_LENGTH) { + q15_t sample = m_buffer[start] - centre; + + if (sample < -threshold) { + WRITE_BIT1(buffer, offset, false); + offset++; + WRITE_BIT1(buffer, offset, true); + offset++; + } else if (sample < 0) { + WRITE_BIT1(buffer, offset, false); + offset++; + WRITE_BIT1(buffer, offset, false); + offset++; + } else if (sample < threshold) { + WRITE_BIT1(buffer, offset, true); + offset++; + WRITE_BIT1(buffer, offset, false); + offset++; + } else { + WRITE_BIT1(buffer, offset, true); + offset++; + WRITE_BIT1(buffer, offset, true); + offset++; + } + } +} + +void CDMRDMORX::setColorCode(uint8_t colorCode) +{ + m_colorCode = colorCode; +} + diff --git a/DMRDMORX.h b/DMRDMORX.h new file mode 100644 index 0000000..a2051e6 --- /dev/null +++ b/DMRDMORX.h @@ -0,0 +1,72 @@ +/* + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(DMRDMORX_H) +#define DMRDMORX_H + +#include "Config.h" +#include "DMRDefines.h" + +const uint16_t DMO_BUFFER_SIZE = 1440U; // 60ms at 24 kHz + +enum DMORX_STATE { + DMORXS_NONE, + DMORXS_VOICE, + DMORXS_DATA +}; + +class CDMRDMORX { +public: + CDMRDMORX(); + + void start(); + + void samples(const q15_t* samples, uint8_t length); + + void setColorCode(uint8_t colorCode); + + void reset(); + +private: + uint32_t m_bitBuffer[DMR_RADIO_SYMBOL_LENGTH]; + q15_t m_buffer[DMO_BUFFER_SIZE]; + uint16_t m_bitPtr; + uint16_t m_dataPtr; + uint16_t m_syncPtr; + uint16_t m_startPtr; + uint16_t m_endPtr; + q31_t m_maxCorr; + q15_t m_centre[4U]; + q15_t m_threshold[4U]; + uint8_t m_averagePtr; + uint8_t m_control; + uint8_t m_syncCount; + uint8_t m_colorCode; + DMORX_STATE m_state; + uint8_t m_n; + uint8_t m_type; + uint16_t m_rssiCount; + uint16_t m_rssi; + + bool processSample(q15_t sample); + void correlateSync(bool first); + void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); +}; + +#endif + diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp index ac5df61..3ba6830 100644 --- a/DMRDMOTX.cpp +++ b/DMRDMOTX.cpp @@ -48,7 +48,9 @@ m_modFilter(), m_modState(), m_poBuffer(), m_poLen(0U), -m_poPtr(0U) +m_poPtr(0U), +m_txDelay(240U), // 200ms +m_count(0U) { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); @@ -57,16 +59,20 @@ m_poPtr(0U) m_modFilter.pCoeffs = DMR_C4FSK_FILTER; } -void CDMRTX::process() +void CDMRDMOTX::process() { if (m_poLen == 0U && m_fifo.getData() > 0U) { - for (unsigned int i = 0U; i < 72U; i++) - m_poBuffer[i] = 0x00U; + if (!m_tx) { + for (uint16_t i = 0U; i < m_txDelay; i++) + m_poBuffer[m_poLen++] = 0x00U; + } else { + for (unsigned int i = 0U; i < 72U; i++) + m_poBuffer[m_poLen++] = 0x00U; - for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) - m_poBuffer[i] = m_fifo.get(); + for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) + m_poBuffer[i] = m_fifo.get(); + } - m_poLen = 72U; m_poPtr = 0U; } @@ -89,7 +95,7 @@ void CDMRTX::process() } } -uint8_t CDMRTX::writeData(const uint8_t* data, uint8_t length) +uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length) { if (length != (DMR_FRAME_LENGTH_BYTES + 1U)) return 4U; @@ -104,7 +110,7 @@ uint8_t CDMRTX::writeData(const uint8_t* data, uint8_t length) return 0U; } -void CDMRTX::writeByte(uint8_t c) +void CDMRDMOTX::writeByte(uint8_t c) { q15_t inBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; q15_t outBuffer[DMR_RADIO_SYMBOL_LENGTH * 4U + 1U]; @@ -152,8 +158,13 @@ void CDMRTX::writeByte(uint8_t c) io.write(STATE_DMR, outBuffer, blockSize); } -uint16_t CDMRTX::getSpace() const +uint16_t CDMRDMOTX::getSpace() const { return m_fifo.getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U); } +void CDMRDMOTX::setTXDelay(uint8_t delay) +{ + m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay +} + diff --git a/DMRDMOTX.h b/DMRDMOTX.h index a081f22..3650d0d 100644 --- a/DMRDMOTX.h +++ b/DMRDMOTX.h @@ -33,6 +33,8 @@ public: void process(); + void setTXDelay(uint8_t delay); + uint16_t getSpace() const; private: @@ -42,6 +44,8 @@ private: uint8_t m_poBuffer[80U]; uint16_t m_poLen; uint16_t m_poPtr; + uint16_t m_txDelay; + uint32_t m_count; void writeByte(uint8_t c); }; diff --git a/DMRDefines.h b/DMRDefines.h index 23de540..9379ec3 100644 --- a/DMRDefines.h +++ b/DMRDefines.h @@ -57,18 +57,30 @@ const uint8_t DMR_MS_DATA_SYNC_BYTES[] = {0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0 const uint8_t DMR_MS_VOICE_SYNC_BYTES[] = {0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U}; const uint8_t DMR_BS_DATA_SYNC_BYTES[] = {0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U}; const uint8_t DMR_BS_VOICE_SYNC_BYTES[] = {0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U}; +const uint8_t DMR_S1_DATA_SYNC_BYTES[] = {0x0FU, 0x7FU, 0xDDU, 0x5DU, 0xDFU, 0xD5U, 0x50U}; +const uint8_t DMR_S1_VOICE_SYNC_BYTES[] = {0x05U, 0xD5U, 0x77U, 0xF7U, 0x75U, 0x7FU, 0xF0U}; +const uint8_t DMR_S2_DATA_SYNC_BYTES[] = {0x0DU, 0x75U, 0x57U, 0xF5U, 0xFFU, 0x7FU, 0x50U}; +const uint8_t DMR_S2_VOICE_SYNC_BYTES[] = {0x07U, 0xDFU, 0xFDU, 0x5FU, 0x55U, 0xD5U, 0xF0U}; const uint8_t DMR_SYNC_BYTES_MASK[] = {0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U}; const uint64_t DMR_MS_DATA_SYNC_BITS = 0x0000D5D7F77FD757U; const uint64_t DMR_MS_VOICE_SYNC_BITS = 0x00007F7D5DD57DFDU; const uint64_t DMR_BS_DATA_SYNC_BITS = 0x0000DFF57D75DF5DU; const uint64_t DMR_BS_VOICE_SYNC_BITS = 0x0000755FD7DF75F7U; +const uint64_t DMR_S1_DATA_SYNC_BITS = 0x0000F7FDD5DDFD55U; +const uint64_t DMR_S1_VOICE_SYNC_BITS = 0x00005D577F7757FFU; +const uint64_t DMR_S2_DATA_SYNC_BITS = 0x0000D7557F5FF7F5U; +const uint64_t DMR_S2_VOICE_SYNC_BITS = 0x00007DFFD5F55D5FU; const uint64_t DMR_SYNC_BITS_MASK = 0x0000FFFFFFFFFFFFU; const uint32_t DMR_MS_DATA_SYNC_SYMBOLS = 0x0076286EU; const uint32_t DMR_MS_VOICE_SYNC_SYMBOLS = 0x0089D791U; const uint32_t DMR_BS_DATA_SYNC_SYMBOLS = 0x00439B4DU; const uint32_t DMR_BS_VOICE_SYNC_SYMBOLS = 0x00BC64B2U; +const uint32_t DMR_S1_DATA_SYNC_SYMBOLS = 0x0021751FU; +const uint32_t DMR_S1_VOICE_SYNC_SYMBOLS = 0x00DE8AE0U; +const uint32_t DMR_S2_DATA_SYNC_SYMBOLS = 0x006F8C23U; +const uint32_t DMR_S2_VOICE_SYNC_SYMBOLS = 0x009073DCU; const uint32_t DMR_SYNC_SYMBOLS_MASK = 0x00FFFFFFU; const uint8_t DT_VOICE_PI_HEADER = 0U; diff --git a/IO.cpp b/IO.cpp index 46a4dd0..696a823 100644 --- a/IO.cpp +++ b/IO.cpp @@ -387,7 +387,7 @@ void CIO::process() else dmrIdleRX.samples(C4FSKVals, blockSize); } else { - dmrDMORX.samples(c4FSKVals, blockSize); + dmrDMORX.samples(C4FSKVals, blockSize); } } } else if (m_modemState == STATE_YSF) { diff --git a/SerialPort.cpp b/SerialPort.cpp index 4983c5b..f8ead0a 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -153,7 +153,7 @@ void CSerialPort::getStatus() reply[7U] = dmrTX.getSpace1(); reply[8U] = dmrTX.getSpace2(); } else { - reply[7U] = 0U; + reply[7U] = 10U; reply[8U] = dmrDMOTX.getSpace(); } } else { @@ -196,7 +196,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) bool rxInvert = (data[0U] & 0x01U) == 0x01U; bool txInvert = (data[0U] & 0x02U) == 0x02U; bool pttInvert = (data[0U] & 0x04U) == 0x04U; - bool duplex = (data[0U] & 0x80U) == 0x80U; + bool simplex = (data[0U] & 0x80U) == 0x80U; bool dstarEnable = (data[1U] & 0x01U) == 0x01U; bool dmrEnable = (data[1U] & 0x02U) == 0x02U; @@ -246,10 +246,11 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_dstarEnable = dstarEnable; m_dmrEnable = dmrEnable; m_ysfEnable = ysfEnable; - m_duplex = duplex; + m_duplex = !simplex; dstarTX.setTXDelay(txDelay); ysfTX.setTXDelay(txDelay); + dmrDMOTX.setTXDelay(txDelay); dmrTX.setColorCode(colorCode); dmrRX.setColorCode(colorCode); @@ -300,6 +301,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_DSTAR: DEBUG1("Mode set to D-Star"); dmrIdleRX.reset(); + dmrDMORX.reset(); dmrRX.reset(); ysfRX.reset(); cwIdTX.reset(); @@ -307,6 +309,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_YSF: DEBUG1("Mode set to System Fusion"); dmrIdleRX.reset(); + dmrDMORX.reset(); dmrRX.reset(); dstarRX.reset(); cwIdTX.reset(); @@ -314,6 +317,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_DSTARCAL: DEBUG1("Mode set to D-Star Calibrate"); dmrIdleRX.reset(); + dmrDMORX.reset(); dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); @@ -322,6 +326,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_DMRCAL: DEBUG1("Mode set to DMR Calibrate"); dmrIdleRX.reset(); + dmrDMORX.reset(); dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); From d948df69a9aabdb14a1fc2ee6b1ce0f073e25303 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 21:03:38 +0100 Subject: [PATCH 147/329] Normalise the data pointers. --- DMRDMORX.cpp | 74 +++++++++++++++++++++++++++++++++++++++++----------- DMRDMORX.h | 4 +-- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index c81b37b..d47dad6 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -99,10 +99,17 @@ void CDMRDMORX::samples(const q15_t* samples, uint8_t length) bool CDMRDMORX::processSample(q15_t sample) { if (m_state != DMORXS_NONE) { - if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) - io.setADCDetection(true); - else - io.setADCDetection(false); + if (m_startPtr < m_endPtr) { + if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) + io.setADCDetection(true); + else + io.setADCDetection(false); + } else { + if (m_dataPtr > m_startPtr || m_dataPtr < m_endPtr) + io.setADCDetection(true); + else + io.setADCDetection(false); + } } else { io.setADCDetection(false); } @@ -121,10 +128,21 @@ bool CDMRDMORX::processSample(q15_t sample) if (m_state == DMORXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) m_rssi = io.getRSSIValue(); #endif - uint16_t min = m_syncPtr - 1U; + uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; uint16_t max = m_syncPtr + 1U; - if (m_dataPtr >= min && m_dataPtr <= max) - correlateSync(false); + + if (min >= DMO_BUFFER_LENGTH_SAMPLES) + min -= DMO_BUFFER_LENGTH_SAMPLES; + if (max >= DMO_BUFFER_LENGTH_SAMPLES) + max -= DMO_BUFFER_LENGTH_SAMPLES; + + if (min < max) { + if (m_dataPtr >= min && m_dataPtr <= max) + correlateSync(false); + } else { + if (m_dataPtr >= min || m_dataPtr <= max) + correlateSync(false); + } } if (m_dataPtr == m_endPtr) { @@ -135,7 +153,10 @@ bool CDMRDMORX::processSample(q15_t sample) uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U]; frame[0U] = m_control; - uint16_t ptr = m_endPtr - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; + uint16_t ptr = m_endPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_FRAME_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH + 1U; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; + samplesToBits(ptr, DMR_FRAME_LENGTH_SYMBOLS, frame, 8U, centre, threshold); if (m_control == CONTROL_DATA) { @@ -260,7 +281,7 @@ bool CDMRDMORX::processSample(q15_t sample) } m_dataPtr++; - if (m_dataPtr >= DMO_BUFFER_SIZE) + if (m_dataPtr >= DMO_BUFFER_LENGTH_SAMPLES) m_dataPtr = 0U; m_bitPtr++; @@ -279,7 +300,9 @@ void CDMRDMORX::correlateSync(bool first) bool voice = (errs >= (DMR_SYNC_LENGTH_SYMBOLS - MAX_SYNC_SYMBOLS_ERRS)); if (data || voice) { - uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + uint16_t ptr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; q31_t corr = 0; q15_t min = 16000; @@ -300,6 +323,8 @@ void CDMRDMORX::correlateSync(bool first) corr += b ? m_buffer[ptr] : -m_buffer[ptr]; ptr += DMR_RADIO_SYMBOL_LENGTH; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; } if (corr > m_maxCorr) { @@ -309,7 +334,10 @@ void CDMRDMORX::correlateSync(bool first) q15_t threshold = q15_t(v1 >> 15); uint8_t sync[DMR_SYNC_BYTES_LENGTH]; - uint16_t ptr = m_dataPtr - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + uint16_t ptr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; + samplesToBits(ptr, DMR_SYNC_LENGTH_SYMBOLS, sync, 4U, centre, threshold); if (data) { @@ -335,8 +363,14 @@ void CDMRDMORX::correlateSync(bool first) m_maxCorr = corr; m_control = CONTROL_DATA; m_syncPtr = m_dataPtr; - m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + + m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + if (m_startPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_startPtr -= DMO_BUFFER_LENGTH_SAMPLES; + + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + if (m_endPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_endPtr -= DMO_BUFFER_LENGTH_SAMPLES; } } else { // if (voice) uint8_t errs = 0U; @@ -361,8 +395,14 @@ void CDMRDMORX::correlateSync(bool first) m_maxCorr = corr; m_control = CONTROL_VOICE; m_syncPtr = m_dataPtr; - m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + + m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + if (m_startPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_startPtr -= DMO_BUFFER_LENGTH_SAMPLES; + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + if (m_endPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_endPtr -= DMO_BUFFER_LENGTH_SAMPLES; } } } @@ -371,7 +411,7 @@ void CDMRDMORX::correlateSync(bool first) 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++, start += DMR_RADIO_SYMBOL_LENGTH) { + for (uint8_t i = 0U; i < count; i++) { q15_t sample = m_buffer[start] - centre; if (sample < -threshold) { @@ -395,6 +435,10 @@ void CDMRDMORX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, ui WRITE_BIT1(buffer, offset, true); offset++; } + + start += DMR_RADIO_SYMBOL_LENGTH; + if (start >= DMO_BUFFER_LENGTH_SAMPLES) + start -= DMO_BUFFER_LENGTH_SAMPLES; } } diff --git a/DMRDMORX.h b/DMRDMORX.h index a2051e6..eac8e80 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -22,7 +22,7 @@ #include "Config.h" #include "DMRDefines.h" -const uint16_t DMO_BUFFER_SIZE = 1440U; // 60ms at 24 kHz +const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz enum DMORX_STATE { DMORXS_NONE, @@ -44,7 +44,7 @@ public: private: uint32_t m_bitBuffer[DMR_RADIO_SYMBOL_LENGTH]; - q15_t m_buffer[DMO_BUFFER_SIZE]; + q15_t m_buffer[DMO_BUFFER_LENGTH_SAMPLES]; uint16_t m_bitPtr; uint16_t m_dataPtr; uint16_t m_syncPtr; From 697cbf9c6c1d1024df64712893a4037a429af38f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 23 Aug 2016 21:11:36 +0100 Subject: [PATCH 148/329] Reset items at the end of the slot and transmission. --- DMRDMORX.cpp | 23 +++++++---------------- DMRDMORX.h | 2 -- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index d47dad6..1fda90d 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -64,19 +64,9 @@ m_rssi(0U) { } -void CDMRDMORX::start() -{ - m_dataPtr = 0U; - m_bitPtr = 0U; - m_maxCorr = 0; - m_control = CONTROL_NONE; -} - void CDMRDMORX::reset() { m_syncPtr = 0U; - m_dataPtr = 0U; - m_bitPtr = 0U; m_maxCorr = 0; m_control = CONTROL_NONE; m_syncCount = 0U; @@ -204,15 +194,13 @@ bool CDMRDMORX::processSample(q15_t sample) 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); - m_state = DMORXS_NONE; - m_endPtr = NOENDPTR; + 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); - m_state = DMORXS_NONE; - m_endPtr = NOENDPTR; + reset(); break; } } @@ -243,8 +231,7 @@ bool CDMRDMORX::processSample(q15_t sample) m_syncCount++; if (m_syncCount >= MAX_SYNC_LOST_FRAMES) { serial.writeDMRLost(true); - m_state = DMORXS_NONE; - m_endPtr = NOENDPTR; + reset(); } } @@ -278,6 +265,10 @@ bool CDMRDMORX::processSample(q15_t sample) } } } + + // End of this slot, reset some items for the next slot. + m_maxCorr = 0; + m_control = CONTROL_NONE; } m_dataPtr++; diff --git a/DMRDMORX.h b/DMRDMORX.h index eac8e80..138333d 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -34,8 +34,6 @@ class CDMRDMORX { public: CDMRDMORX(); - void start(); - void samples(const q15_t* samples, uint8_t length); void setColorCode(uint8_t colorCode); From 67274ff7b6fbb41a03b5c1490466fe0d4696cf9c Mon Sep 17 00:00:00 2001 From: vk4tux Date: Wed, 24 Aug 2016 17:37:25 +1000 Subject: [PATCH 149/329] Update IO.cpp SP8NTH rssi support for V6.1 --- IO.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/IO.cpp b/IO.cpp index f64178c..951cd48 100644 --- a/IO.cpp +++ b/IO.cpp @@ -74,6 +74,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 +#define PIN_RSSI 60 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 From ab81d154d14d6e137c2c09dde74a10a998029dbe Mon Sep 17 00:00:00 2001 From: phl0 Date: Thu, 25 Aug 2016 08:57:44 +0200 Subject: [PATCH 150/329] Add hint about if MMDVM was compiled with EXTERNAL_OSC --- SerialPort.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SerialPort.cpp b/SerialPort.cpp index c3777b7..d87f966 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -61,7 +61,11 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; +#if defined(EXTERNAL_OSC) +const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz TCXO (D-Star/DMR/System Fusion/CW Id)"; +#else const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz (D-Star/DMR/System Fusion/CW Id)"; +#endif const uint8_t PROTOCOL_VERSION = 1U; From 5efe222ec37d62dc518f02c1e870d7873acedff5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 25 Aug 2016 20:18:37 +0100 Subject: [PATCH 151/329] Change the sync bytes to be DMO slot 2. --- DMRDMOTX.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp index 3ba6830..fcbc86c 100644 --- a/DMRDMOTX.cpp +++ b/DMRDMOTX.cpp @@ -104,8 +104,22 @@ uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; + uint8_t buffer[DMR_FRAME_LENGTH_BYTES]; + ::memcpy(buffer, data + 1U, DMR_FRAME_LENGTH_BYTES); + + // Swap the sync bytes to DMO slot 2 + if (::memcmp(buffer + 14U, DMR_BS_DATA_SYNC_BYTES + 1U, 5U) == 0) { + ::memcpy(buffer + 14U, DMR_S2_DATA_SYNC_BYTES + 1U, 5U); + buffer[13U] &= 0xF0U; buffer[13U] |= DMR_S2_DATA_SYNC_BYTES[0U]; + buffer[19U] &= 0x0FU; buffer[19U] |= DMR_S2_DATA_SYNC_BYTES[6U]; + } else if (::memcmp(buffer + 14U, DMR_BS_VOICE_SYNC_BYTES + 1U, 5U) == 0) { + ::memcpy(buffer + 14U, DMR_S2_VOICE_SYNC_BYTES + 1U, 5U); + buffer[13U] &= 0xF0U; buffer[13U] |= DMR_S2_VOICE_SYNC_BYTES[0U]; + buffer[19U] &= 0x0FU; buffer[19U] |= DMR_S2_VOICE_SYNC_BYTES[6U]; + } + for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) - m_fifo.put(data[i + 1U]); + m_fifo.put(buffer[i]); return 0U; } From 8652f58c195747db953292f8758d880c48463cc3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 25 Aug 2016 21:51:25 +0100 Subject: [PATCH 152/329] Work on the DMO RX to improve synchronisation. --- DMRDMORX.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-- DMRDMORX.h | 1 + 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 1fda90d..e13a279 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -118,20 +118,29 @@ bool CDMRDMORX::processSample(q15_t sample) if (m_state == DMORXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) m_rssi = io.getRSSIValue(); #endif - uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; - uint16_t max = m_syncPtr + 1U; + uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; + uint16_t max = m_syncPtr + 1U; + uint16_t max1 = m_syncPtr + 2U; if (min >= DMO_BUFFER_LENGTH_SAMPLES) min -= DMO_BUFFER_LENGTH_SAMPLES; if (max >= DMO_BUFFER_LENGTH_SAMPLES) max -= DMO_BUFFER_LENGTH_SAMPLES; + if (max1 >= DMO_BUFFER_LENGTH_SAMPLES) + max1 -= DMO_BUFFER_LENGTH_SAMPLES; if (min < max) { if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(false); + + // if (m_dataPtr == max1 && m_control == CONTROL_NONE) + // correlateEMB(); } else { if (m_dataPtr >= min || m_dataPtr <= max) correlateSync(false); + + // if (m_dataPtr == max1 && m_control == CONTROL_NONE) + // correlateEMB(); } } @@ -400,6 +409,67 @@ void CDMRDMORX::correlateSync(bool first) } } +void CDMRDMORX::correlateEMB() +{ + uint16_t ptr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH - 3U; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; + + q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; + q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + + bool correct[3U] = {false, false, false}; + for (uint8_t i = 0U; i < 3U; i++) { + uint8_t emb[1U]; + samplesToBits(ptr, DMR_EMB_LENGTH_SYMBOLS / 2U, emb, 0U, centre, threshold); + + uint8_t cc = (emb[0U] & 0xF0U) >> 4; + uint8_t lcss = (emb[0U] & 0x06U) >> 1; + + if (cc == m_colorCode && ((m_n == 0U && lcss == 1U) || + (m_n == 1U && lcss == 3U) || + (m_n == 2U && lcss == 3U) || + (m_n == 3U && lcss == 2U) || + (m_n == 4U && lcss == 0U))) { + correct[i] = true; + int16_t diff = m_syncPtr - ptr; + DEBUG4("DMRDMORX: ptr/emb/diff", ptr, cc, diff); + uint8_t pi = (emb[0U] & 0x08U) >> 3; + DEBUG4("DMRDMORX: pi/lcss/n", pi, lcss, m_n); + } + + ptr++; + if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) + ptr -= DMO_BUFFER_LENGTH_SAMPLES; + } + + if (correct[1U]) { + // Prefer the status quo + return; + } else if (correct[0U]) { + // m_syncPtr-- + m_syncPtr += DMO_BUFFER_LENGTH_SAMPLES - 1U; + } else if (correct[2U]) { + m_syncPtr++; + } else { + // No match, don't change anything + return; + } + + if (m_syncPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_syncPtr -= DMO_BUFFER_LENGTH_SAMPLES; + + m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; + if (m_startPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_startPtr -= DMO_BUFFER_LENGTH_SAMPLES; + + m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; + if (m_endPtr >= DMO_BUFFER_LENGTH_SAMPLES) + m_endPtr -= DMO_BUFFER_LENGTH_SAMPLES; + + DEBUG2("DMRDMORX: m_syncPtr", m_syncPtr); +} + 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++) { diff --git a/DMRDMORX.h b/DMRDMORX.h index 138333d..8f42b3b 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -63,6 +63,7 @@ private: bool processSample(q15_t sample); void correlateSync(bool first); + void correlateEMB(); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; From 90d00846abcd2c36e4a656a07a6d731a1a0f75b2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 25 Aug 2016 22:36:32 +0100 Subject: [PATCH 153/329] Loosen the matching for the frame start sync pattern. --- DStarRX.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 12fac7a..45b4258 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -325,8 +325,8 @@ void CDStarRX::processNone(bool bit) if (bit) m_patternBuffer |= 0x01U; - // Exact matching of the frame sync sequence - if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) == 0U) { + // Fuzzy matching of the frame sync sequence + if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) { DEBUG1("DStarRX: found frame sync in None"); ::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES); From 5fbd7b479050d6470c1fda3119b9546b9be1a5cf Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 28 Aug 2016 11:24:36 +0100 Subject: [PATCH 154/329] Allow for more errors on the D-Star frame sync. --- DStarRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 45b4258..02bf0e7 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -40,7 +40,7 @@ const q15_t THRESHOLD = 0; // D-Star bit order version of 0x55 0x55 0x6E 0x0A const uint32_t FRAME_SYNC_DATA = 0x00557650U; const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU; -const uint8_t FRAME_SYNC_ERRS = 2U; +const uint8_t FRAME_SYNC_ERRS = 3U; // D-Star bit order version of 0x55 0x2D 0x16 const uint32_t DATA_SYNC_DATA = 0x00AAB468U; From 5fb0930c888d131986f8f158b0e91f73a6789211 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 28 Aug 2016 11:30:35 +0100 Subject: [PATCH 155/329] Put the type into the version data. --- SerialPort.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index f8ead0a..9a428e3 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -61,7 +61,11 @@ const uint8_t MMDVM_DEBUG3 = 0xF3U; const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; -const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz (D-Star/DMR/System Fusion/CW Id)"; +#if defined(EXTERNAL_OSC) +const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz DMO TCXO (D-Star/DMR/System Fusion/CW Id)"; +#else +const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz DMO (D-Star/DMR/System Fusion/CW Id)"; +#endif const uint8_t PROTOCOL_VERSION = 1U; From 1f7c16c7e8c235d4d9ddadf8d4b4b8b129de445d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 28 Aug 2016 11:49:31 +0100 Subject: [PATCH 156/329] Add the basic EMB processing. --- DMREMB.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ DMREMB.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 DMREMB.cpp create mode 100644 DMREMB.h diff --git a/DMREMB.cpp b/DMREMB.cpp new file mode 100644 index 0000000..cb6952e --- /dev/null +++ b/DMREMB.cpp @@ -0,0 +1,43 @@ +/* + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "DMREMB.h" + +const uint16_t ENCODING_TABLE_1676[] = + {0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U, + 0x182BU, 0x1A58U, 0x1CCEU, 0x1EBDU, 0x21B7U, 0x23C4U, 0x2552U, 0x2721U, 0x287EU, 0x2A0DU, 0x2C9BU, 0x2EE8U, + 0x3055U, 0x3226U, 0x34B0U, 0x36C3U, 0x399CU, 0x3BEFU, 0x3D79U, 0x3F0AU, 0x411EU, 0x436DU, 0x45FBU, 0x4788U, + 0x48D7U, 0x4AA4U, 0x4C32U, 0x4E41U, 0x50FCU, 0x528FU, 0x5419U, 0x566AU, 0x5935U, 0x5B46U, 0x5DD0U, 0x5FA3U, + 0x60A9U, 0x62DAU, 0x644CU, 0x663FU, 0x6960U, 0x6B13U, 0x6D85U, 0x6FF6U, 0x714BU, 0x7338U, 0x75AEU, 0x77DDU, + 0x7882U, 0x7AF1U, 0x7C67U, 0x7E14U, 0x804FU, 0x823CU, 0x84AAU, 0x86D9U, 0x8986U, 0x8BF5U, 0x8D63U, 0x8F10U, + 0x91ADU, 0x93DEU, 0x9548U, 0x973BU, 0x9864U, 0x9A17U, 0x9C81U, 0x9EF2U, 0xA1F8U, 0xA38BU, 0xA51DU, 0xA76EU, + 0xA831U, 0xAA42U, 0xACD4U, 0xAEA7U, 0xB01AU, 0xB269U, 0xB4FFU, 0xB68CU, 0xB9D3U, 0xBBA0U, 0xBD36U, 0xBF45U, + 0xC151U, 0xC322U, 0xC5B4U, 0xC7C7U, 0xC898U, 0xCAEBU, 0xCC7DU, 0xCE0EU, 0xD0B3U, 0xD2C0U, 0xD456U, 0xD625U, + 0xD97AU, 0xDB09U, 0xDD9FU, 0xDFECU, 0xE0E6U, 0xE295U, 0xE403U, 0xE670U, 0xE92FU, 0xEB5CU, 0xEDCAU, 0xEFB9U, + 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU}; + +uint16_t CDMREMB::emb(uint8_t colorCode, bool pi, uint8_t lcss) +{ + uint8_t index = 0U; + index |= (colorCode << 3) & 0x78U; + index |= pi ? 0x04U : 0x00U; + index |= (lcss << 1) & 0x03U; + + return ENCODING_TABLE_1676[index]; +} + diff --git a/DMREMB.h b/DMREMB.h new file mode 100644 index 0000000..c18ff13 --- /dev/null +++ b/DMREMB.h @@ -0,0 +1,33 @@ +/* + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(DMREMB_H) +#define DMREMB_H + +#include "Config.h" +#include "Globals.h" + +class CDMREMB +{ +public: + static uint16_t emb(uint8_t colorCode, bool pi, uint8_t lcss); + +private: +}; + +#endif From 211fbf1423bb4d65dd654c1d13afe2c9ea5f343e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:13:07 +0100 Subject: [PATCH 157/329] Remove old RSSI code. --- IO.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/IO.cpp b/IO.cpp index 696a823..5f55b9f 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,7 +61,6 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 60 // ADC on Due pin A6 - Due AD1 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -161,11 +160,6 @@ m_lockout(false) pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); #endif - -#if defined(SEND_RSSI_DATA) - pinMode(PIN_RSSI, INPUT); - analogReadResolution(12); -#endif #endif } @@ -581,6 +575,6 @@ bool CIO::hasLockout() const #if defined(SEND_RSSI_DATA) uint16_t CIO::getRSSIValue() { - return analogRead(PIN_RSSI); + return 0U; } #endif From 6059cd358aa03770cfecae73ee22c71e63af11fc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:14:47 +0100 Subject: [PATCH 158/329] Change version message. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 9a428e3..48e8ca8 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -62,9 +62,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz DMO TCXO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160816 DMO TCXO (D-Star/DMR/System Fusion/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz DMO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160816 DMO (D-Star/DMR/System Fusion/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From cf5f960dd10e46ef1e1252f9c1bdab8e84643c84 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:15:02 +0100 Subject: [PATCH 159/329] Fix EMB calculation. --- DMREMB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMREMB.cpp b/DMREMB.cpp index cb6952e..fae4bab 100644 --- a/DMREMB.cpp +++ b/DMREMB.cpp @@ -36,7 +36,7 @@ uint16_t CDMREMB::emb(uint8_t colorCode, bool pi, uint8_t lcss) uint8_t index = 0U; index |= (colorCode << 3) & 0x78U; index |= pi ? 0x04U : 0x00U; - index |= (lcss << 1) & 0x03U; + index |= (lcss << 0) & 0x03U; return ENCODING_TABLE_1676[index]; } From 5af3a14599337cfd213f481f3f4213ced581dfd2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:17:41 +0100 Subject: [PATCH 160/329] Remove old style RSSI. --- IO.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/IO.cpp b/IO.cpp index 951cd48..34b4de0 100644 --- a/IO.cpp +++ b/IO.cpp @@ -61,7 +61,6 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 60 // ADC on Due pin A6 - Due AD1 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -74,7 +73,6 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 -#define PIN_RSSI 60 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 @@ -162,11 +160,6 @@ m_lockout(false) pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); #endif - -#if defined(SEND_RSSI_DATA) - pinMode(PIN_RSSI, INPUT); - analogReadResolution(12); -#endif #endif } @@ -574,6 +567,6 @@ bool CIO::hasLockout() const #if defined(SEND_RSSI_DATA) uint16_t CIO::getRSSIValue() { - return analogRead(PIN_RSSI); + return 0U; } #endif From f124061b858db3e6fe67c3bfd1a670351424e690 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:17:56 +0100 Subject: [PATCH 161/329] Change version string. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 36841a0..067df37 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -62,9 +62,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz TCXO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160816 TCXO (D-Star/DMR/System Fusion/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160816 24kHz (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160816 (D-Star/DMR/System Fusion/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From cc1b39d21b89fdcbb463f8a285bb7ab41119a428 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 30 Aug 2016 17:19:29 +0100 Subject: [PATCH 162/329] Restore old frame sync error threshold. --- DStarRX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DStarRX.cpp b/DStarRX.cpp index 02bf0e7..45b4258 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -40,7 +40,7 @@ const q15_t THRESHOLD = 0; // D-Star bit order version of 0x55 0x55 0x6E 0x0A const uint32_t FRAME_SYNC_DATA = 0x00557650U; const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU; -const uint8_t FRAME_SYNC_ERRS = 3U; +const uint8_t FRAME_SYNC_ERRS = 2U; // D-Star bit order version of 0x55 0x2D 0x16 const uint32_t DATA_SYNC_DATA = 0x00AAB468U; From 2e2acd30fa78e9cfcd7ee3cf6aa39fa513f22d59 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 31 Aug 2016 08:15:06 +0100 Subject: [PATCH 163/329] EMB correlation, work in progress. --- DMRDMORX.cpp | 126 +++++++++++++++++++++++++++++++++++++++------------ DMRDMORX.h | 6 +++ DMRDefines.h | 4 ++ 3 files changed, 107 insertions(+), 29 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index e13a279..01223d4 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -22,6 +22,7 @@ #include "Globals.h" #include "DMRDMORX.h" #include "DMRSlotType.h" +#include "DMREMB.h" #include "Utils.h" const q15_t SCALING_FACTOR = 19505; // Q15(0.60) @@ -60,7 +61,8 @@ m_state(DMORXS_NONE), m_n(0U), m_type(0U), m_rssiCount(0U), -m_rssi(0U) +m_rssi(0U), +m_embs() { } @@ -133,14 +135,14 @@ bool CDMRDMORX::processSample(q15_t sample) if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(false); - // if (m_dataPtr == max1 && m_control == CONTROL_NONE) - // correlateEMB(); + if (m_dataPtr == max1 && m_control == CONTROL_NONE) + correlateEMB(); } else { if (m_dataPtr >= min || m_dataPtr <= max) correlateSync(false); - // if (m_dataPtr == max1 && m_control == CONTROL_NONE) - // correlateEMB(); + if (m_dataPtr == max1 && m_control == CONTROL_NONE) + correlateEMB(); } } @@ -415,27 +417,60 @@ void CDMRDMORX::correlateEMB() if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) ptr -= DMO_BUFFER_LENGTH_SAMPLES; - q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; - q15_t threshold = (m_threshold[0U] + m_threshold[1U] + m_threshold[2U] + m_threshold[3U]) >> 2; + q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; - bool correct[3U] = {false, false, false}; + q31_t corr[3U]; for (uint8_t i = 0U; i < 3U; i++) { - uint8_t emb[1U]; - samplesToBits(ptr, DMR_EMB_LENGTH_SYMBOLS / 2U, emb, 0U, centre, threshold); + uint16_t ptr1 = ptr; + uint16_t ptr2 = ptr + DMR_EMB_LENGTH_SAMPLES / 2U + DMR_EMBSIG_LENGTH_SAMPLES; - uint8_t cc = (emb[0U] & 0xF0U) >> 4; - uint8_t lcss = (emb[0U] & 0x06U) >> 1; + if (ptr2 >= DMO_BUFFER_LENGTH_SAMPLES) + ptr2 -= DMO_BUFFER_LENGTH_SAMPLES; - if (cc == m_colorCode && ((m_n == 0U && lcss == 1U) || - (m_n == 1U && lcss == 3U) || - (m_n == 2U && lcss == 3U) || - (m_n == 3U && lcss == 2U) || - (m_n == 4U && lcss == 0U))) { - correct[i] = true; - int16_t diff = m_syncPtr - ptr; - DEBUG4("DMRDMORX: ptr/emb/diff", ptr, cc, diff); - uint8_t pi = (emb[0U] & 0x08U) >> 3; - DEBUG4("DMRDMORX: pi/lcss/n", pi, lcss, m_n); + corr[i] = 0; + uint16_t emb1 = m_embs[m_n].part1; + uint16_t emb2 = m_embs[m_n].part2; + + for (uint8_t j = 0U; j < 4U; j++) { + q15_t sample1 = m_buffer[ptr1] - centre; + q15_t sample2 = m_buffer[ptr2] - centre; + + switch (emb1 & 0xC0U) { + case 0xC0U: corr[i] += (sample1 + sample1 + sample1); break; + case 0x80U: corr[i] += (sample1); break; + case 0x40U: corr[i] -= (sample1 + sample1 + sample1); break; + default: corr[i] -= (sample1); break; + } + + switch (emb2 & 0xC0U) { + case 0xC0U: corr[i] += (sample2 + sample2 + sample2); break; + case 0x80U: corr[i] += (sample2); break; + case 0x40U: corr[i] -= (sample2 + sample2 + sample2); break; + default: corr[i] -= (sample2); break; + } + + // uint8_t emb1[1U]; + // samplesToBits(ptr1, DMR_EMB_LENGTH_SYMBOLS / 2U, emb1, 0U, centre, threshold); + + // uint8_t emb2[1U]; + // samplesToBits(ptr2, DMR_EMB_LENGTH_SYMBOLS / 2U, emb2, 0U, centre, threshold); + + // errs[i] = countBits8(emb1[0U] ^ m_embs[m_n].part1) + countBits8(emb2[0U] ^ m_embs[m_n].part2); + // if (errs[i] < lowest) + // lowest = errs[i]; + + // DEBUG3("DMRDMORX: ptr/errs", ptr1, errs[i]); + + emb1 <<= 2; + emb2 <<= 2; + + ptr1 += DMR_RADIO_SYMBOL_LENGTH; + if (ptr1 >= DMO_BUFFER_LENGTH_SAMPLES) + ptr1 -= DMO_BUFFER_LENGTH_SAMPLES; + + ptr2 += DMR_RADIO_SYMBOL_LENGTH; + if (ptr2 >= DMO_BUFFER_LENGTH_SAMPLES) + ptr2 -= DMO_BUFFER_LENGTH_SAMPLES; } ptr++; @@ -443,17 +478,30 @@ void CDMRDMORX::correlateEMB() ptr -= DMO_BUFFER_LENGTH_SAMPLES; } - if (correct[1U]) { - // Prefer the status quo + DEBUG4("DMRDMORX: -1/0/+1", corr[0U], corr[1], corr[2]); + + // None of them are very good, don't use + // if (lowest > MAX_EMB_BITS_ERRS) + // return; + + // if (errs[2U] == lowest) { + // // Prefer the status quo + // return; + // } else if (errs[1U] == lowest) { + // // m_syncPtr-- + // m_syncPtr += DMO_BUFFER_LENGTH_SAMPLES - 1U; + // } else { + // m_syncPtr++; + // } + + if (corr[1U] > corr[0U] && corr[1U] > corr[2U]) { + // Nothing has changed return; - } else if (correct[0U]) { + } else if (corr[0U] > corr[1U] && corr[0U] > corr[2U]) { // m_syncPtr-- m_syncPtr += DMO_BUFFER_LENGTH_SAMPLES - 1U; - } else if (correct[2U]) { - m_syncPtr++; } else { - // No match, don't change anything - return; + m_syncPtr++; } if (m_syncPtr >= DMO_BUFFER_LENGTH_SAMPLES) @@ -506,5 +554,25 @@ void CDMRDMORX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, ui void CDMRDMORX::setColorCode(uint8_t colorCode) { m_colorCode = colorCode; + + // Build table of EMB values + uint16_t emb = CDMREMB::emb(colorCode, false, 1U); + m_embs[0U].part1 = (emb >> 8) & 0xFFU; + m_embs[0U].part2 = (emb >> 0) & 0xFFU; + + emb = CDMREMB::emb(colorCode, false, 3U); + m_embs[1U].part1 = (emb >> 8) & 0xFFU; + m_embs[1U].part2 = (emb >> 0) & 0xFFU; + + m_embs[2U].part1 = m_embs[1U].part1; + m_embs[2U].part2 = m_embs[1U].part2; + + emb = CDMREMB::emb(colorCode, false, 2U); + m_embs[3U].part1 = (emb >> 8) & 0xFFU; + m_embs[3U].part2 = (emb >> 0) & 0xFFU; + + emb = CDMREMB::emb(colorCode, false, 0U); + m_embs[4U].part1 = (emb >> 8) & 0xFFU; + m_embs[4U].part2 = (emb >> 0) & 0xFFU; } diff --git a/DMRDMORX.h b/DMRDMORX.h index 8f42b3b..b5c7b6c 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -30,6 +30,11 @@ enum DMORX_STATE { DMORXS_DATA }; +struct EMBList { + uint8_t part1; + uint8_t part2; +}; + class CDMRDMORX { public: CDMRDMORX(); @@ -60,6 +65,7 @@ private: uint8_t m_type; uint16_t m_rssiCount; uint16_t m_rssi; + EMBList m_embs[5U]; bool processSample(q15_t sample); void correlateSync(bool first); diff --git a/DMRDefines.h b/DMRDefines.h index 9379ec3..3b2ccba 100644 --- a/DMRDefines.h +++ b/DMRDefines.h @@ -35,6 +35,10 @@ const unsigned int DMR_EMB_LENGTH_BITS = 16U; const unsigned int DMR_EMB_LENGTH_SYMBOLS = 8U; const unsigned int DMR_EMB_LENGTH_SAMPLES = DMR_EMB_LENGTH_SYMBOLS * DMR_RADIO_SYMBOL_LENGTH; +const unsigned int DMR_EMBSIG_LENGTH_BITS = 32U; +const unsigned int DMR_EMBSIG_LENGTH_SYMBOLS = 16U; +const unsigned int DMR_EMBSIG_LENGTH_SAMPLES = DMR_EMBSIG_LENGTH_SYMBOLS * DMR_RADIO_SYMBOL_LENGTH; + const unsigned int DMR_SLOT_TYPE_LENGTH_BITS = 20U; const unsigned int DMR_SLOT_TYPE_LENGTH_SYMBOLS = 10U; const unsigned int DMR_SLOT_TYPE_LENGTH_SAMPLES = DMR_SLOT_TYPE_LENGTH_SYMBOLS * DMR_RADIO_SYMBOL_LENGTH; From 955648a23f9ae1fee980ed2bf21504277dc13286 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Sep 2016 17:39:51 +0100 Subject: [PATCH 164/329] Remove ADC overload detection for DMR. --- DMRSlotRX.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 4772d8f..58ad5d4 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -100,15 +100,6 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_delayPtr < m_delay) return m_state != DMRRXS_NONE; - if (m_state != DMRRXS_NONE) { - if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) - io.setADCDetection(true); - else - io.setADCDetection(false); - } else { - io.setADCDetection(false); - } - // Ensure that the buffer doesn't overflow if (m_dataPtr > m_endPtr || m_dataPtr >= 900U) return m_state != DMRRXS_NONE; From cffe692055059e837aa0314aa0e1808a2cab53d7 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Sep 2016 19:34:26 +0100 Subject: [PATCH 165/329] Remove ADC overflow detection. --- DMRDMORX.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 01223d4..7c4d09c 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -90,22 +90,6 @@ void CDMRDMORX::samples(const q15_t* samples, uint8_t length) bool CDMRDMORX::processSample(q15_t sample) { - if (m_state != DMORXS_NONE) { - if (m_startPtr < m_endPtr) { - if (m_dataPtr > m_startPtr && m_dataPtr < m_endPtr) - io.setADCDetection(true); - else - io.setADCDetection(false); - } else { - if (m_dataPtr > m_startPtr || m_dataPtr < m_endPtr) - io.setADCDetection(true); - else - io.setADCDetection(false); - } - } else { - io.setADCDetection(false); - } - m_buffer[m_dataPtr] = sample; m_bitBuffer[m_bitPtr] <<= 1; From 0edb4e1c43090c6aa71ff048bcedf24b5ebc2778 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Sep 2016 19:59:37 +0100 Subject: [PATCH 166/329] Fix DMO mode for CS700 as well as PD365. --- DMRDMORX.cpp | 176 ++++++++------------------------------------------- DMRDMORX.h | 7 -- DMRDMOTX.cpp | 16 +---- DMREMB.cpp | 43 ------------- DMREMB.h | 33 ---------- 5 files changed, 29 insertions(+), 246 deletions(-) delete mode 100644 DMREMB.cpp delete mode 100644 DMREMB.h diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 7c4d09c..83b8750 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -22,7 +22,6 @@ #include "Globals.h" #include "DMRDMORX.h" #include "DMRSlotType.h" -#include "DMREMB.h" #include "Utils.h" const q15_t SCALING_FACTOR = 19505; // Q15(0.60) @@ -61,8 +60,7 @@ m_state(DMORXS_NONE), m_n(0U), m_type(0U), m_rssiCount(0U), -m_rssi(0U), -m_embs() +m_rssi(0U) { } @@ -118,15 +116,9 @@ bool CDMRDMORX::processSample(q15_t sample) if (min < max) { if (m_dataPtr >= min && m_dataPtr <= max) correlateSync(false); - - if (m_dataPtr == max1 && m_control == CONTROL_NONE) - correlateEMB(); } else { if (m_dataPtr >= min || m_dataPtr <= max) correlateSync(false); - - if (m_dataPtr == max1 && m_control == CONTROL_NONE) - correlateEMB(); } } @@ -279,13 +271,16 @@ bool CDMRDMORX::processSample(q15_t sample) void CDMRDMORX::correlateSync(bool first) { - uint8_t errs = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_S2_DATA_SYNC_SYMBOLS); + uint8_t errs1 = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_S2_DATA_SYNC_SYMBOLS); + uint8_t errs2 = countBits32((m_bitBuffer[m_bitPtr] & DMR_SYNC_SYMBOLS_MASK) ^ DMR_MS_DATA_SYNC_SYMBOLS); // The voice sync is the complement of the data sync - bool data = (errs <= MAX_SYNC_SYMBOLS_ERRS); - bool voice = (errs >= (DMR_SYNC_LENGTH_SYMBOLS - MAX_SYNC_SYMBOLS_ERRS)); + bool data1 = (errs1 <= MAX_SYNC_SYMBOLS_ERRS); + bool data2 = (errs2 <= MAX_SYNC_SYMBOLS_ERRS); + bool voice1 = (errs1 >= (DMR_SYNC_LENGTH_SYMBOLS - MAX_SYNC_SYMBOLS_ERRS)); + bool voice2 = (errs2 >= (DMR_SYNC_LENGTH_SYMBOLS - MAX_SYNC_SYMBOLS_ERRS)); - if (data || voice) { + if (data1 || data2 || voice1 || voice2) { uint16_t ptr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH; if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) ptr -= DMO_BUFFER_LENGTH_SAMPLES; @@ -296,14 +291,18 @@ void CDMRDMORX::correlateSync(bool first) uint32_t mask = 0x00800000U; for (uint8_t i = 0U; i < DMR_SYNC_LENGTH_SYMBOLS; i++, mask >>= 1) { - bool b = (DMR_MS_DATA_SYNC_SYMBOLS & mask) == mask; + bool b; + if (data1 || voice1) + b = (DMR_S2_DATA_SYNC_SYMBOLS & mask) == mask; + else + b = (DMR_MS_DATA_SYNC_SYMBOLS & mask) == mask; if (m_buffer[ptr] > max) max = m_buffer[ptr]; if (m_buffer[ptr] < min) min = m_buffer[ptr]; - if (data) + if (data1 || data2) corr += b ? -m_buffer[ptr] : m_buffer[ptr]; else // if (voice) corr += b ? m_buffer[ptr] : -m_buffer[ptr]; @@ -326,10 +325,14 @@ void CDMRDMORX::correlateSync(bool first) samplesToBits(ptr, DMR_SYNC_LENGTH_SYMBOLS, sync, 4U, centre, threshold); - if (data) { + if (data1 || data2) { uint8_t errs = 0U; - for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) - errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_DATA_SYNC_BYTES[i]); + for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) { + if (data1) + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_DATA_SYNC_BYTES[i]); + else + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]); + } if (errs <= MAX_SYNC_BYTES_ERRS) { if (first) { @@ -358,10 +361,14 @@ void CDMRDMORX::correlateSync(bool first) if (m_endPtr >= DMO_BUFFER_LENGTH_SAMPLES) m_endPtr -= DMO_BUFFER_LENGTH_SAMPLES; } - } else { // if (voice) + } else { // if (voice1 || voice2) uint8_t errs = 0U; - for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) - errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_VOICE_SYNC_BYTES[i]); + for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++) { + if (voice1) + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_S2_VOICE_SYNC_BYTES[i]); + else + errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]); + } if (errs <= MAX_SYNC_BYTES_ERRS) { if (first) { @@ -395,113 +402,6 @@ void CDMRDMORX::correlateSync(bool first) } } -void CDMRDMORX::correlateEMB() -{ - uint16_t ptr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES + DMR_RADIO_SYMBOL_LENGTH - 3U; - if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) - ptr -= DMO_BUFFER_LENGTH_SAMPLES; - - q15_t centre = (m_centre[0U] + m_centre[1U] + m_centre[2U] + m_centre[3U]) >> 2; - - q31_t corr[3U]; - for (uint8_t i = 0U; i < 3U; i++) { - uint16_t ptr1 = ptr; - uint16_t ptr2 = ptr + DMR_EMB_LENGTH_SAMPLES / 2U + DMR_EMBSIG_LENGTH_SAMPLES; - - if (ptr2 >= DMO_BUFFER_LENGTH_SAMPLES) - ptr2 -= DMO_BUFFER_LENGTH_SAMPLES; - - corr[i] = 0; - uint16_t emb1 = m_embs[m_n].part1; - uint16_t emb2 = m_embs[m_n].part2; - - for (uint8_t j = 0U; j < 4U; j++) { - q15_t sample1 = m_buffer[ptr1] - centre; - q15_t sample2 = m_buffer[ptr2] - centre; - - switch (emb1 & 0xC0U) { - case 0xC0U: corr[i] += (sample1 + sample1 + sample1); break; - case 0x80U: corr[i] += (sample1); break; - case 0x40U: corr[i] -= (sample1 + sample1 + sample1); break; - default: corr[i] -= (sample1); break; - } - - switch (emb2 & 0xC0U) { - case 0xC0U: corr[i] += (sample2 + sample2 + sample2); break; - case 0x80U: corr[i] += (sample2); break; - case 0x40U: corr[i] -= (sample2 + sample2 + sample2); break; - default: corr[i] -= (sample2); break; - } - - // uint8_t emb1[1U]; - // samplesToBits(ptr1, DMR_EMB_LENGTH_SYMBOLS / 2U, emb1, 0U, centre, threshold); - - // uint8_t emb2[1U]; - // samplesToBits(ptr2, DMR_EMB_LENGTH_SYMBOLS / 2U, emb2, 0U, centre, threshold); - - // errs[i] = countBits8(emb1[0U] ^ m_embs[m_n].part1) + countBits8(emb2[0U] ^ m_embs[m_n].part2); - // if (errs[i] < lowest) - // lowest = errs[i]; - - // DEBUG3("DMRDMORX: ptr/errs", ptr1, errs[i]); - - emb1 <<= 2; - emb2 <<= 2; - - ptr1 += DMR_RADIO_SYMBOL_LENGTH; - if (ptr1 >= DMO_BUFFER_LENGTH_SAMPLES) - ptr1 -= DMO_BUFFER_LENGTH_SAMPLES; - - ptr2 += DMR_RADIO_SYMBOL_LENGTH; - if (ptr2 >= DMO_BUFFER_LENGTH_SAMPLES) - ptr2 -= DMO_BUFFER_LENGTH_SAMPLES; - } - - ptr++; - if (ptr >= DMO_BUFFER_LENGTH_SAMPLES) - ptr -= DMO_BUFFER_LENGTH_SAMPLES; - } - - DEBUG4("DMRDMORX: -1/0/+1", corr[0U], corr[1], corr[2]); - - // None of them are very good, don't use - // if (lowest > MAX_EMB_BITS_ERRS) - // return; - - // if (errs[2U] == lowest) { - // // Prefer the status quo - // return; - // } else if (errs[1U] == lowest) { - // // m_syncPtr-- - // m_syncPtr += DMO_BUFFER_LENGTH_SAMPLES - 1U; - // } else { - // m_syncPtr++; - // } - - if (corr[1U] > corr[0U] && corr[1U] > corr[2U]) { - // Nothing has changed - return; - } else if (corr[0U] > corr[1U] && corr[0U] > corr[2U]) { - // m_syncPtr-- - m_syncPtr += DMO_BUFFER_LENGTH_SAMPLES - 1U; - } else { - m_syncPtr++; - } - - if (m_syncPtr >= DMO_BUFFER_LENGTH_SAMPLES) - m_syncPtr -= DMO_BUFFER_LENGTH_SAMPLES; - - m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_SAMPLES - DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U - DMR_INFO_LENGTH_SAMPLES / 2U - DMR_SYNC_LENGTH_SAMPLES; - if (m_startPtr >= DMO_BUFFER_LENGTH_SAMPLES) - m_startPtr -= DMO_BUFFER_LENGTH_SAMPLES; - - m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_SAMPLES / 2U + DMR_INFO_LENGTH_SAMPLES / 2U - 1U; - if (m_endPtr >= DMO_BUFFER_LENGTH_SAMPLES) - m_endPtr -= DMO_BUFFER_LENGTH_SAMPLES; - - DEBUG2("DMRDMORX: m_syncPtr", m_syncPtr); -} - 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++) { @@ -538,25 +438,5 @@ void CDMRDMORX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, ui void CDMRDMORX::setColorCode(uint8_t colorCode) { m_colorCode = colorCode; - - // Build table of EMB values - uint16_t emb = CDMREMB::emb(colorCode, false, 1U); - m_embs[0U].part1 = (emb >> 8) & 0xFFU; - m_embs[0U].part2 = (emb >> 0) & 0xFFU; - - emb = CDMREMB::emb(colorCode, false, 3U); - m_embs[1U].part1 = (emb >> 8) & 0xFFU; - m_embs[1U].part2 = (emb >> 0) & 0xFFU; - - m_embs[2U].part1 = m_embs[1U].part1; - m_embs[2U].part2 = m_embs[1U].part2; - - emb = CDMREMB::emb(colorCode, false, 2U); - m_embs[3U].part1 = (emb >> 8) & 0xFFU; - m_embs[3U].part2 = (emb >> 0) & 0xFFU; - - emb = CDMREMB::emb(colorCode, false, 0U); - m_embs[4U].part1 = (emb >> 8) & 0xFFU; - m_embs[4U].part2 = (emb >> 0) & 0xFFU; } diff --git a/DMRDMORX.h b/DMRDMORX.h index b5c7b6c..138333d 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -30,11 +30,6 @@ enum DMORX_STATE { DMORXS_DATA }; -struct EMBList { - uint8_t part1; - uint8_t part2; -}; - class CDMRDMORX { public: CDMRDMORX(); @@ -65,11 +60,9 @@ private: uint8_t m_type; uint16_t m_rssiCount; uint16_t m_rssi; - EMBList m_embs[5U]; bool processSample(q15_t sample); void correlateSync(bool first); - void correlateEMB(); void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); }; diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp index fcbc86c..3ba6830 100644 --- a/DMRDMOTX.cpp +++ b/DMRDMOTX.cpp @@ -104,22 +104,8 @@ uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; - uint8_t buffer[DMR_FRAME_LENGTH_BYTES]; - ::memcpy(buffer, data + 1U, DMR_FRAME_LENGTH_BYTES); - - // Swap the sync bytes to DMO slot 2 - if (::memcmp(buffer + 14U, DMR_BS_DATA_SYNC_BYTES + 1U, 5U) == 0) { - ::memcpy(buffer + 14U, DMR_S2_DATA_SYNC_BYTES + 1U, 5U); - buffer[13U] &= 0xF0U; buffer[13U] |= DMR_S2_DATA_SYNC_BYTES[0U]; - buffer[19U] &= 0x0FU; buffer[19U] |= DMR_S2_DATA_SYNC_BYTES[6U]; - } else if (::memcmp(buffer + 14U, DMR_BS_VOICE_SYNC_BYTES + 1U, 5U) == 0) { - ::memcpy(buffer + 14U, DMR_S2_VOICE_SYNC_BYTES + 1U, 5U); - buffer[13U] &= 0xF0U; buffer[13U] |= DMR_S2_VOICE_SYNC_BYTES[0U]; - buffer[19U] &= 0x0FU; buffer[19U] |= DMR_S2_VOICE_SYNC_BYTES[6U]; - } - for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) - m_fifo.put(buffer[i]); + m_fifo.put(data[i + 1U]); return 0U; } diff --git a/DMREMB.cpp b/DMREMB.cpp deleted file mode 100644 index fae4bab..0000000 --- a/DMREMB.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "DMREMB.h" - -const uint16_t ENCODING_TABLE_1676[] = - {0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U, - 0x182BU, 0x1A58U, 0x1CCEU, 0x1EBDU, 0x21B7U, 0x23C4U, 0x2552U, 0x2721U, 0x287EU, 0x2A0DU, 0x2C9BU, 0x2EE8U, - 0x3055U, 0x3226U, 0x34B0U, 0x36C3U, 0x399CU, 0x3BEFU, 0x3D79U, 0x3F0AU, 0x411EU, 0x436DU, 0x45FBU, 0x4788U, - 0x48D7U, 0x4AA4U, 0x4C32U, 0x4E41U, 0x50FCU, 0x528FU, 0x5419U, 0x566AU, 0x5935U, 0x5B46U, 0x5DD0U, 0x5FA3U, - 0x60A9U, 0x62DAU, 0x644CU, 0x663FU, 0x6960U, 0x6B13U, 0x6D85U, 0x6FF6U, 0x714BU, 0x7338U, 0x75AEU, 0x77DDU, - 0x7882U, 0x7AF1U, 0x7C67U, 0x7E14U, 0x804FU, 0x823CU, 0x84AAU, 0x86D9U, 0x8986U, 0x8BF5U, 0x8D63U, 0x8F10U, - 0x91ADU, 0x93DEU, 0x9548U, 0x973BU, 0x9864U, 0x9A17U, 0x9C81U, 0x9EF2U, 0xA1F8U, 0xA38BU, 0xA51DU, 0xA76EU, - 0xA831U, 0xAA42U, 0xACD4U, 0xAEA7U, 0xB01AU, 0xB269U, 0xB4FFU, 0xB68CU, 0xB9D3U, 0xBBA0U, 0xBD36U, 0xBF45U, - 0xC151U, 0xC322U, 0xC5B4U, 0xC7C7U, 0xC898U, 0xCAEBU, 0xCC7DU, 0xCE0EU, 0xD0B3U, 0xD2C0U, 0xD456U, 0xD625U, - 0xD97AU, 0xDB09U, 0xDD9FU, 0xDFECU, 0xE0E6U, 0xE295U, 0xE403U, 0xE670U, 0xE92FU, 0xEB5CU, 0xEDCAU, 0xEFB9U, - 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU}; - -uint16_t CDMREMB::emb(uint8_t colorCode, bool pi, uint8_t lcss) -{ - uint8_t index = 0U; - index |= (colorCode << 3) & 0x78U; - index |= pi ? 0x04U : 0x00U; - index |= (lcss << 0) & 0x03U; - - return ENCODING_TABLE_1676[index]; -} - diff --git a/DMREMB.h b/DMREMB.h deleted file mode 100644 index c18ff13..0000000 --- a/DMREMB.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if !defined(DMREMB_H) -#define DMREMB_H - -#include "Config.h" -#include "Globals.h" - -class CDMREMB -{ -public: - static uint16_t emb(uint8_t colorCode, bool pi, uint8_t lcss); - -private: -}; - -#endif From bc2c96cd2c1cbf845f41b376fdbd52ec3a00f20b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 2 Sep 2016 06:25:11 +0100 Subject: [PATCH 167/329] Swap TX syncs from BS to MS. --- DMRDMOTX.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp index 3ba6830..63bc78f 100644 --- a/DMRDMOTX.cpp +++ b/DMRDMOTX.cpp @@ -104,8 +104,22 @@ uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; + uint8_t buffer[DMR_FRAME_LENGTH_BYTES]; + ::memcpy(buffer, data + 1U, DMR_FRAME_LENGTH_BYTES); + + // Swap the sync bytes from BS to MS + if (::memcmp(buffer + 14U, DMR_BS_DATA_SYNC_BYTES + 1U, 5U) == 0) { + ::memcpy(buffer + 14U, DMR_MS_DATA_SYNC_BYTES + 1U, 5U); + buffer[13U] &= 0xF0U; buffer[13U] |= DMR_MS_DATA_SYNC_BYTES[0U]; + buffer[19U] &= 0x0FU; buffer[19U] |= DMR_MS_DATA_SYNC_BYTES[6U]; + } else if (::memcmp(buffer + 14U, DMR_BS_VOICE_SYNC_BYTES + 1U, 5U) == 0) { + ::memcpy(buffer + 14U, DMR_MS_VOICE_SYNC_BYTES + 1U, 5U); + buffer[13U] &= 0xF0U; buffer[13U] |= DMR_MS_VOICE_SYNC_BYTES[0U]; + buffer[19U] &= 0x0FU; buffer[19U] |= DMR_MS_VOICE_SYNC_BYTES[6U]; + } + for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) - m_fifo.put(data[i + 1U]); + m_fifo.put(buffer[i]); return 0U; } From 53503f27c6b9b15c01c30ffc10b7608282f90086 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 3 Sep 2016 13:59:41 +0100 Subject: [PATCH 168/329] Remove unneeded variable. --- DMRDMORX.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 83b8750..90003f1 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -104,14 +104,11 @@ bool CDMRDMORX::processSample(q15_t sample) #endif uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; uint16_t max = m_syncPtr + 1U; - uint16_t max1 = m_syncPtr + 2U; if (min >= DMO_BUFFER_LENGTH_SAMPLES) min -= DMO_BUFFER_LENGTH_SAMPLES; if (max >= DMO_BUFFER_LENGTH_SAMPLES) max -= DMO_BUFFER_LENGTH_SAMPLES; - if (max1 >= DMO_BUFFER_LENGTH_SAMPLES) - max1 -= DMO_BUFFER_LENGTH_SAMPLES; if (min < max) { if (m_dataPtr >= min && m_dataPtr <= max) From e4a1f10261f7914ce6d5ca0f5e2dbf45ae603355 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 3 Sep 2016 15:07:07 +0100 Subject: [PATCH 169/329] Bump the version date. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index f169bbf..75f1baf 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -62,9 +62,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160816 TCXO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160903 TCXO (D-Star/DMR/System Fusion/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160816 (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160903 (D-Star/DMR/System Fusion/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From cc8dc1306ccd61f5fa587248d424d1b7516fa9da Mon Sep 17 00:00:00 2001 From: vk4tux Date: Sun, 4 Sep 2016 14:19:31 +1000 Subject: [PATCH 170/329] Update IO.cpp On FW request G4TSN --- IO.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/IO.cpp b/IO.cpp index 5f55b9f..44337fe 100644 --- a/IO.cpp +++ b/IO.cpp @@ -49,6 +49,9 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS 7 #define PIN_PTT 8 #define PIN_COSLED 11 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 From 2647646a91ea0c550aa57bcb45fbc079b2832a8b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 6 Sep 2016 08:14:54 +0100 Subject: [PATCH 171/329] Remove DMR DMO sync mapping. --- DMRDMOTX.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/DMRDMOTX.cpp b/DMRDMOTX.cpp index 63bc78f..3ba6830 100644 --- a/DMRDMOTX.cpp +++ b/DMRDMOTX.cpp @@ -104,22 +104,8 @@ uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length) if (space < DMR_FRAME_LENGTH_BYTES) return 5U; - uint8_t buffer[DMR_FRAME_LENGTH_BYTES]; - ::memcpy(buffer, data + 1U, DMR_FRAME_LENGTH_BYTES); - - // Swap the sync bytes from BS to MS - if (::memcmp(buffer + 14U, DMR_BS_DATA_SYNC_BYTES + 1U, 5U) == 0) { - ::memcpy(buffer + 14U, DMR_MS_DATA_SYNC_BYTES + 1U, 5U); - buffer[13U] &= 0xF0U; buffer[13U] |= DMR_MS_DATA_SYNC_BYTES[0U]; - buffer[19U] &= 0x0FU; buffer[19U] |= DMR_MS_DATA_SYNC_BYTES[6U]; - } else if (::memcmp(buffer + 14U, DMR_BS_VOICE_SYNC_BYTES + 1U, 5U) == 0) { - ::memcpy(buffer + 14U, DMR_MS_VOICE_SYNC_BYTES + 1U, 5U); - buffer[13U] &= 0xF0U; buffer[13U] |= DMR_MS_VOICE_SYNC_BYTES[0U]; - buffer[19U] &= 0x0FU; buffer[19U] |= DMR_MS_VOICE_SYNC_BYTES[6U]; - } - for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) - m_fifo.put(buffer[i]); + m_fifo.put(data[i + 1U]); return 0U; } From 40e55d84604ceff6504b2d5e6845c2aeb08f35fe Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 6 Sep 2016 17:23:35 +0100 Subject: [PATCH 172/329] Bump the version date. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 75f1baf..8e29950 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -62,9 +62,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160903 TCXO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160906 TCXO (D-Star/DMR/System Fusion/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160903 (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160906 (D-Star/DMR/System Fusion/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From 618529b4788e3b525efa603ba8ba79999e7250b1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 6 Sep 2016 19:11:16 +0100 Subject: [PATCH 173/329] Initial P25 test support. --- Globals.h | 5 + IO.cpp | 10 ++ MMDVM.cpp | 3 + MMDVM.ino | 3 + P25Defines.h | 53 ++++++++++ P25RX.cpp | 281 +++++++++++++++++++++++++++++++++++++++++++++++++ P25RX.h | 59 +++++++++++ SerialPort.cpp | 98 +++++++++++++++-- SerialPort.h | 4 + 9 files changed, 510 insertions(+), 6 deletions(-) create mode 100644 P25Defines.h create mode 100644 P25RX.cpp create mode 100644 P25RX.h diff --git a/Globals.h b/Globals.h index 161641a..5950200 100644 --- a/Globals.h +++ b/Globals.h @@ -39,6 +39,7 @@ enum MMDVM_STATE { STATE_DSTAR = 1, STATE_DMR = 2, STATE_YSF = 3, + STATE_P25 = 4, STATE_DMRCAL = 98, STATE_DSTARCAL = 99 }; @@ -53,6 +54,7 @@ enum MMDVM_STATE { #include "DMRTX.h" #include "YSFRX.h" #include "YSFTX.h" +#include "P25RX.h" #include "CalDStarRX.h" #include "CalDStarTX.h" #include "CalDMR.h" @@ -74,6 +76,7 @@ extern MMDVM_STATE m_modemState; extern bool m_dstarEnable; extern bool m_dmrEnable; extern bool m_ysfEnable; +extern bool m_p25Enable; extern bool m_duplex; @@ -98,6 +101,8 @@ extern CDMRDMOTX dmrDMOTX; extern CYSFRX ysfRX; extern CYSFTX ysfTX; +extern CP25RX p25RX; + extern CCalDStarRX calDStarRX; extern CCalDStarTX calDStarTX; extern CCalDMR calDMR; diff --git a/IO.cpp b/IO.cpp index 44337fe..7a864c6 100644 --- a/IO.cpp +++ b/IO.cpp @@ -364,6 +364,9 @@ void CIO::process() if (m_ysfEnable) ysfRX.samples(C4FSKVals, blockSize); + + if (m_p25Enable) + p25RX.samples(C4FSKVals, blockSize); } } else if (m_modemState == STATE_DSTAR) { if (m_dstarEnable) { @@ -394,6 +397,13 @@ void CIO::process() ysfRX.samples(C4FSKVals, 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); + } } else if (m_modemState == STATE_DSTARCAL) { q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); diff --git a/MMDVM.cpp b/MMDVM.cpp index 49ab79a..78a26d2 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -29,6 +29,7 @@ MMDVM_STATE m_modemState = STATE_IDLE; bool m_dstarEnable = true; bool m_dmrEnable = true; bool m_ysfEnable = true; +bool m_p25Enable = true; bool m_duplex = true; @@ -50,6 +51,8 @@ CDMRDMOTX dmrDMOTX; CYSFRX ysfRX; CYSFTX ysfTX; +CP25RX p25RX; + CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; CCalDMR calDMR; diff --git a/MMDVM.ino b/MMDVM.ino index 2bfac98..f311a1b 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -26,6 +26,7 @@ MMDVM_STATE m_modemState = STATE_IDLE; bool m_dstarEnable = true; bool m_dmrEnable = true; bool m_ysfEnable = true; +bool m_p25Enable = true; bool m_duplex = true; @@ -47,6 +48,8 @@ CDMRDMOTX dmrDMOTX; CYSFRX ysfRX; CYSFTX ysfTX; +CP25RX p25RX; + CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; CCalDMR calDMR; diff --git a/P25Defines.h b/P25Defines.h new file mode 100644 index 0000000..38083ab --- /dev/null +++ b/P25Defines.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(P25DEFINES_H) +#define P25DEFINES_H + +const unsigned int P25_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate + +const unsigned int P25_HDR_FRAME_LENGTH_BYTES = 99U; +const unsigned int P25_HDR_FRAME_LENGTH_BITS = P25_HDR_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_HDR_FRAME_LENGTH_SYMBOLS = P25_HDR_FRAME_LENGTH_BYTES * 4U; + +const unsigned int P25_LDU_FRAME_LENGTH_BYTES = 216U; +const unsigned int P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_LDU_FRAME_LENGTH_SYMBOLS = P25_LDU_FRAME_LENGTH_BYTES * 4U; + +const unsigned int P25_SYNC_LENGTH_BYTES = 6U; +const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U; +const unsigned int P25_SYNC_LENGTH_SYMBOLS = P25_SYNC_LENGTH_BYTES * 4U; + +const unsigned int P25_NID_LENGTH_BITS = 64U; +const unsigned int P25_NID_LENGTH_SYMBOLS = 32U; + +const uint8_t P25_SYNC_BYTES[] = {0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU}; +const uint8_t P25_SYNC_BYTES_LENGTH = 6U; + +const uint64_t P25_SYNC_BITS = 0x00005575F5FF77FFU; +const uint64_t P25_SYNC_BITS_MASK = 0x0000FFFFFFFFFFFFU; + +// 5 5 7 5 F 5 F F 7 7 F F +// 01 01 01 01 01 11 01 01 11 11 01 01 11 11 11 11 01 11 01 11 11 11 11 11 +// +3 +3 +3 +3 +3 -3 +3 +3 -3 -3 +3 +3 -3 -3 -3 -3 +3 -3 +3 -3 -3 -3 -3 -3 + +const uint32_t P25_SYNC_SYMBOLS = 0x00FB30A0U; +const uint32_t P25_SYNC_SYMBOLS_MASK = 0x00FFFFFFU; + +#endif + diff --git a/P25RX.cpp b/P25RX.cpp new file mode 100644 index 0000000..2ba138a --- /dev/null +++ b/P25RX.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define WANT_DEBUG + +#include "Config.h" +#include "Globals.h" +#include "P25RX.h" +#include "Utils.h" + +const unsigned int BUFFER_LENGTH = 200U; + +const q15_t SCALING_FACTOR = 18750; // Q15(0.55) + +const uint32_t PLLMAX = 0x10000U; +const uint32_t PLLINC = PLLMAX / P25_RADIO_SYMBOL_LENGTH; +const uint32_t INC = PLLINC / 32U; + +const uint8_t SYNC_SYMBOL_ERRS = 0U; + +const uint8_t SYNC_BIT_START_ERRS = 2U; +const uint8_t SYNC_BIT_RUN_ERRS = 4U; + +const unsigned int MAX_SYNC_FRAMES = 4U + 1U; + +const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; + +#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) +#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) + +CP25RX::CP25RX() : +m_pll(0U), +m_prev(false), +m_state(P25RXS_NONE), +m_bitBuffer(0x00U), +m_symbols(), +m_outBuffer(), +m_buffer(NULL), +m_bufferPtr(0U), +m_symbolPtr(0U), +m_lostCount(0U), +m_rssiCount(0U), +m_centre(0), +m_threshold(0) +{ + m_buffer = m_outBuffer + 1U; +} + +void CP25RX::reset() +{ + m_pll = 0U; + m_prev = false; + m_state = P25RXS_NONE; + m_bitBuffer = 0x00U; + m_bufferPtr = 0U; + m_symbolPtr = 0U; + m_lostCount = 0U; + m_rssiCount = 0U; + m_centre = 0; + m_threshold = 0; +} + +void CP25RX::samples(const q15_t* samples, uint8_t length) +{ + for (uint16_t i = 0U; i < length; i++) { + bool bit = samples[i] < 0; + + if (bit != m_prev) { + if (m_pll < (PLLMAX / 2U)) + m_pll += INC; + else + m_pll -= INC; + } + + m_prev = bit; + + m_pll += PLLINC; + + if (m_pll >= PLLMAX) { + m_pll -= PLLMAX; + + if (m_state == P25RXS_NONE) + processNone(samples[i]); + else + processData(samples[i]); + } + } +} + +void CP25RX::processNone(q15_t sample) +{ + m_symbolBuffer <<= 1; + if (sample < 0) + m_symbolBuffer |= 0x01U; + + m_symbols[m_symbolPtr] = sample; + + // Fuzzy matching of the data sync bit sequence + if (countBits32((m_symbolBuffer & P25_SYNC_SYMBOLS_MASK) ^ P25_SYNC_SYMBOLS) <= SYNC_SYMBOL_ERRS) { + q15_t max = -16000; + q15_t min = 16000; + + for (uint8_t i = 0U; i < P25_SYNC_LENGTH_SYMBOLS; i++) { + q15_t val = m_symbols[i]; + if (val > max) + max = val; + if (val < min) + min = val; + } + + q15_t centre = (max + min) >> 1; + + q31_t v1 = (max - centre) * SCALING_FACTOR; + q15_t threshold = q15_t(v1 >> 15); + + uint16_t ptr = m_symbolPtr + 1U; + if (ptr >= P25_SYNC_LENGTH_SYMBOLS) + ptr = 0U; + + for (uint8_t i = 0U; i < P25_SYNC_LENGTH_SYMBOLS; i++) { + q15_t sample = m_symbols[ptr] - centre; + + if (sample < -threshold) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x01U; + } else if (sample < 0) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x00U; + } else if (sample < threshold) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x02U; + } else { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x03U; + } + + ptr++; + if (ptr >= P25_SYNC_LENGTH_SYMBOLS) + ptr = 0U; + } + + // Fuzzy matching of the data sync bit sequence + if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_START_ERRS) { + DEBUG5("P25RX: sync found in None min/max/centre/threshold", min, max, centre, threshold); + for (uint8_t i = 0U; i < P25_SYNC_LENGTH_BYTES; i++) + m_buffer[i] = P25_SYNC_BYTES[i]; + m_centre = centre; + m_threshold = threshold; + m_lostCount = MAX_SYNC_FRAMES; + m_bufferPtr = P25_SYNC_LENGTH_BITS; + m_state = P25RXS_DATA; + m_rssiCount = 0U; + + io.setDecode(true); + io.setADCDetection(true); + } + } + + m_symbolPtr++; + if (m_symbolPtr >= P25_SYNC_LENGTH_SYMBOLS) + m_symbolPtr = 0U; +} + +void CP25RX::processData(q15_t sample) +{ + sample -= m_centre; + + if (sample < -m_threshold) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x01U; + WRITE_BIT1(m_buffer, m_bufferPtr, false); + m_bufferPtr++; + WRITE_BIT1(m_buffer, m_bufferPtr, true); + m_bufferPtr++; + } else if (sample < 0) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x00U; + WRITE_BIT1(m_buffer, m_bufferPtr, false); + m_bufferPtr++; + WRITE_BIT1(m_buffer, m_bufferPtr, false); + m_bufferPtr++; + } else if (sample < m_threshold) { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x02U; + WRITE_BIT1(m_buffer, m_bufferPtr, true); + m_bufferPtr++; + WRITE_BIT1(m_buffer, m_bufferPtr, false); + m_bufferPtr++; + } else { + m_bitBuffer <<= 2; + m_bitBuffer |= 0x03U; + WRITE_BIT1(m_buffer, m_bufferPtr, true); + m_bufferPtr++; + WRITE_BIT1(m_buffer, m_bufferPtr, true); + m_bufferPtr++; + } + + // Search for an early sync to indicate an LDU following a header + if (m_bufferPtr >= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS + 2U)) { + // Fuzzy matching of the data sync bit sequence + if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) { + DEBUG2("P25RX: found LDU sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS); + + m_outBuffer[0U] = 0x00U; + serial.writeP25Hdr(m_outBuffer, P25_HDR_FRAME_LENGTH_BYTES + 1U); + + // Restore the sync that's now in the wrong place + for (uint8_t i = 0U; i < P25_SYNC_LENGTH_BYTES; i++) + m_buffer[i] = P25_SYNC_BYTES[i]; + + m_lostCount = MAX_SYNC_FRAMES; + m_bufferPtr = P25_SYNC_LENGTH_BITS; + } + } + + // Only search for a sync in the right place +-2 symbols + if (m_bufferPtr >= (P25_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (P25_SYNC_LENGTH_BITS + 2U)) { + // Fuzzy matching of the data sync bit sequence + if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) { + DEBUG2("P25RX: found sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS); + m_lostCount = MAX_SYNC_FRAMES; + m_bufferPtr = P25_SYNC_LENGTH_BITS; + } + } + + // Send a data frame to the host if the required number of bits have been received + if (m_bufferPtr == P25_LDU_FRAME_LENGTH_BITS) { + // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE + m_lostCount--; + if (m_lostCount == 0U) { + DEBUG1("P25RX: sync timed out, lost lock"); + + io.setDecode(false); + io.setADCDetection(false); + + serial.writeP25Lost(); + + m_state = P25RXS_NONE; + } else { + m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; + +#if defined(SEND_RSSI_DATA) + // Send RSSI data every second + if (m_rssiCount == 0U) { + uint16_t rssi = io.getRSSIValue(); + m_outBuffer[121U] = (rssi >> 8) & 0xFFU; + m_outBuffer[122U] = (rssi >> 0) & 0xFFU; + serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 3U); + } else { + serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U); + } + + m_rssiCount++; + if (m_rssiCount >= 10U) + m_rssiCount = 0U; +#else + serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U); +#endif + + // Start the next frame + ::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U); + m_bufferPtr = 0U; + } + } +} + diff --git a/P25RX.h b/P25RX.h new file mode 100644 index 0000000..79f0ed2 --- /dev/null +++ b/P25RX.h @@ -0,0 +1,59 @@ +/* + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(P25RX_H) +#define P25RX_H + +#include "Config.h" +#include "P25Defines.h" + +enum P25RX_STATE { + P25RXS_NONE, + P25RXS_DATA +}; + +class CP25RX { +public: + CP25RX(); + + void samples(const q15_t* samples, uint8_t length); + + void reset(); + +private: + uint32_t m_pll; + bool m_prev; + P25RX_STATE m_state; + uint32_t m_symbolBuffer; + uint64_t m_bitBuffer; + q15_t m_symbols[P25_SYNC_LENGTH_SYMBOLS]; + uint8_t m_outBuffer[P25_LDU_FRAME_LENGTH_BYTES + 3U]; + uint8_t* m_buffer; + uint16_t m_bufferPtr; + uint16_t m_symbolPtr; + uint16_t m_lostCount; + uint16_t m_rssiCount; + q15_t m_centre; + q15_t m_threshold; + + void processNone(q15_t sample); + void processData(q15_t sample); +}; + +#endif + diff --git a/SerialPort.cpp b/SerialPort.cpp index 8e29950..c9d1d89 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -52,6 +52,10 @@ const uint8_t MMDVM_DMR_ABORT = 0x1EU; const uint8_t MMDVM_YSF_DATA = 0x20U; const uint8_t MMDVM_YSF_LOST = 0x21U; +const uint8_t MMDVM_P25_HDR = 0x30U; +const uint8_t MMDVM_P25_LDU = 0x31U; +const uint8_t MMDVM_P25_LOST = 0x32U; + const uint8_t MMDVM_ACK = 0x70U; const uint8_t MMDVM_NAK = 0x7FU; @@ -62,9 +66,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160906 TCXO (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160906 TCXO (D-Star/DMR/System Fusion/P25/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160906 (D-Star/DMR/System Fusion/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20160906 (D-Star/DMR/System Fusion/P25/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; @@ -109,7 +113,7 @@ void CSerialPort::getStatus() { io.resetWatchdog(); - uint8_t reply[11U]; + uint8_t reply[15U]; // Send all sorts of interesting internal values reply[0U] = MMDVM_FRAME_START; @@ -123,6 +127,8 @@ void CSerialPort::getStatus() reply[3U] |= 0x02U; if (m_ysfEnable) reply[3U] |= 0x04U; + if (m_p25Enable) + reply[3U] |= 0x08U; reply[4U] = uint8_t(m_modemState); @@ -170,7 +176,9 @@ void CSerialPort::getStatus() else reply[9U] = 0U; - write(reply, 10); + reply[10U] = 0U; // P25 + + write(reply, 11); } void CSerialPort::getVersion() @@ -205,6 +213,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) bool dstarEnable = (data[1U] & 0x01U) == 0x01U; bool dmrEnable = (data[1U] & 0x02U) == 0x02U; bool ysfEnable = (data[1U] & 0x04U) == 0x04U; + bool p25Enable = (data[1U] & 0x08U) == 0x08U; uint8_t txDelay = data[2U]; if (txDelay > 50U) @@ -212,7 +221,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) MMDVM_STATE modemState = MMDVM_STATE(data[3U]); - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) return 4U; if (modemState == STATE_DSTAR && !dstarEnable) return 4U; @@ -220,6 +229,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) return 4U; if (modemState == STATE_YSF && !ysfEnable) return 4U; + if (modemState == STATE_P25 && !p25Enable) + return 4U; uint8_t rxLevel = data[4U]; @@ -250,6 +261,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_dstarEnable = dstarEnable; m_dmrEnable = dmrEnable; m_ysfEnable = ysfEnable; + m_p25Enable = p25Enable; m_duplex = !simplex; dstarTX.setTXDelay(txDelay); @@ -279,7 +291,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length) if (modemState == m_modemState) return 0U; - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL) return 4U; if (modemState == STATE_DSTAR && !m_dstarEnable) return 4U; @@ -287,6 +299,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length) return 4U; if (modemState == STATE_YSF && !m_ysfEnable) return 4U; + if (modemState == STATE_P25 && !m_p25Enable) + return 4U; setMode(modemState); @@ -318,6 +332,15 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dstarRX.reset(); cwIdTX.reset(); break; + case STATE_P25: + DEBUG1("Mode set to P25"); + dmrIdleRX.reset(); + dmrDMORX.reset(); + dmrRX.reset(); + dstarRX.reset(); + ysfRX.reset(); + cwIdTX.reset(); + break; case STATE_DSTARCAL: DEBUG1("Mode set to D-Star Calibrate"); dmrIdleRX.reset(); @@ -743,6 +766,69 @@ void CSerialPort::writeYSFLost() write(reply, 3); } +void CSerialPort::writeP25Hdr(const uint8_t* data, uint8_t length) +{ + if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE) + return; + + if (!m_p25Enable) + return; + + uint8_t reply[120U]; + + reply[0U] = MMDVM_FRAME_START; + reply[1U] = 0U; + reply[2U] = MMDVM_P25_HDR; + + uint8_t count = 3U; + for (uint8_t i = 0U; i < length; i++, count++) + reply[count] = data[i]; + + reply[1U] = count; + + write(reply, count); +} + +void CSerialPort::writeP25Ldu(const uint8_t* data, uint8_t length) +{ + if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE) + return; + + if (!m_p25Enable) + return; + + uint8_t reply[250U]; + + reply[0U] = MMDVM_FRAME_START; + reply[1U] = 0U; + reply[2U] = MMDVM_P25_LDU; + + uint8_t count = 3U; + for (uint8_t i = 0U; i < length; i++, count++) + reply[count] = data[i]; + + reply[1U] = count; + + write(reply, count); +} + +void CSerialPort::writeP25Lost() +{ + if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE) + return; + + if (!m_p25Enable) + return; + + uint8_t reply[3U]; + + reply[0U] = MMDVM_FRAME_START; + reply[1U] = 3U; + reply[2U] = MMDVM_P25_LOST; + + write(reply, 3); +} + void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) { if (m_modemState != STATE_DSTARCAL) diff --git a/SerialPort.h b/SerialPort.h index bcf4d05..5ad3881 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -42,6 +42,10 @@ public: void writeYSFData(const uint8_t* data, uint8_t length); void writeYSFLost(); + void writeP25Hdr(const uint8_t* data, uint8_t length); + void writeP25Ldu(const uint8_t* data, uint8_t length); + void writeP25Lost(); + void writeCalData(const uint8_t* data, uint8_t length); void writeDebug(const char* text); From e25b51b4868748582564ff7467d0b50e81e64c4a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 8 Sep 2016 17:43:34 +0100 Subject: [PATCH 174/329] Fix the sync detection byte. --- P25RX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/P25RX.cpp b/P25RX.cpp index 2ba138a..f3e326b 100644 --- a/P25RX.cpp +++ b/P25RX.cpp @@ -216,7 +216,7 @@ void CP25RX::processData(q15_t sample) if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) { DEBUG2("P25RX: found LDU sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS); - m_outBuffer[0U] = 0x00U; + m_outBuffer[0U] = 0x01U; serial.writeP25Hdr(m_outBuffer, P25_HDR_FRAME_LENGTH_BYTES + 1U); // Restore the sync that's now in the wrong place From dbcd17dda75f70dfa816d621c4868a209040bb84 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 8 Sep 2016 17:53:59 +0100 Subject: [PATCH 175/329] Add the P25 transmitter. --- Globals.h | 2 + IO.cpp | 8 ++- IO.h | 3 +- MMDVM.cpp | 4 ++ P25TX.cpp | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ P25TX.h | 52 ++++++++++++++ SerialPort.cpp | 46 +++++++++++-- 7 files changed, 289 insertions(+), 6 deletions(-) create mode 100644 P25TX.cpp create mode 100644 P25TX.h diff --git a/Globals.h b/Globals.h index 5950200..7888891 100644 --- a/Globals.h +++ b/Globals.h @@ -55,6 +55,7 @@ enum MMDVM_STATE { #include "YSFRX.h" #include "YSFTX.h" #include "P25RX.h" +#include "P25TX.h" #include "CalDStarRX.h" #include "CalDStarTX.h" #include "CalDMR.h" @@ -102,6 +103,7 @@ extern CYSFRX ysfRX; extern CYSFTX ysfTX; extern CP25RX p25RX; +extern CP25TX p25TX; extern CCalDStarRX calDStarRX; extern CCalDStarTX calDStarTX; diff --git a/IO.cpp b/IO.cpp index 7a864c6..da45079 100644 --- a/IO.cpp +++ b/IO.cpp @@ -129,6 +129,7 @@ m_rxLevel(128 * 128), m_dstarTXLevel(128 * 128), m_dmrTXLevel(128 * 128), m_ysfTXLevel(128 * 128), +m_p25TXLevel(128 * 128), m_ledCount(0U), m_ledValue(true), m_dcd(false), @@ -439,6 +440,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t case STATE_YSF: txLevel = m_ysfTXLevel; break; + case STATE_P25: + txLevel = m_p25TXLevel; + break; default: txLevel = m_dstarTXLevel; break; @@ -532,7 +536,7 @@ switch (m_modemState) { #endif } -void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel) +void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel) { m_pttInvert = pttInvert; @@ -540,6 +544,7 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_dstarTXLevel = q15_t(dstarTXLevel * 128); m_dmrTXLevel = q15_t(dmrTXLevel * 128); m_ysfTXLevel = q15_t(ysfTXLevel * 128); + m_p25TXLevel = q15_t(p25TXLevel * 128); if (rxInvert) m_rxLevel = -m_rxLevel; @@ -548,6 +553,7 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_dstarTXLevel = -m_dstarTXLevel; m_dmrTXLevel = -m_dmrTXLevel; m_ysfTXLevel = -m_ysfTXLevel; + m_p25TXLevel = -m_p25TXLevel; } } diff --git a/IO.h b/IO.h index b7befcb..910853c 100644 --- a/IO.h +++ b/IO.h @@ -41,7 +41,7 @@ public: void interrupt(); - void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel); + void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -84,6 +84,7 @@ private: q15_t m_dstarTXLevel; q15_t m_dmrTXLevel; q15_t m_ysfTXLevel; + q15_t m_p25TXLevel; uint32_t m_ledCount; bool m_ledValue; diff --git a/MMDVM.cpp b/MMDVM.cpp index 78a26d2..f99cba6 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -52,6 +52,7 @@ CYSFRX ysfRX; CYSFTX ysfTX; CP25RX p25RX; +CP25TX p25TX; CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; @@ -87,6 +88,9 @@ void loop() if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); + if (m_p25Enable && m_modemState == STATE_P25) + p25TX.process(); + if (m_modemState == STATE_DSTARCAL) calDStarTX.process(); diff --git a/P25TX.cpp b/P25TX.cpp new file mode 100644 index 0000000..82ea422 --- /dev/null +++ b/P25TX.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// #define WANT_DEBUG + +#include "Config.h" +#include "Globals.h" +#include "P25TX.h" + +#include "P25Defines.h" + +#if defined(WIDE_C4FSK_FILTERS_TX) +// Generated using rcosdesign(0.2, 4, 5, 'sqrt') in MATLAB +static q15_t P25_C4FSK_FILTER[] = {688, -680, -2158, -3060, -2724, -775, 2684, 7041, 11310, 14425, 15565, 14425, + 11310, 7041, 2684, -775, -2724, -3060, -2158, -680, 688, 0}; +const uint16_t P25_C4FSK_FILTER_LEN = 22U; +#else +// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB +static q15_t P25_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995, + 11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112, + -553, -847, -731, -340, 104, 401, 0}; +const uint16_t P25_C4FSK_FILTER_LEN = 42U; +#endif + +// XXX These will need setting correctly +const q15_t P25_LEVELA[] = { 809, 809, 809, 809, 809}; +const q15_t P25_LEVELB[] = { 269, 269, 269, 269, 269}; +const q15_t P25_LEVELC[] = {-269, -269, -269, -269, -269}; +const q15_t P25_LEVELD[] = {-809, -809, -809, -809, -809}; + +const uint8_t P25_START_SYNC = 0x77U; + +CP25TX::CP25TX() : +m_buffer(1500U), +m_modFilter(), +m_modState(), +m_poBuffer(), +m_poLen(0U), +m_poPtr(0U), +m_txDelay(240U), // 200ms +m_count(0U) +{ + ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); + + m_modFilter.numTaps = P25_C4FSK_FILTER_LEN; + m_modFilter.pState = m_modState; + m_modFilter.pCoeffs = P25_C4FSK_FILTER; +} + +void CP25TX::process() +{ + if (m_buffer.getData() == 0U && m_poLen == 0U) + return; + + if (m_poLen == 0U) { + if (!m_tx) { + m_count = 0U; + + for (uint16_t i = 0U; i < m_txDelay; i++) + m_poBuffer[m_poLen++] = P25_START_SYNC; + } else { + uint8_t length = m_buffer.get(); + for (uint8_t i = 0U; i < length; i++) { + uint8_t c = m_buffer.get(); + m_poBuffer[m_poLen++] = c; + } + } + + m_poPtr = 0U; + } + + if (m_poLen > 0U) { + uint16_t space = io.getSpace(); + + while (space > (4U * P25_RADIO_SYMBOL_LENGTH)) { + uint8_t c = m_poBuffer[m_poPtr++]; + writeByte(c); + + space -= 4U * P25_RADIO_SYMBOL_LENGTH; + + if (m_poPtr >= m_poLen) { + m_poPtr = 0U; + m_poLen = 0U; + return; + } + } + } +} + +uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length) +{ + if (length < (P25_HDR_FRAME_LENGTH_BYTES + 1U)) + return 4U; + + uint16_t space = m_buffer.getSpace(); + if (space < length) + return 5U; + + m_buffer.put(length - 1U); + for (uint8_t i = 0U; i < (length - 1U); i++) + m_buffer.put(data[i + 1U]); + + return 0U; +} + +void CP25TX::writeByte(uint8_t c) +{ + q15_t inBuffer[P25_RADIO_SYMBOL_LENGTH * 4U + 1U]; + q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U + 1U]; + + const uint8_t MASK = 0xC0U; + + q15_t* p = inBuffer; + for (uint8_t i = 0U; i < 4U; i++, c <<= 2, p += P25_RADIO_SYMBOL_LENGTH) { + switch (c & MASK) { + case 0xC0U: + ::memcpy(p, P25_LEVELA, P25_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + case 0x80U: + ::memcpy(p, P25_LEVELB, P25_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + case 0x00U: + ::memcpy(p, P25_LEVELC, P25_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + default: + ::memcpy(p, P25_LEVELD, P25_RADIO_SYMBOL_LENGTH * sizeof(q15_t)); + break; + } + } + + uint16_t blockSize = P25_RADIO_SYMBOL_LENGTH * 4U; + + // Handle the case of the oscillator not being accurate enough + if (m_sampleCount > 0U) { + m_count += P25_RADIO_SYMBOL_LENGTH * 4U; + + if (m_count >= m_sampleCount) { + if (m_sampleInsert) { + inBuffer[P25_RADIO_SYMBOL_LENGTH * 4U] = inBuffer[P25_RADIO_SYMBOL_LENGTH * 4U - 1U]; + blockSize++; + } else { + blockSize--; + } + + m_count -= m_sampleCount; + } + } + + ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + + // Inverse sinc lowpass filter needed here + + io.write(STATE_P25, outBuffer, blockSize); +} + +void CP25TX::setTXDelay(uint8_t delay) +{ + m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay +} + +uint16_t CP25TX::getSpace() const +{ + return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES; +} + diff --git a/P25TX.h b/P25TX.h new file mode 100644 index 0000000..2c432c0 --- /dev/null +++ b/P25TX.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(P25TX_H) +#define P25TX_H + +#include "Config.h" + +#include "SerialRB.h" + +class CP25TX { +public: + CP25TX(); + + uint8_t writeData(const uint8_t* data, uint8_t length); + + void process(); + + void setTXDelay(uint8_t delay); + + uint16_t getSpace() const; + +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]; + uint16_t m_poLen; + uint16_t m_poPtr; + uint16_t m_txDelay; + uint32_t m_count; + + void writeByte(uint8_t c); +}; + +#endif + diff --git a/SerialPort.cpp b/SerialPort.cpp index c9d1d89..86259c3 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -176,7 +176,10 @@ void CSerialPort::getStatus() else reply[9U] = 0U; - reply[10U] = 0U; // P25 + if (m_p25Enable) + reply[10U] = p25TX.getSpace(); + else + reply[10U] = 0U; write(reply, 11); } @@ -202,7 +205,7 @@ void CSerialPort::getVersion() uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) { - if (length < 12U) + if (length < 13U) return 4U; bool rxInvert = (data[0U] & 0x01U) == 0x01U; @@ -255,6 +258,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t dstarTXLevel = data[9U]; uint8_t dmrTXLevel = data[10U]; uint8_t ysfTXLevel = data[11U]; + uint8_t p25TXLevel = data[12U]; m_modemState = modemState; @@ -266,6 +270,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dstarTX.setTXDelay(txDelay); ysfTX.setTXDelay(txDelay); + p25TX.setTXDelay(txDelay); dmrDMOTX.setTXDelay(txDelay); dmrTX.setColorCode(colorCode); @@ -274,7 +279,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrDMORX.setColorCode(colorCode); dmrIdleRX.setColorCode(colorCode); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel); io.start(); @@ -314,6 +319,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) DEBUG1("Mode set to DMR"); dstarRX.reset(); ysfRX.reset(); + p25RX.reset(); cwIdTX.reset(); break; case STATE_DSTAR: @@ -322,6 +328,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrDMORX.reset(); dmrRX.reset(); ysfRX.reset(); + p25RX.reset(); cwIdTX.reset(); break; case STATE_YSF: @@ -330,6 +337,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrDMORX.reset(); dmrRX.reset(); dstarRX.reset(); + p25RX.reset(); cwIdTX.reset(); break; case STATE_P25: @@ -348,6 +356,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); + p25RX.reset(); cwIdTX.reset(); break; case STATE_DMRCAL: @@ -357,6 +366,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState) dmrRX.reset(); dstarRX.reset(); ysfRX.reset(); + p25RX.reset(); cwIdTX.reset(); break; default: @@ -403,7 +413,7 @@ void CSerialPort::process() if (m_ptr == 2U) m_len = m_buffer[1U]; - if (m_ptr == 3U && m_len > 130U) { + if (m_ptr == 3U && m_len > 230U) { sendNAK(3U); m_ptr = 0U; m_len = 0U; @@ -594,6 +604,34 @@ void CSerialPort::process() } break; + case MMDVM_P25_HDR: + if (m_p25Enable) { + if (m_modemState == STATE_IDLE || m_modemState == STATE_P25) + err = p25TX.writeData(m_buffer + 3U, m_len - 3U); + } + if (err == 0U) { + if (m_modemState == STATE_IDLE) + setMode(STATE_P25); + } else { + DEBUG2("Received invalid P25 header", err); + sendNAK(err); + } + break; + + case MMDVM_P25_LDU: + if (m_p25Enable) { + if (m_modemState == STATE_IDLE || m_modemState == STATE_P25) + err = p25TX.writeData(m_buffer + 3U, m_len - 3U); + } + if (err == 0U) { + if (m_modemState == STATE_IDLE) + setMode(STATE_P25); + } else { + DEBUG2("Received invalid P25 LDU", err); + sendNAK(err); + } + break; + default: // Handle this, send a NAK back sendNAK(1U); From d3b7197366345ea12bd0683f1f4a883b3d1a7045 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 8 Sep 2016 18:35:16 +0100 Subject: [PATCH 176/329] Add the .ino file with the P25 support. --- MMDVM.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MMDVM.ino b/MMDVM.ino index f311a1b..dac658a 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -49,6 +49,7 @@ CYSFRX ysfRX; CYSFTX ysfTX; CP25RX p25RX; +CP25TX p25TX; CCalDStarRX calDStarRX; CCalDStarTX calDStarTX; @@ -84,6 +85,9 @@ void loop() if (m_ysfEnable && m_modemState == STATE_YSF) ysfTX.process(); + if (m_p25Enable && m_modemState == STATE_P25) + p25TX.process(); + if (m_modemState == STATE_DSTARCAL) calDStarTX.process(); From cd17c94c8978ec486528833df3d74f378dd78f0d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 9 Sep 2016 09:35:15 +0100 Subject: [PATCH 177/329] Adjust P25 transmit deviations. --- P25TX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index 82ea422..b9d226d 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -38,10 +38,10 @@ const uint16_t P25_C4FSK_FILTER_LEN = 42U; #endif // XXX These will need setting correctly -const q15_t P25_LEVELA[] = { 809, 809, 809, 809, 809}; -const q15_t P25_LEVELB[] = { 269, 269, 269, 269, 269}; -const q15_t P25_LEVELC[] = {-269, -269, -269, -269, -269}; -const q15_t P25_LEVELD[] = {-809, -809, -809, -809, -809}; +const q15_t P25_LEVELA[] = { 539, 539, 539, 539, 539}; +const q15_t P25_LEVELB[] = { 179, 179, 179, 179, 179}; +const q15_t P25_LEVELC[] = {-179, -179, -179, -179, -179}; +const q15_t P25_LEVELD[] = {-539, -539, -539, -539, -539}; const uint8_t P25_START_SYNC = 0x77U; From 84c037e075f1bf2b511a6ee400db302b1cd1fd66 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sat, 10 Sep 2016 17:48:01 +0100 Subject: [PATCH 178/329] Add P25 mode output pin. --- IO.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/IO.cpp b/IO.cpp index da45079..8b92f68 100644 --- a/IO.cpp +++ b/IO.cpp @@ -49,9 +49,6 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_COS 7 #define PIN_PTT 8 #define PIN_COSLED 11 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 @@ -64,6 +61,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 +#define PIN_P25 6 #define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 @@ -76,6 +74,7 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DSTAR 9 #define PIN_DMR 8 #define PIN_YSF 7 +#define PIN_P25 6 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 @@ -163,6 +162,7 @@ m_lockout(false) pinMode(PIN_DSTAR, OUTPUT); pinMode(PIN_DMR, OUTPUT); pinMode(PIN_YSF, OUTPUT); + pinMode(PIN_P25, OUTPUT); #endif #endif } @@ -515,21 +515,31 @@ switch (m_modemState) { digitalWrite(PIN_DSTAR, HIGH); digitalWrite(PIN_DMR, LOW); digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); break; case STATE_DMR: digitalWrite(PIN_DSTAR, LOW); digitalWrite(PIN_DMR, HIGH); digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); break; case STATE_YSF: digitalWrite(PIN_DSTAR, LOW); digitalWrite(PIN_DMR, LOW); digitalWrite(PIN_YSF, HIGH); + digitalWrite(PIN_P25, LOW); + break; + case STATE_P25: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, HIGH); break; default: digitalWrite(PIN_DSTAR, LOW); digitalWrite(PIN_DMR, LOW); digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); break; } #endif From f4262c3a243891f85f87e6d5ff00003e0d1d520c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 12 Sep 2016 17:37:11 +0100 Subject: [PATCH 179/329] Tweaks to the P25 TX and RX. --- P25Defines.h | 20 ++++++++++++++------ P25RX.cpp | 4 ++-- P25TX.cpp | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/P25Defines.h b/P25Defines.h index 38083ab..da21229 100644 --- a/P25Defines.h +++ b/P25Defines.h @@ -21,13 +21,21 @@ const unsigned int P25_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate -const unsigned int P25_HDR_FRAME_LENGTH_BYTES = 99U; -const unsigned int P25_HDR_FRAME_LENGTH_BITS = P25_HDR_FRAME_LENGTH_BYTES * 8U; -const unsigned int P25_HDR_FRAME_LENGTH_SYMBOLS = P25_HDR_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_HDR_FRAME_LENGTH_BYTES = 99U; +const unsigned int P25_HDR_FRAME_LENGTH_BITS = P25_HDR_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_HDR_FRAME_LENGTH_SYMBOLS = P25_HDR_FRAME_LENGTH_BYTES * 4U; -const unsigned int P25_LDU_FRAME_LENGTH_BYTES = 216U; -const unsigned int P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U; -const unsigned int P25_LDU_FRAME_LENGTH_SYMBOLS = P25_LDU_FRAME_LENGTH_BYTES * 4U; +const unsigned int P25_LDU_FRAME_LENGTH_BYTES = 216U; +const unsigned int P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_LDU_FRAME_LENGTH_SYMBOLS = P25_LDU_FRAME_LENGTH_BYTES * 4U; + +const unsigned int P25_TERMLC_FRAME_LENGTH_BYTES = 54U; +const unsigned int P25_TERMLC_FRAME_LENGTH_BITS = P25_TERMLC_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_TERMLC_FRAME_LENGTH_SYMBOLS = P25_TERMLC_FRAME_LENGTH_BYTES * 4U; + +const unsigned int P25_TERM_FRAME_LENGTH_BYTES = 18U; +const unsigned int P25_TERM_FRAME_LENGTH_BITS = P25_TERM_FRAME_LENGTH_BYTES * 8U; +const unsigned int P25_TERM_FRAME_LENGTH_SYMBOLS = P25_TERM_FRAME_LENGTH_BYTES * 4U; const unsigned int P25_SYNC_LENGTH_BYTES = 6U; const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U; diff --git a/P25RX.cpp b/P25RX.cpp index f3e326b..4980468 100644 --- a/P25RX.cpp +++ b/P25RX.cpp @@ -36,7 +36,7 @@ const uint8_t SYNC_SYMBOL_ERRS = 0U; const uint8_t SYNC_BIT_START_ERRS = 2U; const uint8_t SYNC_BIT_RUN_ERRS = 4U; -const unsigned int MAX_SYNC_FRAMES = 4U + 1U; +const unsigned int MAX_SYNC_FRAMES = 3U + 1U; const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -211,7 +211,7 @@ void CP25RX::processData(q15_t sample) } // Search for an early sync to indicate an LDU following a header - if (m_bufferPtr >= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS + 2U)) { + if (m_bufferPtr >= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS - 1U) && m_bufferPtr <= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS + 1U)) { // Fuzzy matching of the data sync bit sequence if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) { DEBUG2("P25RX: found LDU sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS); diff --git a/P25TX.cpp b/P25TX.cpp index b9d226d..bae6954 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -104,7 +104,7 @@ void CP25TX::process() uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length) { - if (length < (P25_HDR_FRAME_LENGTH_BYTES + 1U)) + if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U)) return 4U; uint16_t space = m_buffer.getSpace(); From a1b51d4dffdfafef5217a5f65c6cb60ab9804045 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 12 Sep 2016 23:16:04 +0100 Subject: [PATCH 180/329] Fix buffer overrun in the serial code. --- SerialPort.cpp | 2 +- SerialPort.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 86259c3..529f5dd 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -413,7 +413,7 @@ void CSerialPort::process() if (m_ptr == 2U) m_len = m_buffer[1U]; - if (m_ptr == 3U && m_len > 230U) { + if (m_ptr == 3U && m_len > 250U) { sendNAK(3U); m_ptr = 0U; m_len = 0U; diff --git a/SerialPort.h b/SerialPort.h index 5ad3881..d4981e7 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -60,7 +60,7 @@ private: #if defined(__MBED__) Serial m_serial; #endif - uint8_t m_buffer[130U]; + uint8_t m_buffer[250U]; uint8_t m_ptr; uint8_t m_len; From fe5c5808acba27ec1cbac7c0635372ccaf2b5205 Mon Sep 17 00:00:00 2001 From: George Smart Date: Wed, 14 Sep 2016 22:57:34 +0100 Subject: [PATCH 181/329] More info on Linux & newer libraries OK --- BUILD.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/BUILD.txt b/BUILD.txt index f8e83ba..17c7c15 100644 --- a/BUILD.txt +++ b/BUILD.txt @@ -53,8 +53,9 @@ Likely on Linux As with Arduino 1.6.7 with SAM 1.6.6, see below. -For Arduino 1.6.7 with SAM 1.6.6 +For Arduino 1.6.7 with SAM 1.6.6 -------------------------------- +(checked OK on Arduino 1.6.11 and SAM 1.6.9) 1. Go to the where the platform.txt file is located. On my Windows machine it's in: @@ -69,14 +70,19 @@ On Linux, it's located in my home directory, downloaded and extracted from Ardui /home/m1geo/arduino-1.6.7/hardware/arduino/sam - I (M1GEO) found it was necessary to download SAM-1.6.6 outside of the Arduino IDE, and manually extract the files. +or + +/home/m1geo/.arduino15/packages/arduino/hardware/sam/1.6.9 (if you let the board/library manager install SAM) + + +I (M1GEO) found it was necessary to download SAM-1.6.6 outside of the Arduino IDE, and manually extract the files. The Board Manager didn't seem to install the SAM files correctly. Here's how I did it: a) wget http://downloads.arduino.cc/cores/sam-1.6.6.tar.bz2 -O /tmp/sam-1.6.6.tar.bz2 (download and save in /tmp) b) cd arduino-1.6.7/hardware/arduino/ (Arduino root, here, in my home directory) c) tar xvfj /tmp/sam-1.6.6.tar.bz2 -2. You'll need to open the file in a text editor and find the line: +2. You'll need to open the file (platform.txt) in a text editor and find the line: ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc From 55db02461ca620697a8302fb92b23154f9ffeb3d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 15 Sep 2016 17:40:23 +0100 Subject: [PATCH 182/329] Add the ZUM V1.2 board to the menu. --- mmdvmmenu.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index aa56151..672b9ad 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -67,7 +67,7 @@ do (4) Use the COS to lockout the modem (5) Use pins to output the current mode (6) Use layout for the PAPA board - (7) Use layout for ZUM board V1.0 + (7) Use layout for ZUM board V1.0 and V1.2 (8) Use layout for SP8NTH board (9) Return to Default @@ -82,7 +82,7 @@ EOF "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 and V1.2 enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; "9") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; From e9c2388d32c9b2fdafe863772a98e4f7f43bdae0 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 15 Sep 2016 18:08:40 +0100 Subject: [PATCH 183/329] Add the Inverse-Sinc low-pass filter for P25 TX. --- P25TX.cpp | 21 +++++++++++++++++++-- P25TX.h | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index bae6954..8b4ffca 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -37,6 +37,15 @@ static q15_t P25_C4FSK_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1 const uint16_t P25_C4FSK_FILTER_LEN = 42U; #endif +// Generated in MATLAB using the following commands, and then normalised for unity gain +// shape2 = 'Inverse-sinc Lowpass'; +// d2 = fdesign.interpolator(2, shape2); +// h2 = design(d2, 'SystemObject', true); +static q15_t P25_LP_FILTER[] = {170, 401, 340, -203, -715, -478, 281, 419, -440, -1002, -103, 1114, 528, -1389, -1520, 1108, 2674, -388, -4662, + -2132, 9168, 20241, 20241, 9168, -2132, -4662, -388, 2674, 1108, -1520, -1389, 528, 1114, -103, -1002, -440, 419, + 281, -478, -715, -203, 340, 401, 170}; +const uint16_t P25_LP_FILTER_LEN = 44U; + // XXX These will need setting correctly const q15_t P25_LEVELA[] = { 539, 539, 539, 539, 539}; const q15_t P25_LEVELB[] = { 179, 179, 179, 179, 179}; @@ -48,7 +57,9 @@ const uint8_t P25_START_SYNC = 0x77U; CP25TX::CP25TX() : m_buffer(1500U), m_modFilter(), +m_lpFilter(), m_modState(), +m_lpState(), m_poBuffer(), m_poLen(0U), m_poPtr(0U), @@ -56,10 +67,15 @@ m_txDelay(240U), // 200ms m_count(0U) { ::memset(m_modState, 0x00U, 70U * sizeof(q15_t)); + ::memset(m_lpState, 0x00U, 70U * sizeof(q15_t)); m_modFilter.numTaps = P25_C4FSK_FILTER_LEN; m_modFilter.pState = m_modState; m_modFilter.pCoeffs = P25_C4FSK_FILTER; + + m_lpFilter.numTaps = P25_LP_FILTER_LEN; + m_lpFilter.pState = m_lpState; + m_lpFilter.pCoeffs = P25_LP_FILTER; } void CP25TX::process() @@ -121,6 +137,7 @@ uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length) void CP25TX::writeByte(uint8_t c) { q15_t inBuffer[P25_RADIO_SYMBOL_LENGTH * 4U + 1U]; + q15_t intBuffer[P25_RADIO_SYMBOL_LENGTH * 4U + 1U]; q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U + 1U]; const uint8_t MASK = 0xC0U; @@ -161,9 +178,9 @@ void CP25TX::writeByte(uint8_t c) } } - ::arm_fir_fast_q15(&m_modFilter, inBuffer, outBuffer, blockSize); + ::arm_fir_fast_q15(&m_modFilter, inBuffer, intBuffer, blockSize); - // Inverse sinc lowpass filter needed here + ::arm_fir_fast_q15(&m_lpFilter, intBuffer, outBuffer, blockSize); io.write(STATE_P25, outBuffer, blockSize); } diff --git a/P25TX.h b/P25TX.h index 2c432c0..bbe6393 100644 --- a/P25TX.h +++ b/P25TX.h @@ -38,7 +38,9 @@ public: private: CSerialRB m_buffer; arm_fir_instance_q15 m_modFilter; + 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]; uint16_t m_poLen; uint16_t m_poPtr; From c7cfa5e1ab341d9aee9eaa365b613544b4334ceb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 27 Sep 2016 20:04:27 +0100 Subject: [PATCH 184/329] Remove unneeded RSSI code for all but DMR. --- Config.h | 4 ++-- DStarRX.cpp | 22 +--------------------- DStarRX.h | 1 - P25RX.cpp | 21 +-------------------- P25RX.h | 1 - YSFRX.cpp | 19 ------------------- YSFRX.h | 1 - 7 files changed, 4 insertions(+), 65 deletions(-) diff --git a/Config.h b/Config.h index 27f7290..7a6877f 100644 --- a/Config.h +++ b/Config.h @@ -43,9 +43,9 @@ // For the SP8NTH board // #define ARDUINO_DUE_NTH -// To use wider C4FSK filters for DMR and System Fusion on transmit +// To use wider C4FSK filters for DMR, System Fusion and P25 on transmit // #define WIDE_C4FSK_FILTERS_TX -// To use wider C4FSK filters for DMR and System Fusion on receive +// To use wider C4FSK filters for DMR, System Fusion and P25 on receive // #define WIDE_C4FSK_FILTERS_RX // Pass RSSI information to the host diff --git a/DStarRX.cpp b/DStarRX.cpp index 45b4258..81268cb 100644 --- a/DStarRX.cpp +++ b/DStarRX.cpp @@ -260,8 +260,7 @@ m_pathMemory2(), m_pathMemory3(), m_fecOutput(), m_samples(), -m_samplesPtr(0U), -m_rssiCount(0U) +m_samplesPtr(0U) { } @@ -274,7 +273,6 @@ void CDStarRX::reset() m_rxBufferBits = 0U; m_dataBits = 0U; m_samplesPtr = 0U; - m_rssiCount = 0U; } void CDStarRX::samples(const q15_t* samples, uint8_t length) @@ -349,7 +347,6 @@ void CDStarRX::processNone(bool bit) m_rxBufferBits = 0U; m_dataBits = 0U; - m_rssiCount = 0U; m_rxState = DSRXS_DATA; return; } @@ -379,7 +376,6 @@ void CDStarRX::processHeader(bool bit) m_rxBufferBits = 0U; m_rxState = DSRXS_DATA; - m_rssiCount = 0U; m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U; } else { // The checksum failed, return to looking for syncs @@ -463,23 +459,7 @@ void CDStarRX::processData(bool bit) m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; } -#if defined(SEND_RSSI_DATA) - // Send RSSI data every second - if (m_rssiCount == 0U) { - uint16_t rssi = io.getRSSIValue(); - m_rxBuffer[12U] = (rssi >> 8) & 0xFFU; - m_rxBuffer[13U] = (rssi >> 0) & 0xFFU; - serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES + 2U); - } else { - serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); - } - - m_rssiCount++; - if (m_rssiCount >= 50U) - m_rssiCount = 0U; -#else serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); -#endif // Start the next frame ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); diff --git a/DStarRX.h b/DStarRX.h index a9252a8..dd63ed3 100644 --- a/DStarRX.h +++ b/DStarRX.h @@ -53,7 +53,6 @@ private: uint8_t m_fecOutput[42U]; q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS]; uint8_t m_samplesPtr; - uint16_t m_rssiCount; void processNone(bool bit); void processHeader(bool bit); diff --git a/P25RX.cpp b/P25RX.cpp index 4980468..bb7ad25 100644 --- a/P25RX.cpp +++ b/P25RX.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG +// #define WANT_DEBUG #include "Config.h" #include "Globals.h" @@ -54,7 +54,6 @@ m_buffer(NULL), m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), -m_rssiCount(0U), m_centre(0), m_threshold(0) { @@ -70,7 +69,6 @@ void CP25RX::reset() m_bufferPtr = 0U; m_symbolPtr = 0U; m_lostCount = 0U; - m_rssiCount = 0U; m_centre = 0; m_threshold = 0; } @@ -164,7 +162,6 @@ void CP25RX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = P25_SYNC_LENGTH_BITS; m_state = P25RXS_DATA; - m_rssiCount = 0U; io.setDecode(true); io.setADCDetection(true); @@ -254,23 +251,7 @@ void CP25RX::processData(q15_t sample) } else { m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; -#if defined(SEND_RSSI_DATA) - // Send RSSI data every second - if (m_rssiCount == 0U) { - uint16_t rssi = io.getRSSIValue(); - m_outBuffer[121U] = (rssi >> 8) & 0xFFU; - m_outBuffer[122U] = (rssi >> 0) & 0xFFU; - serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U); - } - - m_rssiCount++; - if (m_rssiCount >= 10U) - m_rssiCount = 0U; -#else serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U); -#endif // Start the next frame ::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U); diff --git a/P25RX.h b/P25RX.h index 79f0ed2..691763d 100644 --- a/P25RX.h +++ b/P25RX.h @@ -47,7 +47,6 @@ private: uint16_t m_bufferPtr; uint16_t m_symbolPtr; uint16_t m_lostCount; - uint16_t m_rssiCount; q15_t m_centre; q15_t m_threshold; diff --git a/YSFRX.cpp b/YSFRX.cpp index f820078..cfe4fab 100644 --- a/YSFRX.cpp +++ b/YSFRX.cpp @@ -54,7 +54,6 @@ m_buffer(NULL), m_bufferPtr(0U), m_symbolPtr(0U), m_lostCount(0U), -m_rssiCount(0U), m_centre(0), m_threshold(0) { @@ -70,7 +69,6 @@ void CYSFRX::reset() m_bufferPtr = 0U; m_symbolPtr = 0U; m_lostCount = 0U; - m_rssiCount = 0U; m_centre = 0; m_threshold = 0; } @@ -164,7 +162,6 @@ void CYSFRX::processNone(q15_t sample) m_lostCount = MAX_SYNC_FRAMES; m_bufferPtr = YSF_SYNC_LENGTH_BITS; m_state = YSFRXS_DATA; - m_rssiCount = 0U; io.setDecode(true); io.setADCDetection(true); @@ -236,23 +233,7 @@ void CYSFRX::processData(q15_t sample) } else { m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; -#if defined(SEND_RSSI_DATA) - // Send RSSI data every second - if (m_rssiCount == 0U) { - uint16_t rssi = io.getRSSIValue(); - m_outBuffer[121U] = (rssi >> 8) & 0xFFU; - m_outBuffer[122U] = (rssi >> 0) & 0xFFU; - serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); - } - - m_rssiCount++; - if (m_rssiCount >= 10U) - m_rssiCount = 0U; -#else serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U); -#endif // Start the next frame ::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); diff --git a/YSFRX.h b/YSFRX.h index 41a8b71..8f8f770 100644 --- a/YSFRX.h +++ b/YSFRX.h @@ -47,7 +47,6 @@ private: uint16_t m_bufferPtr; uint16_t m_symbolPtr; uint16_t m_lostCount; - uint16_t m_rssiCount; q15_t m_centre; q15_t m_threshold; From 970725819b02347312e5e2633844d888db7f855a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 3 Oct 2016 11:20:35 +0100 Subject: [PATCH 185/329] Allow idle P25 reception. --- IO.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO.cpp b/IO.cpp index 8b92f68..0788d22 100644 --- a/IO.cpp +++ b/IO.cpp @@ -352,7 +352,7 @@ void CIO::process() dstarRX.samples(GMSKVals, blockSize); } - if (m_dmrEnable || m_ysfEnable) { + if (m_dmrEnable || m_ysfEnable || m_p25Enable) { q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); From 02c90e3f7f051318072e5a1bc6ca9a02c9d47058 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 5 Oct 2016 07:54:18 +0100 Subject: [PATCH 186/329] Calculate the P25 transmit space a little more accurately. --- P25TX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/P25TX.cpp b/P25TX.cpp index 8b4ffca..6ad8b3e 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -192,6 +192,6 @@ void CP25TX::setTXDelay(uint8_t delay) uint16_t CP25TX::getSpace() const { - return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES; + return m_buffer.getSpace() / (P25_LDU_FRAME_LENGTH_BYTES + 1U); } From ec20831a3cdfc20a1f15b9e03806a4c55973f144 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 5 Oct 2016 09:15:48 +0100 Subject: [PATCH 187/329] Revert the P25 transmitter length calculation. --- P25TX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index 6ad8b3e..55fc64d 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -192,6 +192,5 @@ void CP25TX::setTXDelay(uint8_t delay) uint16_t CP25TX::getSpace() const { - return m_buffer.getSpace() / (P25_LDU_FRAME_LENGTH_BYTES + 1U); + return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES; } - From f8d9c881ff4a17ef7d194dd8eec0082f2edc3d67 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 6 Oct 2016 18:40:43 +0100 Subject: [PATCH 188/329] Allow the modem to host serial displays. --- Config.h | 5 ++++- SerialPort.cpp | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Config.h b/Config.h index 7a6877f..043f0db 100644 --- a/Config.h +++ b/Config.h @@ -22,7 +22,7 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // For 12 MHz -// #define EXTERNAL_OSC 12000000 +#define EXTERNAL_OSC 12000000 // For 14.4 MHz // #define EXTERNAL_OSC 14400000 // For 19.2 MHz @@ -51,5 +51,8 @@ // Pass RSSI information to the host // #define SEND_RSSI_DATA +// Use the modem as a serial repeater for Nextion displays +// #define SERIAL_REPEATER + #endif diff --git a/SerialPort.cpp b/SerialPort.cpp index 529f5dd..706536c 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -59,6 +59,8 @@ const uint8_t MMDVM_P25_LOST = 0x32U; const uint8_t MMDVM_ACK = 0x70U; const uint8_t MMDVM_NAK = 0x7FU; +const uint8_t MMDVM_SERIAL = 0x80U; + const uint8_t MMDVM_DEBUG1 = 0xF1U; const uint8_t MMDVM_DEBUG2 = 0xF2U; const uint8_t MMDVM_DEBUG3 = 0xF3U; @@ -386,6 +388,10 @@ void CSerialPort::start() m_serial.baud(115200); #else Serial.begin(115200); + +#if defined(SERIAL_REPEATER) + Serial3.begin(9600); +#endif #endif } @@ -632,6 +638,12 @@ void CSerialPort::process() } break; +#if defined(SERIAL_REPEATER) + case MMDVM_SERIAL: + Serial3.write(m_buffer + 3U, m_len - 3U); + break; +#endif + default: // Handle this, send a NAK back sendNAK(1U); @@ -643,6 +655,12 @@ void CSerialPort::process() } } } + +#if defined(SERIAL_REPEATER) + // Drain any incoming serial data + while (Serial3.available()) + Serial3.read(); +#endif } void CSerialPort::writeDStarHeader(const uint8_t* header, uint8_t length) From 1e0634c0b1530d556c19ba2072e14fdda4363bda Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 10 Oct 2016 17:26:31 +0100 Subject: [PATCH 189/329] Reduce level of the CW Id. --- CWIdTX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index 8f69311..97a2ce4 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -24,7 +24,7 @@ #include "CWIdTX.h" q15_t TONE[] = { - 0, 647, 1250, 1767, 2165, 2415, 2500, 2415, 2165, 1767, 1250, 647, 0, -647, -1250, -1767, -2165, -2415, -2500, -2415, -2165, -1767, -1250, -647}; + 0, 518, 1000, 1414, 1732, 1932, 2000, 1932, 1732, 1414, 1000, 518, 0, -518, -1000, -1414, -1732, -1932, -2000, -1932, -1732, -1414, -1000, -518}; q15_t SILENCE[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; From 3ef9e401371878bd624742cd6a52d5465fe1e765 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 10 Oct 2016 17:35:33 +0100 Subject: [PATCH 190/329] Allow for adjustable CW Id levels. --- CWIdTX.cpp | 4 ++-- Config.h | 2 +- Globals.h | 3 +++ IO.cpp | 9 +++++++-- IO.h | 3 ++- SerialPort.cpp | 3 ++- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/CWIdTX.cpp b/CWIdTX.cpp index 97a2ce4..0613772 100644 --- a/CWIdTX.cpp +++ b/CWIdTX.cpp @@ -104,9 +104,9 @@ void CCWIdTX::process() while (space > CYCLE_LENGTH) { bool b = READ_BIT1(m_poBuffer, m_poPtr); if (b) - io.write(STATE_DSTAR, TONE, CYCLE_LENGTH); + io.write(STATE_CWID, TONE, CYCLE_LENGTH); else - io.write(STATE_DSTAR, SILENCE, CYCLE_LENGTH); + io.write(STATE_CWID, SILENCE, CYCLE_LENGTH); space -= CYCLE_LENGTH; diff --git a/Config.h b/Config.h index 043f0db..d61abce 100644 --- a/Config.h +++ b/Config.h @@ -52,7 +52,7 @@ // #define SEND_RSSI_DATA // Use the modem as a serial repeater for Nextion displays -// #define SERIAL_REPEATER +#define SERIAL_REPEATER #endif diff --git a/Globals.h b/Globals.h index 7888891..b9ffe97 100644 --- a/Globals.h +++ b/Globals.h @@ -40,6 +40,9 @@ enum MMDVM_STATE { STATE_DMR = 2, STATE_YSF = 3, STATE_P25 = 4, + + // Dummy states start at 90 + STATE_CWID = 97, STATE_DMRCAL = 98, STATE_DSTARCAL = 99 }; diff --git a/IO.cpp b/IO.cpp index 0788d22..4ea26c0 100644 --- a/IO.cpp +++ b/IO.cpp @@ -125,6 +125,7 @@ m_C4FSKState(), m_GMSKState(), m_pttInvert(false), m_rxLevel(128 * 128), +m_cwIdTXLevel(128 * 128), m_dstarTXLevel(128 * 128), m_dmrTXLevel(128 * 128), m_ysfTXLevel(128 * 128), @@ -434,6 +435,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t q15_t txLevel = 0; switch (mode) { + case STATE_DSTAR: + txLevel = m_dstarTXLevel; + break; case STATE_DMR: txLevel = m_dmrTXLevel; break; @@ -444,7 +448,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t txLevel = m_p25TXLevel; break; default: - txLevel = m_dstarTXLevel; + txLevel = m_cwIdTXLevel; break; } @@ -546,11 +550,12 @@ switch (m_modemState) { #endif } -void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel) +void CIO::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) { m_pttInvert = pttInvert; m_rxLevel = q15_t(rxLevel * 128); + m_cwIdTXLevel = q15_t(cwIdTXLevel * 128); m_dstarTXLevel = q15_t(dstarTXLevel * 128); m_dmrTXLevel = q15_t(dmrTXLevel * 128); m_ysfTXLevel = q15_t(ysfTXLevel * 128); diff --git a/IO.h b/IO.h index 910853c..6cb37cc 100644 --- a/IO.h +++ b/IO.h @@ -41,7 +41,7 @@ public: void interrupt(); - void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel); + 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); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -81,6 +81,7 @@ private: bool m_pttInvert; q15_t m_rxLevel; + q15_t m_cwIdTXLevel; q15_t m_dstarTXLevel; q15_t m_dmrTXLevel; q15_t m_ysfTXLevel; diff --git a/SerialPort.cpp b/SerialPort.cpp index 706536c..9384d6d 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -257,6 +257,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) m_sampleInsert = false; } + uint8_t cwIdTXLevel = data[5U]; uint8_t dstarTXLevel = data[9U]; uint8_t dmrTXLevel = data[10U]; uint8_t ysfTXLevel = data[11U]; @@ -281,7 +282,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) dmrDMORX.setColorCode(colorCode); dmrIdleRX.setColorCode(colorCode); - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel); io.start(); From fd3a32c601bce9bbe537e4711aec252fde2667d7 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 10 Oct 2016 19:53:43 +0100 Subject: [PATCH 191/329] Update configuration script. --- mmdvmmenu.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 672b9ad..87b113c 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -69,7 +69,8 @@ do (6) Use layout for the PAPA board (7) Use layout for ZUM board V1.0 and V1.2 (8) Use layout for SP8NTH board - (9) Return to Default + (9) Use modem as display driver + (A) Return to Default (Q)uit --------------------------------------------------------------- @@ -84,7 +85,9 @@ EOF "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 and V1.2 enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; - "9") mv -f $confbak $conf ;; + "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; + "A") mv -f $confbak $conf ;; + "a") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; "q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; * ) echo "invalid option" ;; From 67c976d4d4611c29f73bfce56223417d24f22577 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 11 Oct 2016 08:17:20 +0100 Subject: [PATCH 192/329] Reset the P25 TX levels based on DMR. --- P25TX.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index 55fc64d..2244389 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -46,11 +46,10 @@ static q15_t P25_LP_FILTER[] = {170, 401, 340, -203, -715, -478, 281, 419, -440, 281, -478, -715, -203, 340, 401, 170}; const uint16_t P25_LP_FILTER_LEN = 44U; -// XXX These will need setting correctly -const q15_t P25_LEVELA[] = { 539, 539, 539, 539, 539}; -const q15_t P25_LEVELB[] = { 179, 179, 179, 179, 179}; -const q15_t P25_LEVELC[] = {-179, -179, -179, -179, -179}; -const q15_t P25_LEVELD[] = {-539, -539, -539, -539, -539}; +const q15_t P25_LEVELA[] = { 594, 594, 594, 594, 594}; +const q15_t P25_LEVELB[] = { 198, 198, 198, 198, 198}; +const q15_t P25_LEVELC[] = {-198, -198, -198, -198, -198}; +const q15_t P25_LEVELD[] = {-594, -594, -594, -594, -594}; const uint8_t P25_START_SYNC = 0x77U; From 100ee70a3869eaab713f6659e39120bf63fd4835 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 13 Oct 2016 17:55:37 +0100 Subject: [PATCH 193/329] Add the ZUM V1.2 pin layout. --- Config.h | 3 +++ IO.cpp | 17 +++++++++++++++-- mmdvmmenu.sh | 21 ++++++++++++--------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Config.h b/Config.h index d61abce..ea02eec 100644 --- a/Config.h +++ b/Config.h @@ -40,6 +40,9 @@ // For the ZUM Board V1.0 pin layout #define ARDUINO_DUE_ZUM_V10 +// For the ZUM Board V1.2 pin layout +// #define ARDUINO_DUE_ZUM_V12 + // For the SP8NTH board // #define ARDUINO_DUE_NTH diff --git a/IO.cpp b/IO.cpp index 4ea26c0..69226ba 100644 --- a/IO.cpp +++ b/IO.cpp @@ -62,11 +62,24 @@ const uint16_t DC_OFFSET = 2048U; #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 -#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) (PB20) +#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) #define ADC_ISR_EOC_Chan ADC_ISR_EOC13 #define ADC_CDR_Chan 13 #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 #define DACC_CHER_Chan DACC_CHER_CH1 +#elif defined(ARDUINO_DUE_ZUM_V12) +#define PIN_COS 52 +#define PIN_PTT 23 +#define PIN_COSLED 22 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<10) // ADC on Due pin A8 - Due AD10 - (1 << 10) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC10 +#define ADC_CDR_Chan 10 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 +#define DACC_CHER_Chan DACC_CHER_CH1 #elif defined(ARDUINO_DUE_NTH) #define PIN_COS A7 #define PIN_PTT A8 @@ -81,7 +94,7 @@ const uint16_t DC_OFFSET = 2048U; #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 #else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, ARDUINO_DUE_ZUM_V12, or ARDUINO_DUE_NTH need to be defined" #endif #elif defined(__MBED__) // A generic MBED platform diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 87b113c..101209f 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -67,10 +67,11 @@ do (4) Use the COS to lockout the modem (5) Use pins to output the current mode (6) Use layout for the PAPA board - (7) Use layout for ZUM board V1.0 and V1.2 - (8) Use layout for SP8NTH board - (9) Use modem as display driver - (A) Return to Default + (7) Use layout for ZUM board V1.0 + (8) Use layout for ZUM board V1.2 + (9) Use layout for SP8NTH board + (A) Use modem as display driver + (B) Return to Default (Q)uit --------------------------------------------------------------- @@ -83,11 +84,13 @@ EOF "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 and V1.2 enabled";; - "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; - "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; - "A") mv -f $confbak $conf ;; - "a") mv -f $confbak $conf ;; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 enabled";; + "8") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V12/#define ARDUINO_DUE_ZUM_V12/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.2 enabled";; + "9") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; + "A") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; + "a") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; + "B") mv -f $confbak $conf ;; + "b") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; "q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; * ) echo "invalid option" ;; From c399f81d83120b828599aee7ab2a4c2447488fe3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 16 Oct 2016 15:59:53 +0100 Subject: [PATCH 194/329] Remove the ZUM V1.2 config option, and add to V1.0. --- Config.h | 7 ++----- IO.cpp | 17 ++--------------- mmdvmmenu.sh | 33 +++++++++++++++------------------ 3 files changed, 19 insertions(+), 38 deletions(-) diff --git a/Config.h b/Config.h index ea02eec..c7b73cd 100644 --- a/Config.h +++ b/Config.h @@ -37,11 +37,8 @@ // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA -// For the ZUM Board V1.0 pin layout -#define ARDUINO_DUE_ZUM_V10 - -// For the ZUM Board V1.2 pin layout -// #define ARDUINO_DUE_ZUM_V12 +// For the ZUM V1.0 and V1.2 boards pin layout +#define ARDUINO_DUE_ZUM_V10_V12 // For the SP8NTH board // #define ARDUINO_DUE_NTH diff --git a/IO.cpp b/IO.cpp index 69226ba..8dcbb22 100644 --- a/IO.cpp +++ b/IO.cpp @@ -54,7 +54,7 @@ const uint16_t DC_OFFSET = 2048U; #define ADC_CDR_Chan 7 #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 -#elif defined(ARDUINO_DUE_ZUM_V10) +#elif defined(ARDUINO_DUE_ZUM_V10_V12) #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -67,19 +67,6 @@ const uint16_t DC_OFFSET = 2048U; #define ADC_CDR_Chan 13 #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 #define DACC_CHER_Chan DACC_CHER_CH1 -#elif defined(ARDUINO_DUE_ZUM_V12) -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 -#define ADC_CHER_Chan (1<<10) // ADC on Due pin A8 - Due AD10 - (1 << 10) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC10 -#define ADC_CDR_Chan 10 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 -#define DACC_CHER_Chan DACC_CHER_CH1 #elif defined(ARDUINO_DUE_NTH) #define PIN_COS A7 #define PIN_PTT A8 @@ -94,7 +81,7 @@ const uint16_t DC_OFFSET = 2048U; #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 #else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, ARDUINO_DUE_ZUM_V12, or ARDUINO_DUE_NTH need to be defined" +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10_V12, or ARDUINO_DUE_NTH need to be defined" #endif #elif defined(__MBED__) // A generic MBED platform diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 101209f..61c38a3 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -67,30 +67,27 @@ do (4) Use the COS to lockout the modem (5) Use pins to output the current mode (6) Use layout for the PAPA board - (7) Use layout for ZUM board V1.0 - (8) Use layout for ZUM board V1.2 - (9) Use layout for SP8NTH board - (A) Use modem as display driver - (B) Return to Default + (7) Use layout for ZUM V1.0 and V1.2 boards + (8) Use layout for SP8NTH board + (9) Use modem as display driver + (A) Return to Default (Q)uit --------------------------------------------------------------- EOF read -n1 -s case "$REPLY" in - "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHz clock enabled";; - "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHz clock enabled";; - "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; - "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; - "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; - "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.0 enabled";; - "8") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V12/#define ARDUINO_DUE_ZUM_V12/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM board V1.2 enabled";; - "9") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; - "A") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; - "a") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; - "B") mv -f $confbak $conf ;; - "b") mv -f $confbak $conf ;; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHz clock enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHz clock enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; + "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; + "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; + "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10_V12/#define ARDUINO_DUE_ZUM_V10_V12/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.2 boards enabled";; + "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; + "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; + "A") mv -f $confbak $conf ;; + "a") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; "q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; * ) echo "invalid option" ;; From 89f6702d70c4a4cf1837e1cf56c30bedcde70d58 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 17 Oct 2016 19:29:09 +0100 Subject: [PATCH 195/329] Reset P25 transmit levels. --- P25TX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index 2244389..8b2b079 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -46,10 +46,10 @@ static q15_t P25_LP_FILTER[] = {170, 401, 340, -203, -715, -478, 281, 419, -440, 281, -478, -715, -203, 340, 401, 170}; const uint16_t P25_LP_FILTER_LEN = 44U; -const q15_t P25_LEVELA[] = { 594, 594, 594, 594, 594}; -const q15_t P25_LEVELB[] = { 198, 198, 198, 198, 198}; -const q15_t P25_LEVELC[] = {-198, -198, -198, -198, -198}; -const q15_t P25_LEVELD[] = {-594, -594, -594, -594, -594}; +const q15_t P25_LEVELA[] = { 539, 539, 539, 539, 539}; +const q15_t P25_LEVELB[] = { 179, 179, 179, 179, 179}; +const q15_t P25_LEVELC[] = {-179, -179, -179, -179, -179}; +const q15_t P25_LEVELD[] = {-539, -539, -539, -539, -539}; const uint8_t P25_START_SYNC = 0x77U; From feef673878befba886ebe7d428964e55653456a4 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 18 Oct 2016 17:53:26 +0100 Subject: [PATCH 196/329] Reset P25 transmit level. --- P25TX.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/P25TX.cpp b/P25TX.cpp index 8b2b079..5eb03be 100644 --- a/P25TX.cpp +++ b/P25TX.cpp @@ -46,10 +46,10 @@ static q15_t P25_LP_FILTER[] = {170, 401, 340, -203, -715, -478, 281, 419, -440, 281, -478, -715, -203, 340, 401, 170}; const uint16_t P25_LP_FILTER_LEN = 44U; -const q15_t P25_LEVELA[] = { 539, 539, 539, 539, 539}; -const q15_t P25_LEVELB[] = { 179, 179, 179, 179, 179}; -const q15_t P25_LEVELC[] = {-179, -179, -179, -179, -179}; -const q15_t P25_LEVELD[] = {-539, -539, -539, -539, -539}; +const q15_t P25_LEVELA[] = { 396, 396, 396, 396, 396}; +const q15_t P25_LEVELB[] = { 132, 132, 132, 132, 132}; +const q15_t P25_LEVELC[] = {-132, -132, -132, -132, -132}; +const q15_t P25_LEVELD[] = {-396, -396, -396, -396, -396}; const uint8_t P25_START_SYNC = 0x77U; From 2238ad524e9f7d48cec8efcc872f7f1858367e96 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 20 Oct 2016 18:26:04 +0100 Subject: [PATCH 197/329] Remove MBED definitions. --- Globals.h | 4 -- IO.cpp | 119 +++++++++++++------------------------------------ IO.h | 12 ----- MMDVM.cpp | 2 +- SampleRB.h | 4 -- SerialPort.cpp | 19 +------- SerialPort.h | 3 -- SerialRB.h | 4 -- Utils.h | 4 -- 9 files changed, 34 insertions(+), 137 deletions(-) diff --git a/Globals.h b/Globals.h index b9ffe97..49b620d 100644 --- a/Globals.h +++ b/Globals.h @@ -19,11 +19,7 @@ #if !defined(GLOBALS_H) #define GLOBALS_H -#if defined(__MBED__) -#include "mbed.h" -#else #include -#endif #if defined(__SAM3X8E__) || defined(__STM32F1__) || defined(__STM32F2__) #define ARM_MATH_CM3 diff --git a/IO.cpp b/IO.cpp index 8dcbb22..531b492 100644 --- a/IO.cpp +++ b/IO.cpp @@ -83,13 +83,6 @@ const uint16_t DC_OFFSET = 2048U; #else #error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10_V12, or ARDUINO_DUE_NTH need to be defined" #endif -#elif defined(__MBED__) -// A generic MBED platform -#define PIN_COS PB_4 // D5 -#define PIN_PTT PA_8 // D7 -#define PIN_COSLED PB_10 // D6 -#define PIN_ADC PA_0 // A0 -#define PIN_DAC PA_4 // A2 #else #error "Unknown hardware type" #endif @@ -100,22 +93,11 @@ extern "C" { #if defined(__SAM3X8E__) if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg io.interrupt(); -#elif defined(__MBED__) - io.interrupt(); #endif } } CIO::CIO() : -#if defined(__MBED__) -m_pinPTT(PIN_PTT), -m_pinCOSLED(PIN_COSLED), -m_pinLED(LED1), -m_pinCOS(PIN_COS), -m_pinADC(PIN_ADC), -m_pinDAC(PIN_DAC), -m_ticker(), -#endif m_started(false), m_rxBuffer(RX_RINGBUFFER_SIZE), m_txBuffer(TX_RINGBUFFER_SIZE), @@ -151,7 +133,6 @@ m_lockout(false) m_GMSKFilter.pState = m_GMSKState; m_GMSKFilter.pCoeffs = GMSK_FILTER; -#if !defined(__MBED__) // Set up the TX, COS and LED pins pinMode(PIN_PTT, OUTPUT); pinMode(PIN_COSLED, OUTPUT); @@ -165,7 +146,6 @@ m_lockout(false) pinMode(PIN_YSF, OUTPUT); pinMode(PIN_P25, OUTPUT); #endif -#endif } void CIO::start() @@ -233,12 +213,6 @@ void CIO::start() digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); -#elif defined(__MBED__) - m_ticker.attach(&ADC_Handler, 1.0 / 24000.0); - - m_pinPTT.write(m_pttInvert ? 1 : 0); - m_pinCOSLED.write(0); - m_pinLED.write(1); #endif m_count = 0U; @@ -266,41 +240,25 @@ void CIO::process() if (m_ledCount >= 24000U) { m_ledCount = 0U; m_ledValue = !m_ledValue; -#if defined(__MBED__) - m_pinLED.write(m_ledValue ? 1 : 0); -#else digitalWrite(PIN_LED, m_ledValue ? HIGH : LOW); -#endif } } else { if (m_ledCount >= 240000U) { m_ledCount = 0U; m_ledValue = !m_ledValue; -#if defined(__MBED__) - m_pinLED.write(m_ledValue ? 1 : 0); -#else digitalWrite(PIN_LED, m_ledValue ? HIGH : LOW); -#endif } return; } #if defined(USE_COS_AS_LOCKOUT) -#if defined(__MBED__) - m_lockout = m_pinCOS.read() == 1; -#else m_lockout = digitalRead(PIN_COS) == HIGH; -#endif #endif // Switch off the transmitter if needed if (m_txBuffer.getData() == 0U && m_tx) { m_tx = false; -#if defined(__MBED__) - m_pinPTT.write(m_pttInvert ? 1 : 0); -#else digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); -#endif } if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { @@ -426,11 +384,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t // Switch the transmitter on if needed if (!m_tx) { m_tx = true; -#if defined(__MBED__) - m_pinPTT.write(m_pttInvert ? 0 : 1); -#else digitalWrite(PIN_PTT, m_pttInvert ? LOW : HIGH); -#endif } q15_t txLevel = 0; @@ -483,9 +437,6 @@ void CIO::interrupt() #if defined(__SAM3X8E__) DACC->DACC_CDR = sample; sample = ADC->ADC_CDR[ADC_CDR_Chan]; -#elif defined(__MBED__) - m_pinDAC.write_u16(sample); - sample = m_pinADC.read_u16(); #endif m_rxBuffer.put(sample, control); @@ -496,11 +447,7 @@ void CIO::interrupt() void CIO::setDecode(bool dcd) { if (dcd != m_dcd) -#if defined(__MBED__) - m_pinCOSLED.write(dcd ? 1 : 0); -#else digitalWrite(PIN_COSLED, dcd ? HIGH : LOW); -#endif m_dcd = dcd; } @@ -512,41 +459,39 @@ void CIO::setADCDetection(bool detect) void CIO::setMode() { -#if !defined(__MBED__) #if defined(ARDUINO_MODE_PINS) -switch (m_modemState) { - case STATE_DSTAR: - digitalWrite(PIN_DSTAR, HIGH); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); - break; - case STATE_DMR: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, HIGH); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); - break; - case STATE_YSF: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, HIGH); - digitalWrite(PIN_P25, LOW); - break; - case STATE_P25: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, HIGH); - break; - default: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); - break; -} -#endif + switch (m_modemState) { + case STATE_DSTAR: + digitalWrite(PIN_DSTAR, HIGH); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); + break; + case STATE_DMR: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, HIGH); + digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); + break; + case STATE_YSF: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, HIGH); + digitalWrite(PIN_P25, LOW); + break; + case STATE_P25: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, HIGH); + break; + default: + digitalWrite(PIN_DSTAR, LOW); + digitalWrite(PIN_DMR, LOW); + digitalWrite(PIN_YSF, LOW); + digitalWrite(PIN_P25, LOW); + break; + } #endif } diff --git a/IO.h b/IO.h index 6cb37cc..53321f7 100644 --- a/IO.h +++ b/IO.h @@ -57,18 +57,6 @@ public: #endif private: -#if defined(__MBED__) - DigitalOut m_pinPTT; - DigitalOut m_pinCOSLED; - DigitalOut m_pinLED; - DigitalIn m_pinCOS; - - AnalogIn m_pinADC; - AnalogOut m_pinDAC; - - Ticker m_ticker; -#endif - bool m_started; CSampleRB m_rxBuffer; diff --git a/MMDVM.cpp b/MMDVM.cpp index f99cba6..69f916d 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if defined(__MBED__) +#if defined(notdef) #include "Config.h" #include "Globals.h" diff --git a/SampleRB.h b/SampleRB.h index 73aad36..284a1a5 100644 --- a/SampleRB.h +++ b/SampleRB.h @@ -21,11 +21,7 @@ Boston, MA 02110-1301, USA. #if !defined(SAMPLERB_H) #define SAMPLERB_H -#if defined(__MBED__) -#include "mbed.h" -#else #include -#endif class CSampleRB { public: diff --git a/SerialPort.cpp b/SerialPort.cpp index 9384d6d..3b915a8 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -77,9 +77,6 @@ const uint8_t PROTOCOL_VERSION = 1U; CSerialPort::CSerialPort() : -#if defined(__MBED__) -m_serial(SERIAL_TX, SERIAL_RX), -#endif m_buffer(), m_ptr(0U), m_len(0U) @@ -385,26 +382,17 @@ void CSerialPort::setMode(MMDVM_STATE modemState) void CSerialPort::start() { -#if defined(__MBED__) - m_serial.baud(115200); -#else Serial.begin(115200); #if defined(SERIAL_REPEATER) Serial3.begin(9600); #endif -#endif } void CSerialPort::process() { -#if defined(__MBED__) - while (m_serial.readable()) { - uint8_t c = m_serial.getc(); -#else while (Serial.available()) { uint8_t c = Serial.read(); -#endif if (m_ptr == 0U && c == MMDVM_FRAME_START) { // Handle the frame start correctly @@ -908,15 +896,10 @@ void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) { -#if defined(__MBED__) - for (uint16_t i = 0U; i < length; i++) - m_serial.putc(data[i]); - // No explicit flush function -#else Serial.write(data, length); + if (flush) Serial.flush(); -#endif } void CSerialPort::writeDebug(const char* text) diff --git a/SerialPort.h b/SerialPort.h index d4981e7..e54ee7e 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -57,9 +57,6 @@ public: void writeAssert(bool cond, const char* text, const char* file, long line); private: -#if defined(__MBED__) - Serial m_serial; -#endif uint8_t m_buffer[250U]; uint8_t m_ptr; uint8_t m_len; diff --git a/SerialRB.h b/SerialRB.h index ec6dd4c..ea7421e 100644 --- a/SerialRB.h +++ b/SerialRB.h @@ -21,11 +21,7 @@ Boston, MA 02110-1301, USA. #if !defined(SERIALRB_H) #define SERIALRB_H -#if defined(__MBED__) -#include "mbed.h" -#else #include -#endif const uint16_t SERIAL_RINGBUFFER_SIZE = 370U; diff --git a/Utils.h b/Utils.h index b037ca9..913e9a6 100644 --- a/Utils.h +++ b/Utils.h @@ -19,11 +19,7 @@ #if !defined(UTILS_H) #define UTILS_H -#if defined(__MBED__) -#include "mbed.h" -#else #include -#endif uint8_t countBits8(uint8_t bits); From f7ba767b57fc2968fdc00d8189e717134dbc9772 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 21 Oct 2016 06:56:15 +0100 Subject: [PATCH 198/329] Bump the version date. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index 3b915a8..30ea8b6 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -68,9 +68,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20160906 TCXO (D-Star/DMR/System Fusion/P25/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20161021 TCXO (D-Star/DMR/System Fusion/P25/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20160906 (D-Star/DMR/System Fusion/P25/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20161021 (D-Star/DMR/System Fusion/P25/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From 87414c5e5fc9e0baa5ab3d56716b0b15ba8ede52 Mon Sep 17 00:00:00 2001 From: phl0 Date: Tue, 25 Oct 2016 22:58:06 +0200 Subject: [PATCH 199/329] Disable external TCXO by default --- Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.h b/Config.h index c7b73cd..0c6b22c 100644 --- a/Config.h +++ b/Config.h @@ -22,7 +22,7 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // For 12 MHz -#define EXTERNAL_OSC 12000000 +// #define EXTERNAL_OSC 12000000 // For 14.4 MHz // #define EXTERNAL_OSC 14400000 // For 19.2 MHz From d3a3d51e77dcbb45df25c12d5354a9b2d13972b8 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 26 Oct 2016 10:05:49 +0200 Subject: [PATCH 200/329] Add note from Colin, G4ELM to Config.h --- Config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Config.h b/Config.h index 0c6b22c..f12e1a0 100644 --- a/Config.h +++ b/Config.h @@ -21,6 +21,11 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. +// +// The frequency of the TCXO must be an integer multiple of 24000. +// Frequencies such as 12.0 Mhz (24000 * 500) and 14.4 Mhz ( 24000 *600) are suitable. +// Frequencies such as 10.0 Mhz (24000 * 416.666) or 20 Mhz (24000 * 833.333) are not suitable. +// // For 12 MHz // #define EXTERNAL_OSC 12000000 // For 14.4 MHz From 3045fd408dd2b5a36f72a55b60296ae602f083b4 Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 26 Oct 2016 10:06:56 +0200 Subject: [PATCH 201/329] Add P25 to supported modes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cb145fc..fd13ce8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This is the source code of the MMDVM firmware that supports D-Star, DMR, and System Fusion. +This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25. Currently it only runs on the Arduino Due, but other platforms are planned. From 6f07eedebcb45f1c7d4631d87a6fea33ff132d1b Mon Sep 17 00:00:00 2001 From: phl0 Date: Sun, 30 Oct 2016 22:51:07 +0100 Subject: [PATCH 202/329] Correct spaces in order to make mmdvmmenu.sh work (again) --- Config.h | 6 +++--- mmdvmmenu.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Config.h b/Config.h index f12e1a0..28bcc03 100644 --- a/Config.h +++ b/Config.h @@ -40,13 +40,13 @@ // #define ARDUINO_MODE_PINS // For the original Arduino Due pin layout -// #define ARDUINO_DUE_PAPA +// #define ARDUINO_DUE_PAPA // For the ZUM V1.0 and V1.2 boards pin layout -#define ARDUINO_DUE_ZUM_V10_V12 +#define ARDUINO_DUE_ZUM_V10_V12 // For the SP8NTH board -// #define ARDUINO_DUE_NTH +// #define ARDUINO_DUE_NTH // To use wider C4FSK filters for DMR, System Fusion and P25 on transmit // #define WIDE_C4FSK_FILTERS_TX diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 61c38a3..0fa8b5d 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -82,7 +82,7 @@ EOF "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; - "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; + "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10_V12/#define ARDUINO_DUE_ZUM_V10_V12/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.2 boards enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; From bbe6a8cf077dbc4b703b02dfc05d81f0be78f6d5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 31 Oct 2016 18:21:24 +0000 Subject: [PATCH 203/329] Add 12.288 MHz TCXO option. --- Config.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Config.h b/Config.h index 28bcc03..0947fb2 100644 --- a/Config.h +++ b/Config.h @@ -22,12 +22,14 @@ // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // -// The frequency of the TCXO must be an integer multiple of 24000. -// Frequencies such as 12.0 Mhz (24000 * 500) and 14.4 Mhz ( 24000 *600) are suitable. -// Frequencies such as 10.0 Mhz (24000 * 416.666) or 20 Mhz (24000 * 833.333) are not suitable. +// The frequency of the TCXO must be an integer multiple of 48000. +// Frequencies such as 12.0 Mhz (48000 * 250) and 14.4 Mhz (48000 * 300) are suitable. +// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable. // // For 12 MHz // #define EXTERNAL_OSC 12000000 +// For 12.288 MHz +// #define EXTERNAL_OSC 12288000 // For 14.4 MHz // #define EXTERNAL_OSC 14400000 // For 19.2 MHz From e0ea81bbc942fab89d1baccbd386bc7c297a40a5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 31 Oct 2016 19:18:03 +0000 Subject: [PATCH 204/329] REplace the ZUM V1.2 definitions with V1.0.1 --- Config.h | 6 +++--- IO.cpp | 4 ++-- mmdvmmenu.sh | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Config.h b/Config.h index 0947fb2..3eb0ed4 100644 --- a/Config.h +++ b/Config.h @@ -44,8 +44,8 @@ // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA -// For the ZUM V1.0 and V1.2 boards pin layout -#define ARDUINO_DUE_ZUM_V10_V12 +// For the ZUM V1.0 and V1.0.1 boards pin layout +#define ARDUINO_DUE_ZUM_V10 // For the SP8NTH board // #define ARDUINO_DUE_NTH @@ -59,7 +59,7 @@ // #define SEND_RSSI_DATA // Use the modem as a serial repeater for Nextion displays -#define SERIAL_REPEATER +// #define SERIAL_REPEATER #endif diff --git a/IO.cpp b/IO.cpp index 531b492..1599592 100644 --- a/IO.cpp +++ b/IO.cpp @@ -54,7 +54,7 @@ const uint16_t DC_OFFSET = 2048U; #define ADC_CDR_Chan 7 #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 -#elif defined(ARDUINO_DUE_ZUM_V10_V12) +#elif defined(ARDUINO_DUE_ZUM_V10) #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -81,7 +81,7 @@ const uint16_t DC_OFFSET = 2048U; #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 #define DACC_CHER_Chan DACC_CHER_CH0 #else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10_V12, or ARDUINO_DUE_NTH need to be defined" +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" #endif #else #error "Unknown hardware type" diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 0fa8b5d..5ed9413 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -67,7 +67,7 @@ do (4) Use the COS to lockout the modem (5) Use pins to output the current mode (6) Use layout for the PAPA board - (7) Use layout for ZUM V1.0 and V1.2 boards + (7) Use layout for ZUM V1.0 and V1.0.1 boards (8) Use layout for SP8NTH board (9) Use modem as display driver (A) Return to Default @@ -83,7 +83,7 @@ EOF "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10_V12/#define ARDUINO_DUE_ZUM_V10_V12/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.2 boards enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.0.1 boards enabled";; "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; "A") mv -f $confbak $conf ;; From ba969d85d025ba584979ec1eb61aea9cef65d462 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 31 Oct 2016 19:39:32 +0000 Subject: [PATCH 205/329] Add dummy RSSI sampling code. --- DMRDMORX.cpp | 13 +++---- DMRDMORX.h | 4 +- DMRRX.cpp | 6 +-- DMRRX.h | 2 +- DMRSlotRX.cpp | 9 ++--- DMRSlotRX.h | 2 +- IO.cpp | 20 +++++----- IO.h | 6 +-- RSSIRB.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ RSSIRB.h | 50 ++++++++++++++++++++++++ 10 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 RSSIRB.cpp create mode 100644 RSSIRB.h diff --git a/DMRDMORX.cpp b/DMRDMORX.cpp index 90003f1..5eefa23 100644 --- a/DMRDMORX.cpp +++ b/DMRDMORX.cpp @@ -76,17 +76,17 @@ void CDMRDMORX::reset() m_rssiCount = 0U; } -void CDMRDMORX::samples(const q15_t* samples, uint8_t length) +void CDMRDMORX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) { bool dcd = false; for (uint8_t i = 0U; i < length; i++) - dcd = processSample(samples[i]); + dcd = processSample(samples[i], rssi[i]); io.setDecode(dcd); } -bool CDMRDMORX::processSample(q15_t sample) +bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi) { m_buffer[m_dataPtr] = sample; @@ -97,11 +97,10 @@ bool CDMRDMORX::processSample(q15_t sample) if (m_state == DMORXS_NONE) { correlateSync(true); } else { -#if defined(SEND_RSSI_DATA) // Grab the RSSI data during the frame - if (m_state == DMORXS_VOICE && m_dataPtr == m_syncPtr && m_rssiCount == 2U) - m_rssi = io.getRSSIValue(); -#endif + if (m_state == DMORXS_VOICE && m_dataPtr == m_syncPtr) + m_rssi = rssi; + uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_SAMPLES - 1U; uint16_t max = m_syncPtr + 1U; diff --git a/DMRDMORX.h b/DMRDMORX.h index 138333d..1049fd1 100644 --- a/DMRDMORX.h +++ b/DMRDMORX.h @@ -34,7 +34,7 @@ class CDMRDMORX { public: CDMRDMORX(); - void samples(const q15_t* samples, uint8_t length); + void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length); void setColorCode(uint8_t colorCode); @@ -61,7 +61,7 @@ private: uint16_t m_rssiCount; uint16_t m_rssi; - bool processSample(q15_t sample); + 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); }; diff --git a/DMRRX.cpp b/DMRRX.cpp index 9137b94..64320e8 100644 --- a/DMRRX.cpp +++ b/DMRRX.cpp @@ -26,7 +26,7 @@ m_slot2RX(true) { } -void CDMRRX::samples(const q15_t* samples, const uint8_t* control, uint8_t length) +void CDMRRX::samples(const q15_t* samples, const uint16_t* rssi, const uint8_t* control, uint8_t length) { bool dcd1 = false; bool dcd2 = false; @@ -43,8 +43,8 @@ void CDMRRX::samples(const q15_t* samples, const uint8_t* control, uint8_t lengt break; } - dcd1 = m_slot1RX.processSample(samples[i]); - dcd2 = m_slot2RX.processSample(samples[i]); + dcd1 = m_slot1RX.processSample(samples[i], rssi[i]); + dcd2 = m_slot2RX.processSample(samples[i], rssi[i]); } io.setDecode(dcd1 || dcd2); diff --git a/DMRRX.h b/DMRRX.h index 2f8810d..6c99cd0 100644 --- a/DMRRX.h +++ b/DMRRX.h @@ -26,7 +26,7 @@ class CDMRRX { public: CDMRRX(); - void samples(const q15_t* samples, const uint8_t* control, uint8_t length); + void samples(const q15_t* samples, const uint16_t* rssi, const uint8_t* control, uint8_t length); void setColorCode(uint8_t colorCode); void setDelay(uint8_t delay); diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 58ad5d4..6abe38d 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -94,7 +94,7 @@ void CDMRSlotRX::reset() m_rssiCount = 0U; } -bool CDMRSlotRX::processSample(q15_t sample) +bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) { m_delayPtr++; if (m_delayPtr < m_delay) @@ -114,11 +114,10 @@ bool CDMRSlotRX::processSample(q15_t sample) if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END) correlateSync(true); } else { -#if defined(SEND_RSSI_DATA) // Grab the RSSI data during the frame - if (m_state == DMRRXS_VOICE && m_dataPtr == m_startPtr && m_rssiCount == 2U) - m_rssi = io.getRSSIValue(); -#endif + if (m_state == DMRRXS_VOICE && m_dataPtr == m_syncPtr) + m_rssi = rssi; + uint16_t min = m_syncPtr - 1U; uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 12482d0..7be5552 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -34,7 +34,7 @@ public: void start(); - bool processSample(q15_t sample); + bool processSample(q15_t sample, uint16_t rssi); void setColorCode(uint8_t colorCode); void setDelay(uint8_t delay); diff --git a/IO.cpp b/IO.cpp index 1599592..233c950 100644 --- a/IO.cpp +++ b/IO.cpp @@ -101,6 +101,7 @@ CIO::CIO() : m_started(false), m_rxBuffer(RX_RINGBUFFER_SIZE), m_txBuffer(TX_RINGBUFFER_SIZE), +m_rssiBuffer(RX_RINGBUFFER_SIZE), m_C4FSKFilter(), m_GMSKFilter(), m_C4FSKState(), @@ -262,14 +263,16 @@ void CIO::process() } if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { - q15_t samples[RX_BLOCK_SIZE + 1U]; - uint8_t control[RX_BLOCK_SIZE + 1U]; + q15_t samples[RX_BLOCK_SIZE + 1U]; + uint8_t control[RX_BLOCK_SIZE + 1U]; + uint16_t rssi[RX_BLOCK_SIZE + 1U]; uint8_t blockSize = RX_BLOCK_SIZE; for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) { uint16_t sample; m_rxBuffer.get(sample, control[i]); + m_rssiBuffer.get(rssi[i]); // Detect ADC overflow if (m_detect && (sample == 0U || sample == 4095U)) @@ -319,7 +322,7 @@ void CIO::process() if (m_duplex) dmrIdleRX.samples(C4FSKVals, blockSize); else - dmrDMORX.samples(C4FSKVals, blockSize); + dmrDMORX.samples(C4FSKVals, rssi, blockSize); } if (m_ysfEnable) @@ -343,11 +346,11 @@ void CIO::process() if (m_duplex) { // If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs if (m_tx) - dmrRX.samples(C4FSKVals, control, blockSize); + dmrRX.samples(C4FSKVals, rssi, control, blockSize); else dmrIdleRX.samples(C4FSKVals, blockSize); } else { - dmrDMORX.samples(C4FSKVals, blockSize); + dmrDMORX.samples(C4FSKVals, rssi, blockSize); } } } else if (m_modemState == STATE_YSF) { @@ -440,6 +443,7 @@ void CIO::interrupt() #endif m_rxBuffer.put(sample, control); + m_rssiBuffer.put(0U); m_watchdog++; } @@ -551,9 +555,3 @@ bool CIO::hasLockout() const return m_lockout; } -#if defined(SEND_RSSI_DATA) -uint16_t CIO::getRSSIValue() -{ - return 0U; -} -#endif diff --git a/IO.h b/IO.h index 53321f7..a8f9c7e 100644 --- a/IO.h +++ b/IO.h @@ -22,6 +22,7 @@ #include "Globals.h" #include "SampleRB.h" +#include "RSSIRB.h" class CIO { public: @@ -52,15 +53,12 @@ public: void resetWatchdog(); -#if defined(SEND_RSSI_DATA) - uint16_t getRSSIValue(); -#endif - private: bool m_started; CSampleRB m_rxBuffer; CSampleRB m_txBuffer; + CRSSIRB m_rssiBuffer; arm_fir_instance_q15 m_C4FSKFilter; arm_fir_instance_q15 m_GMSKFilter; diff --git a/RSSIRB.cpp b/RSSIRB.cpp new file mode 100644 index 0000000..98a519b --- /dev/null +++ b/RSSIRB.cpp @@ -0,0 +1,104 @@ +/* +TX fifo control - Copyright (C) KI6ZUM 2015 +Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include "RSSIRB.h" + +CRSSIRB::CRSSIRB(uint16_t length) : +m_length(length), +m_rssi(NULL), +m_head(0U), +m_tail(0U), +m_full(false), +m_overflow(false) +{ + m_rssi = new uint16_t[length]; +} + +uint16_t CRSSIRB::getSpace() const +{ + uint16_t n = 0U; + + if (m_tail == m_head) + n = m_full ? 0U : m_length; + else if (m_tail < m_head) + n = m_length - m_head + m_tail; + else + n = m_tail - m_head; + + if (n > m_length) + n = 0U; + + return n; +} + +uint16_t CRSSIRB::getData() const +{ + if (m_tail == m_head) + return m_full ? m_length : 0U; + else if (m_tail < m_head) + return m_head - m_tail; + else + return m_length - m_tail + m_head; +} + +bool CRSSIRB::put(uint16_t rssi) +{ + if (m_full) { + m_overflow = true; + return false; + } + + m_rssi[m_head] = rssi; + + m_head++; + if (m_head >= m_length) + m_head = 0U; + + if (m_head == m_tail) + m_full = true; + + return true; +} + +bool CRSSIRB::get(uint16_t& rssi) +{ + if (m_head == m_tail && !m_full) + return false; + + rssi = m_rssi[m_tail]; + + m_full = false; + + m_tail++; + if (m_tail >= m_length) + m_tail = 0U; + + return true; +} + +bool CRSSIRB::hasOverflowed() +{ + bool overflow = m_overflow; + + m_overflow = false; + + return overflow; +} + diff --git a/RSSIRB.h b/RSSIRB.h new file mode 100644 index 0000000..41e6b8c --- /dev/null +++ b/RSSIRB.h @@ -0,0 +1,50 @@ +/* +Serial fifo control - Copyright (C) KI6ZUM 2015 +Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#if !defined(RSSIRB_H) +#define RSSIRB_H + +#include + +class CRSSIRB { +public: + CRSSIRB(uint16_t length); + + uint16_t getSpace() const; + + uint16_t getData() const; + + bool put(uint16_t rssi); + + bool get(uint16_t& rssi); + + bool hasOverflowed(); + +private: + uint16_t m_length; + volatile uint16_t* m_rssi; + volatile uint16_t m_head; + volatile uint16_t m_tail; + volatile bool m_full; + bool m_overflow; +}; + +#endif + From 7aeb1b6371103463ea7532371ff36975fa089ecb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 31 Oct 2016 20:08:35 +0000 Subject: [PATCH 206/329] Abstract Due specific I/O to a seperate file. --- IO.cpp | 196 +++++++------------------------------------------ IO.h | 15 ++++ IODue.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 170 deletions(-) create mode 100644 IODue.cpp diff --git a/IO.cpp b/IO.cpp index 233c950..e1d9f93 100644 --- a/IO.cpp +++ b/IO.cpp @@ -43,60 +43,6 @@ const uint16_t GMSK_FILTER_LEN = 12U; const uint16_t DC_OFFSET = 2048U; -#if defined(__SAM3X8E__) -// An Arduino Due -#if defined(ARDUINO_DUE_PAPA) -#define PIN_COS 7 -#define PIN_PTT 8 -#define PIN_COSLED 11 -#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC7 -#define ADC_CDR_Chan 7 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 -#define DACC_CHER_Chan DACC_CHER_CH0 -#elif defined(ARDUINO_DUE_ZUM_V10) -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 -#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 -#define ADC_CDR_Chan 13 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 -#define DACC_CHER_Chan DACC_CHER_CH1 -#elif defined(ARDUINO_DUE_NTH) -#define PIN_COS A7 -#define PIN_PTT A8 -#define PIN_COSLED A11 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 -#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC7 -#define ADC_CDR_Chan 7 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 -#define DACC_CHER_Chan DACC_CHER_CH0 -#else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" -#endif -#else -#error "Unknown hardware type" -#endif - -extern "C" { - void ADC_Handler() - { -#if defined(__SAM3X8E__) - if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg - io.interrupt(); -#endif - } -} - CIO::CIO() : m_started(false), m_rxBuffer(RX_RINGBUFFER_SIZE), @@ -134,19 +80,7 @@ m_lockout(false) m_GMSKFilter.pState = m_GMSKState; m_GMSKFilter.pCoeffs = GMSK_FILTER; - // Set up the TX, COS and LED pins - pinMode(PIN_PTT, OUTPUT); - pinMode(PIN_COSLED, OUTPUT); - pinMode(PIN_LED, OUTPUT); - pinMode(PIN_COS, INPUT); - -#if defined(ARDUINO_MODE_PINS) - // Set up the mode output pins - pinMode(PIN_DSTAR, OUTPUT); - pinMode(PIN_DMR, OUTPUT); - pinMode(PIN_YSF, OUTPUT); - pinMode(PIN_P25, OUTPUT); -#endif + initInt(); } void CIO::start() @@ -154,67 +88,7 @@ void CIO::start() if (m_started) return; -#if defined(__SAM3X8E__) - if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg - io.interrupt(); - - // Set up the ADC - NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector - ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts - ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt - ADC->ADC_CHDR = 0xFFFF; // Disable all channels - ADC->ADC_CHER = ADC_CHER_Chan; // Enable just one channel - ADC->ADC_CGR = 0x15555555; // All gains set to x1 - ADC->ADC_COR = 0x00000000; // All offsets off - ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 - -#if defined(EXTERNAL_OSC) - // Set up the external clock input on PA4 = AI5 - REG_PIOA_ODR = 0x10; // Set pin as input - REG_PIOA_PDR = 0x10; // Disable PIO A bit 4 - REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input -#endif - - // Set up the timer - pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0 - TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0 - t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs - t->TC_IDR = 0xFFFFFFFF; // Disable interrupts - t->TC_SR; // Read int status reg to clear pending -#if defined(EXTERNAL_OSC) - t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock -#else - t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) -#endif - TC_CMR_WAVE | // Waveform mode - TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold - TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) - TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | - TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; -#if defined(EXTERNAL_OSC) - t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock - t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave -#else - t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock - t->TC_RA = 880; // Roughly square wave -#endif - t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares - t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. - - // Set up the DAC - pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC - DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC - DACC->DACC_MR = - DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 - DACC_MR_USER_SEL_Chan | // Select channel - (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz - DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts - DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel - - digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); - digitalWrite(PIN_COSLED, LOW); - digitalWrite(PIN_LED, HIGH); -#endif + startInt(); m_count = 0U; m_started = true; @@ -253,13 +127,13 @@ void CIO::process() } #if defined(USE_COS_AS_LOCKOUT) - m_lockout = digitalRead(PIN_COS) == HIGH; + m_lockout = getCOSInt(); #endif // Switch off the transmitter if needed if (m_txBuffer.getData() == 0U && m_tx) { m_tx = false; - digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); + setPTTInt(m_pttInvert ? true : false); } if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) { @@ -387,7 +261,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t // Switch the transmitter on if needed if (!m_tx) { m_tx = true; - digitalWrite(PIN_PTT, m_pttInvert ? LOW : HIGH); + setPTTInt(m_pttInvert ? false : true); } q15_t txLevel = 0; @@ -430,28 +304,10 @@ uint16_t CIO::getSpace() const return m_txBuffer.getSpace(); } -void CIO::interrupt() -{ - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; - - m_txBuffer.get(sample, control); - -#if defined(__SAM3X8E__) - DACC->DACC_CDR = sample; - sample = ADC->ADC_CDR[ADC_CDR_Chan]; -#endif - - m_rxBuffer.put(sample, control); - m_rssiBuffer.put(0U); - - m_watchdog++; -} - void CIO::setDecode(bool dcd) { if (dcd != m_dcd) - digitalWrite(PIN_COSLED, dcd ? HIGH : LOW); + setCOSInt(dcd ? true : false); m_dcd = dcd; } @@ -466,34 +322,34 @@ void CIO::setMode() #if defined(ARDUINO_MODE_PINS) switch (m_modemState) { case STATE_DSTAR: - digitalWrite(PIN_DSTAR, HIGH); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); + setDStarInt(true); + setDMRInt(false); + setYSFInt(false); + setP25Int(false); break; case STATE_DMR: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, HIGH); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); + setDStarInt(false); + setDMRInt(true); + setYSFInt(false); + setP25Int(false); break; case STATE_YSF: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, HIGH); - digitalWrite(PIN_P25, LOW); + setDStarInt(false); + setDMRInt(false); + setYSFInt(true); + setP25Int(false); break; case STATE_P25: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, HIGH); + setDStarInt(false); + setDMRInt(false); + setYSFInt(false); + setP25Int(true); break; default: - digitalWrite(PIN_DSTAR, LOW); - digitalWrite(PIN_DMR, LOW); - digitalWrite(PIN_YSF, LOW); - digitalWrite(PIN_P25, LOW); + setDStarInt(false); + setDMRInt(false); + setYSFInt(false); + setP25Int(false); break; } #endif diff --git a/IO.h b/IO.h index a8f9c7e..9e4dced 100644 --- a/IO.h +++ b/IO.h @@ -87,6 +87,21 @@ private: volatile uint32_t m_watchdog; bool m_lockout; + + // Hardware specific routines + void initInt(); + void startInt(); + + bool getCOSInt(); + + void setLEDInt(bool on); + void setPTTInt(bool on); + void setCOSInt(bool on); + + void setDStarInt(bool on); + void setDMRInt(bool on); + void setYSFInt(bool on); + void setP25Int(bool on); }; #endif diff --git a/IODue.cpp b/IODue.cpp new file mode 100644 index 0000000..5fb4983 --- /dev/null +++ b/IODue.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM + * Copyright (C) 2016 by Colin Durbridge G4EML + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" +#include "IO.h" + +#if defined(__SAM3X8E__) + +// An Arduino Due +#if defined(ARDUINO_DUE_PAPA) +#define PIN_COS 7 +#define PIN_PTT 8 +#define PIN_COSLED 11 +#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC7 +#define ADC_CDR_Chan 7 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 +#define DACC_CHER_Chan DACC_CHER_CH0 +#elif defined(ARDUINO_DUE_ZUM_V10) +#define PIN_COS 52 +#define PIN_PTT 23 +#define PIN_COSLED 22 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 +#define ADC_CDR_Chan 13 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 +#define DACC_CHER_Chan DACC_CHER_CH1 +#elif defined(ARDUINO_DUE_NTH) +#define PIN_COS A7 +#define PIN_PTT A8 +#define PIN_COSLED A11 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC7 +#define ADC_CDR_Chan 7 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0 +#define DACC_CHER_Chan DACC_CHER_CH0 +#else +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" +#endif + +const uint16_t DC_OFFSET = 2048U; + +extern "C" { + void ADC_Handler() + { + if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg + io.interrupt(); + } +} + +void CIO::initInt() +{ + // Set up the TX, COS and LED pins + pinMode(PIN_PTT, OUTPUT); + pinMode(PIN_COSLED, OUTPUT); + pinMode(PIN_LED, OUTPUT); + pinMode(PIN_COS, INPUT); + +#if defined(ARDUINO_MODE_PINS) + // Set up the mode output pins + pinMode(PIN_DSTAR, OUTPUT); + pinMode(PIN_DMR, OUTPUT); + pinMode(PIN_YSF, OUTPUT); + pinMode(PIN_P25, OUTPUT); +#endif +} + +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(); + + // Set up the ADC + NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector + ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts + ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt + ADC->ADC_CHDR = 0xFFFF; // Disable all channels + ADC->ADC_CHER = ADC_CHER_Chan; // Enable just one channel + ADC->ADC_CGR = 0x15555555; // All gains set to x1 + ADC->ADC_COR = 0x00000000; // All offsets off + ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 + +#if defined(EXTERNAL_OSC) + // Set up the external clock input on PA4 = AI5 + REG_PIOA_ODR = 0x10; // Set pin as input + REG_PIOA_PDR = 0x10; // Disable PIO A bit 4 + REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input +#endif + + // Set up the timer + pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0 + TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0 + t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs + t->TC_IDR = 0xFFFFFFFF; // Disable interrupts + t->TC_SR; // Read int status reg to clear pending +#if defined(EXTERNAL_OSC) + t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock +#else + t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) +#endif + TC_CMR_WAVE | // Waveform mode + TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold + TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) + TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | + TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; +#if defined(EXTERNAL_OSC) + t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock + t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave +#else + t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock + t->TC_RA = 880; // Roughly square wave +#endif + t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares + t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. + + // Set up the DAC + pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC + DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC + DACC->DACC_MR = + DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 + DACC_MR_USER_SEL_Chan | // Select channel + (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz + DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts + DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel + + digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); + digitalWrite(PIN_COSLED, LOW); + digitalWrite(PIN_LED, HIGH); +} + +void CIO::interrupt() +{ + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; + + m_txBuffer.get(sample, control); + + DACC->DACC_CDR = sample; + sample = ADC->ADC_CDR[ADC_CDR_Chan]; + + m_rxBuffer.put(sample, control); + m_rssiBuffer.put(0U); + + m_watchdog++; +} + +bool CIO::getCOSInt() +{ + return digitalRead(PIN_COS) == HIGH; +} + +void CIO::setLEDInt(bool on) +{ + digitalWrite(PIN_LED, on ? HIGH : LOW); +} + +void CIO::setPTTInt(bool on) +{ + digitalWrite(PIN_PTT, on ? LOW : HIGH); +} + +void CIO::setCOSInt(bool on) +{ + digitalWrite(PIN_COSLED, on ? HIGH : LOW); +} + +void CIO::setDStarInt(bool on) +{ + digitalWrite(PIN_DSTAR, on ? HIGH : LOW); +} + +void CIO::setDMRInt(bool on) +{ + digitalWrite(PIN_DMR, on ? HIGH : LOW); +} + +void CIO::setYSFInt(bool on) +{ + digitalWrite(PIN_YSF, on ? HIGH : LOW); +} + +void CIO::setP25Int(bool on) +{ + digitalWrite(PIN_P25, on ? HIGH : LOW); +} + +#endif + From d70fb4f0f91c9e7399dea6f55cfe9ad903857a0f Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 31 Oct 2016 20:16:33 +0000 Subject: [PATCH 207/329] Placeholder for Teensy support. --- IOTeensy.cpp | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 IOTeensy.cpp diff --git a/IOTeensy.cpp b/IOTeensy.cpp new file mode 100644 index 0000000..4c5c4d8 --- /dev/null +++ b/IOTeensy.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" +#include "IO.h" + +#if defined(__MK20DX256__) || defined(__MK66DX1024__) + +// A Teensy 3.1/3.2 +#if defined(__MK20DX256__) +#define PIN_COS 52 +#define PIN_PTT 23 +#define PIN_COSLED 22 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 +#define ADC_CDR_Chan 13 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 +#define DACC_CHER_Chan DACC_CHER_CH1 + +// A Teensy 3.6?? +#elif defined(__MK66DX1024__) +#define PIN_COS 52 +#define PIN_PTT 23 +#define PIN_COSLED 22 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 +#define ADC_CDR_Chan 13 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 +#define DACC_CHER_Chan DACC_CHER_CH1 + +#else +#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" +#endif + +const uint16_t DC_OFFSET = 2048U; + +extern "C" { + void ADC_Handler() + { + if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg + io.interrupt(); + } +} + +void CIO::initInt() +{ + // Set up the TX, COS and LED pins + pinMode(PIN_PTT, OUTPUT); + pinMode(PIN_COSLED, OUTPUT); + pinMode(PIN_LED, OUTPUT); + pinMode(PIN_COS, INPUT); + +#if defined(ARDUINO_MODE_PINS) + // Set up the mode output pins + pinMode(PIN_DSTAR, OUTPUT); + pinMode(PIN_DMR, OUTPUT); + pinMode(PIN_YSF, OUTPUT); + pinMode(PIN_P25, OUTPUT); +#endif +} + +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(); + + // Set up the ADC + NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector + ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts + ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt + ADC->ADC_CHDR = 0xFFFF; // Disable all channels + ADC->ADC_CHER = ADC_CHER_Chan; // Enable just one channel + ADC->ADC_CGR = 0x15555555; // All gains set to x1 + ADC->ADC_COR = 0x00000000; // All offsets off + ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 + +#if defined(EXTERNAL_OSC) + // Set up the external clock input on PA4 = AI5 + REG_PIOA_ODR = 0x10; // Set pin as input + REG_PIOA_PDR = 0x10; // Disable PIO A bit 4 + REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input +#endif + + // Set up the timer + pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0 + TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0 + t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs + t->TC_IDR = 0xFFFFFFFF; // Disable interrupts + t->TC_SR; // Read int status reg to clear pending +#if defined(EXTERNAL_OSC) + t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock +#else + t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) +#endif + TC_CMR_WAVE | // Waveform mode + TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold + TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) + TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | + TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; +#if defined(EXTERNAL_OSC) + t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock + t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave +#else + t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock + t->TC_RA = 880; // Roughly square wave +#endif + t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares + t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. + + // Set up the DAC + pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC + DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC + DACC->DACC_MR = + DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 + DACC_MR_USER_SEL_Chan | // Select channel + (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz + DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts + DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel + + digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); + digitalWrite(PIN_COSLED, LOW); + digitalWrite(PIN_LED, HIGH); +} + +void CIO::interrupt() +{ + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; + + m_txBuffer.get(sample, control); + + DACC->DACC_CDR = sample; + sample = ADC->ADC_CDR[ADC_CDR_Chan]; + + m_rxBuffer.put(sample, control); + m_rssiBuffer.put(0U); + + m_watchdog++; +} + +bool CIO::getCOSInt() +{ + return digitalRead(PIN_COS) == HIGH; +} + +void CIO::setLEDInt(bool on) +{ + digitalWrite(PIN_LED, on ? HIGH : LOW); +} + +void CIO::setPTTInt(bool on) +{ + digitalWrite(PIN_PTT, on ? LOW : HIGH); +} + +void CIO::setCOSInt(bool on) +{ + digitalWrite(PIN_COSLED, on ? HIGH : LOW); +} + +void CIO::setDStarInt(bool on) +{ + digitalWrite(PIN_DSTAR, on ? HIGH : LOW); +} + +void CIO::setDMRInt(bool on) +{ + digitalWrite(PIN_DMR, on ? HIGH : LOW); +} + +void CIO::setYSFInt(bool on) +{ + digitalWrite(PIN_YSF, on ? HIGH : LOW); +} + +void CIO::setP25Int(bool on) +{ + digitalWrite(PIN_P25, on ? HIGH : LOW); +} + +#endif + From 959cb7f32e5abed8345a3bf3bf6c17ec27306caa Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 1 Nov 2016 18:00:53 +0000 Subject: [PATCH 208/329] Cleanups and bug fixes. --- IODue.cpp | 4 ++-- IOTeensy.cpp | 33 +++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/IODue.cpp b/IODue.cpp index 5fb4983..85d039a 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -143,7 +143,7 @@ void CIO::startInt() pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC DACC->DACC_MR = - DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 + DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 DACC_MR_USER_SEL_Chan | // Select channel (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts @@ -182,7 +182,7 @@ void CIO::setLEDInt(bool on) void CIO::setPTTInt(bool on) { - digitalWrite(PIN_PTT, on ? LOW : HIGH); + digitalWrite(PIN_PTT, on ? HIGH : LOW); } void CIO::setCOSInt(bool on) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 4c5c4d8..0f514cf 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -20,7 +20,7 @@ #include "Globals.h" #include "IO.h" -#if defined(__MK20DX256__) || defined(__MK66DX1024__) +#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) // A Teensy 3.1/3.2 #if defined(__MK20DX256__) @@ -37,8 +37,8 @@ #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 #define DACC_CHER_Chan DACC_CHER_CH1 -// A Teensy 3.6?? -#elif defined(__MK66DX1024__) +// A Teensy 3.5 +#elif defined(__MK64FX512__) #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -52,8 +52,20 @@ #define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 #define DACC_CHER_Chan DACC_CHER_CH1 -#else -#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined" +// A Teensy 3.6 +#elif defined(__MK66FX1M0__) +#define PIN_COS 52 +#define PIN_PTT 23 +#define PIN_COSLED 22 +#define PIN_DSTAR 9 +#define PIN_DMR 8 +#define PIN_YSF 7 +#define PIN_P25 6 +#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) +#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 +#define ADC_CDR_Chan 13 +#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 +#define DACC_CHER_Chan DACC_CHER_CH1 #endif const uint16_t DC_OFFSET = 2048U; @@ -132,6 +144,11 @@ void CIO::startInt() t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. // Set up the DAC + SIM_SCGC2 |= SIM_SCGC2_DAC0; + DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 + + + pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC DACC->DACC_MR = @@ -153,8 +170,8 @@ void CIO::interrupt() m_txBuffer.get(sample, control); - DACC->DACC_CDR = sample; - sample = ADC->ADC_CDR[ADC_CDR_Chan]; + *(int16_t *)&(DAC0_DAT0L) = sample; + // sample = ADC->ADC_CDR[ADC_CDR_Chan]; m_rxBuffer.put(sample, control); m_rssiBuffer.put(0U); @@ -174,7 +191,7 @@ void CIO::setLEDInt(bool on) void CIO::setPTTInt(bool on) { - digitalWrite(PIN_PTT, on ? LOW : HIGH); + digitalWrite(PIN_PTT, on ? HIGH : LOW); } void CIO::setCOSInt(bool on) From 2cb7d37195e93483849e92a0caa094df008f47d1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 1 Nov 2016 18:01:22 +0000 Subject: [PATCH 209/329] Abstract the serial port handling. --- SerialArduino.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++ SerialPort.cpp | 66 +++++++++++++++----------------- SerialPort.h | 7 +++- 3 files changed, 130 insertions(+), 38 deletions(-) create mode 100644 SerialArduino.cpp diff --git a/SerialArduino.cpp b/SerialArduino.cpp new file mode 100644 index 0000000..e723fee --- /dev/null +++ b/SerialArduino.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" + +#include "SerialPort.h" + +#if defined(__SAM3X8E__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) + +void CSerialPort::beginInt(uint8_t n, int speed) +{ + switch (n) { + case 1U: + Serial.begin(speed); + break; + case 2U: + Serial2.begin(speed); + break; + case 3U: + Serial3.begin(speed); + break; + default: + break; + } +} + +int CSerialPort::availableInt(uint8_t n) +{ + switch (n) { + case 1U: + return Serial.available(); + case 2U: + return Serial2.available(); + case 3U: + return Serial3.available(); + default: + return false; + } +} + +uint8_t CSerialPort::readInt(uint8_t n) +{ + switch (n) { + case 1U: + return Serial.read(); + case 2U: + return Serial2.read(); + case 3U: + return Serial3.read(); + default: + return 0U; + } +} + +void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush) +{ + switch (n) { + case 1U: + Serial.write(data, length); + if (flush) + Serial.flush(); + break; + case 2U: + Serial2.write(data, length); + if (flush) + Serial2.flush(); + break; + case 3U: + Serial3.write(data, length); + if (flush) + Serial3.flush(); + break; + default: + break; + } +} + +#endif + diff --git a/SerialPort.cpp b/SerialPort.cpp index 30ea8b6..faf72a4 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -92,7 +92,7 @@ void CSerialPort::sendACK() reply[2U] = MMDVM_ACK; reply[3U] = m_buffer[2U]; - write(reply, 4); + writeInt(1U, reply, 4); } void CSerialPort::sendNAK(uint8_t err) @@ -105,7 +105,7 @@ void CSerialPort::sendNAK(uint8_t err) reply[3U] = m_buffer[2U]; reply[4U] = err; - write(reply, 5); + writeInt(1U, reply, 5); } void CSerialPort::getStatus() @@ -180,7 +180,7 @@ void CSerialPort::getStatus() else reply[10U] = 0U; - write(reply, 11); + writeInt(1U, reply, 11); } void CSerialPort::getVersion() @@ -199,7 +199,7 @@ void CSerialPort::getVersion() reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) @@ -382,17 +382,17 @@ void CSerialPort::setMode(MMDVM_STATE modemState) void CSerialPort::start() { - Serial.begin(115200); + beginInt(1U, 115200); #if defined(SERIAL_REPEATER) - Serial3.begin(9600); + beginInt(3U, 9600); #endif } void CSerialPort::process() { - while (Serial.available()) { - uint8_t c = Serial.read(); + while (availableInt(1U)) { + uint8_t c = readInt(1U); if (m_ptr == 0U && c == MMDVM_FRAME_START) { // Handle the frame start correctly @@ -629,7 +629,7 @@ void CSerialPort::process() #if defined(SERIAL_REPEATER) case MMDVM_SERIAL: - Serial3.write(m_buffer + 3U, m_len - 3U); + writeInt(3U, m_buffer + 3U, m_len - 3U); break; #endif @@ -647,8 +647,8 @@ void CSerialPort::process() #if defined(SERIAL_REPEATER) // Drain any incoming serial data - while (Serial3.available()) - Serial3.read(); + while (availableInt(3U)) + readInt(3U); #endif } @@ -671,7 +671,7 @@ void CSerialPort::writeDStarHeader(const uint8_t* header, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeDStarData(const uint8_t* data, uint8_t length) @@ -694,7 +694,7 @@ void CSerialPort::writeDStarData(const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeDStarLost() @@ -711,7 +711,7 @@ void CSerialPort::writeDStarLost() reply[1U] = 3U; reply[2U] = MMDVM_DSTAR_LOST; - write(reply, 3); + writeInt(1U, reply, 3); } void CSerialPort::writeDStarEOT() @@ -728,7 +728,7 @@ void CSerialPort::writeDStarEOT() reply[1U] = 3U; reply[2U] = MMDVM_DSTAR_EOT; - write(reply, 3); + writeInt(1U, reply, 3); } void CSerialPort::writeDMRData(bool slot, const uint8_t* data, uint8_t length) @@ -751,7 +751,7 @@ void CSerialPort::writeDMRData(bool slot, const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeDMRLost(bool slot) @@ -768,7 +768,7 @@ void CSerialPort::writeDMRLost(bool slot) reply[1U] = 3U; reply[2U] = slot ? MMDVM_DMR_LOST2 : MMDVM_DMR_LOST1; - write(reply, 3); + writeInt(1U, reply, 3); } void CSerialPort::writeYSFData(const uint8_t* data, uint8_t length) @@ -791,7 +791,7 @@ void CSerialPort::writeYSFData(const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeYSFLost() @@ -808,7 +808,7 @@ void CSerialPort::writeYSFLost() reply[1U] = 3U; reply[2U] = MMDVM_YSF_LOST; - write(reply, 3); + writeInt(1U, reply, 3); } void CSerialPort::writeP25Hdr(const uint8_t* data, uint8_t length) @@ -831,7 +831,7 @@ void CSerialPort::writeP25Hdr(const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeP25Ldu(const uint8_t* data, uint8_t length) @@ -854,7 +854,7 @@ void CSerialPort::writeP25Ldu(const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); + writeInt(1U, reply, count); } void CSerialPort::writeP25Lost() @@ -871,7 +871,7 @@ void CSerialPort::writeP25Lost() reply[1U] = 3U; reply[2U] = MMDVM_P25_LOST; - write(reply, 3); + writeInt(1U, reply, 3); } void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) @@ -891,15 +891,7 @@ void CSerialPort::writeCalData(const uint8_t* data, uint8_t length) reply[1U] = count; - write(reply, count); -} - -void CSerialPort::write(const uint8_t* data, uint16_t length, bool flush) -{ - Serial.write(data, length); - - if (flush) - Serial.flush(); + writeInt(1U, reply, count); } void CSerialPort::writeDebug(const char* text) @@ -916,7 +908,7 @@ void CSerialPort::writeDebug(const char* text) reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } void CSerialPort::writeDebug(const char* text, int16_t n1) @@ -936,7 +928,7 @@ void CSerialPort::writeDebug(const char* text, int16_t n1) reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2) @@ -959,7 +951,7 @@ void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2) reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3) @@ -985,7 +977,7 @@ void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4) @@ -1014,7 +1006,7 @@ void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } void CSerialPort::writeAssert(bool cond, const char* text, const char* file, long line) @@ -1042,6 +1034,6 @@ void CSerialPort::writeAssert(bool cond, const char* text, const char* file, lon reply[1U] = count; - write(reply, count, true); + writeInt(1U, reply, count, true); } diff --git a/SerialPort.h b/SerialPort.h index e54ee7e..527ff64 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -67,8 +67,13 @@ private: void getVersion(); uint8_t setConfig(const uint8_t* data, uint8_t length); uint8_t setMode(const uint8_t* data, uint8_t length); - void write(const uint8_t* data, uint16_t length, bool flush = false); void setMode(MMDVM_STATE modemState); + + // Hardware versions + void beginInt(uint8_t n, int speed); + int availableInt(uint8_t n); + uint8_t readInt(uint8_t n); + void writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush = false); }; #endif From 423af323ed93a72b63145de9f07b4c336e75a7e6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 1 Nov 2016 20:30:18 +0000 Subject: [PATCH 210/329] Cleanups for Teensy support. --- Globals.h | 2 +- IO.cpp | 4 +-- IOTeensy.cpp | 84 +++------------------------------------------------- 3 files changed, 7 insertions(+), 83 deletions(-) diff --git a/Globals.h b/Globals.h index 49b620d..8f3d22e 100644 --- a/Globals.h +++ b/Globals.h @@ -23,7 +23,7 @@ #if defined(__SAM3X8E__) || defined(__STM32F1__) || defined(__STM32F2__) #define ARM_MATH_CM3 -#elif defined(__STM32F3__) || defined(__STM32F4__) +#elif defined(__STM32F3__) || defined(__STM32F4__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define ARM_MATH_CM4 #else #error "Unknown processor type" diff --git a/IO.cpp b/IO.cpp index e1d9f93..e769cf1 100644 --- a/IO.cpp +++ b/IO.cpp @@ -115,13 +115,13 @@ void CIO::process() if (m_ledCount >= 24000U) { m_ledCount = 0U; m_ledValue = !m_ledValue; - digitalWrite(PIN_LED, m_ledValue ? HIGH : LOW); + setLEDInt(m_ledValue); } } else { if (m_ledCount >= 240000U) { m_ledCount = 0U; m_ledValue = !m_ledValue; - digitalWrite(PIN_LED, m_ledValue ? HIGH : LOW); + setLEDInt(m_ledValue); } return; } diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 0f514cf..8c3ce9c 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -24,6 +24,7 @@ // A Teensy 3.1/3.2 #if defined(__MK20DX256__) +#define PIN_LED 13 #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -31,14 +32,10 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 -#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 -#define ADC_CDR_Chan 13 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 -#define DACC_CHER_Chan DACC_CHER_CH1 // A Teensy 3.5 #elif defined(__MK64FX512__) +#define PIN_LED 13 #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -46,14 +43,10 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 -#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 -#define ADC_CDR_Chan 13 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 -#define DACC_CHER_Chan DACC_CHER_CH1 // A Teensy 3.6 #elif defined(__MK66FX1M0__) +#define PIN_LED 13 #define PIN_COS 52 #define PIN_PTT 23 #define PIN_COSLED 22 @@ -61,11 +54,6 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 -#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13) -#define ADC_ISR_EOC_Chan ADC_ISR_EOC13 -#define ADC_CDR_Chan 13 -#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1 -#define DACC_CHER_Chan DACC_CHER_CH1 #endif const uint16_t DC_OFFSET = 2048U; @@ -73,8 +61,7 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { void ADC_Handler() { - if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg - io.interrupt(); + io.interrupt(); } } @@ -97,67 +84,6 @@ 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(); - - // Set up the ADC - NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector - ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts - ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt - ADC->ADC_CHDR = 0xFFFF; // Disable all channels - ADC->ADC_CHER = ADC_CHER_Chan; // Enable just one channel - ADC->ADC_CGR = 0x15555555; // All gains set to x1 - ADC->ADC_COR = 0x00000000; // All offsets off - ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0 - -#if defined(EXTERNAL_OSC) - // Set up the external clock input on PA4 = AI5 - REG_PIOA_ODR = 0x10; // Set pin as input - REG_PIOA_PDR = 0x10; // Disable PIO A bit 4 - REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input -#endif - - // Set up the timer - pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0 - TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0 - t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs - t->TC_IDR = 0xFFFFFFFF; // Disable interrupts - t->TC_SR; // Read int status reg to clear pending -#if defined(EXTERNAL_OSC) - t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock -#else - t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz) -#endif - TC_CMR_WAVE | // Waveform mode - TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold - TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output) - TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR | - TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR; -#if defined(EXTERNAL_OSC) - t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock - t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave -#else - t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock - t->TC_RA = 880; // Roughly square wave -#endif - t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares - t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source. - - // Set up the DAC - SIM_SCGC2 |= SIM_SCGC2_DAC0; - DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 - - - - pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC - DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC - DACC->DACC_MR = - DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0 - DACC_MR_USER_SEL_Chan | // Select channel - (24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz - DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts - DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel - digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); @@ -170,8 +96,6 @@ void CIO::interrupt() m_txBuffer.get(sample, control); - *(int16_t *)&(DAC0_DAT0L) = sample; - // sample = ADC->ADC_CDR[ADC_CDR_Chan]; m_rxBuffer.put(sample, control); m_rssiBuffer.put(0U); From 81ec23ecccd7d576358913101e3f07a1dd5c89e5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 3 Nov 2016 20:33:22 +0000 Subject: [PATCH 211/329] Simplify the mode pin code. --- IO.cpp | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/IO.cpp b/IO.cpp index e769cf1..282a7de 100644 --- a/IO.cpp +++ b/IO.cpp @@ -320,38 +320,10 @@ void CIO::setADCDetection(bool detect) void CIO::setMode() { #if defined(ARDUINO_MODE_PINS) - switch (m_modemState) { - case STATE_DSTAR: - setDStarInt(true); - setDMRInt(false); - setYSFInt(false); - setP25Int(false); - break; - case STATE_DMR: - setDStarInt(false); - setDMRInt(true); - setYSFInt(false); - setP25Int(false); - break; - case STATE_YSF: - setDStarInt(false); - setDMRInt(false); - setYSFInt(true); - setP25Int(false); - break; - case STATE_P25: - setDStarInt(false); - setDMRInt(false); - setYSFInt(false); - setP25Int(true); - break; - default: - setDStarInt(false); - setDMRInt(false); - setYSFInt(false); - setP25Int(false); - break; - } + setDStarInt(m_modemState == STATE_DSTAR); + setDMRInt(m_modemState == STATE_DMR); + setYSFInt(m_modemState == STATE_YSF); + setP25Int(m_modemState == STATE_P25); #endif } From 48c83b19c6eabae6ee350aef1f1da321c2347b61 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 4 Nov 2016 06:45:12 +0000 Subject: [PATCH 212/329] Improve the serial port parsing. --- SerialPort.cpp | 28 ++++++++++++---------------- SerialPort.h | 2 +- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index faf72a4..3092ef6 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -394,26 +394,22 @@ void CSerialPort::process() while (availableInt(1U)) { uint8_t c = readInt(1U); - if (m_ptr == 0U && c == MMDVM_FRAME_START) { - // Handle the frame start correctly - m_buffer[0U] = c; - m_ptr = 1U; - m_len = 0U; - } else if (m_ptr > 0U) { + if (m_ptr == 0U) { + if (c == MMDVM_FRAME_START) { + // Handle the frame start correctly + m_buffer[0U] = c; + m_ptr = 1U; + m_len = 0U; + } + } else if (m_ptr == 1U) { + // Handle the frame length + m_len = m_buffer[m_ptr] = c; + m_ptr = 2U; + } else { // Any other bytes are added to the buffer m_buffer[m_ptr] = c; m_ptr++; - // Once we have enough bytes, calculate the expected length - if (m_ptr == 2U) - m_len = m_buffer[1U]; - - if (m_ptr == 3U && m_len > 250U) { - sendNAK(3U); - m_ptr = 0U; - m_len = 0U; - } - // The full packet has been received, process it if (m_ptr == m_len) { uint8_t err = 2U; diff --git a/SerialPort.h b/SerialPort.h index 527ff64..455dfdb 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -57,7 +57,7 @@ public: void writeAssert(bool cond, const char* text, const char* file, long line); private: - uint8_t m_buffer[250U]; + uint8_t m_buffer[256U]; uint8_t m_ptr; uint8_t m_len; From 97fe8ad3fde8f25399bcb04573d18a0dd6f359d3 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 18:15:02 +0000 Subject: [PATCH 213/329] Add mode pins for the original Papa board. --- IODue.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IODue.cpp b/IODue.cpp index 85d039a..5e0060a 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -29,6 +29,10 @@ #define PIN_COS 7 #define PIN_PTT 8 #define PIN_COSLED 11 +#define PIN_DSTAR 16 +#define PIN_DMR 17 +#define PIN_YSF 18 +#define PIN_P25 19 #define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7) #define ADC_ISR_EOC_Chan ADC_ISR_EOC7 #define ADC_CDR_Chan 7 From 4a5027b18b3fa5c44951b7cb51f5ca57a103acf8 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 20:09:35 +0000 Subject: [PATCH 214/329] Add the STM32F CPU support. --- Config.h | 2 +- Globals.h | 22 +- IOSTM.cpp | 353 ++++++++++++++++++++++++++++ MMDVM.cpp | 2 +- MMDVM_STM32F4xx.cogui | 485 +++++++++++++++++++++++++++++++++++++++ MMDVM_STM32F4xx.comarker | 23 ++ MMDVM_STM32F4xx.coproj | 186 +++++++++++++++ Makefile | 104 +++++++++ README.md | 4 +- RSSIRB.h | 5 + SampleRB.h | 5 + SerialRB.h | 5 + SerialSTM.cpp | 464 +++++++++++++++++++++++++++++++++++++ Utils.h | 7 +- stm32_flash.ld | 170 ++++++++++++++ 15 files changed, 1830 insertions(+), 7 deletions(-) create mode 100644 IOSTM.cpp create mode 100644 MMDVM_STM32F4xx.cogui create mode 100644 MMDVM_STM32F4xx.comarker create mode 100644 MMDVM_STM32F4xx.coproj create mode 100644 Makefile create mode 100644 SerialSTM.cpp create mode 100644 stm32_flash.ld diff --git a/Config.h b/Config.h index 3eb0ed4..156e850 100644 --- a/Config.h +++ b/Config.h @@ -27,7 +27,7 @@ // Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable. // // For 12 MHz -// #define EXTERNAL_OSC 12000000 +#define EXTERNAL_OSC 12000000 // For 12.288 MHz // #define EXTERNAL_OSC 12288000 // For 14.4 MHz diff --git a/Globals.h b/Globals.h index 8f3d22e..807417e 100644 --- a/Globals.h +++ b/Globals.h @@ -19,16 +19,34 @@ #if !defined(GLOBALS_H) #define GLOBALS_H +#if defined(STM32F4XX) || defined(STM32F4) +#include "stm32f4xx.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_dac.h" +#include "stm32f4xx_adc.h" +#include "stm32f4xx_tim.h" +#include "stm32f4xx_usart.h" +#include "misc.h" +#include +#include +#else #include +#endif -#if defined(__SAM3X8E__) || defined(__STM32F1__) || defined(__STM32F2__) +#if defined(__SAM3X8E__) #define ARM_MATH_CM3 -#elif defined(__STM32F3__) || defined(__STM32F4__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) +#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK66FX1M0__) #define ARM_MATH_CM4 #else #error "Unknown processor type" #endif + +#if defined(STM32F4XX) || defined(STM32F4) +#include "cmsis.h" +#else #include +#endif enum MMDVM_STATE { STATE_IDLE = 0, diff --git a/IOSTM.cpp b/IOSTM.cpp new file mode 100644 index 0000000..1388367 --- /dev/null +++ b/IOSTM.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2016 by Jim McLaughlin KI6ZUM + * Copyright (C) 2016 by Andy Uribe CA6JAU + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" +#include "IO.h" + +#if defined(STM32F4XX) || defined(STM32F4) + +/* +Pin definitions: + +PTT PD8 output +COSLED PA7 output +LED PD15 output +COS PA5 input +ADC1 PA0 analog input +ADC2 PA1 analog input +DAC1 PA4 analog output + +DSTAR PD12 output +DMR PD13 output +YSF PD14 output +P25 PD11 output +*/ + +#define PIN_COS GPIO_Pin_5 +#define PORT_COS GPIOA +#define PIN_PTT GPIO_Pin_8 +#define PORT_PTT GPIOD +#define PIN_COSLED GPIO_Pin_7 +#define PORT_COSLED GPIOA +#define PIN_LED GPIO_Pin_15 +#define PORT_LED GPIOD +#define PIN_ADC GPIO_Pin_0 +#define PORT_ADC GPIOA +#define PIN_DAC GPIO_Pin_4 +#define PORT_DAC GPIOA + +#define PIN_P25 GPIO_Pin_11 +#define PORT_P25 GPIOD +#define PIN_DSTAR GPIO_Pin_12 +#define PORT_DSTAR GPIOD +#define PIN_DMR GPIO_Pin_13 +#define PORT_DMR GPIOD +#define PIN_YSF GPIO_Pin_14 +#define PORT_YSF GPIOD + +const uint16_t DC_OFFSET = 2048U; + +extern "C" { + void TIM2_IRQHandler() { + if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { + TIM_ClearITPendingBit(TIM2, TIM_IT_Update); + io.interrupt(); + } + } +} + +void CIO::initInt() +{ + GPIO_InitTypeDef GPIO_InitStruct; + + // PTT pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_PTT; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_PTT, &GPIO_InitStruct); + + // COSLED pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_COSLED; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_COSLED, &GPIO_InitStruct); + + // LED pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_LED; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_LED, &GPIO_InitStruct); + + // Init the input pins PIN_COS + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_COS; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(PORT_COS, &GPIO_InitStruct); + + // DSTAR pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_DSTAR; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_DSTAR, &GPIO_InitStruct); + + // DMR pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_DMR; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_DMR, &GPIO_InitStruct); + + // YSF pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_YSF; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_YSF, &GPIO_InitStruct); + + // P25 pin + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = PIN_P25; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_Init(PORT_P25, &GPIO_InitStruct); +} + +void CIO::startInt() +{ + if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)) + io.interrupt(); + + // ADC1 PA0 analog input + // ADC2 PA1 analog input + // DAC1 PA4 analog output + + // Init the ADC + GPIO_InitTypeDef GPIO_InitStruct; + ADC_InitTypeDef ADC_InitStructure; + ADC_CommonInitTypeDef ADC_CommonInitStructure; + + GPIO_StructInit(&GPIO_InitStruct); + ADC_CommonStructInit(&ADC_CommonInitStructure); + ADC_StructInit(&ADC_InitStructure); + + // Enable ADC clock + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); +#if defined(SEND_RSSI_DATA) + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2, ENABLE); +#else + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); +#endif + + // For ADC1 on PA0, ADC2 on PA1 +#if defined(SEND_RSSI_DATA) + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; +#else + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; +#endif + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + // Init ADCs in dual mode, div clock by two + ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInit(&ADC_CommonInitStructure); + + // Init ADC1 and ADC2: 12bit, single-conversion + ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = 0; + ADC_InitStructure.ADC_ExternalTrigConv = 0; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + + ADC_Init(ADC1, &ADC_InitStructure); + + ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE); + ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles); + + // Enable ADC1 + ADC_Cmd(ADC1, ENABLE); + +#if defined(SEND_RSSI_DATA) + ADC_Init(ADC2, &ADC_InitStructure); + + ADC_EOCOnEachRegularChannelCmd(ADC2, ENABLE); + ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_3Cycles); + + // Enable ADC2 + ADC_Cmd(ADC2, ENABLE); +#endif + + // Init the DAC + DAC_InitTypeDef DAC_InitStructure; + + GPIO_StructInit(&GPIO_InitStruct); + DAC_StructInit(&DAC_InitStructure); + + // GPIOA & D clock enable + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + + // DAC Periph clock enable + RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); + + // GPIO CONFIGURATION of DAC Pins + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; + DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; + DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; + DAC_Init(DAC_Channel_1, &DAC_InitStructure); + DAC_Cmd(DAC_Channel_1, ENABLE); + + // Init the timer + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + + TIM_TimeBaseInitTypeDef timerInitStructure; + TIM_TimeBaseStructInit (&timerInitStructure); + timerInitStructure.TIM_Prescaler = 1749; // 24 kHz + timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; + timerInitStructure.TIM_Period = 1; + timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; + timerInitStructure.TIM_RepetitionCounter = 0; + TIM_TimeBaseInit(TIM2, &timerInitStructure); + TIM_Cmd(TIM2, ENABLE); + TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); + + NVIC_InitTypeDef nvicStructure; + nvicStructure.NVIC_IRQChannel = TIM2_IRQn; + nvicStructure.NVIC_IRQChannelPreemptionPriority = 0; + nvicStructure.NVIC_IRQChannelSubPriority = 1; + nvicStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvicStructure); + + GPIO_ResetBits(PORT_COSLED, PIN_COSLED); + GPIO_SetBits(PORT_LED, PIN_LED); +} + +void CIO::interrupt() +{ + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; + uint16_t rawRSSI = 0U; + + m_txBuffer.get(sample, control); + + // Send the value to the DAC + DAC_SetChannel1Data(DAC_Align_12b_R, sample); + + // Read value from ADC1 and ADC2 + if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)) { + // shouldn't be still in reset at this point so null the sample value? + sample = 0U; + } else { + sample = ADC_GetConversionValue(ADC1); +#if defined(SEND_RSSI_DATA) + rawRSSI = ADC_GetConversionValue(ADC2); +#endif + } + + // trigger next ADC1 + ADC_ClearFlag(ADC1, ADC_FLAG_EOC); + ADC_SoftwareStartConv(ADC1); + + m_rxBuffer.put(sample, control); + m_rssiBuffer.put(rawRSSI); + + m_watchdog++; +} + +bool CIO::getCOSInt() +{ + return GPIO_ReadOutputDataBit(PORT_COS, PIN_COS) == Bit_SET; +} + +void CIO::setLEDInt(bool on) +{ + GPIO_WriteBit(PORT_LED, PIN_LED, on ? Bit_SET : Bit_RESET); +} + +void CIO::setPTTInt(bool on) +{ + GPIO_WriteBit(PORT_PTT, PIN_PTT, on ? Bit_SET : Bit_RESET); +} + +void CIO::setCOSInt(bool on) +{ + GPIO_WriteBit(PORT_COSLED, PIN_COSLED, on ? Bit_SET : Bit_RESET); +} + +void CIO::setDStarInt(bool on) +{ + GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET); +} + +void CIO::setDMRInt(bool on) +{ + GPIO_WriteBit(PORT_DMR, PIN_DMR, on ? Bit_SET : Bit_RESET); +} + +void CIO::setYSFInt(bool on) +{ + GPIO_WriteBit(PORT_YSF, PIN_YSF, on ? Bit_SET : Bit_RESET); +} + +void CIO::setP25Int(bool on) +{ + GPIO_WriteBit(PORT_P25, PIN_P25, on ? Bit_SET : Bit_RESET); +} + +#endif + diff --git a/MMDVM.cpp b/MMDVM.cpp index 69f916d..4f21843 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if defined(notdef) +#if defined(STM32F4XX) || defined(STM32F4) #include "Config.h" #include "Globals.h" diff --git a/MMDVM_STM32F4xx.cogui b/MMDVM_STM32F4xx.cogui new file mode 100644 index 0000000..0b4cff9 --- /dev/null +++ b/MMDVM_STM32F4xx.cogui @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MMDVM_STM32F4xx.comarker b/MMDVM_STM32F4xx.comarker new file mode 100644 index 0000000..b78ac1c --- /dev/null +++ b/MMDVM_STM32F4xx.comarker @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MMDVM_STM32F4xx.coproj b/MMDVM_STM32F4xx.coproj new file mode 100644 index 0000000..c0fa940 --- /dev/null +++ b/MMDVM_STM32F4xx.coproj @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4e72d56 --- /dev/null +++ b/Makefile @@ -0,0 +1,104 @@ +### +# GNU ARM Embedded Toolchain +CC=arm-none-eabi-gcc +CXX=arm-none-eabi-g++ +LD=arm-none-eabi-ld +AR=arm-none-eabi-ar +AS=arm-none-eabi-as +CP=arm-none-eabi-objcopy +OD=arm-none-eabi-objdump +NM=arm-none-eabi-nm +SIZE=arm-none-eabi-size +A2L=arm-none-eabi-addr2line + +### +# Directory Structure +BINDIR=bin + +### +# Find source files +ASOURCES=$(shell find . -name '*.s') +CSOURCES=$(shell find . -name '*.c') +CXXSOURCES=$(shell find . -name '*.cpp') +# Find header directories +INC=$(shell find . -name '*.h' -exec dirname {} \; | uniq) +INCLUDES=$(INC:%=-I%) +# Find libraries +INCLUDES_LIBS=libarm_cortexM4lf_math.a +LINK_LIBS= +# Create object list +OBJECTS=$(ASOURCES:%.s=%.o) +OBJECTS+=$(CSOURCES:%.c=%.o) +OBJECTS+=$(CXXSOURCES:%.cpp=%.o) +# Define output files ELF & IHEX +BINELF=outp.elf +BINHEX=outp.hex + +### +# MCU FLAGS +MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ +-mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork +# COMPILE FLAGS +DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F407VG +CFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) +CXXFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) +# LINKER FLAGS +LDSCRIPT=stm32_flash.ld +LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS) + +### +# Build Rules +.PHONY: all release release-memopt debug clean + +all: release-memopt + +release-memopt: DEFS+=-DCUSTOM_NEW -DNO_EXCEPTIONS +release-memopt: CFLAGS+=-Os -ffunction-sections -fdata-sections -fno-builtin # -flto +release-memopt: CXXFLAGS+=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti # -flto +release-memopt: LDFLAGS+=-Os --specs=nano.specs # -flto +release-memopt: release + +debug: CFLAGS+=-g +debug: CXXFLAGS+=-g +debug: LDFLAGS+=-g +debug: release + +release: $(BINDIR)/$(BINHEX) + +$(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF) + $(CP) -O ihex $< $@ + @echo "Objcopy from ELF to IHEX complete!\n" + +$(BINDIR)/$(BINELF): $(OBJECTS) + $(CXX) $(OBJECTS) $(LDFLAGS) -o $@ + @echo "Linking complete!\n" + $(SIZE) $(BINDIR)/$(BINELF) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) $< -o $@ + @echo "Compiled "$<"!\n" + +%.o: %.c + $(CC) $(CFLAGS) $< -o $@ + @echo "Compiled "$<"!\n" + +%.o: %.s + $(CC) $(CFLAGS) $< -o $@ + @echo "Assambled "$<"!\n" + +clean: + rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX) $(BINDIR)/output.map + +deploy: +ifneq ($(wildcard /usr/bin/openocd),) + /usr/bin/openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit" +endif + +ifneq ($(wildcard /usr/local/bin/openocd),) + /usr/local/bin/openocd -f /usr/local/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit" +endif + +ifneq ($(wildcard /opt/openocd/bin/openocd),) + /opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit" +endif + diff --git a/README.md b/README.md index fd13ce8..3bfea68 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25. -Currently it only runs on the Arduino Due, but other platforms are planned. +It runs on the Arduino Due, and the STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.6) is being added. -In order to build this software you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. +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. This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden. diff --git a/RSSIRB.h b/RSSIRB.h index 41e6b8c..111a3ef 100644 --- a/RSSIRB.h +++ b/RSSIRB.h @@ -21,7 +21,12 @@ Boston, MA 02110-1301, USA. #if !defined(RSSIRB_H) #define RSSIRB_H +#if defined(STM32F4XX) || defined(STM32F4) +#include "stm32f4xx.h" +#include +#else #include +#endif class CRSSIRB { public: diff --git a/SampleRB.h b/SampleRB.h index 284a1a5..16d3441 100644 --- a/SampleRB.h +++ b/SampleRB.h @@ -21,7 +21,12 @@ Boston, MA 02110-1301, USA. #if !defined(SAMPLERB_H) #define SAMPLERB_H +#if defined(STM32F4XX) || defined(STM32F4) +#include "stm32f4xx.h" +#include +#else #include +#endif class CSampleRB { public: diff --git a/SerialRB.h b/SerialRB.h index ea7421e..1671b23 100644 --- a/SerialRB.h +++ b/SerialRB.h @@ -21,7 +21,12 @@ Boston, MA 02110-1301, USA. #if !defined(SERIALRB_H) #define SERIALRB_H +#if defined(STM32F4XX) || defined(STM32F4) +#include "stm32f4xx.h" +#include +#else #include +#endif const uint16_t SERIAL_RINGBUFFER_SIZE = 370U; diff --git a/SerialSTM.cpp b/SerialSTM.cpp new file mode 100644 index 0000000..73cde0a --- /dev/null +++ b/SerialSTM.cpp @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2016 by Jim McLaughlin KI6ZUM + * Copyright (C) 2016 by Andy Uribe CA6JAU + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "Config.h" +#include "Globals.h" + +#include "SerialPort.h" + +#if defined(STM32F4XX) || defined(STM32F4) + +volatile uint32_t intcount1, intcount3; + +#define TX_SERIAL_FIFO_SIZE 256U +#define RX_SERIAL_FIFO_SIZE 256U + +volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead1, TXSerialfifotail1; +volatile uint16_t RXSerialfifohead1, RXSerialfifotail1; + +volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; +volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; + +extern "C" { + void USART1_IRQHandler(); + void USART3_IRQHandler(); +} + +/* ************* USART1 ***************** */ + +// Init queues +void TXSerialfifoinit1() +{ + TXSerialfifohead1 = 0U; + TXSerialfifotail1 = 0U; +} + +void RXSerialfifoinit1() +{ + RXSerialfifohead1 = 0U; + RXSerialfifotail1 = 0U; +} + +// How full is queue +// TODO decide if how full or how empty is preferred info to return +uint16_t TXSerialfifolevel1() +{ + uint32_t tail = TXSerialfifotail1; + uint32_t head = TXSerialfifohead1; + + if (tail > head) + return TX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +uint16_t RXSerialfifolevel1() +{ + uint32_t tail = RXSerialfifotail1; + uint32_t head = RXSerialfifohead1; + + if (tail > head) + return RX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +// Flushes the transmit shift register +// warning: this call is blocking +void TXSerialFlush1() +{ + // wait until the TXE shows the shift register is empty + while (USART_GetITStatus(USART1, USART_FLAG_TXE)) + ; +} + +uint8_t TXSerialfifoput1(uint8_t next) +{ + if (TXSerialfifolevel1() < TX_SERIAL_FIFO_SIZE) { + TXSerialfifo1[TXSerialfifohead1] = next; + + TXSerialfifohead1++; + if (TXSerialfifohead1 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifohead1 = 0U; + + // make sure transmit interrupts are enabled as long as there is data to send + USART_ITConfig(USART1, USART_IT_TXE, ENABLE); + return 1U; + } else { + return 0U; // signal an overflow occurred by returning a zero count + } +} + +void USART1_IRQHandler() +{ + uint8_t c; + + if (USART_GetITStatus(USART1, USART_IT_RXNE)) { + c = (uint8_t) USART_ReceiveData(USART1); + + if (RXSerialfifolevel1() < RX_SERIAL_FIFO_SIZE) { + RXSerialfifo1[RXSerialfifohead1] = c; + + RXSerialfifohead1++; + if (RXSerialfifohead1 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifohead1 = 0U; + } else { + // TODO - do something if rx fifo is full? + } + + USART_ClearITPendingBit(USART1, USART_IT_RXNE); + intcount1++; + } + + if (USART_GetITStatus(USART1, USART_IT_TXE)) { + c = 0U; + + if (TXSerialfifohead1 != TXSerialfifotail1) { // if the fifo is not empty + c = TXSerialfifo1[TXSerialfifotail1]; + + TXSerialfifotail1++; + if (TXSerialfifotail1 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifotail1 = 0U; + + USART_SendData(USART1, c); + } else { // if there's no more data to transmit then turn off TX interrupts + USART_ITConfig(USART1, USART_IT_TXE, DISABLE); + } + + USART_ClearITPendingBit(USART1, USART_IT_TXE); + } +} + +void InitUSART1(int speed) +{ + // USART1 - TXD PA9 - RXD PA10 - pins on mmdvm pi board + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); + + // USART IRQ init + NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init(&NVIC_InitStructure); + + // Configure USART as alternate function + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // Tx | Rx + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // Configure USART baud rate + USART_StructInit(&USART_InitStructure); + USART_InitStructure.USART_BaudRate = speed; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART1, &USART_InitStructure); + + USART_Cmd(USART1, ENABLE); + + USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); + + // initialize the fifos + TXSerialfifoinit1(); + RXSerialfifoinit1(); +} + +uint8_t AvailUSART1(void) +{ + if (RXSerialfifolevel1() > 0U) + return 1U; + else + return 0U; +} + +uint8_t ReadUSART1(void) +{ + uint8_t data_c = RXSerialfifo1[RXSerialfifotail1]; + + RXSerialfifotail1++; + if (RXSerialfifotail1 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifotail1 = 0U; + + return data_c; +} + +void WriteUSART1(const uint8_t* data, uint16_t length) +{ + for (uint16_t i = 0U; i < length; i++) + TXSerialfifoput1(data[i]); + + USART_ITConfig(USART1, USART_IT_TXE, ENABLE); +} + +/* ************* USART3 ***************** */ + +// Init queues +void TXSerialfifoinit3() +{ + TXSerialfifohead3 = 0U; + TXSerialfifotail3 = 0U; +} + +void RXSerialfifoinit3() +{ + RXSerialfifohead3 = 0U; + RXSerialfifotail3 = 0U; +} + +// How full is queue +// TODO decide if how full or how empty is preferred info to return +uint16_t TXSerialfifolevel3() +{ + uint32_t tail = TXSerialfifotail3; + uint32_t head = TXSerialfifohead3; + + if (tail > head) + return TX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +uint16_t RXSerialfifolevel3() +{ + uint32_t tail = RXSerialfifotail3; + uint32_t head = RXSerialfifohead3; + + if (tail > head) + return RX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +// Flushes the transmit shift register +// warning: this call is blocking +void TXSerialFlush3() +{ + // wait until the TXE shows the shift register is empty + while (USART_GetITStatus(USART3, USART_FLAG_TXE)) + ; +} + +uint8_t TXSerialfifoput3(uint8_t next) +{ + if (TXSerialfifolevel3() < TX_SERIAL_FIFO_SIZE) { + TXSerialfifo3[TXSerialfifohead3] = next; + + TXSerialfifohead3++; + if (TXSerialfifohead3 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifohead3 = 0U; + + // make sure transmit interrupts are enabled as long as there is data to send + USART_ITConfig(USART3, USART_IT_TXE, ENABLE); + return 1U; + } else { + return 0U; // signal an overflow occurred by returning a zero count + } +} + +void USART3_IRQHandler() +{ + uint8_t c; + + if (USART_GetITStatus(USART3, USART_IT_RXNE)) { + c = (uint8_t) USART_ReceiveData(USART3); + + if (RXSerialfifolevel3() < RX_SERIAL_FIFO_SIZE) { + RXSerialfifo3[RXSerialfifohead3] = c; + + RXSerialfifohead3++; + if (RXSerialfifohead3 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifohead3 = 0U; + } else { + // TODO - do something if rx fifo is full? + } + + USART_ClearITPendingBit(USART3, USART_IT_RXNE); + intcount3++; + } + + if (USART_GetITStatus(USART3, USART_IT_TXE)) { + c = 0U; + + if (TXSerialfifohead3 != TXSerialfifotail3) { // if the fifo is not empty + c = TXSerialfifo3[TXSerialfifotail3]; + + TXSerialfifotail3++; + if (TXSerialfifotail3 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifotail3 = 0U; + + USART_SendData(USART3, c); + } else { // if there's no more data to transmit then turn off TX interrupts + USART_ITConfig(USART3, USART_IT_TXE, DISABLE); + } + + USART_ClearITPendingBit(USART3, USART_IT_TXE); + } +} + +void InitUSART3(int speed) +{ + // USART3 - TXD PB10 - RXD PB11 - pins when jumpered from FTDI board to F4Discovery board + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); + GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); + + // USART IRQ init + NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init(&NVIC_InitStructure); + + // Configure USART as alternate function + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // Tx | Rx + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + // Configure USART baud rate + USART_StructInit(&USART_InitStructure); + USART_InitStructure.USART_BaudRate = speed; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART3, &USART_InitStructure); + + USART_Cmd(USART3, ENABLE); + + USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); + + // initialize the fifos + TXSerialfifoinit3(); + RXSerialfifoinit3(); +} + +uint8_t AvailUSART3(void) +{ + if (RXSerialfifolevel3() > 0U) + return 1U; + else + return 0U; +} + +uint8_t ReadUSART3(void) +{ + uint8_t data_c = RXSerialfifo3[RXSerialfifotail3]; + + RXSerialfifotail3++; + if (RXSerialfifotail3 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifotail3 = 0U; + + return data_c; +} + +void WriteUSART3(const uint8_t* data, uint16_t length) +{ + for (uint16_t i = 0U; i < length; i++) + TXSerialfifoput3(data[i]); + + USART_ITConfig(USART3, USART_IT_TXE, ENABLE); +} + +///////////////////////////////////////////////////////////////// + +void CSerialPort::beginInt(uint8_t n, int speed) +{ + switch (n) { + case 1U: + InitUSART3(speed); + break; + case 3U: + InitUSART1(speed); + break; + default: + break; + } +} + +int CSerialPort::availableInt(uint8_t n) +{ + switch (n) { + case 1U: + return AvailUSART3(); + case 3U: + return AvailUSART1(); + default: + return false; + } +} + +uint8_t CSerialPort::readInt(uint8_t n) +{ + switch (n) { + case 1U: + return ReadUSART3(); + case 3U: + return ReadUSART1(); + default: + return 0U; + } +} + +void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush) +{ + switch (n) { + case 1U: + WriteUSART3(data, length); + if (flush) + TXSerialFlush3(); + break; + case 3U: + WriteUSART1(data, length); + if (flush) + TXSerialFlush1(); + break; + default: + break; + } +} + +#endif + diff --git a/Utils.h b/Utils.h index 913e9a6..d158c6b 100644 --- a/Utils.h +++ b/Utils.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 @@ -19,7 +19,12 @@ #if !defined(UTILS_H) #define UTILS_H +#if defined(STM32F4XX) || defined(STM32F4) +#include "stm32f4xx.h" +#include +#else #include +#endif uint8_t countBits8(uint8_t bits); diff --git a/stm32_flash.ld b/stm32_flash.ld new file mode 100644 index 0000000..1a0b4b8 --- /dev/null +++ b/stm32_flash.ld @@ -0,0 +1,170 @@ +/* +***************************************************************************** +** +** File : stm32_flash.ld +** +** Abstract : Linker script for STM32F407VG Device with +** 1024KByte FLASH, 192KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of 128K RAM on AHB bus*/ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} From 9aa450713a031ea2a8777b94055c81dad1306ef5 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 20:20:06 +0000 Subject: [PATCH 215/329] Conditional compile of mode pins for STM32F4. --- IOSTM.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IOSTM.cpp b/IOSTM.cpp index 1388367..b2ab143 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -117,6 +117,7 @@ void CIO::initInt() GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(PORT_COS, &GPIO_InitStruct); +#if defined(ARDUINO_MODE_PINS) // DSTAR pin RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_StructInit(&GPIO_InitStruct); @@ -156,6 +157,7 @@ void CIO::initInt() GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_P25, &GPIO_InitStruct); +#endif } void CIO::startInt() From c6e36f81fcf15b9062087a15dde105ec8cfb0227 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 20:26:38 +0000 Subject: [PATCH 216/329] Framework for Teensy IO. --- IOTeensy.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 8c3ce9c..9641297 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -20,7 +20,7 @@ #include "Globals.h" #include "IO.h" -#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) +#if defined(__MK20DX256__) || defined(__MK66FX1M0__) // A Teensy 3.1/3.2 #if defined(__MK20DX256__) @@ -33,17 +33,6 @@ #define PIN_YSF 7 #define PIN_P25 6 -// A Teensy 3.5 -#elif defined(__MK64FX512__) -#define PIN_LED 13 -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 - // A Teensy 3.6 #elif defined(__MK66FX1M0__) #define PIN_LED 13 @@ -84,6 +73,25 @@ void CIO::initInt() void CIO::startInt() { + // Initialise ADC1 conversion to be triggered by the PDB + + // Setup interrupt on ADC1 conversion finished + + // Setup PDB for ADC1 at 24 kHz + + +#if defined(SEND_RSSI_DATA) + // Initialise ADC2 conversion to be triggered by the PDB + + // Setup interrupt on ADC2 conversion finished + + // Setup PDB for ADC2 at 24 kHz +#endif + + // Initialise the DAC + SIM_SCGC2 |= SIM_SCGC2_DAC0; + DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 + digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); @@ -96,6 +104,10 @@ void CIO::interrupt() m_txBuffer.get(sample, control); + DAC0_DAT0L = (sample >> 0) & 0xFFU; + DAC0_DATH = (sample >> 8) & 0xFFU; + + // sample = m_rxBuffer.put(sample, control); m_rssiBuffer.put(0U); From 2a5149180d7a689706190e3efc2c70839ae7cd50 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 21:02:09 +0000 Subject: [PATCH 217/329] Start building the Teensy support. --- IOTeensy.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 9641297..4655cae 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -79,7 +79,6 @@ void CIO::startInt() // Setup PDB for ADC1 at 24 kHz - #if defined(SEND_RSSI_DATA) // Initialise ADC2 conversion to be triggered by the PDB @@ -90,7 +89,7 @@ void CIO::startInt() // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; - DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 + DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); @@ -99,20 +98,29 @@ void CIO::startInt() void CIO::interrupt() { - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; + if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; - m_txBuffer.get(sample, control); + m_txBuffer.get(sample, control); + *(int16_t *)&(DAC0_DAT0L) = sample; - DAC0_DAT0L = (sample >> 0) & 0xFFU; - DAC0_DATH = (sample >> 8) & 0xFFU; + sample = ADC0_RA; + m_rxBuffer.put(sample, control); - // sample = +#if !defined(SEND_RSSI_DATA) + m_rssiBuffer.put(0U); +#endif - m_rxBuffer.put(sample, control); - m_rssiBuffer.put(0U); + m_watchdog++; + } - m_watchdog++; +#if defined(SEND_RSSI_DATA) + if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { + uint16_t rssi = ADC1_RA; + m_rssiBuffer.put(rssi); + } +#endif } bool CIO::getCOSInt() From ee44fd81efda65e6241c797dcbd2cce85e78c80b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 21:25:25 +0000 Subject: [PATCH 218/329] Clean up the Due's interrupt handler. --- IODue.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/IODue.cpp b/IODue.cpp index 5e0060a..b31b776 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -73,8 +73,7 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { void ADC_Handler() { - if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg - io.interrupt(); + io.interrupt(); } } @@ -160,18 +159,20 @@ void CIO::startInt() void CIO::interrupt() { - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; + if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg + uint8_t control = MARK_NONE; + uint16_t sample = DC_OFFSET; - m_txBuffer.get(sample, control); + m_txBuffer.get(sample, control); + DACC->DACC_CDR = sample; - DACC->DACC_CDR = sample; - sample = ADC->ADC_CDR[ADC_CDR_Chan]; + sample = ADC->ADC_CDR[ADC_CDR_Chan]; + m_rxBuffer.put(sample, control); - m_rxBuffer.put(sample, control); - m_rssiBuffer.put(0U); + m_rssiBuffer.put(0U); - m_watchdog++; + m_watchdog++; + } } bool CIO::getCOSInt() From 612b10cd11feff60948063bd31ee6acb79e41b8e Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 7 Nov 2016 21:28:06 +0000 Subject: [PATCH 219/329] Small clean up. --- IODue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IODue.cpp b/IODue.cpp index b31b776..e465da3 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -159,7 +159,7 @@ void CIO::startInt() void CIO::interrupt() { - if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg + 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; uint16_t sample = DC_OFFSET; From 934bad3fb9c9ea30c65f57f72924b023934e5ebd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 8 Nov 2016 07:41:31 +0000 Subject: [PATCH 220/329] More work on the Teensy raw IO. --- IOTeensy.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 4655cae..bb58f20 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -48,7 +48,7 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { - void ADC_Handler() + void adc0_isr() { io.interrupt(); } @@ -71,25 +71,47 @@ void CIO::initInt() #endif } +#define PDB_CH0C1_TOS 0x0100 +#define PDB_CH0C1_EN 0x01 + void CIO::startInt() { + // Initialise ADC0 conversion to be triggered by the PDB + ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | + ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time + ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb + ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger + ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC0_SC1A = ADC_SC1_AIEN | 5; // Enable ADC interrupt, use A0 + NVIC_ENABLE_IRQ(IRQ_ADC0); + + // Setup PDB for ADC0 at 24 kHz + SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock +#if F_BUS == 60000000 + // 60 MHz for the Teensy 3.5/3.6 + PDB0_MOD = 2500; // Timer period for 60 MHz bus +#else + // 48 MHz for the Teensy 3.1/3.2 + PDB0_MOD = 2000; // Timer period for 48 MHz bus +#endif + PDB0_IDLY = 0; // Interrupt delay + PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | + PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | + PDB_SC_LDOK; + PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) + +#if defined(SEND_RSSI_DATA) // Initialise ADC1 conversion to be triggered by the PDB // Setup interrupt on ADC1 conversion finished // Setup PDB for ADC1 at 24 kHz - -#if defined(SEND_RSSI_DATA) - // Initialise ADC2 conversion to be triggered by the PDB - - // Setup interrupt on ADC2 conversion finished - - // Setup PDB for ADC2 at 24 kHz #endif // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; - DAC0_C0 = DAC_C0_DACEN; // 1.2V VDDA is DACREF_2 + DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); From 1aa3c62f0942161cc889a2779568c8820f4c45ee Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Wed, 9 Nov 2016 23:40:38 -0300 Subject: [PATCH 221/329] some minor changes --- Config.h | 2 +- IOSTM.cpp | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Config.h b/Config.h index 156e850..3eb0ed4 100644 --- a/Config.h +++ b/Config.h @@ -27,7 +27,7 @@ // Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable. // // For 12 MHz -#define EXTERNAL_OSC 12000000 +// #define EXTERNAL_OSC 12000000 // For 12.288 MHz // #define EXTERNAL_OSC 12288000 // For 14.4 MHz diff --git a/IOSTM.cpp b/IOSTM.cpp index b2ab143..39e4e99 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -26,7 +26,7 @@ /* Pin definitions: -PTT PD8 output +PTT PA6 output COSLED PA7 output LED PD15 output COS PA5 input @@ -42,8 +42,8 @@ P25 PD11 output #define PIN_COS GPIO_Pin_5 #define PORT_COS GPIOA -#define PIN_PTT GPIO_Pin_8 -#define PORT_PTT GPIOD +#define PIN_PTT GPIO_Pin_6 +#define PORT_PTT GPIOA #define PIN_COSLED GPIO_Pin_7 #define PORT_COSLED GPIOA #define PIN_LED GPIO_Pin_15 @@ -78,7 +78,7 @@ void CIO::initInt() GPIO_InitTypeDef GPIO_InitStruct; // PTT pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = PIN_PTT; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; @@ -196,8 +196,12 @@ void CIO::startInt() GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStruct); - // Init ADCs in dual mode, div clock by two + // Init ADCs in dual mode (RSSI), div clock by two +#if defined(SEND_RSSI_DATA) ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult; +#else + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; +#endif ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; From 6f33cfdf4f0729a09f5ae473648e4966d2e44527 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Nov 2016 11:33:02 +0000 Subject: [PATCH 222/329] Reinstate the original config options. --- Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.h b/Config.h index 3eb0ed4..156e850 100644 --- a/Config.h +++ b/Config.h @@ -27,7 +27,7 @@ // Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable. // // For 12 MHz -// #define EXTERNAL_OSC 12000000 +#define EXTERNAL_OSC 12000000 // For 12.288 MHz // #define EXTERNAL_OSC 12288000 // For 14.4 MHz From 5f26a6c67d161dd807ad89be3f0e04b282549c2c Mon Sep 17 00:00:00 2001 From: phl0 Date: Thu, 10 Nov 2016 16:44:29 +0100 Subject: [PATCH 223/329] Some minor corrections --- mmdvmmenu.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 5ed9413..9031f5e 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -23,9 +23,9 @@ ############################################################################### # # On a Linux based system, such as a Raspberry Pi, this script will perform -# Modafacation to the Config.c file for most options. It makes a Back up when -# you staet the script if none is present. You must recompile and load firmwhare -# on Due if changes are made. +# Modification of the Config.h file for most options. It makes a Back up when +# you start the script if none is present. You must recompile and load firmware +# onto the Arduino Due if changes are made. # ############################################################################### # From 150ea24a83d6d5de403b89ca4174331110f95c03 Mon Sep 17 00:00:00 2001 From: phl0 Date: Thu, 10 Nov 2016 16:48:52 +0100 Subject: [PATCH 224/329] Add 12.288MHz TCXO to mmdvmmenu.sh --- mmdvmmenu.sh | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/mmdvmmenu.sh b/mmdvmmenu.sh index 9031f5e..b5f5ded 100755 --- a/mmdvmmenu.sh +++ b/mmdvmmenu.sh @@ -61,15 +61,16 @@ do -------------------------------------------------------------- Please enter your choice: - (1) Enable 12.0 MHZ Clock - (2) Enable 14.4 MHz Clock - (3) Enable 19.2 MHz Clock - (4) Use the COS to lockout the modem - (5) Use pins to output the current mode - (6) Use layout for the PAPA board - (7) Use layout for ZUM V1.0 and V1.0.1 boards - (8) Use layout for SP8NTH board - (9) Use modem as display driver + (1) Enable 12.000 MHZ Clock + (2) Enable 12.288 MHZ Clock + (3) Enable 14.400 MHz Clock + (4) Enable 19.200 MHz Clock + (5) Use the COS to lockout the modem + (6) Use pins to output the current mode + (7) Use layout for the PAPA board + (8) Use layout for ZUM V1.0 and V1.0.1 boards + (9) Use layout for SP8NTH board + (0) Use modem as display driver (A) Return to Default (Q)uit @@ -77,15 +78,16 @@ do EOF read -n1 -s case "$REPLY" in - "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.0 MHz clock enabled";; - "2") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.4 MHz clock enabled";; - "3") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.2 MHz clock enabled";; - "4") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; - "5") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins Enabled";; - "6") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; - "7") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.0.1 boards enabled";; - "8") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; - "9") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; + "1") sed -e 's/\/\/ #define EXTERNAL_OSC 12000000/#define EXTERNAL_OSC 12000000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.000 MHz clock enabled";; + "2") sed -e 's/\/\/ #define EXTERNAL_OSC 12288000/#define EXTERNAL_OSC 12288000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "12.288 MHz clock enabled";; + "3") sed -e 's/\/\/ #define EXTERNAL_OSC 14400000/#define EXTERNAL_OSC 14400000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "14.400 MHz clock enabled";; + "4") sed -e 's/\/\/ #define EXTERNAL_OSC 19200000/#define EXTERNAL_OSC 19200000/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "19.200 MHz clock enabled";; + "5") sed -e 's/\/\/ #define USE_COS_AS_LOCKOUT /#define USE_COS_AS_LOCKOUT/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "COS as Lockout enabled";; + "6") sed -e 's/\/\/ #define ARDUINO_MODE_PINS/#define ARDUINO_MODE_PINS/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Mode pins enabled";; + "7") sed -e 's/\/\/ #define ARDUINO_DUE_PAPA/#define ARDUINO_DUE_PAPA/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for the PAPA board enabled";; + "8") sed -e 's/\/\/ #define ARDUINO_DUE_ZUM_V10/#define ARDUINO_DUE_ZUM_V10/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for ZUM V1.0 and V1.0.1 boards enabled";; + "9") sed -e 's/\/\/ #define ARDUINO_DUE_NTH/#define ARDUINO_DUE_NTH/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Layout for SP8NTH board enabled";; + "0") sed -e 's/\/\/ #define SERIAL_REPEATER/#define SERIAL_REPEATER/' $conf > $conf.tmp && mv -f $conf.tmp $conf && echo "Modem display driver enabled";; "A") mv -f $confbak $conf ;; "a") mv -f $confbak $conf ;; "Q") echo "If any changes are made you need to (re-)upload the firmware to MMDVM" && exit;; From 584134d1d1653412baa52cecc90501588a9bf520 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Nov 2016 19:45:35 +0000 Subject: [PATCH 225/329] Add more Teensy IO code. --- IOTeensy.cpp | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index bb58f20..78a058a 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -32,6 +32,8 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 +#define PIN_ADC 5 // A0 +#define PIN_RSSI 8 // A2 // A Teensy 3.6 #elif defined(__MK66FX1M0__) @@ -43,6 +45,8 @@ #define PIN_DMR 8 #define PIN_YSF 7 #define PIN_P25 6 +#define PIN_ADC 5 // A0 +#define PIN_RSSI 8 // A2 #endif const uint16_t DC_OFFSET = 2048U; @@ -52,6 +56,11 @@ extern "C" { { io.interrupt(); } + + void adc1_isr() + { + io.interrupt(); + } } void CIO::initInt() @@ -82,17 +91,26 @@ void CIO::startInt() ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - ADC0_SC1A = ADC_SC1_AIEN | 5; // Enable ADC interrupt, use A0 + + ADC0_SC3 = ADC_SC3_CAL; // Begin calibration + while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + ; + + uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; // Plus side gain + sum0 = (sum0 / 2U) | 0x8000U; + ADC0_PG = sum0; + + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock #if F_BUS == 60000000 // 60 MHz for the Teensy 3.5/3.6 - PDB0_MOD = 2500; // Timer period for 60 MHz bus + PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus #else // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000; // Timer period for 48 MHz bus + PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus #endif PDB0_IDLY = 0; // Interrupt delay PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger @@ -103,10 +121,22 @@ void CIO::startInt() #if defined(SEND_RSSI_DATA) // Initialise ADC1 conversion to be triggered by the PDB + ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | + ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time + ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb + ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger + ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - // Setup interrupt on ADC1 conversion finished + ADC1_SC3 = ADC_SC3_CAL; // Begin calibration + while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + ; - // Setup PDB for ADC1 at 24 kHz + uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain + sum1 = (sum1 / 2U) | 0x8000U; + ADC1_PG = sum1; + + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A0 + NVIC_ENABLE_IRQ(IRQ_ADC1); #endif // Initialise the DAC From 823b68d5ed2ad41e93f6fec6b9b6256f17841239 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 10 Nov 2016 20:15:06 +0000 Subject: [PATCH 226/329] More ADC IRQ work for the Teensy. --- IOTeensy.cpp | 96 ++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 78a058a..c555f7d 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -49,15 +49,13 @@ #define PIN_RSSI 8 // A2 #endif +#define PDB_CH0C1_TOS 0x0100 +#define PDB_CH0C1_EN 0x01 + const uint16_t DC_OFFSET = 2048U; extern "C" { - void adc0_isr() - { - io.interrupt(); - } - - void adc1_isr() + void pdb_isr() { io.interrupt(); } @@ -80,12 +78,9 @@ void CIO::initInt() #endif } -#define PDB_CH0C1_TOS 0x0100 -#define PDB_CH0C1_EN 0x01 - void CIO::startInt() { - // Initialise ADC0 conversion to be triggered by the PDB + // Initialise ADC0 ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -100,27 +95,8 @@ void CIO::startInt() sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; - ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 - NVIC_ENABLE_IRQ(IRQ_ADC0); - - // Setup PDB for ADC0 at 24 kHz - SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock -#if F_BUS == 60000000 - // 60 MHz for the Teensy 3.5/3.6 - PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus -#else - // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus -#endif - PDB0_IDLY = 0; // Interrupt delay - PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger - PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | - PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | - PDB_SC_LDOK; - PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) - #if defined(SEND_RSSI_DATA) - // Initialise ADC1 conversion to be triggered by the PDB + // Initialise ADC1 ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -134,11 +110,25 @@ void CIO::startInt() uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; - - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A0 - NVIC_ENABLE_IRQ(IRQ_ADC1); #endif + // Setup PDB for ADC0 at 24 kHz + SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock +#if F_BUS == 60000000 + // 60 MHz for the Teensy 3.5/3.6 + PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus +#else + // 48 MHz for the Teensy 3.1/3.2 + PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus +#endif + PDB0_IDLY = 0; // Interrupt delay + PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | + PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | + PDB_SC_LDOK; + PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) + NVIC_ENABLE_IRQ(IRQ_PDB); + // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 @@ -150,29 +140,39 @@ void CIO::startInt() void CIO::interrupt() { - if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - 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; - sample = ADC0_RA; - m_rxBuffer.put(sample, control); + ADC0_SC1A = PIN_ADC; // Start read on A0 + + // Wait for the read to complete + while ((ADC0_SC1A & ADC_SC1_COCO) != ADC_SC1_COCO) + ; + + sample = ADC0_RA; + m_rxBuffer.put(sample, control); #if !defined(SEND_RSSI_DATA) - m_rssiBuffer.put(0U); + m_rssiBuffer.put(0U); #endif - m_watchdog++; - } - #if defined(SEND_RSSI_DATA) - if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { - uint16_t rssi = ADC1_RA; - m_rssiBuffer.put(rssi); - } + ADC1_SC1A = PIN_RSSI; // Start read on A2 + + // Wait for the read to complete + while ((ADC1_SC1A & ADC_SC1_COCO) != ADC_SC1_COCO) + ; + + uint16_t rssi = ADC1_RA; + m_rssiBuffer.put(rssi); #endif + + PDB0_SC &= ~PDB_SC_PDBIF; // Clear interrupt flag + + m_watchdog++; } bool CIO::getCOSInt() From e97c1dc746277419d772337f915c2741440cc761 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 11 Nov 2016 06:56:02 +0000 Subject: [PATCH 227/329] More work on Teensy interrupts. --- IO.h | 2 +- IODue.cpp | 6 ++--- IOSTM.cpp | 6 ++--- IOTeensy.cpp | 71 +++++++++++++++++++++++++++++++--------------------- 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/IO.h b/IO.h index 9e4dced..2113358 100644 --- a/IO.h +++ b/IO.h @@ -40,7 +40,7 @@ public: void setADCDetection(bool detect); void setMode(); - void interrupt(); + void interrupt(uint8_t source); 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 e465da3..17d4fa4 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -73,7 +73,7 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { void ADC_Handler() { - io.interrupt(); + io.interrupt(0U); } } @@ -97,7 +97,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(); + io.interrupt(0U); // Set up the ADC NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector @@ -157,7 +157,7 @@ void CIO::startInt() digitalWrite(PIN_LED, HIGH); } -void CIO::interrupt() +void CIO::interrupt(uint8_t source) { 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 39e4e99..fdfb2ae 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -68,7 +68,7 @@ extern "C" { void TIM2_IRQHandler() { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - io.interrupt(); + io.interrupt(0U); } } } @@ -163,7 +163,7 @@ void CIO::initInt() void CIO::startInt() { if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)) - io.interrupt(); + io.interrupt(0U); // ADC1 PA0 analog input // ADC2 PA1 analog input @@ -283,7 +283,7 @@ void CIO::startInt() GPIO_SetBits(PORT_LED, PIN_LED); } -void CIO::interrupt() +void CIO::interrupt(uint8_t source) { uint8_t control = MARK_NONE; uint16_t sample = DC_OFFSET; diff --git a/IOTeensy.cpp b/IOTeensy.cpp index c555f7d..1cd90f9 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -55,10 +55,17 @@ const uint16_t DC_OFFSET = 2048U; extern "C" { - void pdb_isr() + void adc0_isr() { - io.interrupt(); + io.interrupt(0U); } + +#if defined(SEND_RSSI_DATA) + void adc1_isr() + { + io.interrupt(1U); + } +#endif } void CIO::initInt() @@ -80,6 +87,14 @@ void CIO::initInt() void CIO::startInt() { + if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) + io.interrupt(0U); + +#if defined(SEND_RSSI_DATA) + if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) + io.interrupt(1U); +#endif + // Initialise ADC0 ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time @@ -95,6 +110,9 @@ void CIO::startInt() sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 + NVIC_ENABLE_IRQ(IRQ_ADC0); + #if defined(SEND_RSSI_DATA) // Initialise ADC1 ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | @@ -110,6 +128,9 @@ void CIO::startInt() uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; + + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 + NVIC_ENABLE_IRQ(IRQ_ADC1); #endif // Setup PDB for ADC0 at 24 kHz @@ -138,41 +159,35 @@ void CIO::startInt() digitalWrite(PIN_LED, HIGH); } -void CIO::interrupt() +void CIO::interrupt(uint8_t source) { - uint8_t control = MARK_NONE; - uint16_t sample = DC_OFFSET; + if (source == 0U) { // ADC0 + 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; - ADC0_SC1A = PIN_ADC; // Start read on A0 - - // Wait for the read to complete - while ((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) - m_rssiBuffer.put(0U); + m_rssiBuffer.put(0U); #endif + } + + m_watchdog++; + } #if defined(SEND_RSSI_DATA) - ADC1_SC1A = PIN_RSSI; // Start read on A2 - - // Wait for the read to complete - while ((ADC1_SC1A & ADC_SC1_COCO) != ADC_SC1_COCO) - ; - - uint16_t rssi = ADC1_RA; - m_rssiBuffer.put(rssi); + if (source == 1U) { // ADC1 + if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { + uint16_t rssi = ADC1_RA; + m_rssiBuffer.put(rssi); + } + } #endif - - PDB0_SC &= ~PDB_SC_PDBIF; // Clear interrupt flag - - m_watchdog++; } bool CIO::getCOSInt() From 052c5b30bd47834c3a64827334920af9526f403c Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sat, 12 Nov 2016 14:54:41 -0300 Subject: [PATCH 228/329] EXTERNAL_OSC change EXTERNAL_OSC disabled by default --- Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.h b/Config.h index 156e850..3eb0ed4 100644 --- a/Config.h +++ b/Config.h @@ -27,7 +27,7 @@ // Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable. // // For 12 MHz -#define EXTERNAL_OSC 12000000 +// #define EXTERNAL_OSC 12000000 // For 12.288 MHz // #define EXTERNAL_OSC 12288000 // For 14.4 MHz From 26e0801ff0ae7a1a8b04f44ea08cdadb4421b0fa Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sun, 13 Nov 2016 17:52:01 -0300 Subject: [PATCH 229/329] New linker script file for SMT32F4XX, some minor changes on Makefile --- Makefile | 8 +-- stm32_flash.ld | 170 ---------------------------------------------- stm32f4xx_link.ld | 138 +++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 174 deletions(-) delete mode 100644 stm32_flash.ld create mode 100644 stm32f4xx_link.ld diff --git a/Makefile b/Makefile index 4e72d56..96cd0e9 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F407VG CFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) CXXFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) # LINKER FLAGS -LDSCRIPT=stm32_flash.ld +LDSCRIPT=stm32f4xx_link.ld LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS) ### @@ -53,9 +53,9 @@ LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_L all: release-memopt release-memopt: DEFS+=-DCUSTOM_NEW -DNO_EXCEPTIONS -release-memopt: CFLAGS+=-Os -ffunction-sections -fdata-sections -fno-builtin # -flto -release-memopt: CXXFLAGS+=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti # -flto -release-memopt: LDFLAGS+=-Os --specs=nano.specs # -flto +release-memopt: CFLAGS+=-Os -ffunction-sections -fdata-sections -fno-builtin +release-memopt: CXXFLAGS+=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti +release-memopt: LDFLAGS+=-Os --specs=nano.specs release-memopt: release debug: CFLAGS+=-g diff --git a/stm32_flash.ld b/stm32_flash.ld deleted file mode 100644 index 1a0b4b8..0000000 --- a/stm32_flash.ld +++ /dev/null @@ -1,170 +0,0 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for STM32F407VG Device with -** 1024KByte FLASH, 192KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20020000; /* end of 128K RAM on AHB bus*/ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/stm32f4xx_link.ld b/stm32f4xx_link.ld new file mode 100644 index 0000000..24ee380 --- /dev/null +++ b/stm32f4xx_link.ld @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2016 by Andy Uribe CA6JAU + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Required amount of heap and stack */ +_min_heap_size = 0x1000; +_min_stack_size = 0x0800; + +/* The entry point in the interrupt vector table */ +ENTRY(Reset_Handler) + +/* Memory areas */ +MEMORY +{ + ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K /* FLASH */ + CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K /* Core Coupled Memory (CPU only access) */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Main RAM (bus matrix)*/ +} + +/* Stack start address (end of 128K RAM) */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .text : + { + /* The interrupt vector table */ + . = ALIGN(4); + KEEP(*(.isr_vector .isr_vector.*)) + + /* The program code */ + . = ALIGN(4); + *(.text .text*) + *(.rodata .rodata*) + + /* ARM-Thumb code */ + *(.glue_7) *(.glue_7t) + + . = ALIGN(4); + KEEP(*(.init)) + KEEP(*(.fini)) + + /* EABI C++ global constructors support */ + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + /* EABI C++ global constructors support */ + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + /* EABI C++ global constructors support */ + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + } > ROM + + /* ARM sections containing exception unwinding information */ + .ARM.extab : { + __extab_start = .; + *(.ARM.extab* .gnu.linkonce.armextab.*) + __extab_end = .; + } > ROM + + /* ARM index entries for section unwinding */ + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > ROM + + /* Start address for the initialization values of the .data section */ + _sidata = .; + + /* The .data section (initialized data) */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = . ; /* Start address for the .data section */ + *(.data .data*) + + . = ALIGN(4); + _edata = . ; /* End address for the .data section */ + } > RAM + + /* The .bss section (uninitialized data) */ + .bss : + { + . = ALIGN(4); + _sbss = .; /* Start address for the .bss section */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = . ; /* End address for the .bss section */ + __bss_end__ = _ebss; + } > RAM + + /* Space for heap and stack */ + .heap_stack : + { + end = . ; /* 'end' symbol defines heap location */ + _end = end ; + . = . + _min_heap_size; /* Additional space for heap and stack */ + . = . + _min_stack_size; + } > RAM + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } +} From 762482f6f58c1fba5761882c72833fc692b4e8ed Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 14 Nov 2016 11:41:58 +0000 Subject: [PATCH 230/329] Include the Teensy 3.5 as a supported platform. --- IOTeensy.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 1cd90f9..b59e3a4 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -20,10 +20,8 @@ #include "Globals.h" #include "IO.h" -#if defined(__MK20DX256__) || defined(__MK66FX1M0__) +#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) -// A Teensy 3.1/3.2 -#if defined(__MK20DX256__) #define PIN_LED 13 #define PIN_COS 52 #define PIN_PTT 23 @@ -35,20 +33,6 @@ #define PIN_ADC 5 // A0 #define PIN_RSSI 8 // A2 -// A Teensy 3.6 -#elif defined(__MK66FX1M0__) -#define PIN_LED 13 -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 -#define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 -#define PIN_ADC 5 // A0 -#define PIN_RSSI 8 // A2 -#endif - #define PDB_CH0C1_TOS 0x0100 #define PDB_CH0C1_EN 0x01 @@ -231,4 +215,3 @@ void CIO::setP25Int(bool on) } #endif - From f946824639adbd04eb006be2c9255484bdcc15dc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 14 Nov 2016 11:44:38 +0000 Subject: [PATCH 231/329] Add more info about the new platforms. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3bfea68..030f94c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25. -It runs on the Arduino Due, and the STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.6) is being added. +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. -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. +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. This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden. From de289c125826164a0b9818d3d7524d5bac804c91 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 14 Nov 2016 21:47:38 +0000 Subject: [PATCH 232/329] Further refinement of the Teensy IO. --- IOTeensy.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index b59e3a4..55c56df 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -33,8 +33,8 @@ #define PIN_ADC 5 // A0 #define PIN_RSSI 8 // A2 -#define PDB_CH0C1_TOS 0x0100 -#define PDB_CH0C1_EN 0x01 +#define PDB_CHnC1_TOS 0x0100 +#define PDB_CHnC1_EN 0x0001 const uint16_t DC_OFFSET = 2048U; @@ -84,9 +84,8 @@ void CIO::startInt() ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger - ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - ADC0_SC3 = ADC_SC3_CAL; // Begin calibration while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration ; @@ -103,9 +102,8 @@ void CIO::startInt() ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger - ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - ADC1_SC3 = ADC_SC3_CAL; // Begin calibration while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration ; @@ -117,20 +115,16 @@ void CIO::startInt() NVIC_ENABLE_IRQ(IRQ_ADC1); #endif - // Setup PDB for ADC0 at 24 kHz + // Setup PDB for ADC0 (and ADC1) at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock -#if F_BUS == 60000000 - // 60 MHz for the Teensy 3.5/3.6 - PDB0_MOD = 2500 - 1; // Timer period for 60 MHz bus -#else - // 48 MHz for the Teensy 3.1/3.2 - PDB0_MOD = 2000 - 1; // Timer period for 48 MHz bus -#endif + PDB0_MOD = F_BUS / 24000; // Timer period PDB0_IDLY = 0; // Interrupt delay - PDB0_CH0C1 = PDB_CH0C1_TOS | PDB_CH0C1_EN; // Enable pre-trigger - PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | PDB_SC_PDBIE | - PDB_SC_CONT | PDB_SC_PRESCALER(7) | PDB_SC_MULT(1) | - PDB_SC_LDOK; + PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 +#if defined(SEND_RSSI_DATA) + PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-t9rigger for ADC1 +#endif + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode + PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) NVIC_ENABLE_IRQ(IRQ_PDB); From cc051152809fe06c6643d1121891f95b3f08fe8c Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 14 Nov 2016 22:39:14 +0000 Subject: [PATCH 233/329] Enable the ADC clocks. --- IOTeensy.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 55c56df..385b7e2 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -80,38 +80,40 @@ void CIO::startInt() #endif // Initialise ADC0 - ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | - ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time - ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb - ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger - ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + SIM_SCGC6 |= SIM_SCGC6_ADC0; + ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | + ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time + ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb + ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger + ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration ; uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; // Plus side gain sum0 = (sum0 / 2U) | 0x8000U; - ADC0_PG = sum0; + ADC0_PG = sum0; ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 NVIC_ENABLE_IRQ(IRQ_ADC0); #if defined(SEND_RSSI_DATA) // Initialise ADC1 - ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | - ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time - ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb - ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger - ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + SIM_SCGC3 |= SIM_SCGC3_ADC1; + ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | + ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time + ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb + ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger + ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration ; uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; // Plus side gain sum1 = (sum1 / 2U) | 0x8000U; - ADC1_PG = sum1; + ADC1_PG = sum1; - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 NVIC_ENABLE_IRQ(IRQ_ADC1); #endif From dd5940fe2e042760f14eeeb1dad3002694ba3610 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Nov 2016 06:27:46 +0000 Subject: [PATCH 234/329] Add the Teensy 3.5 as a supported platform. --- Globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Globals.h b/Globals.h index 807417e..9e18082 100644 --- a/Globals.h +++ b/Globals.h @@ -36,7 +36,7 @@ #if defined(__SAM3X8E__) #define ARM_MATH_CM3 -#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK66FX1M0__) +#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define ARM_MATH_CM4 #else #error "Unknown processor type" From 59d93b5a6f61fb5a1e6445aeb5753d1e69bdacec Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Nov 2016 08:07:24 +0000 Subject: [PATCH 235/329] First attempt at using external clock for Teensy ADC. --- IOTeensy.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 385b7e2..a7d1806 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -50,6 +50,21 @@ extern "C" { io.interrupt(1U); } #endif + +#if defined(EXTERNAL_OSC) + void ftm0_isr() + { + FTM0_CNT = 0; // Reset count value + if ((FTM0_SC & FTM_SC_TOF) == FTM_SC_TOF) // Read the timer overflow flag (TOF in FTM0_SC) + FTM0_SC &= ~FTM_SC_TOF; // If set, clear overflow flag + + // Kick off the ADCs with interrupt at the end of conversion + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; +#if defined(SEND_RSSI_DATA) + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; +#endif + } +#endif } void CIO::initInt() @@ -84,7 +99,11 @@ void CIO::startInt() ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb +#if defined(EXTERNAL_OSC) + ADC0_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger +#else ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger +#endif ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration @@ -94,7 +113,10 @@ void CIO::startInt() sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; - ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 +#if !defined(EXTERNAL_OSC) + ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 +#endif + NVIC_ENABLE_IRQ(IRQ_ADC0); #if defined(SEND_RSSI_DATA) @@ -103,7 +125,11 @@ void CIO::startInt() ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb +#if defined(EXTERNAL_OSC) + ADC1_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger +#else ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger +#endif ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration @@ -113,22 +139,34 @@ void CIO::startInt() sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 +#if !defined(EXTERNAL_OSC) + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 +#endif + NVIC_ENABLE_IRQ(IRQ_ADC1); #endif +#if defined(EXTERNAL_OSC) + // Set up for an external oscillator input + SIM_SCGC6 |= SIM_SCGC6_FTM0; + FTM0_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; + FTM0_MOD = EXTERNAL_OSC / 24000; + FTM0_CNTIN = 0; + FTM0_SC = FTM_SC_TOIE | FTM_SC_CLKS(3); // External clock, overflow interrupts, no prescaling + NVIC_ENABLE_IRQ(IRQ_FTM0); +#else // Setup PDB for ADC0 (and ADC1) at 24 kHz - SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock - PDB0_MOD = F_BUS / 24000; // Timer period - PDB0_IDLY = 0; // Interrupt delay - PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 + SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock + PDB0_MOD = F_BUS / 24000; // Timer period + PDB0_IDLY = 0; // Interrupt delay + PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 #if defined(SEND_RSSI_DATA) - PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-t9rigger for ADC1 + PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-t9rigger for ADC1 +#endif + PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode + PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling + PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) #endif - PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode - PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling - PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) - NVIC_ENABLE_IRQ(IRQ_PDB); // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; From cd2042aa9b3cfa2ab439979c2d20046bb98bea42 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Nov 2016 17:04:51 +0000 Subject: [PATCH 236/329] Clean up pin assignments. --- IOTeensy.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index a7d1806..a0579c8 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -23,13 +23,13 @@ #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define PIN_LED 13 -#define PIN_COS 52 -#define PIN_PTT 23 -#define PIN_COSLED 22 +#define PIN_COS 4 +#define PIN_PTT 5 +#define PIN_COSLED 6 #define PIN_DSTAR 9 -#define PIN_DMR 8 -#define PIN_YSF 7 -#define PIN_P25 6 +#define PIN_DMR 10 +#define PIN_YSF 11 +#define PIN_P25 12 #define PIN_ADC 5 // A0 #define PIN_RSSI 8 // A2 @@ -166,6 +166,7 @@ void CIO::startInt() PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) + NVIC_ENABLE_IRQ(IRQ_PDB); #endif // Initialise the DAC From df202e19df90762c4e16a8c85af198e72ad6db85 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 15 Nov 2016 18:59:57 +0000 Subject: [PATCH 237/329] Use the LPTMR to triger the ADC from an external oscillator. --- IOTeensy.cpp | 58 +++++++++++++++++++--------------------------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index a0579c8..66adc7e 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -22,7 +22,11 @@ #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) +#if defined(EXTERNAL_OSC) +#define PIN_LED 3 +#else #define PIN_LED 13 +#endif #define PIN_COS 4 #define PIN_PTT 5 #define PIN_COSLED 6 @@ -50,21 +54,6 @@ extern "C" { io.interrupt(1U); } #endif - -#if defined(EXTERNAL_OSC) - void ftm0_isr() - { - FTM0_CNT = 0; // Reset count value - if ((FTM0_SC & FTM_SC_TOF) == FTM_SC_TOF) // Read the timer overflow flag (TOF in FTM0_SC) - FTM0_SC &= ~FTM_SC_TOF; // If set, clear overflow flag - - // Kick off the ADCs with interrupt at the end of conversion - ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; -#if defined(SEND_RSSI_DATA) - ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; -#endif - } -#endif } void CIO::initInt() @@ -99,11 +88,7 @@ void CIO::startInt() ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb -#if defined(EXTERNAL_OSC) - ADC0_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger -#else ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger -#endif ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration @@ -113,10 +98,7 @@ void CIO::startInt() sum0 = (sum0 / 2U) | 0x8000U; ADC0_PG = sum0; -#if !defined(EXTERNAL_OSC) ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0 -#endif - NVIC_ENABLE_IRQ(IRQ_ADC0); #if defined(SEND_RSSI_DATA) @@ -125,11 +107,7 @@ void CIO::startInt() ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; // Single-ended 12 bits, long sample time ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb -#if defined(EXTERNAL_OSC) - ADC1_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger -#else ADC1_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger -#endif ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration @@ -139,21 +117,27 @@ void CIO::startInt() sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; -#if !defined(EXTERNAL_OSC) ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 -#endif - NVIC_ENABLE_IRQ(IRQ_ADC1); #endif #if defined(EXTERNAL_OSC) - // Set up for an external oscillator input - SIM_SCGC6 |= SIM_SCGC6_FTM0; - FTM0_MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN; - FTM0_MOD = EXTERNAL_OSC / 24000; - FTM0_CNTIN = 0; - FTM0_SC = FTM_SC_TOIE | FTM_SC_CLKS(3); // External clock, overflow interrupts, no prescaling - NVIC_ENABLE_IRQ(IRQ_FTM0); + SIM_SCGC5 |= SIM_SCGC5_LPTIMER; + LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter + LPTMR0_CMR = EXTERNAL_OSC / 24000; + LPTMR0_CSR = LPTMR_CSR_TIE | LPTMR_CSR_TPS(2) | // Interrupt, counter, input=Alt2, free running mode, enable + LPTMR_CSR_TFC | LPTMR_CSR_TMS | + LPTMR_CSR_TEN; + + CORE_PIN13_CONFIG = PORT_PCR_MUX(3); + + // Set ADC0 to trigger from the LPTMR + SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | SIM_SOPT7_ADC0TRGSEL(14); +#if defined(SEND_RSSI_DATA) + // Set ADC1 to trigger from the LPTMR + SIM_SOPT7 |= SIM_SOPT7_ADC1ALTTRGEN | SIM_SOPT7_ADC1TRGSEL(14); +#endif + NVIC_ENABLE_IRQ(IRQ_LPTMR); #else // Setup PDB for ADC0 (and ADC1) at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock @@ -161,7 +145,7 @@ void CIO::startInt() PDB0_IDLY = 0; // Interrupt delay PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0 #if defined(SEND_RSSI_DATA) - PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-t9rigger for ADC1 + PDB0_CH1C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC1 #endif PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling From 381afbb70af0aa6010351d4d920b166da15ed6d7 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Wed, 16 Nov 2016 01:06:26 -0300 Subject: [PATCH 238/329] Simplifying STM32F4XX library definitions, some minor changes on Makefile --- Globals.h | 13 ------------- Makefile | 3 ++- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Globals.h b/Globals.h index 9e18082..82d4f8e 100644 --- a/Globals.h +++ b/Globals.h @@ -21,15 +21,6 @@ #if defined(STM32F4XX) || defined(STM32F4) #include "stm32f4xx.h" -#include "stm32f4xx_gpio.h" -#include "stm32f4xx_rcc.h" -#include "stm32f4xx_dac.h" -#include "stm32f4xx_adc.h" -#include "stm32f4xx_tim.h" -#include "stm32f4xx_usart.h" -#include "misc.h" -#include -#include #else #include #endif @@ -42,11 +33,7 @@ #error "Unknown processor type" #endif -#if defined(STM32F4XX) || defined(STM32F4) -#include "cmsis.h" -#else #include -#endif enum MMDVM_STATE { STATE_IDLE = 0, diff --git a/Makefile b/Makefile index 96cd0e9..f5816d1 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ CXXSOURCES=$(shell find . -name '*.cpp') INC=$(shell find . -name '*.h' -exec dirname {} \; | uniq) INCLUDES=$(INC:%=-I%) # Find libraries -INCLUDES_LIBS=libarm_cortexM4lf_math.a +INCLUDES_LIBS=STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a LINK_LIBS= # Create object list OBJECTS=$(ASOURCES:%.s=%.o) @@ -70,6 +70,7 @@ $(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF) @echo "Objcopy from ELF to IHEX complete!\n" $(BINDIR)/$(BINELF): $(OBJECTS) + @mkdir -p $(@D) $(CXX) $(OBJECTS) $(LDFLAGS) -o $@ @echo "Linking complete!\n" $(SIZE) $(BINDIR)/$(BINELF) From 9098161032aa3a5ce7405b22bae1b15f66fc4f09 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Wed, 16 Nov 2016 01:57:17 -0300 Subject: [PATCH 239/329] Update CooCox project files --- MMDVM_STM32F4xx.cogui | 968 +++++++++++++++++++-------------------- MMDVM_STM32F4xx.comarker | 44 +- MMDVM_STM32F4xx.coproj | 138 +++--- 3 files changed, 578 insertions(+), 572 deletions(-) diff --git a/MMDVM_STM32F4xx.cogui b/MMDVM_STM32F4xx.cogui index 0b4cff9..7834d26 100644 --- a/MMDVM_STM32F4xx.cogui +++ b/MMDVM_STM32F4xx.cogui @@ -1,485 +1,485 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MMDVM_STM32F4xx.comarker b/MMDVM_STM32F4xx.comarker index b78ac1c..22e5da1 100644 --- a/MMDVM_STM32F4xx.comarker +++ b/MMDVM_STM32F4xx.comarker @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MMDVM_STM32F4xx.coproj b/MMDVM_STM32F4xx.coproj index c0fa940..95312cb 100644 --- a/MMDVM_STM32F4xx.coproj +++ b/MMDVM_STM32F4xx.coproj @@ -25,17 +25,14 @@ \ No newline at end of file diff --git a/MMDVM_STM32F4xx.comarker b/MMDVM_STM32F4xx.comarker index 22e5da1..b29d0e4 100644 --- a/MMDVM_STM32F4xx.comarker +++ b/MMDVM_STM32F4xx.comarker @@ -16,8 +16,8 @@ - + \ No newline at end of file diff --git a/MMDVM_STM32F4xx.coproj b/MMDVM_STM32F4xx.coproj index 95312cb..3038fa0 100644 --- a/MMDVM_STM32F4xx.coproj +++ b/MMDVM_STM32F4xx.coproj @@ -13,12 +13,12 @@ - + @@ -97,9 +97,9 @@ + - @@ -115,29 +115,29 @@ - - + + + - + - - - + + @@ -175,16 +175,16 @@ - + - + diff --git a/Makefile b/Makefile index d0fb1f5..890e2f0 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,9 @@ BINHEX=outp.hex MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork # COMPILE FLAGS -DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DHSE_VALUE=12000000 +# Discovery board: +DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DHSE_VALUE=8000000 +# Pi board: #DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DHSE_VALUE=12000000 CFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) CXXFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) From ac47130c71d4da430f90219e8bc1a2f8dfe9f3f6 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Nov 2016 17:49:36 +0000 Subject: [PATCH 252/329] Bump the version date. --- SerialPort.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SerialPort.cpp b/SerialPort.cpp index e73dc98..29535f7 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -68,9 +68,9 @@ const uint8_t MMDVM_DEBUG4 = 0xF4U; const uint8_t MMDVM_DEBUG5 = 0xF5U; #if defined(EXTERNAL_OSC) -const uint8_t HARDWARE[] = "MMDVM 20161021 TCXO (D-Star/DMR/System Fusion/P25/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20161124 TCXO (D-Star/DMR/System Fusion/P25/CW Id)"; #else -const uint8_t HARDWARE[] = "MMDVM 20161021 (D-Star/DMR/System Fusion/P25/CW Id)"; +const uint8_t HARDWARE[] = "MMDVM 20161124 (D-Star/DMR/System Fusion/P25/CW Id)"; #endif const uint8_t PROTOCOL_VERSION = 1U; From e6e887e4af0650c3f1cc1936f7932982acb56c77 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sun, 27 Nov 2016 01:07:10 -0300 Subject: [PATCH 253/329] Adding Windows shell support for Makefile, oscillator frequency option and target selection. --- Makefile | 107 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 890e2f0..3a2d5fa 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,20 @@ -### +# Copyright (C) 2016 by Andy Uribe CA6JAU +# Copyright (C) 2016 by Jim McLaughlin KI6ZUM + +# 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + # GNU ARM Embedded Toolchain CC=arm-none-eabi-gcc CXX=arm-none-eabi-g++ @@ -11,69 +27,111 @@ NM=arm-none-eabi-nm SIZE=arm-none-eabi-size A2L=arm-none-eabi-addr2line -### # Directory Structure BINDIR=bin -### # Find source files -ASOURCES=$(shell find . -name '*.s') -CSOURCES=$(shell find . -name '*.c') -CXXSOURCES=$(shell find . -name '*.cpp') +# "SystemRoot" is only defined in Windows +ifdef SYSTEMROOT + ASOURCES=$(shell dir /S /B *.s) + CSOURCES=$(shell dir /S /B *.c) + CXXSOURCES=$(shell dir /S /B *.cpp) + CLEANCMD=del /S *.o *.hex *.bin *.elf + MDBIN=md $@ +else ifdef SystemRoot + ASOURCES=$(shell dir /S /B *.s) + CSOURCES=$(shell dir /S /B *.c) + CXXSOURCES=$(shell dir /S /B *.cpp) + CLEANCMD=del /S *.o *.hex *.bin *.elf + MDBIN=md $@ +else + ASOURCES=$(shell find . -name '*.s') + CSOURCES=$(shell find . -name '*.c') + CXXSOURCES=$(shell find . -name '*.cpp') + CLEANCMD=rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX) $(BINDIR)/$(BINBIN) + MDBIN=mkdir $@ +endif + +# Default reference oscillator frequencies +ifndef $(OSC) + ifeq ($(MAKECMDGOALS),pi) + OSC=12000000 + else + OSC=8000000 + endif +endif + # Find header directories -INC=$(shell find . -name '*.h' -exec dirname {} \; | uniq) +INC= . STM32F4XX_Lib/CMSIS/Include/ STM32F4XX_Lib/Device/ STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/ INCLUDES=$(INC:%=-I%) + # Find libraries INCLUDES_LIBS=STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a LINK_LIBS= + # Create object list OBJECTS=$(ASOURCES:%.s=%.o) OBJECTS+=$(CSOURCES:%.c=%.o) OBJECTS+=$(CXXSOURCES:%.cpp=%.o) + # Define output files ELF & IHEX BINELF=outp.elf BINHEX=outp.hex +BINBIN=outp.bin -### # MCU FLAGS MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork + # COMPILE FLAGS -# Discovery board: -DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DHSE_VALUE=8000000 +# STM32F4 Discovery board: +DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DHSE_VALUE=$(OSC) # Pi board: -#DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DHSE_VALUE=12000000 -CFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) -CXXFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES) +DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DHSE_VALUE=$(OSC) +CFLAGS=-c $(MCFLAGS) $(INCLUDES) +CXXFLAGS=-c $(MCFLAGS) $(INCLUDES) + # LINKER FLAGS LDSCRIPT=stm32f4xx_link.ld LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS) -### # Build Rules -.PHONY: all release release-memopt debug clean +.PHONY: all release dis pi debug clean -all: release-memopt +# Default target: STM32F4 Discovery board +all: dis -release-memopt: DEFS+=-DCUSTOM_NEW -DNO_EXCEPTIONS -release-memopt: CFLAGS+=-Os -ffunction-sections -fdata-sections -fno-builtin -release-memopt: CXXFLAGS+=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -release-memopt: LDFLAGS+=-Os --specs=nano.specs -release-memopt: release +pi: CFLAGS+=$(DEFS_PI) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS +pi: CXXFLAGS+=$(DEFS_PI) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS +pi: LDFLAGS+=-Os --specs=nano.specs +pi: release + +dis: CFLAGS+=$(DEFS_DIS) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS +dis: CXXFLAGS+=$(DEFS_DIS) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS +dis: LDFLAGS+=-Os --specs=nano.specs +dis: release debug: CFLAGS+=-g debug: CXXFLAGS+=-g debug: LDFLAGS+=-g debug: release +release: $(BINDIR) release: $(BINDIR)/$(BINHEX) +release: $(BINDIR)/$(BINBIN) + +$(BINDIR): + $(MDBIN) $(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF) $(CP) -O ihex $< $@ @echo "Objcopy from ELF to IHEX complete!\n" + +$(BINDIR)/$(BINBIN): $(BINDIR)/$(BINELF) + $(CP) -O binary $< $@ + @echo "Objcopy from ELF to BINARY complete!\n" $(BINDIR)/$(BINELF): $(OBJECTS) - @mkdir -p $(@D) $(CXX) $(OBJECTS) $(LDFLAGS) -o $@ @echo "Linking complete!\n" $(SIZE) $(BINDIR)/$(BINELF) @@ -91,8 +149,8 @@ $(BINDIR)/$(BINELF): $(OBJECTS) @echo "Assambled "$<"!\n" clean: - rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX) $(BINDIR)/output.map - + $(CLEANCMD) + deploy: ifneq ($(wildcard /usr/bin/openocd),) /usr/bin/openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit" @@ -105,4 +163,3 @@ endif ifneq ($(wildcard /opt/openocd/bin/openocd),) /opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit" endif - From 9144ed41ec47e686c3ed9295e9bd2087ff29eac1 Mon Sep 17 00:00:00 2001 From: phl0 Date: Mon, 28 Nov 2016 12:44:45 +0100 Subject: [PATCH 254/329] Correct calibration --- IOTeensy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index eb0bbbb..2485f32 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -91,7 +91,7 @@ void CIO::startInt() ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - while ((ADC0_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + while ((ADC0_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration ; uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + // Plus side gain @@ -111,7 +111,7 @@ void CIO::startInt() ADC1_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples - while ((ADC1_SC3 & ADC_SC3_CAL) == ADC_SC3_CAL) // Wait for calibration + while ((ADC1_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration ; uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + // Plus side gain From 4584b20c451a0609f243f4c30f326fecf7438463 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 28 Nov 2016 14:02:21 +0000 Subject: [PATCH 255/329] Make calibration into a seperate step. --- IOTeensy.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 2485f32..49e8a03 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -75,22 +75,15 @@ void CIO::initInt() void CIO::startInt() { - if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) - io.interrupt(0U); - -#if defined(SEND_RSSI_DATA) - if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) - io.interrupt(1U); -#endif - // Initialise ADC0 SIM_SCGC6 |= SIM_SCGC6_ADC0; ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC0_SC2 = ADC_SC2_REFSEL(1) | ADC_SC2_ADTRG; // Voltage ref internal, hardware trigger - ADC0_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC0_SC3 = ADC_SC3_CAL; while ((ADC0_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration ; @@ -109,8 +102,9 @@ void CIO::startInt() ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb ADC1_SC2 = ADC_SC2_REFSEL(1); // Voltage ref internal, software trigger - ADC1_SC3 = ADC_SC3_CAL | ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples + ADC1_SC3 = ADC_SC3_CAL; while ((ADC1_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration ; From 91b4dddd8b873d5b2ea996f8bc421d94c3ff18a7 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 28 Nov 2016 16:20:51 +0000 Subject: [PATCH 256/329] Disable ADC clocks. --- IOTeensy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 49e8a03..f99b1dd 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -76,7 +76,7 @@ void CIO::initInt() void CIO::startInt() { // Initialise ADC0 - SIM_SCGC6 |= SIM_SCGC6_ADC0; + // SIM_SCGC6 |= SIM_SCGC6_ADC0; ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -97,7 +97,7 @@ void CIO::startInt() #if defined(SEND_RSSI_DATA) // Initialise ADC1 - SIM_SCGC3 |= SIM_SCGC3_ADC1; + // SIM_SCGC3 |= SIM_SCGC3_ADC1; ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb From 004205192c730b4d38776949b533ce890d43070f Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Tue, 29 Nov 2016 01:35:00 -0300 Subject: [PATCH 257/329] Adding Pi board support --- Config.h | 12 +++- IOSTM.cpp | 202 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 135 insertions(+), 79 deletions(-) diff --git a/Config.h b/Config.h index 3eb0ed4..bb47e63 100644 --- a/Config.h +++ b/Config.h @@ -39,24 +39,30 @@ // #define USE_COS_AS_LOCKOUT // Use pins to output the current mode -// #define ARDUINO_MODE_PINS +#define ARDUINO_MODE_PINS // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA // For the ZUM V1.0 and V1.0.1 boards pin layout -#define ARDUINO_DUE_ZUM_V10 +// #define ARDUINO_DUE_ZUM_V10 // For the SP8NTH board // #define ARDUINO_DUE_NTH +// For the STM32F4 Discovery Board +#define STM32F4_DISCOVERY + +// For the STM32F4 Pi Board +// #define STM32F4_PI + // To use wider C4FSK filters for DMR, System Fusion and P25 on transmit // #define WIDE_C4FSK_FILTERS_TX // To use wider C4FSK filters for DMR, System Fusion and P25 on receive // #define WIDE_C4FSK_FILTERS_RX // Pass RSSI information to the host -// #define SEND_RSSI_DATA +#define SEND_RSSI_DATA // Use the modem as a serial repeater for Nextion displays // #define SERIAL_REPEATER diff --git a/IOSTM.cpp b/IOSTM.cpp index fdfb2ae..2681eb9 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -23,44 +23,124 @@ #if defined(STM32F4XX) || defined(STM32F4) +#if defined(STM32F4_DISCOVERY) /* -Pin definitions: +Pin definitions for STM32F4 Discovery Board: PTT PA6 output COSLED PA7 output LED PD15 output COS PA5 input -ADC1 PA0 analog input -ADC2 PA1 analog input -DAC1 PA4 analog output DSTAR PD12 output DMR PD13 output YSF PD14 output P25 PD11 output + +RX PA0 analog input +RSSI PA1 analog input +TX PA4 analog output */ -#define PIN_COS GPIO_Pin_5 -#define PORT_COS GPIOA -#define PIN_PTT GPIO_Pin_6 -#define PORT_PTT GPIOA -#define PIN_COSLED GPIO_Pin_7 -#define PORT_COSLED GPIOA -#define PIN_LED GPIO_Pin_15 -#define PORT_LED GPIOD -#define PIN_ADC GPIO_Pin_0 -#define PORT_ADC GPIOA -#define PIN_DAC GPIO_Pin_4 -#define PORT_DAC GPIOA +#define PIN_COS GPIO_Pin_5 +#define PORT_COS GPIOA +#define RCC_Per_COS RCC_AHB1Periph_GPIOA + +#define PIN_PTT GPIO_Pin_6 +#define PORT_PTT GPIOA +#define RCC_Per_PTT RCC_AHB1Periph_GPIOA + +#define PIN_COSLED GPIO_Pin_7 +#define PORT_COSLED GPIOA +#define RCC_Per_COSLED RCC_AHB1Periph_GPIOA + +#define PIN_LED GPIO_Pin_15 +#define PORT_LED GPIOD +#define RCC_Per_LED RCC_AHB1Periph_GPIOD + +#define PIN_P25 GPIO_Pin_11 +#define PORT_P25 GPIOD +#define RCC_Per_P25 RCC_AHB1Periph_GPIOD + +#define PIN_DSTAR GPIO_Pin_12 +#define PORT_DSTAR GPIOD +#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOD + +#define PIN_DMR GPIO_Pin_13 +#define PORT_DMR GPIOD +#define RCC_Per_DMR RCC_AHB1Periph_GPIOD + +#define PIN_YSF GPIO_Pin_14 +#define PORT_YSF GPIOD +#define RCC_Per_YSF RCC_AHB1Periph_GPIOD + +#define PIN_RX GPIO_Pin_0 +#define PIN_RX_CH ADC_Channel_0 + +#define PIN_RSSI GPIO_Pin_1 +#define PIN_RSSI_CH ADC_Channel_1 + +#elif defined(STM32F4_PI) +/* +Pin definitions for STM32F4 Pi Board: + +PTT PB13 output +COSLED PB14 output +LED PB15 output +COS PC0 input + +DSTAR PC7 output +DMR PC8 output +YSF PA8 output +P25 PC9 output + +RX PA0 analog input +RSSI PA7 analog input +TX PA4 analog output +*/ + +#define PIN_COS GPIO_Pin_0 +#define PORT_COS GPIOC +#define RCC_Per_COS RCC_AHB1Periph_GPIOC + +#define PIN_PTT GPIO_Pin_13 +#define PORT_PTT GPIOB +#define RCC_Per_PTT RCC_AHB1Periph_GPIOB + +#define PIN_COSLED GPIO_Pin_14 +#define PORT_COSLED GPIOB +#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB + +#define PIN_LED GPIO_Pin_15 +#define PORT_LED GPIOB +#define RCC_Per_LED RCC_AHB1Periph_GPIOB + +#define PIN_P25 GPIO_Pin_9 +#define PORT_P25 GPIOC +#define RCC_Per_P25 RCC_AHB1Periph_GPIOC + +#define PIN_DSTAR GPIO_Pin_7 +#define PORT_DSTAR GPIOC +#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC + +#define PIN_DMR GPIO_Pin_8 +#define PORT_DMR GPIOC +#define RCC_Per_DMR RCC_AHB1Periph_GPIOC + +#define PIN_YSF GPIO_Pin_8 +#define PORT_YSF GPIOA +#define RCC_Per_YSF RCC_AHB1Periph_GPIOA + +#define PIN_RX GPIO_Pin_0 +#define PIN_RX_CH ADC_Channel_0 + +#define PIN_RSSI GPIO_Pin_7 +#define PIN_RSSI_CH ADC_Channel_7 + +#else +#error "Either STM32F4_DISCOVERY or STM32F4_PI need to be defined" +#endif -#define PIN_P25 GPIO_Pin_11 -#define PORT_P25 GPIOD -#define PIN_DSTAR GPIO_Pin_12 -#define PORT_DSTAR GPIOD -#define PIN_DMR GPIO_Pin_13 -#define PORT_DMR GPIOD -#define PIN_YSF GPIO_Pin_14 -#define PORT_YSF GPIOD const uint16_t DC_OFFSET = 2048U; @@ -76,86 +156,58 @@ extern "C" { void CIO::initInt() { GPIO_InitTypeDef GPIO_InitStruct; - - // PTT pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_StructInit(&GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = PIN_PTT; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; + + // PTT pin + RCC_AHB1PeriphClockCmd(RCC_Per_PTT, ENABLE); + GPIO_InitStruct.GPIO_Pin = PIN_PTT; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(PORT_PTT, &GPIO_InitStruct); // COSLED pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_COSLED, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_COSLED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_COSLED, &GPIO_InitStruct); // LED pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_LED, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_LED; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_LED, &GPIO_InitStruct); // Init the input pins PIN_COS - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_COS, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_COS; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(PORT_COS, &GPIO_InitStruct); #if defined(ARDUINO_MODE_PINS) // DSTAR pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_DSTAR, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_DSTAR; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_DSTAR, &GPIO_InitStruct); // DMR pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_DMR, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_DMR; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_DMR, &GPIO_InitStruct); // YSF pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_YSF, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_YSF; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_YSF, &GPIO_InitStruct); // P25 pin - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); - GPIO_StructInit(&GPIO_InitStruct); + RCC_AHB1PeriphClockCmd(RCC_Per_P25, ENABLE); GPIO_InitStruct.GPIO_Pin = PIN_P25; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(PORT_P25, &GPIO_InitStruct); #endif } @@ -164,10 +216,6 @@ void CIO::startInt() { if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)) io.interrupt(0U); - - // ADC1 PA0 analog input - // ADC2 PA1 analog input - // DAC1 PA4 analog output // Init the ADC GPIO_InitTypeDef GPIO_InitStruct; @@ -186,11 +234,10 @@ void CIO::startInt() RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); #endif - // For ADC1 on PA0, ADC2 on PA1 #if defined(SEND_RSSI_DATA) - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; + GPIO_InitStruct.GPIO_Pin = PIN_RX | PIN_RSSI; #else - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; + GPIO_InitStruct.GPIO_Pin = PIN_RX; #endif GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ; @@ -219,7 +266,7 @@ void CIO::startInt() ADC_Init(ADC1, &ADC_InitStructure); ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE); - ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles); + ADC_RegularChannelConfig(ADC1, PIN_RX_CH, 1, ADC_SampleTime_3Cycles); // Enable ADC1 ADC_Cmd(ADC1, ENABLE); @@ -228,7 +275,7 @@ void CIO::startInt() ADC_Init(ADC2, &ADC_InitStructure); ADC_EOCOnEachRegularChannelCmd(ADC2, ENABLE); - ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_3Cycles); + ADC_RegularChannelConfig(ADC2, PIN_RSSI_CH, 1, ADC_SampleTime_3Cycles); // Enable ADC2 ADC_Cmd(ADC2, ENABLE); @@ -240,13 +287,13 @@ void CIO::startInt() GPIO_StructInit(&GPIO_InitStruct); DAC_StructInit(&DAC_InitStructure); - // GPIOA & D clock enable + // GPIOA clock enable RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // DAC Periph clock enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); - // GPIO CONFIGURATION of DAC Pins + // GPIO CONFIGURATION of DAC Pins (PA4) GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; @@ -263,7 +310,10 @@ void CIO::startInt() TIM_TimeBaseInitTypeDef timerInitStructure; TIM_TimeBaseStructInit (&timerInitStructure); - timerInitStructure.TIM_Prescaler = 1749; // 24 kHz + + // TIM2 at 24 kHz + timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*24000)) - 1); + timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_Period = 1; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; From a40506aff0c577819ef9a8ac03c0f531d7503ffc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Nov 2016 09:22:32 +0000 Subject: [PATCH 258/329] More interrupt changes. --- IOTeensy.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index f99b1dd..d7cfbfb 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -76,7 +76,7 @@ void CIO::initInt() void CIO::startInt() { // Initialise ADC0 - // SIM_SCGC6 |= SIM_SCGC6_ADC0; + SIM_SCGC6 |= SIM_SCGC6_ADC0; ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -84,7 +84,7 @@ void CIO::startInt() ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples ADC0_SC3 = ADC_SC3_CAL; - while ((ADC0_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration + while (ADC0_SC3 & ADC_SC3_CAL) // Wait for calibration ; uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + // Plus side gain @@ -97,7 +97,7 @@ void CIO::startInt() #if defined(SEND_RSSI_DATA) // Initialise ADC1 - // SIM_SCGC3 |= SIM_SCGC3_ADC1; + SIM_SCGC3 |= SIM_SCGC3_ADC1; ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP; ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb @@ -105,7 +105,7 @@ void CIO::startInt() ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples ADC1_SC3 = ADC_SC3_CAL; - while ((ADC1_SC3 & ADC_SC3_CAL) != ADC_SC3_CAL) // Wait for calibration + while (ADC1_SC3 & ADC_SC3_CAL) // Wait for calibration ; uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + // Plus side gain @@ -113,6 +113,7 @@ void CIO::startInt() sum1 = (sum1 / 2U) | 0x8000U; ADC1_PG = sum1; + ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; // Enable ADC interrupt, use A2 NVIC_ENABLE_IRQ(IRQ_ADC1); #endif @@ -131,7 +132,7 @@ void CIO::startInt() !SIM_SOPT7_ADC0PRETRGSEL | SIM_SOPT7_ADC0TRGSEL(14); - NVIC_ENABLE_IRQ(IRQ_LPTMR); + // NVIC_ENABLE_IRQ(IRQ_LPTMR); #else // Setup PDB for ADC0 (and ADC1) at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock @@ -141,7 +142,7 @@ void CIO::startInt() PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) - NVIC_ENABLE_IRQ(IRQ_PDB); + // NVIC_ENABLE_IRQ(IRQ_PDB); #endif // Initialise the DAC From 77829f31573a79ae4c6a656ff4a497868cee7ebb Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Nov 2016 16:34:11 +0000 Subject: [PATCH 259/329] Small tweak to the LPTMR. --- IOTeensy.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index d7cfbfb..a96a66f 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -129,12 +129,9 @@ void CIO::startInt() // Set ADC0 to trigger from the LPTMR SIM_SOPT7 |= SIM_SOPT7_ADC0ALTTRGEN | - !SIM_SOPT7_ADC0PRETRGSEL | SIM_SOPT7_ADC0TRGSEL(14); - - // NVIC_ENABLE_IRQ(IRQ_LPTMR); #else - // Setup PDB for ADC0 (and ADC1) at 24 kHz + // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock PDB0_MOD = F_BUS / 24000; // Timer period PDB0_IDLY = 0; // Interrupt delay @@ -142,7 +139,6 @@ void CIO::startInt() PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) - // NVIC_ENABLE_IRQ(IRQ_PDB); #endif // Initialise the DAC From e640e469fcda67e6c7b548fcee5e1da2cd037c82 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 29 Nov 2016 16:37:43 +0000 Subject: [PATCH 260/329] Change SIM_SOPT7 setting. --- IOTeensy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index a96a66f..6f629a6 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -128,7 +128,7 @@ void CIO::startInt() CORE_PIN13_CONFIG = PORT_PCR_MUX(3); // Set ADC0 to trigger from the LPTMR - SIM_SOPT7 |= SIM_SOPT7_ADC0ALTTRGEN | + SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | SIM_SOPT7_ADC0TRGSEL(14); #else // Setup PDB for ADC0 at 24 kHz From 765c6809134a4bc5f82197fe6957e8fbb49cd435 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Tue, 29 Nov 2016 20:06:42 -0300 Subject: [PATCH 261/329] Adding Pi board support (STM32F446) --- Config.h | 12 +-- IOSTM.cpp | 8 +- Makefile | 4 +- SerialSTM.cpp | 245 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 235 insertions(+), 34 deletions(-) diff --git a/Config.h b/Config.h index bb47e63..3eb0ed4 100644 --- a/Config.h +++ b/Config.h @@ -39,30 +39,24 @@ // #define USE_COS_AS_LOCKOUT // Use pins to output the current mode -#define ARDUINO_MODE_PINS +// #define ARDUINO_MODE_PINS // For the original Arduino Due pin layout // #define ARDUINO_DUE_PAPA // For the ZUM V1.0 and V1.0.1 boards pin layout -// #define ARDUINO_DUE_ZUM_V10 +#define ARDUINO_DUE_ZUM_V10 // For the SP8NTH board // #define ARDUINO_DUE_NTH -// For the STM32F4 Discovery Board -#define STM32F4_DISCOVERY - -// For the STM32F4 Pi Board -// #define STM32F4_PI - // To use wider C4FSK filters for DMR, System Fusion and P25 on transmit // #define WIDE_C4FSK_FILTERS_TX // To use wider C4FSK filters for DMR, System Fusion and P25 on receive // #define WIDE_C4FSK_FILTERS_RX // Pass RSSI information to the host -#define SEND_RSSI_DATA +// #define SEND_RSSI_DATA // Use the modem as a serial repeater for Nextion displays // #define SERIAL_REPEATER diff --git a/IOSTM.cpp b/IOSTM.cpp index 2681eb9..12265ad 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -27,7 +27,7 @@ /* Pin definitions for STM32F4 Discovery Board: -PTT PA6 output +PTT PB13 output COSLED PA7 output LED PD15 output COS PA5 input @@ -46,9 +46,9 @@ TX PA4 analog output #define PORT_COS GPIOA #define RCC_Per_COS RCC_AHB1Periph_GPIOA -#define PIN_PTT GPIO_Pin_6 -#define PORT_PTT GPIOA -#define RCC_Per_PTT RCC_AHB1Periph_GPIOA +#define PIN_PTT GPIO_Pin_13 +#define PORT_PTT GPIOB +#define RCC_Per_PTT RCC_AHB1Periph_GPIOB #define PIN_COSLED GPIO_Pin_7 #define PORT_COSLED GPIOA diff --git a/Makefile b/Makefile index 3a2d5fa..d23d1e8 100644 --- a/Makefile +++ b/Makefile @@ -85,9 +85,9 @@ MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ # COMPILE FLAGS # STM32F4 Discovery board: -DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DHSE_VALUE=$(OSC) +DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) # Pi board: -DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DHSE_VALUE=$(OSC) +DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) CFLAGS=-c $(MCFLAGS) $(INCLUDES) CXXFLAGS=-c $(MCFLAGS) $(INCLUDES) diff --git a/SerialSTM.cpp b/SerialSTM.cpp index 73cde0a..2955508 100644 --- a/SerialSTM.cpp +++ b/SerialSTM.cpp @@ -24,7 +24,7 @@ #if defined(STM32F4XX) || defined(STM32F4) -volatile uint32_t intcount1, intcount3; +volatile uint32_t intcount1, intcount3, intcount5; #define TX_SERIAL_FIFO_SIZE 256U #define RX_SERIAL_FIFO_SIZE 256U @@ -39,9 +39,15 @@ volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; +volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead5, TXSerialfifotail5; +volatile uint16_t RXSerialfifohead5, RXSerialfifotail5; + extern "C" { void USART1_IRQHandler(); void USART3_IRQHandler(); + void UART5_IRQHandler(); } /* ************* USART1 ***************** */ @@ -330,15 +336,15 @@ void USART3_IRQHandler() void InitUSART3(int speed) { - // USART3 - TXD PB10 - RXD PB11 - pins when jumpered from FTDI board to F4Discovery board + // USART3 - TXD PC10 - RXD PC11 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); - GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); + GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3); + GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3); // USART IRQ init NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; @@ -354,7 +360,7 @@ void InitUSART3(int speed) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // Tx | Rx GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_Init(GPIOC, &GPIO_InitStructure); // Configure USART baud rate USART_StructInit(&USART_InitStructure); @@ -402,16 +408,203 @@ void WriteUSART3(const uint8_t* data, uint16_t length) USART_ITConfig(USART3, USART_IT_TXE, ENABLE); } +/* ************* UART5 ***************** */ + +// Init queues +void TXSerialfifoinit5() +{ + TXSerialfifohead5 = 0U; + TXSerialfifotail5 = 0U; +} + +void RXSerialfifoinit5() +{ + RXSerialfifohead5 = 0U; + RXSerialfifotail5 = 0U; +} + +// How full is queue +// TODO decide if how full or how empty is preferred info to return +uint16_t TXSerialfifolevel5() +{ + uint32_t tail = TXSerialfifotail5; + uint32_t head = TXSerialfifohead5; + + if (tail > head) + return TX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +uint16_t RXSerialfifolevel5() +{ + uint32_t tail = RXSerialfifotail5; + uint32_t head = RXSerialfifohead5; + + if (tail > head) + return RX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +// Flushes the transmit shift register +// warning: this call is blocking +void TXSerialFlush5() +{ + // wait until the TXE shows the shift register is empty + while (USART_GetITStatus(UART5, USART_FLAG_TXE)) + ; +} + +uint8_t TXSerialfifoput5(uint8_t next) +{ + if (TXSerialfifolevel5() < TX_SERIAL_FIFO_SIZE) { + TXSerialfifo5[TXSerialfifohead5] = next; + + TXSerialfifohead5++; + if (TXSerialfifohead5 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifohead5 = 0U; + + // make sure transmit interrupts are enabled as long as there is data to send + USART_ITConfig(UART5, USART_IT_TXE, ENABLE); + return 1U; + } else { + return 0U; // signal an overflow occurred by returning a zero count + } +} + +void UART5_IRQHandler() +{ + uint8_t c; + + if (USART_GetITStatus(UART5, USART_IT_RXNE)) { + c = (uint8_t) USART_ReceiveData(UART5); + + if (RXSerialfifolevel5() < RX_SERIAL_FIFO_SIZE) { + RXSerialfifo5[RXSerialfifohead5] = c; + + RXSerialfifohead5++; + if (RXSerialfifohead5 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifohead5 = 0U; + } else { + // TODO - do something if rx fifo is full? + } + + USART_ClearITPendingBit(UART5, USART_IT_RXNE); + intcount5++; + } + + if (USART_GetITStatus(UART5, USART_IT_TXE)) { + c = 0U; + + if (TXSerialfifohead5 != TXSerialfifotail5) { // if the fifo is not empty + c = TXSerialfifo5[TXSerialfifotail5]; + + TXSerialfifotail5++; + if (TXSerialfifotail5 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifotail5 = 0U; + + USART_SendData(UART5, c); + } else { // if there's no more data to transmit then turn off TX interrupts + USART_ITConfig(UART5, USART_IT_TXE, DISABLE); + } + + USART_ClearITPendingBit(UART5, USART_IT_TXE); + } +} + +void InitUART5(int speed) +{ + // USART5 - TXD PC12 - RXD PD2 + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); + GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5); + + // USART IRQ init + NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init(&NVIC_InitStructure); + + // Configure USART as alternate function + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // Tx + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // Rx + GPIO_Init(GPIOD, &GPIO_InitStructure); + + // Configure USART baud rate + USART_StructInit(&USART_InitStructure); + USART_InitStructure.USART_BaudRate = speed; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(UART5, &USART_InitStructure); + + USART_Cmd(UART5, ENABLE); + + USART_ITConfig(UART5, USART_IT_RXNE, ENABLE); + + // initialize the fifos + TXSerialfifoinit5(); + RXSerialfifoinit5(); +} + +uint8_t AvailUART5(void) +{ + if (RXSerialfifolevel5() > 0U) + return 1U; + else + return 0U; +} + +uint8_t ReadUART5(void) +{ + uint8_t data_c = RXSerialfifo5[RXSerialfifotail5]; + + RXSerialfifotail5++; + if (RXSerialfifotail5 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifotail5 = 0U; + + return data_c; +} + +void WriteUART5(const uint8_t* data, uint16_t length) +{ + for (uint16_t i = 0U; i < length; i++) + TXSerialfifoput5(data[i]); + + USART_ITConfig(UART5, USART_IT_TXE, ENABLE); +} + ///////////////////////////////////////////////////////////////// void CSerialPort::beginInt(uint8_t n, int speed) { switch (n) { case 1U: - InitUSART3(speed); + #if defined(STM32F4_DISCOVERY) + InitUSART3(speed); + #elif defined(STM32F4_PI) + InitUSART1(speed); + #endif break; case 3U: - InitUSART1(speed); + InitUART5(speed); break; default: break; @@ -421,10 +614,14 @@ void CSerialPort::beginInt(uint8_t n, int speed) int CSerialPort::availableInt(uint8_t n) { switch (n) { - case 1U: - return AvailUSART3(); + case 1U: + #if defined(STM32F4_DISCOVERY) + return AvailUSART3(); + #elif defined(STM32F4_PI) + return AvailUSART1(); + #endif case 3U: - return AvailUSART1(); + return AvailUART5(); default: return false; } @@ -434,9 +631,13 @@ uint8_t CSerialPort::readInt(uint8_t n) { switch (n) { case 1U: - return ReadUSART3(); + #if defined(STM32F4_DISCOVERY) + return ReadUSART3(); + #elif defined(STM32F4_PI) + return ReadUSART1(); + #endif case 3U: - return ReadUSART1(); + return ReadUART5(); default: return 0U; } @@ -446,14 +647,20 @@ void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool { switch (n) { case 1U: - WriteUSART3(data, length); - if (flush) - TXSerialFlush3(); - break; + #if defined(STM32F4_DISCOVERY) + WriteUSART3(data, length); + if (flush) + TXSerialFlush3(); + #elif defined(STM32F4_PI) + WriteUSART1(data, length); + if (flush) + TXSerialFlush1(); + #endif + break; case 3U: - WriteUSART1(data, length); + WriteUART5(data, length); if (flush) - TXSerialFlush1(); + TXSerialFlush5(); break; default: break; From 6d383332e1f6ed2aa9a7ed3c2990aa4e522c88ed Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 30 Nov 2016 09:42:10 +0000 Subject: [PATCH 262/329] Reorganise the code slightly. --- IOTeensy.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 6f629a6..ae143a7 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -75,6 +75,10 @@ void CIO::initInt() void CIO::startInt() { + // Initialise the DAC + SIM_SCGC2 |= SIM_SCGC2_DAC0; + DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 + // Initialise ADC0 SIM_SCGC6 |= SIM_SCGC6_ADC0; ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time @@ -118,18 +122,18 @@ void CIO::startInt() #endif #if defined(EXTERNAL_OSC) + // Set ADC0 to trigger from the LPTMR at 24 kHz + SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | + SIM_SOPT7_ADC0TRGSEL(14); + + CORE_PIN13_CONFIG = PORT_PCR_MUX(3); + SIM_SCGC5 |= SIM_SCGC5_LPTIMER; LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter LPTMR0_CMR = EXTERNAL_OSC / 24000; LPTMR0_CSR = LPTMR_CSR_TIE | LPTMR_CSR_TPS(2) | // Interrupt, counter, input=Alt2, free running mode, enable LPTMR_CSR_TFC | LPTMR_CSR_TMS | LPTMR_CSR_TEN; - - CORE_PIN13_CONFIG = PORT_PCR_MUX(3); - - // Set ADC0 to trigger from the LPTMR - SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | - SIM_SOPT7_ADC0TRGSEL(14); #else // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock @@ -141,10 +145,6 @@ void CIO::startInt() PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter) #endif - // Initialise the DAC - SIM_SCGC2 |= SIM_SCGC2_DAC0; - DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 - digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW); digitalWrite(PIN_COSLED, LOW); digitalWrite(PIN_LED, HIGH); From d022276c94e7070cb30366ec00dbf4ad473e7571 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 30 Nov 2016 09:44:17 +0000 Subject: [PATCH 263/329] Move the LPTMR enable. --- IOTeensy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index ae143a7..f5e7514 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -131,9 +131,9 @@ void CIO::startInt() SIM_SCGC5 |= SIM_SCGC5_LPTIMER; LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter LPTMR0_CMR = EXTERNAL_OSC / 24000; - LPTMR0_CSR = LPTMR_CSR_TIE | LPTMR_CSR_TPS(2) | // Interrupt, counter, input=Alt2, free running mode, enable - LPTMR_CSR_TFC | LPTMR_CSR_TMS | - LPTMR_CSR_TEN; + LPTMR0_CSR = LPTMR_CSR_TIE | LPTMR_CSR_TPS(2) | // Interrupt, counter, input=Alt2, free running mode + LPTMR_CSR_TFC | LPTMR_CSR_TMS; + LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable #else // Setup PDB for ADC0 at 24 kHz SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock From 51faaed8808196878f7a7fe2963157d2fe68c65d Mon Sep 17 00:00:00 2001 From: phl0 Date: Wed, 30 Nov 2016 13:17:36 +0100 Subject: [PATCH 264/329] Add some comments --- IOTeensy.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index f5e7514..e5d3230 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -34,8 +34,8 @@ #define PIN_DMR 10 #define PIN_YSF 11 #define PIN_P25 12 -#define PIN_ADC 5 // A0 -#define PIN_RSSI 8 // A2 +#define PIN_ADC 5 // A0, Pin 14 +#define PIN_RSSI 8 // A2, Pin 16 #define PDB_CHnC1_TOS 0x0100 #define PDB_CHnC1_EN 0x0001 @@ -77,7 +77,7 @@ void CIO::startInt() { // Initialise the DAC SIM_SCGC2 |= SIM_SCGC2_DAC0; - DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 + DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 1.2V VDDA is DACREF_2 // Initialise ADC0 SIM_SCGC6 |= SIM_SCGC6_ADC0; @@ -123,16 +123,18 @@ void CIO::startInt() #if defined(EXTERNAL_OSC) // Set ADC0 to trigger from the LPTMR at 24 kHz - SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | - SIM_SOPT7_ADC0TRGSEL(14); + SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | // Enable ADC0 alternate trigger + SIM_SOPT7_ADC0TRGSEL(14); // Trigger ADC0 by LPTMR0 CORE_PIN13_CONFIG = PORT_PCR_MUX(3); - SIM_SCGC5 |= SIM_SCGC5_LPTIMER; + SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter LPTMR0_CMR = EXTERNAL_OSC / 24000; - LPTMR0_CSR = LPTMR_CSR_TIE | LPTMR_CSR_TPS(2) | // Interrupt, counter, input=Alt2, free running mode - LPTMR_CSR_TFC | LPTMR_CSR_TMS; + LPTMR0_CSR = LPTMR_CSR_TIE | // Interrupt Enable + LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13 + LPTMR_CSR_TFC | // Free-Running Counter + LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable #else // Setup PDB for ADC0 at 24 kHz From 7607c8199457e345d47b495722bdaa6cdbdafe85 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Thu, 1 Dec 2016 01:04:40 -0300 Subject: [PATCH 265/329] Adding external clock for STM32F4 (pin PA15) --- IOSTM.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/IOSTM.cpp b/IOSTM.cpp index 12265ad..e580897 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -40,6 +40,8 @@ P25 PD11 output RX PA0 analog input RSSI PA1 analog input TX PA4 analog output + +EXT_CLK PA15 input */ #define PIN_COS GPIO_Pin_5 @@ -97,6 +99,8 @@ P25 PC9 output RX PA0 analog input RSSI PA7 analog input TX PA4 analog output + +EXT_CLK PA15 input */ #define PIN_COS GPIO_Pin_0 @@ -144,6 +148,8 @@ TX PA4 analog output const uint16_t DC_OFFSET = 2048U; +#define SAMP_FREQ 24000 + extern "C" { void TIM2_IRQHandler() { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { @@ -306,19 +312,38 @@ void CIO::startInt() DAC_Cmd(DAC_Channel_1, ENABLE); // Init the timer + +#if defined(EXTERNAL_OSC) + // Configure GPIO PA15 as external TIM2 clock source + GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOA, &GPIO_InitStructure); +#endif + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef timerInitStructure; TIM_TimeBaseStructInit (&timerInitStructure); - // TIM2 at 24 kHz - timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*24000)) - 1); + // TIM2 frequency +#if defined(EXTERNAL_OSC) + timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/SAMP_FREQ) - 1); +#else + timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*SAMP_FREQ)) - 1); +#endif timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up; timerInitStructure.TIM_Period = 1; timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; timerInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &timerInitStructure); + + // Enable external clock +#if defined(EXTERNAL_OSC) + TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); +#endif + TIM_Cmd(TIM2, ENABLE); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); From a6d3bd593324a8515b87c3041cc62ceb6a29dd95 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Thu, 1 Dec 2016 01:08:52 -0300 Subject: [PATCH 266/329] Fix var names --- IOSTM.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IOSTM.cpp b/IOSTM.cpp index e580897..9186102 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -316,9 +316,9 @@ void CIO::startInt() #if defined(EXTERNAL_OSC) // Configure GPIO PA15 as external TIM2 clock source GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_TIM2); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOA, &GPIO_InitStruct); #endif RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); From 1e4b5e6b897ba34ca261338e54c1beba90fd9c52 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Dec 2016 10:10:12 +0000 Subject: [PATCH 267/329] Reorder LPTMR initialisation in accordance with the chip specification. --- IOTeensy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index e5d3230..ac09ca6 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -129,12 +129,12 @@ void CIO::startInt() CORE_PIN13_CONFIG = PORT_PCR_MUX(3); SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access - LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter - LPTMR0_CMR = EXTERNAL_OSC / 24000; LPTMR0_CSR = LPTMR_CSR_TIE | // Interrupt Enable LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13 LPTMR_CSR_TFC | // Free-Running Counter LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter + LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter + LPTMR0_CMR = EXTERNAL_OSC / 24000; LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable #else // Setup PDB for ADC0 at 24 kHz From 955a804cde795743665d0d13ccc17d0f6f50ed65 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 1 Dec 2016 10:26:18 +0000 Subject: [PATCH 268/329] Disable the LPTMR before configuring it. --- IOTeensy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index ac09ca6..632dccf 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -129,12 +129,13 @@ void CIO::startInt() CORE_PIN13_CONFIG = PORT_PCR_MUX(3); SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access + LPTMR0_CSR = 0; // Disable + LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter + LPTMR0_CMR = EXTERNAL_OSC / 24000; LPTMR0_CSR = LPTMR_CSR_TIE | // Interrupt Enable LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13 LPTMR_CSR_TFC | // Free-Running Counter LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter - LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter - LPTMR0_CMR = EXTERNAL_OSC / 24000; LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable #else // Setup PDB for ADC0 at 24 kHz From b8febb517f28626380b9e25239a0193400b85e5a Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Fri, 2 Dec 2016 00:13:47 -0300 Subject: [PATCH 269/329] External TCXO support for STM32F4 and Nucleo 446 board support --- IOSTM.cpp | 79 ++++++++++++++-- Makefile | 12 ++- SerialSTM.cpp | 255 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 318 insertions(+), 28 deletions(-) diff --git a/IOSTM.cpp b/IOSTM.cpp index 9186102..bb27e20 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -141,13 +141,72 @@ EXT_CLK PA15 input #define PIN_RSSI GPIO_Pin_7 #define PIN_RSSI_CH ADC_Channel_7 -#else -#error "Either STM32F4_DISCOVERY or STM32F4_PI need to be defined" -#endif +#elif defined(STM32F4_NUCLEO) +/* +Pin definitions for STM32F4 Nucleo boards: +PTT PB13 output +COSLED PB14 output +LED PA5 output +COS PB15 input + +DSTAR PB10 output +DMR PB4 output +YSF PB5 output +P25 PB3 output + +RX PA0 analog input +RSSI PA1 analog input +TX PA4 analog output + +EXT_CLK PA15 input +*/ + +#define PIN_COS GPIO_Pin_15 +#define PORT_COS GPIOB +#define RCC_Per_COS RCC_AHB1Periph_GPIOB + +#define PIN_PTT GPIO_Pin_13 +#define PORT_PTT GPIOB +#define RCC_Per_PTT RCC_AHB1Periph_GPIOB + +#define PIN_COSLED GPIO_Pin_14 +#define PORT_COSLED GPIOB +#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB + +#define PIN_LED GPIO_Pin_5 +#define PORT_LED GPIOA +#define RCC_Per_LED RCC_AHB1Periph_GPIOA + +#define PIN_P25 GPIO_Pin_3 +#define PORT_P25 GPIOB +#define RCC_Per_P25 RCC_AHB1Periph_GPIOB + +#define PIN_DSTAR GPIO_Pin_10 +#define PORT_DSTAR GPIOB +#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB + +#define PIN_DMR GPIO_Pin_4 +#define PORT_DMR GPIOB +#define RCC_Per_DMR RCC_AHB1Periph_GPIOB + +#define PIN_YSF GPIO_Pin_5 +#define PORT_YSF GPIOB +#define RCC_Per_YSF RCC_AHB1Periph_GPIOB + +#define PIN_RX GPIO_Pin_0 +#define PIN_RX_CH ADC_Channel_0 + +#define PIN_RSSI GPIO_Pin_1 +#define PIN_RSSI_CH ADC_Channel_1 + +#else +#error "Either STM32F4_DISCOVERY, STM32F4_PI or STM32F4_NUCLEO need to be defined" +#endif const uint16_t DC_OFFSET = 2048U; +// Sampling frequency #define SAMP_FREQ 24000 extern "C" { @@ -312,6 +371,7 @@ void CIO::startInt() DAC_Cmd(DAC_Channel_1, ENABLE); // Init the timer + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); #if defined(EXTERNAL_OSC) // Configure GPIO PA15 as external TIM2 clock source @@ -321,14 +381,12 @@ void CIO::startInt() GPIO_Init(GPIOA, &GPIO_InitStruct); #endif - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - TIM_TimeBaseInitTypeDef timerInitStructure; TIM_TimeBaseStructInit (&timerInitStructure); - // TIM2 frequency + // TIM2 output frequency #if defined(EXTERNAL_OSC) - timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/SAMP_FREQ) - 1); + timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/(2*SAMP_FREQ)) - 1); #else timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*SAMP_FREQ)) - 1); #endif @@ -339,12 +397,17 @@ void CIO::startInt() timerInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &timerInitStructure); - // Enable external clock #if defined(EXTERNAL_OSC) + // Enable external clock (PA15) TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); +#else + // Enable internal clock + TIM_InternalClockConfig(TIM2); #endif + // Enable TIM2 TIM_Cmd(TIM2, ENABLE); + // Enable TIM2 interrupt TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); NVIC_InitTypeDef nvicStructure; diff --git a/Makefile b/Makefile index d23d1e8..a97316d 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,10 @@ MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \ # STM32F4 Discovery board: DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) # Pi board: -DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) +DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DARDUINO_MODE_PINS -DSEND_RSSI_DATA -DSERIAL_REPEATER -DHSE_VALUE=$(OSC) +# STM32F4 Nucleo 446 board: +DEFS_NUCLEO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_NUCLEO -DHSE_VALUE=$(OSC) + CFLAGS=-c $(MCFLAGS) $(INCLUDES) CXXFLAGS=-c $(MCFLAGS) $(INCLUDES) @@ -96,7 +99,7 @@ LDSCRIPT=stm32f4xx_link.ld LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS) # Build Rules -.PHONY: all release dis pi debug clean +.PHONY: all release dis pi nucleo debug clean # Default target: STM32F4 Discovery board all: dis @@ -106,6 +109,11 @@ pi: CXXFLAGS+=$(DEFS_PI) -Os -fno-exceptions -ffunction-sections -fdata-sections pi: LDFLAGS+=-Os --specs=nano.specs pi: release +nucleo: CFLAGS+=$(DEFS_NUCLEO) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS +nucleo: CXXFLAGS+=$(DEFS_NUCLEO) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS +nucleo: LDFLAGS+=-Os --specs=nano.specs +nucleo: release + dis: CFLAGS+=$(DEFS_DIS) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS dis: CXXFLAGS+=$(DEFS_DIS) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS dis: LDFLAGS+=-Os --specs=nano.specs diff --git a/SerialSTM.cpp b/SerialSTM.cpp index 2955508..904ec10 100644 --- a/SerialSTM.cpp +++ b/SerialSTM.cpp @@ -22,35 +22,39 @@ #include "SerialPort.h" -#if defined(STM32F4XX) || defined(STM32F4) +/* +Pin definitions: -volatile uint32_t intcount1, intcount3, intcount5; +- Host communication: +USART1 - TXD PA9 - RXD PA10 (Pi board) +USART2 - TXD PA2 - RXD PA3 (Nucleo board) +USART3 - TXD PC10 - RXD PC11 (Discovery board) + +- Serial repeater: +UART5 - TXD PC12 - RXD PD2 + +*/ + +#if defined(STM32F4XX) || defined(STM32F4) #define TX_SERIAL_FIFO_SIZE 256U #define RX_SERIAL_FIFO_SIZE 256U -volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead1, TXSerialfifotail1; -volatile uint16_t RXSerialfifohead1, RXSerialfifotail1; - -volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; -volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; - -volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; -volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE]; -volatile uint16_t TXSerialfifohead5, TXSerialfifotail5; -volatile uint16_t RXSerialfifohead5, RXSerialfifotail5; - extern "C" { void USART1_IRQHandler(); + void USART2_IRQHandler(); void USART3_IRQHandler(); void UART5_IRQHandler(); } /* ************* USART1 ***************** */ +#if defined(STM32F4_PI) + +volatile uint32_t intcount1; +volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead1, TXSerialfifotail1; +volatile uint16_t RXSerialfifohead1, RXSerialfifotail1; // Init queues void TXSerialfifoinit1() @@ -229,7 +233,204 @@ void WriteUSART1(const uint8_t* data, uint16_t length) USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } +#endif + +/* ************* USART2 ***************** */ +#if defined(STM32F4_NUCLEO) + +volatile uint32_t intcount2; +volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead2, TXSerialfifotail2; +volatile uint16_t RXSerialfifohead2, RXSerialfifotail2; + +// Init queues +void TXSerialfifoinit2() +{ + TXSerialfifohead2 = 0U; + TXSerialfifotail2 = 0U; +} + +void RXSerialfifoinit2() +{ + RXSerialfifohead2 = 0U; + RXSerialfifotail2 = 0U; +} + +// How full is queue +// TODO decide if how full or how empty is preferred info to return +uint16_t TXSerialfifolevel2() +{ + uint32_t tail = TXSerialfifotail2; + uint32_t head = TXSerialfifohead2; + + if (tail > head) + return TX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +uint16_t RXSerialfifolevel2() +{ + uint32_t tail = RXSerialfifotail2; + uint32_t head = RXSerialfifohead2; + + if (tail > head) + return RX_SERIAL_FIFO_SIZE + head - tail; + else + return head - tail; +} + +// Flushes the transmit shift register +// warning: this call is blocking +void TXSerialFlush2() +{ + // wait until the TXE shows the shift register is empty + while (USART_GetITStatus(USART2, USART_FLAG_TXE)) + ; +} + +uint8_t TXSerialfifoput2(uint8_t next) +{ + if (TXSerialfifolevel2() < TX_SERIAL_FIFO_SIZE) { + TXSerialfifo2[TXSerialfifohead2] = next; + + TXSerialfifohead2++; + if (TXSerialfifohead2 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifohead2 = 0U; + + // make sure transmit interrupts are enabled as long as there is data to send + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); + return 1U; + } else { + return 0U; // signal an overflow occurred by returning a zero count + } +} + +void USART2_IRQHandler() +{ + uint8_t c; + + if (USART_GetITStatus(USART2, USART_IT_RXNE)) { + c = (uint8_t) USART_ReceiveData(USART2); + + if (RXSerialfifolevel2() < RX_SERIAL_FIFO_SIZE) { + RXSerialfifo2[RXSerialfifohead2] = c; + + RXSerialfifohead2++; + if (RXSerialfifohead2 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifohead2 = 0U; + } else { + // TODO - do something if rx fifo is full? + } + + USART_ClearITPendingBit(USART2, USART_IT_RXNE); + intcount2++; + } + + if (USART_GetITStatus(USART2, USART_IT_TXE)) { + c = 0U; + + if (TXSerialfifohead2 != TXSerialfifotail2) { // if the fifo is not empty + c = TXSerialfifo2[TXSerialfifotail2]; + + TXSerialfifotail2++; + if (TXSerialfifotail2 >= TX_SERIAL_FIFO_SIZE) + TXSerialfifotail2 = 0U; + + USART_SendData(USART2, c); + } else { // if there's no more data to transmit then turn off TX interrupts + USART_ITConfig(USART2, USART_IT_TXE, DISABLE); + } + + USART_ClearITPendingBit(USART2, USART_IT_TXE); + } +} + +void InitUSART2(int speed) +{ + // USART2 - TXD PA2 - RXD PA3 + GPIO_InitTypeDef GPIO_InitStructure; + USART_InitTypeDef USART_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); + + // USART IRQ init + NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init(&NVIC_InitStructure); + + // Configure USART as alternate function + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Tx | Rx + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // Configure USART baud rate + USART_StructInit(&USART_InitStructure); + USART_InitStructure.USART_BaudRate = speed; + USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_StopBits = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_Init(USART2, &USART_InitStructure); + + USART_Cmd(USART2, ENABLE); + + USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); + + // initialize the fifos + TXSerialfifoinit2(); + RXSerialfifoinit2(); +} + +uint8_t AvailUSART2(void) +{ + if (RXSerialfifolevel2() > 0U) + return 1U; + else + return 0U; +} + +uint8_t ReadUSART2(void) +{ + uint8_t data_c = RXSerialfifo2[RXSerialfifotail2]; + + RXSerialfifotail2++; + if (RXSerialfifotail2 >= RX_SERIAL_FIFO_SIZE) + RXSerialfifotail2 = 0U; + + return data_c; +} + +void WriteUSART2(const uint8_t* data, uint16_t length) +{ + for (uint16_t i = 0U; i < length; i++) + TXSerialfifoput2(data[i]); + + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); +} + +#endif + /* ************* USART3 ***************** */ +#if defined(STM32F4_DISCOVERY) || defined(STM32F4_PI) + +volatile uint32_t intcount3; +volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead3, TXSerialfifotail3; +volatile uint16_t RXSerialfifohead3, RXSerialfifotail3; // Init queues void TXSerialfifoinit3() @@ -408,8 +609,16 @@ void WriteUSART3(const uint8_t* data, uint16_t length) USART_ITConfig(USART3, USART_IT_TXE, ENABLE); } +#endif + /* ************* UART5 ***************** */ +volatile uint32_t intcount5; +volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE]; +volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE]; +volatile uint16_t TXSerialfifohead5, TXSerialfifotail5; +volatile uint16_t RXSerialfifohead5, RXSerialfifotail5; + // Init queues void TXSerialfifoinit5() { @@ -515,7 +724,7 @@ void UART5_IRQHandler() void InitUART5(int speed) { - // USART5 - TXD PC12 - RXD PD2 + // UART5 - TXD PC12 - RXD PD2 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; @@ -601,6 +810,8 @@ void CSerialPort::beginInt(uint8_t n, int speed) InitUSART3(speed); #elif defined(STM32F4_PI) InitUSART1(speed); + #elif defined(STM32F4_NUCLEO) + InitUSART2(speed); #endif break; case 3U: @@ -619,6 +830,8 @@ int CSerialPort::availableInt(uint8_t n) return AvailUSART3(); #elif defined(STM32F4_PI) return AvailUSART1(); + #elif defined(STM32F4_NUCLEO) + return AvailUSART2(); #endif case 3U: return AvailUART5(); @@ -635,6 +848,8 @@ uint8_t CSerialPort::readInt(uint8_t n) return ReadUSART3(); #elif defined(STM32F4_PI) return ReadUSART1(); + #elif defined(STM32F4_NUCLEO) + return ReadUSART2(); #endif case 3U: return ReadUART5(); @@ -655,6 +870,10 @@ void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool WriteUSART1(data, length); if (flush) TXSerialFlush1(); + #elif defined(STM32F4_NUCLEO) + WriteUSART2(data, length); + if (flush) + TXSerialFlush2(); #endif break; case 3U: From 0ffd77732e8571864d3f9fad3cdec34bd9ef5c0e Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sat, 3 Dec 2016 11:55:15 -0300 Subject: [PATCH 270/329] CooCox files not necessary for CooCox IDE support. It just works with *.coproj --- MMDVM_STM32F4xx.cogui | 484 --------------------------------------- MMDVM_STM32F4xx.comarker | 23 -- 2 files changed, 507 deletions(-) delete mode 100644 MMDVM_STM32F4xx.cogui delete mode 100644 MMDVM_STM32F4xx.comarker diff --git a/MMDVM_STM32F4xx.cogui b/MMDVM_STM32F4xx.cogui deleted file mode 100644 index 65c5c84..0000000 --- a/MMDVM_STM32F4xx.cogui +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MMDVM_STM32F4xx.comarker b/MMDVM_STM32F4xx.comarker deleted file mode 100644 index b29d0e4..0000000 --- a/MMDVM_STM32F4xx.comarker +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 3fd02223ef0b646005320c65a019976849db4b4b Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sat, 3 Dec 2016 12:20:29 -0300 Subject: [PATCH 271/329] Updating CooCox project file --- MMDVM_STM32F4xx.coproj | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/MMDVM_STM32F4xx.coproj b/MMDVM_STM32F4xx.coproj index 3038fa0..3348a05 100644 --- a/MMDVM_STM32F4xx.coproj +++ b/MMDVM_STM32F4xx.coproj @@ -4,7 +4,7 @@ - @@ -30,7 +31,7 @@