From 5fb5986d50419d34b115abfa8c92a194e0afd0ce Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 27 Aug 2025 18:35:30 +0100 Subject: [PATCH] Remove M17 and AX.25 --- AX25Defines.h | 36 ---- AX25Demodulator.cpp | 319 ----------------------------- AX25Demodulator.h | 77 ------- AX25Frame.cpp | 127 ------------ AX25Frame.h | 47 ----- AX25RX.cpp | 211 ------------------- AX25RX.h | 63 ------ AX25TX.cpp | 191 ----------------- AX25TX.h | 53 ----- AX25Twist.cpp | 316 ----------------------------- AX25Twist.h | 42 ---- CalM17.cpp | 66 ------ CalM17.h | 43 ---- Config.h | 11 +- Globals.h | 26 +-- IO.cpp | 100 +-------- IO.h | 13 +- IODue.cpp | 15 +- IOSTM.cpp | 39 +--- IOTeensy.cpp | 15 +- M17Defines.h | 67 ------ M17RX.cpp | 485 -------------------------------------------- M17RX.h | 77 ------- M17TX.cpp | 190 ----------------- M17TX.h | 60 ------ MMDVM.cpp | 32 +-- MMDVM.ino | 31 +-- README.md | 2 +- SerialPort.cpp | 276 +------------------------ SerialPort.h | 14 +- 30 files changed, 24 insertions(+), 3020 deletions(-) delete mode 100644 AX25Defines.h delete mode 100644 AX25Demodulator.cpp delete mode 100644 AX25Demodulator.h delete mode 100644 AX25Frame.cpp delete mode 100644 AX25Frame.h delete mode 100644 AX25RX.cpp delete mode 100644 AX25RX.h delete mode 100644 AX25TX.cpp delete mode 100644 AX25TX.h delete mode 100644 AX25Twist.cpp delete mode 100644 AX25Twist.h delete mode 100644 CalM17.cpp delete mode 100644 CalM17.h delete mode 100644 M17Defines.h delete mode 100644 M17RX.cpp delete mode 100644 M17RX.h delete mode 100644 M17TX.cpp delete mode 100644 M17TX.h diff --git a/AX25Defines.h b/AX25Defines.h deleted file mode 100644 index 7087847..0000000 --- a/AX25Defines.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2020 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(AX25DEFINES_H) -#define AX25DEFINES_H - -const uint8_t AX25_RADIO_SYMBOL_LENGTH = 20U; // At 24 kHz sample rate - -const uint8_t AX25_FRAME_START = 0x7EU; -const uint8_t AX25_FRAME_END = 0x7EU; -const uint8_t AX25_FRAME_ABORT = 0xFEU; - -const uint8_t AX25_MAX_ONES = 5U; - -const uint16_t AX25_MIN_FRAME_LENGTH = 17U; // Callsign (7) + Callsign (7) + Control (1) + Checksum (2) - -const uint16_t AX25_MAX_FRAME_LENGTH = 330U; // Callsign (7) + Callsign (7) + 8 Digipeaters (56) + - // Control (1) + PID (1) + Data (256) + Checksum (2) - -#endif - diff --git a/AX25Demodulator.cpp b/AX25Demodulator.cpp deleted file mode 100644 index eb0022d..0000000 --- a/AX25Demodulator.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2020 by Jonathan Naylor G4KLX - * Copyright 2015-2019 Mobilinkd LLC - * - * 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" - -#if defined(MODE_AX25) - -#include "Globals.h" -#include "AX25Demodulator.h" -#include "AX25Defines.h" - -const float32_t SAMPLE_RATE = 24000.0F; -const float32_t SYMBOL_RATE = 1200.0F; - -const uint16_t DELAY_LEN = 11U; - -const float32_t SAMPLES_PER_SYMBOL = SAMPLE_RATE / SYMBOL_RATE; -const float32_t PLL_LIMIT = SAMPLES_PER_SYMBOL / 2.0F; - -const uint32_t LPF_FILTER_LEN = 48U; - -q15_t LPF_FILTER_COEFFS[] = { - -2, -8, -17, -28, -40, -47, -47, -34, - -5, 46, 122, 224, 354, 510, 689, 885, - 1092, 1302, 1506, 1693, 1856, 1987, 2077, 2124, - 2124, 2077, 1987, 1856, 1693, 1506, 1302, 1092, - 885, 689, 510, 354, 224, 122, 46, -5, - -34, -47, -47, -40, -28, -17, -8, -2 -}; - -// Lock low-pass filter taps (80Hz Bessel) -// scipy.signal: -// b, a = bessel(4, [80.0/(1200/2)], 'lowpass') -// -const uint8_t PLL_IIR_SIZE = 5U; - -const float32_t PLL_LOCK_B[] = { - 1.077063e-03,4.308253e-03,6.462379e-03,4.308253e-03,1.077063e-03}; - -const float32_t PLL_LOCK_A[] = { - 1.000000e+00,-2.774567e+00,2.962960e+00,-1.437990e+00,2.668296e-01}; - -// 64 Hz loop filter. -// scipy.signal: -// loop_coeffs = firwin(9, [64.0/(1200/2)], width = None, -// pass_zero = True, scale = True, window='hann') -// -const uint32_t PLL_FILTER_LEN = 7U; - -float32_t PLL_FILTER_COEFFS[] = {3.196252e-02F, 1.204223e-01F, 2.176819e-01F, 2.598666e-01F, 2.176819e-01F, 1.204223e-01F, 3.196252e-02F}; - -CAX25Demodulator::CAX25Demodulator(int8_t n) : -m_frame(), -m_twist(n), -m_lpfFilter(), -m_lpfState(), -m_delayLine(NULL), -m_delayPos(0U), -m_nrziState(false), -m_pllFilter(), -m_pllState(), -m_pllLast(false), -m_pllBits(1U), -m_pllCount(0.0F), -m_pllJitter(0.0F), -m_pllDCD(false), -m_iirHistory(), -m_hdlcOnes(0U), -m_hdlcFlag(false), -m_hdlcBuffer(0U), -m_hdlcBits(0U), -m_hdlcState(AX25_IDLE) -{ - m_delayLine = new bool[DELAY_LEN]; - - m_lpfFilter.numTaps = LPF_FILTER_LEN; - m_lpfFilter.pState = m_lpfState; - m_lpfFilter.pCoeffs = LPF_FILTER_COEFFS; - - m_pllFilter.numTaps = PLL_FILTER_LEN; - m_pllFilter.pState = m_pllState; - m_pllFilter.pCoeffs = PLL_FILTER_COEFFS; - - for (uint8_t i = 0U; i < PLL_IIR_SIZE; i++) - m_iirHistory[i] = 0.0F; -} - -bool CAX25Demodulator::process(q15_t* samples, uint8_t length, CAX25Frame& frame) -{ - bool result = false; - - q15_t fa[RX_BLOCK_SIZE]; - m_twist.process(samples, fa, RX_BLOCK_SIZE); - - int16_t buffer[RX_BLOCK_SIZE]; - for (uint8_t i = 0; i < length; i++) { - bool level = (fa[i] >= 0); - bool delayed = delay(level); - buffer[i] = (int16_t(level ^ delayed) << 1) - 1; - } - - q15_t fc[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_lpfFilter, buffer, fc, RX_BLOCK_SIZE); - - for (uint8_t i = 0; i < length; i++) { - bool bit = fc[i] >= 0; - bool sample = PLL(bit); - - if (sample) { - // We will only ever get one frame because there are - // not enough bits in a block for more than one. - if (result) { - HDLC(NRZI(bit)); - } else { - result = HDLC(NRZI(bit)); - if (result) { - // Copy the frame data. - ::memcpy(frame.m_data, m_frame.m_data, AX25_MAX_PACKET_LEN); - frame.m_length = m_frame.m_length; - frame.m_fcs = m_frame.m_fcs; - m_frame.m_length = 0U; - } - } - } - } - - return result; -} - -bool CAX25Demodulator::delay(bool b) -{ - bool r = m_delayLine[m_delayPos]; - - m_delayLine[m_delayPos++] = b; - - if (m_delayPos >= DELAY_LEN) - m_delayPos = 0U; - - return r; -} - -bool CAX25Demodulator::NRZI(bool b) -{ - bool result = (b == m_nrziState); - - m_nrziState = b; - - return result; -} - -bool CAX25Demodulator::PLL(bool input) -{ - bool sample = false; - - if (input != m_pllLast || m_pllBits > 16U) { - // Record transition. - m_pllLast = input; - - if (m_pllCount > PLL_LIMIT) - m_pllCount -= SAMPLES_PER_SYMBOL; - - float32_t adjust = m_pllBits > 16U ? 5.0F : 0.0F; - float32_t offset = m_pllCount / float32_t(m_pllBits); - float32_t jitter; - ::arm_fir_f32(&m_pllFilter, &offset, &jitter, 1U); - - float32_t absOffset = adjust; - if (offset < 0.0F) - absOffset -= offset; - else - absOffset += offset; - m_pllJitter = iir(absOffset); - - m_pllCount -= jitter / 2.0F; - m_pllBits = 1U; - } else { - if (m_pllCount > PLL_LIMIT) { - sample = true; - m_pllCount -= SAMPLES_PER_SYMBOL; - m_pllBits++; - } - } - - m_pllCount += 1.0F; - - return sample; -} - -bool CAX25Demodulator::HDLC(bool b) -{ - if (m_hdlcOnes == AX25_MAX_ONES) { - if (b) { - // flag byte - m_hdlcFlag = true; - } else { - // bit stuffing... - m_hdlcFlag = false; - m_hdlcOnes = 0U; - return false; - } - } - - m_hdlcBuffer >>= 1; - m_hdlcBuffer |= b ? 128U : 0U; - m_hdlcBits++; // Free-running until Sync byte. - - if (b) - m_hdlcOnes++; - else - m_hdlcOnes = 0U; - - if (m_hdlcFlag) { - bool result = false; - - switch (m_hdlcBuffer) { - case AX25_FRAME_END: - if (m_frame.m_length >= AX25_MIN_FRAME_LENGTH) { - result = m_frame.checkCRC(); - if (!result) - m_frame.m_length = 0U; - } else { - m_frame.m_length = 0U; - } - m_hdlcState = AX25_SYNC; - m_hdlcFlag = false; - m_hdlcBits = 0U; - break; - - case AX25_FRAME_ABORT: - // Frame aborted - m_frame.m_length = 0U; - m_hdlcState = AX25_IDLE; - m_hdlcFlag = false; - m_hdlcBits = 0U; - break; - - default: - break; - } - - return result; - } - - switch (m_hdlcState) { - case AX25_IDLE: - break; - - case AX25_SYNC: - if (m_hdlcBits == 8U) { // 8th bit. - // Start of frame data. - m_hdlcState = AX25_RECEIVE; - m_frame.append(m_hdlcBuffer); - m_hdlcBits = 0U; - } - break; - - case AX25_RECEIVE: - if (m_hdlcBits == 8U) { // 8th bit. - m_frame.append(m_hdlcBuffer); - m_hdlcBits = 0U; - } - break; - - default: - break; - } - - return false; -} - -void CAX25Demodulator::setTwist(int8_t n) -{ - m_twist.setTwist(n); -} - -bool CAX25Demodulator::isDCD() -{ - if (m_pllJitter <= (SAMPLES_PER_SYMBOL * 0.03F)) - m_pllDCD = true; - else if (m_pllJitter >= (SAMPLES_PER_SYMBOL * 0.15F)) - m_pllDCD = false; - - return m_pllDCD; -} - -float32_t CAX25Demodulator::iir(float32_t input) -{ - for (int8_t i = int8_t(PLL_IIR_SIZE) - 1; i != 0; i--) - m_iirHistory[i] = m_iirHistory[i - 1]; - - m_iirHistory[0] = input; - for (uint8_t i = 1U; i < PLL_IIR_SIZE; i++) - m_iirHistory[0] -= PLL_LOCK_A[i] * m_iirHistory[i]; - - float32_t result = 0.0F; - for (uint8_t i = 0U; i < PLL_IIR_SIZE; i++) - result += PLL_LOCK_B[i] * m_iirHistory[i]; - - return result; -} - -#endif - diff --git a/AX25Demodulator.h b/AX25Demodulator.h deleted file mode 100644 index dacd5ab..0000000 --- a/AX25Demodulator.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#if !defined(AX25Demodulator_H) -#define AX25Demodulator_H - -#include "AX25Frame.h" -#include "AX25Twist.h" - -enum AX25_STATE { - AX25_IDLE, - AX25_SYNC, - AX25_RECEIVE -}; - -class CAX25Demodulator { -public: - CAX25Demodulator(int8_t n); - - bool process(q15_t* samples, uint8_t length, CAX25Frame& frame); - - void setTwist(int8_t n); - - bool isDCD(); - -private: - CAX25Frame m_frame; - CAX25Twist m_twist; - arm_fir_instance_q15 m_lpfFilter; - q15_t m_lpfState[70U]; // NoTaps + BlockSize - 1, 48 + 20 - 1 plus some spare - bool* m_delayLine; - uint16_t m_delayPos; - bool m_nrziState; - arm_fir_instance_f32 m_pllFilter; - float32_t m_pllState[20U]; // NoTaps + BlockSize - 1, 7 + 1 - 1 plus some spare - bool m_pllLast; - uint8_t m_pllBits; - float32_t m_pllCount; - float32_t m_pllJitter; - bool m_pllDCD; - float32_t m_iirHistory[5U]; - uint16_t m_hdlcOnes; - bool m_hdlcFlag; - uint16_t m_hdlcBuffer; - uint16_t m_hdlcBits; - AX25_STATE m_hdlcState; - - bool delay(bool b); - bool NRZI(bool b); - bool PLL(bool b); - bool HDLC(bool b); - float32_t iir(float32_t input); -}; - -#endif - -#endif - diff --git a/AX25Frame.cpp b/AX25Frame.cpp deleted file mode 100644 index 1f54571..0000000 --- a/AX25Frame.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#include "Globals.h" -#include "AX25Frame.h" - -const uint16_t CCITT_TABLE[] = { - 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, - 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, - 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, - 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, - 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, - 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, - 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, - 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, - 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, - 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, - 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, - 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, - 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, - 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, - 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, - 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, - 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, - 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, - 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, - 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, - 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, - 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, - 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, - 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, - 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, - 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, - 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, - 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, - 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, - 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, - 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, - 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 }; - -CAX25Frame::CAX25Frame(const uint8_t* data, uint16_t length) : -m_data(), -m_length(0U), -m_fcs(0U) -{ - for (uint16_t i = 0U; i < length && i < (AX25_MAX_PACKET_LEN - 2U); i++) - m_data[m_length++] = data[i]; -} - -CAX25Frame::CAX25Frame() : -m_data(), -m_length(0U), -m_fcs(0U) -{ -} - -bool CAX25Frame::append(uint16_t c) -{ - if (m_length == AX25_MAX_PACKET_LEN) - return false; - - m_data[m_length++] = uint8_t(c); - - return true; -} - -bool CAX25Frame::checkCRC() -{ - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; - - crc16 = 0xFFFFU; - for (uint16_t i = 0U; i < (m_length - 2U); i++) - crc16 = uint16_t(crc8[1U]) ^ CCITT_TABLE[crc8[0U] ^ m_data[i]]; - - crc16 = ~crc16; - - if (crc8[0U] == m_data[m_length - 2U] && crc8[1U] == m_data[m_length - 1U]) { - m_fcs = crc16; - return true; - } else { - return false; - } -} - -void CAX25Frame::addCRC() -{ - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; - - crc16 = 0xFFFFU; - for (uint16_t i = 0U; i < m_length; i++) - crc16 = uint16_t(crc8[1U]) ^ CCITT_TABLE[crc8[0U] ^ m_data[i]]; - - crc16 = ~crc16; - - m_fcs = crc16; - - m_data[m_length++] = crc8[0U]; - m_data[m_length++] = crc8[1U]; -} - -#endif - diff --git a/AX25Frame.h b/AX25Frame.h deleted file mode 100644 index c83bffa..0000000 --- a/AX25Frame.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#if !defined(AX25Frame_H) -#define AX25Frame_H - -const uint16_t AX25_MAX_PACKET_LEN = 300U; - -class CAX25Frame { -public: - CAX25Frame(const uint8_t* data, uint16_t length); - CAX25Frame(); - - bool append(uint16_t c); - - bool checkCRC(); - - void addCRC(); - - uint8_t m_data[AX25_MAX_PACKET_LEN]; - uint16_t m_length; - uint16_t m_fcs; -}; - -#endif - -#endif - diff --git a/AX25RX.cpp b/AX25RX.cpp deleted file mode 100644 index eddac27..0000000 --- a/AX25RX.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#include "Globals.h" -#include "AX25RX.h" - -/* - * Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass, - * Hann window, starting and ending 0 value coefficients removed. - * - * np.array( - * firwin2(152, - * [ - * 0.0, - * 1000.0/(sample_rate/2), - * 1100.0/(sample_rate/2), - * 2350.0/(sample_rate/2), - * 2500.0/(sample_rate/2), - * 1.0 - * ], - * [0,0,1,1,0,0], - * antisymmetric = False, - * window='hann') * 32768, - * dtype=int)[10:-10] - */ - -const uint32_t FILTER_LEN = 130U; - -q15_t FILTER_COEFFS[] = { - 5, 12, 18, 21, 19, 11, -2, -15, -25, -27, - -21, -11, -3, -5, -19, -43, -69, -83, -73, -35, - 27, 98, 155, 180, 163, 109, 39, -20, -45, -26, - 23, 74, 89, 39, -81, -247, -407, -501, -480, -334, - -92, 175, 388, 479, 429, 275, 99, 5, 68, 298, - 626, 913, 994, 740, 115, -791, -1770, -2544, -2847, -2509, - -1527, -76, 1518, 2875, 3653, 3653, 2875, 1518, -76, -1527, - -2509, -2847, -2544, -1770, -791, 115, 740, 994, 913, 626, - 298, 68, 5, 99, 275, 429, 479, 388, 175, -92, - -334, -480, -501, -407, -247, -81, 39, 89, 74, 23, - -26, -45, -20, 39, 109, 163, 180, 155, 98, 27, - -35, -73, -83, -69, -43, -19, -5, -3, -11, -21, - -27, -25, -15, -2, 11, 19, 21, 18, 12, 5 -}; - -CAX25RX::CAX25RX() : -m_filter(), -m_state(), -m_demod1(3), -m_demod2(6), -m_demod3(9), -m_lastFCS(0U), -m_count(0U), -m_slotTime(30U), -m_slotCount(0U), -m_pPersist(128U), -m_dcd(false), -m_canTX(false), -m_x(1U), -m_a(0xB7U), -m_b(0x73U), -m_c(0xF6U) -{ - m_filter.numTaps = FILTER_LEN; - m_filter.pState = m_state; - m_filter.pCoeffs = FILTER_COEFFS; - - initRand(); -} - -void CAX25RX::samples(q15_t* samples, uint8_t length) -{ - q15_t output[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_filter, samples, output, RX_BLOCK_SIZE); - - m_count++; - - CAX25Frame frame; - - bool ret = m_demod1.process(output, length, frame); - if (ret) { - if (frame.m_fcs != m_lastFCS || m_count > 2U) { - m_lastFCS = frame.m_fcs; - m_count = 0U; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } - DEBUG1("Decoder 1 reported"); - } - - ret = m_demod2.process(output, length, frame); - if (ret) { - if (frame.m_fcs != m_lastFCS || m_count > 2U) { - m_lastFCS = frame.m_fcs; - m_count = 0U; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } - DEBUG1("Decoder 2 reported"); - } - - ret = m_demod3.process(output, length, frame); - if (ret) { - if (frame.m_fcs != m_lastFCS || m_count > 2U) { - m_lastFCS = frame.m_fcs; - m_count = 0U; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } - DEBUG1("Decoder 3 reported"); - } - - m_slotCount += RX_BLOCK_SIZE; - if (m_slotCount >= m_slotTime) { - m_slotCount = 0U; - - bool dcd1 = m_demod1.isDCD(); - bool dcd2 = m_demod2.isDCD(); - bool dcd3 = m_demod3.isDCD(); - - if (dcd1 || dcd2 || dcd3) { - if (!m_dcd) { - io.setDecode(true); - io.setADCDetection(true); - m_dcd = true; - } - - m_canTX = false; - } else { - if (m_dcd) { - io.setDecode(false); - io.setADCDetection(false); - m_dcd = false; - } - - m_canTX = m_pPersist >= rand(); - } - } -} - -bool CAX25RX::canTX() const -{ - return m_canTX; -} - -void CAX25RX::setParams(int8_t twist, uint8_t slotTime, uint8_t pPersist) -{ - m_demod1.setTwist(twist - 3); - m_demod2.setTwist(twist); - m_demod3.setTwist(twist + 3); - - m_slotTime = slotTime * 240U; // Slot time in samples - m_pPersist = pPersist; -} - -// Taken from https://www.electro-tech-online.com/threads/ultra-fast-pseudorandom-number-generator-for-8-bit.124249/ -//X ABC Algorithm Random Number Generator for 8-Bit Devices: -//This is a small PRNG, experimentally verified to have at least a 50 million byte period -//by generating 50 million bytes and observing that there were no overapping sequences and repeats. -//This generator passes serial correlation, entropy , Monte Carlo Pi value, arithmetic mean, -//And many other statistical tests. This generator may have a period of up to 2^32, but this has -//not been verified. -// -// By XORing 3 bytes into the a,b, and c registers, you can add in entropy from -//an external source easily. -// -//This generator is free to use, but is not suitable for cryptography due to its short period(by //cryptographic standards) and simple construction. No attempt was made to make this generator -// suitable for cryptographic use. -// -//Due to the use of a constant counter, the generator should be resistant to latching up. -//A significant performance gain is had in that the x variable is only ever incremented. -// -//Only 4 bytes of ram are needed for the internal state, and generating a byte requires 3 XORs , //2 ADDs, one bit shift right , and one increment. Difficult or slow operations like multiply, etc -//were avoided for maximum speed on ultra low power devices. - - -void CAX25RX::initRand() //Can also be used to seed the rng with more entropy during use. -{ - m_a = (m_a ^ m_c ^ m_x); - m_b = (m_b + m_a); - m_c = (m_c + (m_b >> 1) ^ m_a); -} - -uint8_t CAX25RX::rand() -{ - m_x++; //x is incremented every round and is not affected by any other variable - - m_a = (m_a ^ m_c ^ m_x); //note the mix of addition and XOR - m_b = (m_b + m_a); //And the use of very few instructions - m_c = (m_c + (m_b >> 1) ^ m_a); //the right shift is to ensure that high-order bits from b can affect - - return uint8_t(m_c); //low order bits of other variables -} - -#endif - diff --git a/AX25RX.h b/AX25RX.h deleted file mode 100644 index 61e50fd..0000000 --- a/AX25RX.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#if !defined(AX25RX_H) -#define AX25RX_H - -#include "AX25Demodulator.h" - -class CAX25RX { -public: - CAX25RX(); - - void samples(q15_t* samples, uint8_t length); - - void setParams(int8_t twist, uint8_t slotTime, uint8_t pPersist); - - bool canTX() const; - -private: - arm_fir_instance_q15 m_filter; - q15_t m_state[160U]; // NoTaps + BlockSize - 1, 130 + 20 - 1 plus some spare - CAX25Demodulator m_demod1; - CAX25Demodulator m_demod2; - CAX25Demodulator m_demod3; - uint16_t m_lastFCS; - uint32_t m_count; - uint32_t m_slotTime; - uint32_t m_slotCount; - uint8_t m_pPersist; - bool m_dcd; - bool m_canTX; - uint8_t m_x; - uint8_t m_a; - uint8_t m_b; - uint8_t m_c; - - void initRand(); - uint8_t rand(); -}; - -#endif - -#endif - diff --git a/AX25TX.cpp b/AX25TX.cpp deleted file mode 100644 index aacc05a..0000000 --- a/AX25TX.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#include "Globals.h" -#include "AX25TX.h" - -#include "AX25Defines.h" -#include "AX25Frame.h" - - -const uint8_t START_FLAG[] = { AX25_FRAME_START }; -const uint8_t END_FLAG[] = { AX25_FRAME_END }; - -const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; - -#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7]) -#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7]) - -const uint8_t BIT_MASK_TABLE2[] = { 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U }; - -#define WRITE_BIT2(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE2[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE2[(i)&7]) -#define READ_BIT2(p,i) (p[(i)>>3] & BIT_MASK_TABLE2[(i)&7]) - -const uint16_t AUDIO_TABLE_LEN = 120U; - -const q15_t AUDIO_TABLE_DATA[] = { - 0, 214, 428, 641, 851, 1060, 1265, 1468, 1666, 1859, 2048, 2230, 2407, 2577, 2740, 2896, 3043, 3182, 3313, 3434, 3546, 3649, - 3741, 3823, 3895, 3955, 4006, 4045, 4073, 4089, 4095, 4089, 4073, 4045, 4006, 3955, 3895, 3823, 3741, 3649, 3546, 3434, 3313, - 3182, 3043, 2896, 2740, 2577, 2407, 2230, 2048, 1859, 1666, 1468, 1265, 1060, 851, 641, 428, 214, 0, -214, -428, -641, -851, - -1060, -1265, -1468, -1666, -1859, -2047, -2230, -2407, -2577, -2740, -2896, -3043, -3182, -3313, -3434, -3546, -3649, -3741, - -3823, -3895, -3955, -4006, -4045, -4073, -4089, -4095, -4089, -4073, -4045, -4006, -3955, -3895, -3823, -3741, -3649, -3546, - -3434, -3313, -3182, -3043, -2896, -2740, -2577, -2407, -2230, -2047, -1859, -1666, -1468, -1265, -1060, -851, -641, -428, -214 -}; - -CAX25TX::CAX25TX() : -m_poBuffer(), -m_poLen(0U), -m_poPtr(0U), -m_txDelay(360U), -m_tablePtr(0U), -m_nrzi(false) -{ -} - -void CAX25TX::process() -{ - if (m_poLen == 0U) - return; - - if (!m_duplex) { - if (m_poPtr == 0U) { - bool tx = ax25RX.canTX(); - if (!tx) - return; - } - } - - uint16_t space = io.getSpace(); - - while (space > AX25_RADIO_SYMBOL_LENGTH) { - bool b = READ_BIT1(m_poBuffer, m_poPtr) != 0U; - m_poPtr++; - - writeBit(b); - - space -= AX25_RADIO_SYMBOL_LENGTH; - - if (m_poPtr >= m_poLen) { - m_poPtr = 0U; - m_poLen = 0U; - return; - } - } -} - -uint8_t CAX25TX::writeData(const uint8_t* data, uint16_t length) -{ - CAX25Frame frame(data, length); - frame.addCRC(); - - m_poLen = 0U; - m_poPtr = 0U; - m_nrzi = false; - m_tablePtr = 0U; - - // Add TX delay - for (uint16_t i = 0U; i < m_txDelay; i++, m_poLen++) { - bool preamble = NRZI(false); - WRITE_BIT1(m_poBuffer, m_poLen, preamble); - } - - // Add the Start Flag - for (uint16_t i = 0U; i < 8U; i++, m_poLen++) { - bool b1 = READ_BIT1(START_FLAG, i) != 0U; - bool b2 = NRZI(b1); - WRITE_BIT1(m_poBuffer, m_poLen, b2); - } - - uint8_t ones = 0U; - for (uint16_t i = 0U; i < (frame.m_length * 8U); i++) { - bool b1 = READ_BIT2(frame.m_data, i) != 0U; - bool b2 = NRZI(b1); - WRITE_BIT1(m_poBuffer, m_poLen, b2); - m_poLen++; - - if (b1) { - ones++; - if (ones == AX25_MAX_ONES) { - // Bit stuffing - bool b = NRZI(false); - WRITE_BIT1(m_poBuffer, m_poLen, b); - m_poLen++; - ones = 0U; - } - } else { - ones = 0U; - } - } - - // Add the End Flag - for (uint16_t i = 0U; i < 8U; i++, m_poLen++) { - bool b1 = READ_BIT1(END_FLAG, i) != 0U; - bool b2 = NRZI(b1); - WRITE_BIT1(m_poBuffer, m_poLen, b2); - } - - return 0U; -} - -void CAX25TX::writeBit(bool b) -{ - q15_t buffer[AX25_RADIO_SYMBOL_LENGTH]; - for (uint8_t i = 0U; i < AX25_RADIO_SYMBOL_LENGTH; i++) { - q15_t value = AUDIO_TABLE_DATA[m_tablePtr]; - - if (b) { - // De-emphasise the lower frequency by 6dB - value >>= 2; - m_tablePtr += 6U; - } else { - m_tablePtr += 11U; - } - - buffer[i] = value >> 1; - - if (m_tablePtr >= AUDIO_TABLE_LEN) - m_tablePtr -= AUDIO_TABLE_LEN; - } - - io.write(STATE_AX25, buffer, AX25_RADIO_SYMBOL_LENGTH); -} - -void CAX25TX::setTXDelay(uint8_t delay) -{ - m_txDelay = delay * 12U; -} - -uint8_t CAX25TX::getSpace() const -{ - return m_poLen == 0U ? 255U : 0U; -} - -bool CAX25TX::NRZI(bool b) -{ - if (!b) - m_nrzi = !m_nrzi; - - return m_nrzi; -} - -#endif - diff --git a/AX25TX.h b/AX25TX.h deleted file mode 100644 index f2e02f8..0000000 --- a/AX25TX.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#if !defined(AX25TX_H) -#define AX25TX_H - -class CAX25TX { -public: - CAX25TX(); - - uint8_t writeData(const uint8_t* data, uint16_t length); - - void process(); - - void setTXDelay(uint8_t delay); - - uint8_t getSpace() const; - -private: - uint8_t m_poBuffer[600U]; - uint16_t m_poLen; - uint16_t m_poPtr; - uint16_t m_txDelay; - uint16_t m_tablePtr; - bool m_nrzi; - - void writeBit(bool b); - bool NRZI(bool b); -}; - -#endif - -#endif - diff --git a/AX25Twist.cpp b/AX25Twist.cpp deleted file mode 100644 index 988a07d..0000000 --- a/AX25Twist.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#include "Globals.h" -#include "AX25Twist.h" - -// 1200Hz = -12dB, 2200Hz = 0dB; 3381Hz cutoff; cosine. -q15_t dB12[] = { - 176, - -812, - -3916, - -7586, - 23536, - -7586, - -3916, - -812, - 176 -}; - -// 1200Hz = -11dB, 2200Hz = 0dB; 3258Hz cutoff; cosine. -q15_t dB11[] = { - 121, - -957, - -3959, - -7383, - 23871, - -7383, - -3959, - -957, - 121 -}; - -// 1200Hz = -10dB, 2200Hz = 0dB; 3118Hz cutoff; cosine. -q15_t dB10[] = { - 56, - -1110, - -3987, - -7141, - 24254, - -7141, - -3987, - -1110, - 56 -}; - -// 1200Hz = -9dB, 2200Hz = 0dB; 2959Hz cutoff; cosine. -q15_t dB9[] = { - -19, - -1268, - -3994, - -6856, - 24688, - -6856, - -3994, - -1268, - -19 -}; - -// 1200Hz = -8dB, 2200Hz = 0dB; 2778Hz cutoff; cosine. -q15_t dB8[] = { - -104, - -1424, - -3968, - -6516, - 25182, - -6516, - -3968, - -1424, - -104 -}; - -// 1200Hz = -7dB, 2200Hz = 0dB; 2573Hz cutoff; cosine. -q15_t dB7[] = { - -196, - -1565, - -3896, - -6114, - 25742, - -6114, - -3896, - -1565, - -196 -}; - -// 1200Hz = -6dB, 2200Hz = 0dB; 2343Hz cutoff; cosine. -q15_t dB6[] = { - -288, - -1676, - -3761, - -5642, - 26370, - -5642, - -3761, - -1676, - -288 -}; - -// 1200Hz = -5dB, 2200Hz = 0dB; 2085Hz cutoff; cosine. -q15_t dB5[] = { - -370, - -1735, - -3545, - -5088, - 27075, - -5088, - -3545, - -1735, - -370 -}; - -// 1200Hz = -4dB, 2200Hz = 0dB; 1790Hz cutoff; cosine. -q15_t dB4[] = { - -432, - -1715, - -3220, - -4427, - 27880, - -4427, - -3220, - -1715, - -432 -}; - -// 1200Hz = -3dB, 2200Hz = 0dB; 1456Hz cutoff; cosine. -q15_t dB3[] = { - -452, - -1582, - -2759, - -3646, - 28792, - -3646, - -2759, - -1582, - -452 -}; - -// 1200Hz = -2dB, 2200Hz = 0dB; 1070Hz cutoff; cosine. -q15_t dB2[] = { - -408, - -1295, - -2123, - -2710, - 29846, - -2710, - -2123, - -1295, - -408 -}; - -// 1200Hz = -1dB, 2200Hz = 0dB; 605Hz cutoff; cosine. -q15_t dB1[] = { - -268, - -795, - -1244, - -1546, - 31116, - -1546, - -1244, - -795, - -268 -}; - -q15_t dB0[] = { - 0, - 0, - 0, - 0, - 32767, - 0, - 0, - 0, - 0, -}; - -// 1200Hz = 0dB, 2200Hz = -1dB; 4130Hz cutoff; cosine. -q15_t dB_1[] = { - -419, - -177, - 3316, - 8650, - 11278, - 8650, - 3316, - -177, - -419 -}; - -// 1200Hz = 0dB, 2200Hz = -2dB; 3190Hz cutoff; cosine. -q15_t dB_2[] = { - -90, - 1033, - 3975, - 7267, - 8711, - 7267, - 3975, - 1033, - -90 -}; - -// 1200Hz = 0dB, 2200Hz = -3dB; 2330Hz cutoff; cosine. -q15_t dB_3[] = { - 292, - 1680, - 3752, - 5615, - 6362, - 5615, - 3752, - 1680, - 292 -}; - -// 1200Hz = 0dB, 2200Hz = -4dB; 2657Hz cutoff; boxcar. -q15_t dB_4[] = { - 917, - 3024, - 5131, - 6684, - 7255, - 6684, - 5131, - 3024, - 917 -}; - -// 1200Hz = 0dB, 2200Hz = -5dB; 2360Hz cutoff; boxcar. -q15_t dB_5[] = { - 1620, - 3339, - 4925, - 6042, - 6444, - 6042, - 4925, - 3339, - 1620 -}; - -// 1200Hz = 0dB, 2200Hz = -6dB; 2067Hz cutoff; boxcar. -q15_t dB_6[] = { - 2161, - 3472, - 4605, - 5373, - 5644, - 5373, - 4605, - 3472, - 2161 -}; - -q15_t* coeffs[] = { - dB12, - dB11, - dB10, - dB9, - dB8, - dB7, - dB6, - dB5, - dB4, - dB3, - dB2, - dB1, - dB0, - dB_1, - dB_2, - dB_3, - dB_4, - dB_5, - dB_6 -}; - -CAX25Twist::CAX25Twist(int8_t n) : -m_filter(), -m_state() -{ - setTwist(n); -} - -void CAX25Twist::process(q15_t* in, q15_t* out, uint8_t length) -{ - ::arm_fir_fast_q15(&m_filter, in, out, length); -} - -void CAX25Twist::setTwist(int8_t n) -{ - uint8_t twist = uint8_t(n + 6); - - m_filter.numTaps = 9; - m_filter.pState = m_state; - m_filter.pCoeffs = coeffs[twist]; -} - -#endif - diff --git a/AX25Twist.h b/AX25Twist.h deleted file mode 100644 index e127e7a..0000000 --- a/AX25Twist.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2020 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" - -#if defined(MODE_AX25) - -#if !defined(AX25Twist_H) -#define AX25Twist_H - -class CAX25Twist { -public: - CAX25Twist(int8_t n); - - void process(q15_t* in, q15_t* out, uint8_t length); - - void setTwist(int8_t n); - -private: - arm_fir_instance_q15 m_filter; - q15_t m_state[40U]; // NoTaps + BlockSize - 1, 9 + 20 - 1 plus some spare -}; - -#endif - -#endif - diff --git a/CalM17.cpp b/CalM17.cpp deleted file mode 100644 index 4c567f2..0000000 --- a/CalM17.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009-2015,2020,2021 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" - -#if defined(MODE_M17) - -#include "Globals.h" -#include "CalM17.h" -#include "M17Defines.h" - -const uint8_t PREAMBLE[] = {0x00U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, - 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U, 0x77U}; - -CCalM17::CCalM17() : -m_transmit(false) -{ -} - -void CCalM17::process() -{ - m17TX.process(); - - if (!m_transmit) - return; - - uint16_t space = m17TX.getSpace(); - if (space < 2U) - return; - - m17TX.writeData(PREAMBLE, M17_FRAME_LENGTH_BYTES + 1U); -} - -uint8_t CCalM17::write(const uint8_t* data, uint16_t length) -{ - if (length != 1U) - return 4U; - - m_transmit = data[0U] == 1U; - - return 0U; -} - -#endif - diff --git a/CalM17.h b/CalM17.h deleted file mode 100644 index bf8257e..0000000 --- a/CalM17.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2009-2015,2020,2021 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" - -#if defined(MODE_M17) - -#if !defined(CALM17_H) -#define CALM17_H - - -class CCalM17 { -public: - CCalM17(); - - void process(); - - uint8_t write(const uint8_t* data, uint16_t length); - -private: - bool m_transmit; -}; - -#endif - -#endif - diff --git a/Config.h b/Config.h index 828e231..28b070f 100644 --- a/Config.h +++ b/Config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2025 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,18 +38,12 @@ #define MODE_NXDN #define USE_NXDN_BOXCAR -// Enable M17 support. -#define MODE_M17 - // Enable POCSAG support. #define MODE_POCSAG // Enable FM support. #define MODE_FM -// Enable AX.25 support, this is only enabled if FM is also enabled. -#define MODE_AX25 - // Allow for the use of high quality external clock oscillators // The number is the frequency of the oscillator in Hertz. // @@ -116,9 +110,6 @@ // Use the YSF and P25 LEDs for NXDN // #define USE_ALTERNATE_NXDN_LEDS -// Use the D-Star and P25 LEDs for M17 -#define USE_ALTERNATE_M17_LEDS - // Use the D-Star and DMR LEDs for POCSAG #define USE_ALTERNATE_POCSAG_LEDS diff --git a/Globals.h b/Globals.h index 33b7334..84e8eae 100644 --- a/Globals.h +++ b/Globals.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 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 @@ -48,9 +48,7 @@ enum MMDVM_STATE { STATE_P25 = 4, STATE_NXDN = 5, STATE_POCSAG = 6, - STATE_M17 = 7, STATE_FM = 10, - STATE_AX25 = 11, // Dummy states start at 90 STATE_NXDNCAL1K = 91, @@ -69,8 +67,7 @@ enum MMDVM_STATE { STATE_FMCAL15K = 104, STATE_FMCAL20K = 105, STATE_FMCAL25K = 106, - STATE_FMCAL30K = 107, - STATE_M17CAL = 108 + STATE_FMCAL30K = 107 }; #include "SerialPort.h" @@ -85,8 +82,6 @@ enum MMDVM_STATE { #include "YSFTX.h" #include "P25RX.h" #include "P25TX.h" -#include "M17RX.h" -#include "M17TX.h" #include "NXDNRX.h" #include "NXDNTX.h" #include "POCSAGTX.h" @@ -99,9 +94,6 @@ enum MMDVM_STATE { #include "CalPOCSAG.h" #include "CalRSSI.h" #include "CWIdTX.h" -#include "AX25RX.h" -#include "AX25TX.h" -#include "CalM17.h" #include "Debug.h" #include "IO.h" #include "FM.h" @@ -129,9 +121,7 @@ extern bool m_ysfEnable; extern bool m_p25Enable; extern bool m_nxdnEnable; extern bool m_pocsagEnable; -extern bool m_m17Enable; extern bool m_fmEnable; -extern bool m_ax25Enable; extern bool m_duplex; @@ -184,23 +174,11 @@ extern CPOCSAGTX pocsagTX; extern CCalPOCSAG calPOCSAG; #endif -#if defined(MODE_M17) -extern CM17RX m17RX; -extern CM17TX m17TX; - -extern CCalM17 calM17; -#endif - #if defined(MODE_FM) extern CFM fm; extern CCalFM calFM; #endif -#if defined(MODE_AX25) -extern CAX25RX ax25RX; -extern CAX25TX ax25TX; -#endif - extern CCalRSSI calRSSI; extern CCWIdTX cwIdTX; diff --git a/IO.cpp b/IO.cpp index 4c973e4..adbba73 100644 --- a/IO.cpp +++ b/IO.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM * Copyright (C) 2016 by Colin Durbridge G4EML * @@ -36,14 +36,6 @@ static q15_t RRC_0_2_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 147 const uint16_t RRC_0_2_FILTER_LEN = 42U; #endif -#if defined(MODE_M17) -// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB -static q15_t RRC_0_5_FILTER[] = {-147, -88, 72, 220, 223, 46, -197, -285, -79, 334, 623, 390, -498, -1691, -2363, -1556, 1284, 5872, 11033, - 15109, 16656, 15109, 11033, 5872, 1284, -1556, -2363, -1691, -498, 390, 623, 334, -79, -285, -197, 46, 223, - 220, 72, -88, -147, 0}; -const uint16_t RRC_0_5_FILTER_LEN = 42U; -#endif - #if defined(MODE_NXDN) #if defined(USE_NXDN_BOXCAR) // One symbol boxcar filter @@ -114,10 +106,6 @@ m_nxdnState(), m_nxdnISincState(), #endif #endif -#if defined(MODE_M17) -m_rrc05Filter(), -m_rrc05State(), -#endif m_pttInvert(false), m_rxLevel(128 * 128), m_cwIdTXLevel(128 * 128), @@ -126,10 +114,8 @@ m_dmrTXLevel(128 * 128), m_ysfTXLevel(128 * 128), m_p25TXLevel(128 * 128), m_nxdnTXLevel(128 * 128), -m_m17TXLevel(128 * 128), m_pocsagTXLevel(128 * 128), m_fmTXLevel(128 * 128), -m_ax25TXLevel(128 * 128), m_rxDCOffset(DC_OFFSET), m_txDCOffset(DC_OFFSET), m_useCOSAsLockout(false), @@ -197,13 +183,6 @@ m_lockout(false) #endif #endif -#if defined(MODE_M17) - ::memset(m_rrc05State, 0x00U, 70U * sizeof(q15_t)); - m_rrc05Filter.numTaps = RRC_0_5_FILTER_LEN; - m_rrc05Filter.pState = m_rrc05State; - m_rrc05Filter.pCoeffs = RRC_0_5_FILTER; -#endif - initInt(); selfTest(); @@ -227,9 +206,6 @@ void CIO::selfTest() #if !defined(USE_ALTERNATE_NXDN_LEDS) setNXDNInt(ledValue); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - setM17Int(ledValue); -#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) setPOCSAGInt(ledValue); #endif @@ -248,9 +224,6 @@ void CIO::selfTest() #if !defined(USE_ALTERNATE_NXDN_LEDS) setNXDNInt(false); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - setM17Int(false); -#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) setPOCSAGInt(false); #endif @@ -273,11 +246,6 @@ void CIO::selfTest() setNXDNInt(true); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - delayInt(250); - setM17Int(true); -#endif - #if !defined(USE_ALTERNATE_POCSAG_LEDS) delayInt(250); setPOCSAGInt(true); @@ -296,11 +264,6 @@ void CIO::selfTest() setPOCSAGInt(false); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - delayInt(250); - setM17Int(false); -#endif - #if !defined(USE_ALTERNATE_NXDN_LEDS) delayInt(250); setNXDNInt(false); @@ -338,7 +301,7 @@ void CIO::process() if (m_started) { // Two seconds timeout if (m_watchdog >= 48000U) { - if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_M17 || m_modemState == STATE_POCSAG) { + if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_POCSAG) { #if defined(MODE_DMR) if (m_modemState == STATE_DMR && m_tx) dmrTX.setStart(false); @@ -490,18 +453,6 @@ void CIO::process() } #endif -#if defined(MODE_M17) - if (m_m17Enable) { - q15_t RRCVals[RX_BLOCK_SIZE]; -#if defined(USE_DCBLOCKER) - ::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, RRCVals, RX_BLOCK_SIZE); -#else - ::arm_fir_fast_q15(&m_rrc05Filter, samples, RRCVals, RX_BLOCK_SIZE); -#endif - m17RX.samples(RRCVals, rssi, RX_BLOCK_SIZE); - } -#endif - #if defined(MODE_FM) if (m_fmEnable) { bool cos = getCOSInt(); @@ -512,16 +463,6 @@ void CIO::process() #endif } #endif - -#if defined(MODE_FM) && defined(MODE_AX25) - if (m_ax25Enable) { -#if defined(USE_DCBLOCKER) - ax25RX.samples(dcSamples, RX_BLOCK_SIZE); -#else - ax25RX.samples(samples, RX_BLOCK_SIZE); -#endif - } -#endif } #if defined(MODE_DSTAR) @@ -609,37 +550,13 @@ void CIO::process() } #endif -#if defined(MODE_M17) - else if (m_modemState == STATE_M17) { - if (m_m17Enable) { - q15_t M17Vals[RX_BLOCK_SIZE]; -#if defined(USE_DCBLOCKER) - ::arm_fir_fast_q15(&m_rrc05Filter, dcSamples, M17Vals, RX_BLOCK_SIZE); -#else - ::arm_fir_fast_q15(&m_rrc05Filter, samples, M17Vals, RX_BLOCK_SIZE); -#endif - m17RX.samples(M17Vals, rssi, RX_BLOCK_SIZE); - } - } -#endif - #if defined(MODE_FM) else if (m_modemState == STATE_FM) { bool cos = getCOSInt(); #if defined(USE_DCBLOCKER) fm.samples(cos, dcSamples, RX_BLOCK_SIZE); - -#if defined(MODE_AX25) - if (m_ax25Enable) - ax25RX.samples(dcSamples, RX_BLOCK_SIZE); -#endif #else fm.samples(cos, samples, RX_BLOCK_SIZE); - -#if defined(MODE_AX25) - if (m_ax25Enable) - ax25RX.samples(samples, RX_BLOCK_SIZE); -#endif #endif } #endif @@ -691,18 +608,12 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t case STATE_NXDN: txLevel = m_nxdnTXLevel; break; - case STATE_M17: - txLevel = m_m17TXLevel; - break; case STATE_POCSAG: txLevel = m_pocsagTXLevel; break; case STATE_FM: txLevel = m_fmTXLevel; break; - case STATE_AX25: - txLevel = m_ax25TXLevel; - break; default: txLevel = m_cwIdTXLevel; break; @@ -754,7 +665,6 @@ void CIO::setMode(MMDVM_STATE state) case STATE_YSF: setYSFInt(false); break; case STATE_P25: setP25Int(false); break; case STATE_NXDN: setNXDNInt(false); break; - case STATE_M17: setM17Int(false); break; case STATE_POCSAG: setPOCSAGInt(false); break; case STATE_FM: setFMInt(false); break; default: break; @@ -766,7 +676,6 @@ void CIO::setMode(MMDVM_STATE state) case STATE_YSF: setYSFInt(true); break; case STATE_P25: setP25Int(true); break; case STATE_NXDN: setNXDNInt(true); break; - case STATE_M17: setM17Int(true); break; case STATE_POCSAG: setPOCSAGInt(true); break; case STATE_FM: setFMInt(true); break; default: break; @@ -776,7 +685,7 @@ void CIO::setMode(MMDVM_STATE state) m_modemState = state; } -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, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, uint8_t ax25TXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout) +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, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout) { m_pttInvert = pttInvert; @@ -787,10 +696,8 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_ysfTXLevel = q15_t(ysfTXLevel * 128); m_p25TXLevel = q15_t(p25TXLevel * 128); m_nxdnTXLevel = q15_t(nxdnTXLevel * 128); - m_m17TXLevel = q15_t(m17TXLevel * 128); m_pocsagTXLevel = q15_t(pocsagTXLevel * 128); m_fmTXLevel = q15_t(fmTXLevel * 128); - m_ax25TXLevel = q15_t(ax25TXLevel * 128); m_rxDCOffset = DC_OFFSET + rxDCOffset; m_txDCOffset = DC_OFFSET + txDCOffset; @@ -806,7 +713,6 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx m_ysfTXLevel = -m_ysfTXLevel; m_p25TXLevel = -m_p25TXLevel; m_nxdnTXLevel = -m_nxdnTXLevel; - m_m17TXLevel = -m_m17TXLevel; m_pocsagTXLevel = -m_pocsagTXLevel; } } diff --git a/IO.h b/IO.h index b1cf1ab..3e18c33 100644 --- a/IO.h +++ b/IO.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 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 @@ -46,7 +46,7 @@ public: void interrupt(); - void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, uint8_t ax25TXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout); + 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, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout); void getOverflow(bool& adcOverflow, bool& dacOverflow); @@ -108,11 +108,6 @@ private: #endif #endif -#if defined(MODE_M17) - arm_fir_instance_q15 m_rrc05Filter; - q15_t m_rrc05State[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare -#endif - bool m_pttInvert; q15_t m_rxLevel; q15_t m_cwIdTXLevel; @@ -121,10 +116,8 @@ private: q15_t m_ysfTXLevel; q15_t m_p25TXLevel; q15_t m_nxdnTXLevel; - q15_t m_m17TXLevel; q15_t m_pocsagTXLevel; q15_t m_fmTXLevel; - q15_t m_ax25TXLevel; uint16_t m_rxDCOffset; uint16_t m_txDCOffset; @@ -159,10 +152,10 @@ private: void setP25Int(bool on); void setNXDNInt(bool on); void setPOCSAGInt(bool on); - void setM17Int(bool on); void setFMInt(bool on); void delayInt(unsigned int dly); }; #endif + diff --git a/IODue.cpp b/IODue.cpp index f2e7b36..e77c388 100644 --- a/IODue.cpp +++ b/IODue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX * Copyright (C) 2015 by Jim Mclaughlin KI6ZUM * Copyright (C) 2016 by Colin Durbridge G4EML * @@ -107,9 +107,6 @@ void CIO::initInt() #if !defined(USE_ALTERNATE_NXDN_LEDS) pinMode(PIN_NXDN, OUTPUT); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - pinMode(PIN_M17, OUTPUT); -#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) pinMode(PIN_POCSAG, OUTPUT); #endif @@ -256,16 +253,6 @@ void CIO::setNXDNInt(bool on) #endif } -void CIO::setM17Int(bool on) -{ -#if defined(USE_ALTERNATE_M17_LEDS) - digitalWrite(PIN_DSTAR, on ? HIGH : LOW); - digitalWrite(PIN_P25, on ? HIGH : LOW); -#else - digitalWrite(PIN_M17, on ? HIGH : LOW); -#endif -} - void CIO::setPOCSAGInt(bool on) { #if defined(USE_ALTERNATE_POCSAG_LEDS) diff --git a/IOSTM.cpp b/IOSTM.cpp index db87da0..2c9bcdd 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU - * Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2017,2018,2020,2025 by Jonathan Naylor G4KLX * Copyright (C) 2019,2020 by BG5HHP * * This program is free software; you can redistribute it and/or modify @@ -106,14 +106,6 @@ void CIO::initInt() GPIO_Init(PORT_NXDN, &GPIO_InitStruct); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - // M17 pin - RCC_AHB1PeriphClockCmd(RCC_Per_M17, ENABLE); - GPIO_InitStruct.GPIO_Pin = PIN_M17; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_Init(PORT_M17, &GPIO_InitStruct); -#endif - #if !defined(USE_ALTERNATE_POCSAG_LEDS) // POCSAG pin RCC_AHB1PeriphClockCmd(RCC_Per_POCSAG, ENABLE); @@ -165,14 +157,6 @@ void CIO::initInt() GPIO_Init(PORT_MNXDN, &GPIO_InitStruct); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - // M17 mode pin - RCC_AHB1PeriphClockCmd(RCC_Per_MM17, ENABLE); - GPIO_InitStruct.GPIO_Pin = PIN_MM17; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_Init(PORT_MM17, &GPIO_InitStruct); -#endif - #if !defined(USE_ALTERNATE_POCSAG_LEDS) // POCSAG mode pin RCC_AHB1PeriphClockCmd(RCC_Per_MPOCSAG, ENABLE); @@ -456,27 +440,6 @@ void CIO::setNXDNInt(bool on) #endif } -void CIO::setM17Int(bool on) -{ -#if defined(MODE_LEDS) -#if defined(USE_ALTERNATE_M17_LEDS) - GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET); - GPIO_WriteBit(PORT_P25, PIN_P25, on ? Bit_SET : Bit_RESET); -#else - GPIO_WriteBit(PORT_M17, PIN_M17, on ? Bit_SET : Bit_RESET); -#endif -#endif - -#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT)) -#if defined(USE_ALTERNATE_M17_LEDS) - GPIO_WriteBit(PORT_MDSTAR, PIN_MDSTAR, on ? Bit_SET : Bit_RESET); - GPIO_WriteBit(PORT_MP25, PIN_MP25, on ? Bit_SET : Bit_RESET); -#else - GPIO_WriteBit(PORT_MM17, PIN_MM17, on ? Bit_SET : Bit_RESET); -#endif -#endif -} - void CIO::setPOCSAGInt(bool on) { #if defined(MODE_LEDS) diff --git a/IOTeensy.cpp b/IOTeensy.cpp index 5e1028d..82162fe 100644 --- a/IOTeensy.cpp +++ b/IOTeensy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2025 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 @@ -75,9 +75,6 @@ void CIO::initInt() #if !defined(USE_ALTERNATE_NXDN_LEDS) pinMode(PIN_NXDN, OUTPUT); #endif -#if !defined(USE_ALTERNATE_M17_LEDS) - pinMode(PIN_M17, OUTPUT); -#endif #if !defined(USE_ALTERNATE_POCSAG_LEDS) pinMode(PIN_POCSAG, OUTPUT); #endif @@ -240,16 +237,6 @@ void CIO::setNXDNInt(bool on) #endif } -void CIO::setM17Int(bool on) -{ -#if defined(USE_ALTERNATE_M17_LEDS) - digitalWrite(PIN_DSTAR, on ? HIGH : LOW); - digitalWrite(PIN_P25, on ? HIGH : LOW); -#else - digitalWrite(PIN_M17, on ? HIGH : LOW); -#endif -} - void CIO::setPOCSAGInt(bool on) { #if defined(USE_ALTERNATE_POCSAG_LEDS) diff --git a/M17Defines.h b/M17Defines.h deleted file mode 100644 index 27f91c9..0000000 --- a/M17Defines.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016,2017,2018,2020,2021 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(M17DEFINES_H) -#define M17DEFINES_H - -const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate - -const unsigned int M17_FRAME_LENGTH_BITS = 384U; -const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U; -const unsigned int M17_FRAME_LENGTH_SYMBOLS = M17_FRAME_LENGTH_BITS / 2U; -const unsigned int M17_FRAME_LENGTH_SAMPLES = M17_FRAME_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH; - -const unsigned int M17_SYNC_LENGTH_BITS = 16U; -const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U; -const unsigned int M17_SYNC_LENGTH_SYMBOLS = M17_SYNC_LENGTH_BITS / 2U; -const unsigned int M17_SYNC_LENGTH_SAMPLES = M17_SYNC_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH; - -const uint8_t M17_LINK_SETUP_SYNC_BYTES[] = {0x55U, 0xF7U}; -const uint8_t M17_STREAM_SYNC_BYTES[] = {0xFFU, 0x5DU}; -const uint8_t M17_EOF_SYNC_BYTES[] = {0x55U, 0x5DU}; - -const uint16_t M17_LINK_SETUP_SYNC_BITS = 0x55F7U; -const uint16_t M17_STREAM_SYNC_BITS = 0xFF5DU; -const uint16_t M17_EOF_SYNC_BITS = 0x555DU; - -// 5 5 F 7 -// 01 01 01 01 11 11 01 11 -// +3 +3 +3 +3 -3 -3 +3 -3 - -const int8_t M17_LINK_SETUP_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, -3, -3, +3, -3}; - -const uint8_t M17_LINK_SETUP_SYNC_SYMBOLS = 0xF2U; - -// F F 5 D -// 11 11 11 11 01 01 11 01 -// -3 -3 -3 -3 +3 +3 -3 +3 - -const int8_t M17_STREAM_SYNC_SYMBOLS_VALUES[] = {-3, -3, -3, -3, +3, +3, -3, +3}; - -const uint8_t M17_STREAM_SYNC_SYMBOLS = 0x0DU; - -// 5 5 5 D -// 01 01 01 01 01 01 11 01 -// +3 +3 +3 +3 +3 +3 -3 +3 - -const int8_t M17_EOF_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, +3, +3, -3, +3}; - -const uint8_t M17_EOF_SYNC_SYMBOLS = 0xFDU; - -#endif - diff --git a/M17RX.cpp b/M17RX.cpp deleted file mode 100644 index 44ee13f..0000000 --- a/M17RX.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (C) 2009-2017,2020,2021 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" - -#if defined(MODE_M17) - -#include "Globals.h" -#include "M17RX.h" -#include "Utils.h" - -const q15_t SCALING_FACTOR = 18750; // Q15(0.55) - -const uint8_t MAX_SYNC_BIT_START_ERRS = 0U; -const uint8_t MAX_SYNC_BIT_RUN_ERRS = 2U; - -const uint8_t MAX_SYNC_SYMBOL_START_ERRS = 0U; -const uint8_t MAX_SYNC_SYMBOL_RUN_ERRS = 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]) - -const uint8_t NOAVEPTR = 99U; - -const uint16_t NOENDPTR = 9999U; - -const unsigned int MAX_SYNC_FRAMES = 3U + 1U; - -CM17RX::CM17RX() : -m_state(M17RXS_NONE), -m_bitBuffer(), -m_buffer(), -m_bitPtr(0U), -m_dataPtr(0U), -m_startPtr(NOENDPTR), -m_endPtr(NOENDPTR), -m_syncPtr(NOENDPTR), -m_minSyncPtr(NOENDPTR), -m_maxSyncPtr(NOENDPTR), -m_maxCorr(0), -m_lostCount(0U), -m_countdown(0U), -m_nextState(M17RXS_NONE), -m_centre(), -m_centreVal(0), -m_threshold(), -m_thresholdVal(0), -m_averagePtr(NOAVEPTR), -m_rssiAccum(0U), -m_rssiCount(0U) -{ -} - -void CM17RX::reset() -{ - m_state = M17RXS_NONE; - m_dataPtr = 0U; - m_bitPtr = 0U; - m_maxCorr = 0; - m_averagePtr = NOAVEPTR; - m_startPtr = NOENDPTR; - m_endPtr = NOENDPTR; - m_syncPtr = NOENDPTR; - m_minSyncPtr = NOENDPTR; - m_maxSyncPtr = NOENDPTR; - m_centreVal = 0; - m_thresholdVal = 0; - m_lostCount = 0U; - m_countdown = 0U; - m_nextState = M17RXS_NONE; - m_rssiAccum = 0U; - m_rssiCount = 0U; -} - -void CM17RX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length) -{ - for (uint8_t i = 0U; i < length; i++) { - q15_t sample = samples[i]; - - m_rssiAccum += rssi[i]; - m_rssiCount++; - - m_bitBuffer[m_bitPtr] <<= 1; - if (sample < 0) - m_bitBuffer[m_bitPtr] |= 0x01U; - - m_buffer[m_dataPtr] = sample; - - switch (m_state) { - case M17RXS_LINK_SETUP: - case M17RXS_STREAM: - processData(sample); - break; - default: - processNone(sample); - break; - } - - m_dataPtr++; - if (m_dataPtr >= M17_FRAME_LENGTH_SAMPLES) - m_dataPtr = 0U; - - m_bitPtr++; - if (m_bitPtr >= M17_RADIO_SYMBOL_LENGTH) - m_bitPtr = 0U; - } -} - -void CM17RX::processNone(q15_t sample) -{ - bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS); - bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS); - - if (ret1 || ret2) { - // On the first sync, start the countdown to the state change - if (m_countdown == 0U) { - m_rssiAccum = 0U; - m_rssiCount = 0U; - - io.setDecode(true); - io.setADCDetection(true); - - m_averagePtr = NOAVEPTR; - - m_countdown = 5U; - - if (ret1) m_nextState = M17RXS_LINK_SETUP; - if (ret2) m_nextState = M17RXS_STREAM; - } - } - - if (m_countdown > 0U) - m_countdown--; - - if (m_countdown == 1U) { - m_minSyncPtr = m_syncPtr + M17_FRAME_LENGTH_SAMPLES - 1U; - if (m_minSyncPtr >= M17_FRAME_LENGTH_SAMPLES) - m_minSyncPtr -= M17_FRAME_LENGTH_SAMPLES; - - m_maxSyncPtr = m_syncPtr + 1U; - if (m_maxSyncPtr >= M17_FRAME_LENGTH_SAMPLES) - m_maxSyncPtr -= M17_FRAME_LENGTH_SAMPLES; - - m_state = m_nextState; - m_countdown = 0U; - m_nextState = M17RXS_NONE; - } -} - -void CM17RX::processData(q15_t sample) -{ - bool eof = false; - - if (m_minSyncPtr < m_maxSyncPtr) { - if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) { - bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS); - - eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS); - - if (ret) m_state = M17RXS_STREAM; - } - } else { - if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) { - bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS); - - eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS); - - if (ret) m_state = M17RXS_STREAM; - } - } - - if (eof) { - DEBUG4("M17RX: eof sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal); - - io.setDecode(false); - io.setADCDetection(false); - - serial.writeM17EOT(); - - m_state = M17RXS_NONE; - m_endPtr = NOENDPTR; - m_averagePtr = NOAVEPTR; - m_countdown = 0U; - m_nextState = M17RXS_NONE; - m_maxCorr = 0; - } - - if (m_dataPtr == m_endPtr) { - // Only update the centre and threshold if they are from a good sync - if (m_lostCount == MAX_SYNC_FRAMES) { - m_minSyncPtr = m_syncPtr + M17_FRAME_LENGTH_SAMPLES - 1U; - if (m_minSyncPtr >= M17_FRAME_LENGTH_SAMPLES) - m_minSyncPtr -= M17_FRAME_LENGTH_SAMPLES; - - m_maxSyncPtr = m_syncPtr + 1U; - if (m_maxSyncPtr >= M17_FRAME_LENGTH_SAMPLES) - m_maxSyncPtr -= M17_FRAME_LENGTH_SAMPLES; - } - - calculateLevels(m_startPtr, M17_FRAME_LENGTH_SYMBOLS); - - switch (m_state) { - case M17RXS_LINK_SETUP: - DEBUG4("M17RX: link setup sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal); - break; - case M17RXS_STREAM: - DEBUG4("M17RX: stream sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal); - break; - default: - break; - } - - uint8_t frame[M17_FRAME_LENGTH_BYTES + 3U]; - samplesToBits(m_startPtr, M17_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal); - - // We've not seen a stream sync for too long, signal RXLOST and change to RX_NONE - m_lostCount--; - if (m_lostCount == 0U) { - DEBUG1("M17RX: sync timed out, lost lock"); - - io.setDecode(false); - io.setADCDetection(false); - - serial.writeM17Lost(); - - m_state = M17RXS_NONE; - m_endPtr = NOENDPTR; - m_averagePtr = NOAVEPTR; - m_countdown = 0U; - m_nextState = M17RXS_NONE; - m_maxCorr = 0; - } else { - frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; - - switch (m_state) { - case M17RXS_LINK_SETUP: - writeRSSILinkSetup(frame); - break; - case M17RXS_STREAM: - writeRSSIStream(frame); - break; - default: - break; - } - - m_maxCorr = 0; - m_nextState = M17RXS_NONE; - } - } -} - -bool CM17RX::correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues, const uint8_t* syncBytes, uint8_t maxSymbolErrs, uint8_t maxBitErrs) -{ - if (countBits8(m_bitBuffer[m_bitPtr] ^ syncSymbols) <= maxSymbolErrs) { - uint16_t ptr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES + M17_RADIO_SYMBOL_LENGTH; - if (ptr >= M17_FRAME_LENGTH_SAMPLES) - ptr -= M17_FRAME_LENGTH_SAMPLES; - - q31_t corr = 0; - q15_t min = 16000; - q15_t max = -16000; - - for (uint8_t i = 0U; i < M17_SYNC_LENGTH_SYMBOLS; i++) { - q15_t val = m_buffer[ptr]; - - if (val > max) - max = val; - if (val < min) - min = val; - - switch (syncSymbolValues[i]) { - case +3: - corr -= (val + val + val); - break; - case +1: - corr -= val; - break; - case -1: - corr += val; - break; - default: // -3 - corr += (val + val + val); - break; - } - - ptr += M17_RADIO_SYMBOL_LENGTH; - if (ptr >= M17_FRAME_LENGTH_SAMPLES) - ptr -= M17_FRAME_LENGTH_SAMPLES; - } - - if (corr > m_maxCorr) { - if (m_averagePtr == NOAVEPTR) { - m_centreVal = (max + min) >> 1; - - q31_t v1 = (max - m_centreVal) * SCALING_FACTOR; - m_thresholdVal = q15_t(v1 >> 15); - } - - uint16_t startPtr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES + M17_RADIO_SYMBOL_LENGTH; - if (startPtr >= M17_FRAME_LENGTH_SAMPLES) - startPtr -= M17_FRAME_LENGTH_SAMPLES; - - uint8_t sync[M17_SYNC_LENGTH_BYTES]; - samplesToBits(startPtr, M17_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal); - - uint8_t errs = 0U; - for (uint8_t i = 0U; i < M17_SYNC_LENGTH_BYTES; i++) - errs += countBits8(sync[i] ^ syncBytes[i]); - - if (errs <= maxBitErrs) { - m_maxCorr = corr; - m_lostCount = MAX_SYNC_FRAMES; - m_syncPtr = m_dataPtr; - - m_startPtr = startPtr; - - m_endPtr = m_dataPtr + M17_FRAME_LENGTH_SAMPLES - M17_SYNC_LENGTH_SAMPLES - 1U; - if (m_endPtr >= M17_FRAME_LENGTH_SAMPLES) - m_endPtr -= M17_FRAME_LENGTH_SAMPLES; - - return true; - } - } - } - - return false; -} - -void CM17RX::calculateLevels(uint16_t start, uint16_t count) -{ - q15_t maxPos = -16000; - q15_t minPos = 16000; - q15_t maxNeg = 16000; - q15_t minNeg = -16000; - - for (uint16_t i = 0U; i < count; i++) { - q15_t sample = m_buffer[start]; - - if (sample > 0) { - if (sample > maxPos) - maxPos = sample; - if (sample < minPos) - minPos = sample; - } else { - if (sample < maxNeg) - maxNeg = sample; - if (sample > minNeg) - minNeg = sample; - } - - start += M17_RADIO_SYMBOL_LENGTH; - if (start >= M17_FRAME_LENGTH_SAMPLES) - start -= M17_FRAME_LENGTH_SAMPLES; - } - - q15_t posThresh = (maxPos + minPos) >> 1; - q15_t negThresh = (maxNeg + minNeg) >> 1; - - q15_t centre = (posThresh + negThresh) >> 1; - - q15_t threshold = posThresh - centre; - - DEBUG5("M17RX: pos/neg/centre/threshold", posThresh, negThresh, centre, threshold); - - if (m_averagePtr == NOAVEPTR) { - for (uint8_t i = 0U; i < 16U; i++) { - m_centre[i] = centre; - m_threshold[i] = threshold; - } - - m_averagePtr = 0U; - } else { - m_centre[m_averagePtr] = centre; - m_threshold[m_averagePtr] = threshold; - - m_averagePtr++; - if (m_averagePtr >= 16U) - m_averagePtr = 0U; - } - - m_centreVal = 0; - m_thresholdVal = 0; - - for (uint8_t i = 0U; i < 16U; i++) { - m_centreVal += m_centre[i]; - m_thresholdVal += m_threshold[i]; - } - - m_centreVal >>= 4; - m_thresholdVal >>= 4; -} - -void CM17RX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold) -{ - for (uint16_t i = 0U; i < count; i++) { - 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++; - } - - start += M17_RADIO_SYMBOL_LENGTH; - if (start >= M17_FRAME_LENGTH_SAMPLES) - start -= M17_FRAME_LENGTH_SAMPLES; - } -} - -void CM17RX::writeRSSILinkSetup(uint8_t* data) -{ -#if defined(SEND_RSSI_DATA) - if (m_rssiCount > 0U) { - uint16_t rssi = m_rssiAccum / m_rssiCount; - - data[49U] = (rssi >> 8) & 0xFFU; - data[50U] = (rssi >> 0) & 0xFFU; - - serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 1U); - } -#else - serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 1U); -#endif - - m_rssiAccum = 0U; - m_rssiCount = 0U; -} - -void CM17RX::writeRSSIStream(uint8_t* data) -{ -#if defined(SEND_RSSI_DATA) - if (m_rssiCount > 0U) { - uint16_t rssi = m_rssiAccum / m_rssiCount; - - data[49U] = (rssi >> 8) & 0xFFU; - data[50U] = (rssi >> 0) & 0xFFU; - - serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 3U); - } else { - serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 1U); - } -#else - serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 1U); -#endif - - m_rssiAccum = 0U; - m_rssiCount = 0U; -} - -#endif - diff --git a/M17RX.h b/M17RX.h deleted file mode 100644 index de6ed6d..0000000 --- a/M17RX.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2015,2016,2017,2020,2021 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" - -#if defined(MODE_M17) - -#if !defined(M17RX_H) -#define M17RX_H - -#include "M17Defines.h" - -enum M17RX_STATE { - M17RXS_NONE, - M17RXS_LINK_SETUP, - M17RXS_STREAM -}; - -class CM17RX { -public: - CM17RX(); - - void samples(const q15_t* samples, uint16_t* rssi, uint8_t length); - - void reset(); - -private: - M17RX_STATE m_state; - uint8_t m_bitBuffer[M17_RADIO_SYMBOL_LENGTH]; - q15_t m_buffer[M17_FRAME_LENGTH_SAMPLES]; - uint16_t m_bitPtr; - uint16_t m_dataPtr; - uint16_t m_startPtr; - uint16_t m_endPtr; - uint16_t m_syncPtr; - uint16_t m_minSyncPtr; - uint16_t m_maxSyncPtr; - q31_t m_maxCorr; - uint16_t m_lostCount; - uint8_t m_countdown; - M17RX_STATE m_nextState; - q15_t m_centre[16U]; - q15_t m_centreVal; - q15_t m_threshold[16U]; - q15_t m_thresholdVal; - uint8_t m_averagePtr; - uint32_t m_rssiAccum; - uint16_t m_rssiCount; - - void processNone(q15_t sample); - void processData(q15_t sample); - bool correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues, const uint8_t* syncBytes, uint8_t maxSymbolErrs, uint8_t maxBitErrs); - void calculateLevels(uint16_t start, uint16_t count); - void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); - void writeRSSILinkSetup(uint8_t* data); - void writeRSSIStream(uint8_t* data); -}; - -#endif - -#endif - diff --git a/M17TX.cpp b/M17TX.cpp deleted file mode 100644 index 107c405..0000000 --- a/M17TX.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2009-2018,2020,2021,2025 by Jonathan Naylor G4KLX - * Copyright (C) 2017 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" - -#if defined(MODE_M17) - -#include "Globals.h" -#include "M17TX.h" - -#include "M17Defines.h" - -// Generated using rcosdesign(0.5, 8, 5, 'sqrt') in MATLAB -static q15_t RRC_0_5_FILTER[] = {0, 0, 0, 0, -290, -174, 142, 432, 438, 90, -387, -561, -155, 658, 1225, 767, - -980, -3326, -4648, -3062, 2527, 11552, 21705, 29724, 32767, 29724, 21705, - 11552, 2527, -3062, -4648, -3326, -980, 767, 1225, 658, -155, -561, -387, 90, - 438, 432, 142, -174, -290}; // numTaps = 45, L = 5 -const uint16_t RRC_0_5_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L - -const q15_t M17_LEVELA = 1481; -const q15_t M17_LEVELB = 494; -const q15_t M17_LEVELC = -494; -const q15_t M17_LEVELD = -1481; - -const uint8_t M17_START_SYNC = 0x77U; -const uint8_t M17_END_SYNC = 0xFFU; -const uint8_t M17_HANG = 0x00U; - -CM17TX::CM17TX() : -m_buffer(TX_BUFFER_LEN), -m_modFilter(), -m_modState(), -m_poBuffer(), -m_poLen(0U), -m_poPtr(0U), -m_txDelay(240U), // 200ms -m_txHang(4800U), // 4s -m_txCount(0U) -{ - ::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); - - m_modFilter.L = M17_RADIO_SYMBOL_LENGTH; - m_modFilter.phaseLength = RRC_0_5_FILTER_PHASE_LEN; - m_modFilter.pCoeffs = RRC_0_5_FILTER; - m_modFilter.pState = m_modState; -} - -void CM17TX::process() -{ - // If we have M17 data to transmit, do so. - if (m_poLen == 0U && m_buffer.getData() > 0U) { - if (!m_tx) { - for (uint16_t i = 0U; i < m_txDelay; i++) - m_poBuffer[m_poLen++] = M17_START_SYNC; - } else { - for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++) { - uint8_t c = 0U; - m_buffer.get(c); - m_poBuffer[m_poLen++] = c; - } - } - - m_poPtr = 0U; - } - - if (m_poLen > 0U) { - // Transmit M17 data. - uint16_t space = io.getSpace(); - - while (space > (4U * M17_RADIO_SYMBOL_LENGTH)) { - uint8_t c = m_poBuffer[m_poPtr++]; - writeByte(c); - - // Reduce space and reset the hang timer. - space -= 4U * M17_RADIO_SYMBOL_LENGTH; - if (m_duplex) - m_txCount = m_txHang; - - if (m_poPtr >= m_poLen) { - m_poPtr = 0U; - m_poLen = 0U; - return; - } - } - } else if (m_txCount > 0U) { - // Transmit silence until the hang timer has expired. - uint16_t space = io.getSpace(); - - while (space > (4U * M17_RADIO_SYMBOL_LENGTH)) { - writeSilence(); - - space -= 4U * M17_RADIO_SYMBOL_LENGTH; - m_txCount--; - - if (m_txCount == 0U) - return; - } - } -} - -uint8_t CM17TX::writeData(const uint8_t* data, uint16_t length) -{ - if (length != (M17_FRAME_LENGTH_BYTES + 1U)) - return 4U; - - uint16_t space = m_buffer.getSpace(); - if (space < M17_FRAME_LENGTH_BYTES) - return 5U; - - for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++) - m_buffer.put(data[i + 1U]); - - return 0U; -} - -void CM17TX::writeByte(uint8_t c) -{ - q15_t inBuffer[4U]; - q15_t outBuffer[M17_RADIO_SYMBOL_LENGTH * 4U]; - - const uint8_t MASK = 0xC0U; - - for (uint8_t i = 0U; i < 4U; i++, c <<= 2) { - switch (c & MASK) { - case 0xC0U: - inBuffer[i] = M17_LEVELA; - break; - case 0x80U: - inBuffer[i] = M17_LEVELB; - break; - case 0x00U: - inBuffer[i] = M17_LEVELC; - break; - default: - inBuffer[i] = M17_LEVELD; - break; - } - } - - ::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 4U); - - io.write(STATE_M17, outBuffer, M17_RADIO_SYMBOL_LENGTH * 4U); -} - -void CM17TX::writeSilence() -{ - q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U}; - q15_t outBuffer[M17_RADIO_SYMBOL_LENGTH * 4U]; - - ::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 4U); - - io.write(STATE_M17, outBuffer, M17_RADIO_SYMBOL_LENGTH * 4U); -} - -void CM17TX::setTXDelay(uint8_t delay) -{ - m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay - - if (m_txDelay > 1200U) - m_txDelay = 1200U; -} - -uint8_t CM17TX::getSpace() const -{ - return m_buffer.getSpace() / M17_FRAME_LENGTH_BYTES; -} - -void CM17TX::setParams(uint8_t txHang) -{ - m_txHang = txHang * 1200U; -} - -#endif - diff --git a/M17TX.h b/M17TX.h deleted file mode 100644 index 586954d..0000000 --- a/M17TX.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015,2016,2017,2020,2025 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" - -#if defined(MODE_M17) - -#if !defined(M17TX_H) -#define M17TX_H - -#include "RingBuffer.h" - -class CM17TX { -public: - CM17TX(); - - uint8_t writeData(const uint8_t* data, uint16_t length); - - void process(); - - void setTXDelay(uint8_t delay); - - uint8_t getSpace() const; - - void setParams(uint8_t txHang); - -private: - CRingBuffer m_buffer; - arm_fir_interpolate_instance_q15 m_modFilter; - q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare - uint8_t m_poBuffer[1200U]; - uint16_t m_poLen; - uint16_t m_poPtr; - uint16_t m_txDelay; - uint32_t m_txHang; - uint32_t m_txCount; - - void writeByte(uint8_t c); - void writeSilence(); -}; - -#endif - -#endif - diff --git a/MMDVM.cpp b/MMDVM.cpp index abc755b..324c1d0 100644 --- a/MMDVM.cpp +++ b/MMDVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX * Copyright (C) 2016 by Mathis Schmieder DB9MAT * Copyright (C) 2016 by Colin Durbridge G4EML * @@ -31,10 +31,8 @@ bool m_dmrEnable = true; bool m_ysfEnable = true; bool m_p25Enable = true; bool m_nxdnEnable = true; -bool m_m17Enable = true; bool m_pocsagEnable = true; bool m_fmEnable = true; -bool m_ax25Enable = true; bool m_duplex = true; @@ -79,13 +77,6 @@ CNXDNTX nxdnTX; CCalNXDN calNXDN; #endif -#if defined(MODE_M17) -CM17RX m17RX; -CM17TX m17TX; - -CCalM17 calM17; -#endif - #if defined(MODE_POCSAG) CPOCSAGTX pocsagTX; CCalPOCSAG calPOCSAG; @@ -96,11 +87,6 @@ CFM fm; CCalFM calFM; #endif -#if defined(MODE_AX25) -CAX25RX ax25RX; -CAX25TX ax25TX; -#endif - CCalRSSI calRSSI; CCWIdTX cwIdTX; @@ -149,21 +135,11 @@ void loop() nxdnTX.process(); #endif -#if defined(MODE_M17) - if (m_m17Enable && m_modemState == STATE_M17) - m17TX.process(); -#endif - #if defined(MODE_POCSAG) if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy())) pocsagTX.process(); #endif -#if defined(MODE_AX25) - if (m_ax25Enable && (m_modemState == STATE_IDLE || m_modemState == STATE_FM)) - ax25TX.process(); -#endif - #if defined(MODE_FM) if (m_fmEnable && m_modemState == STATE_FM) fm.process(); @@ -194,11 +170,6 @@ void loop() calNXDN.process(); #endif -#if defined(MODE_M17) - if (m_modemState == STATE_M17CAL) - calM17.process(); -#endif - #if defined(MODE_POCSAG) if (m_modemState == STATE_POCSAGCAL) calPOCSAG.process(); @@ -217,3 +188,4 @@ int main() } #endif + diff --git a/MMDVM.ino b/MMDVM.ino index b8754a3..e67a00e 100644 --- a/MMDVM.ino +++ b/MMDVM.ino @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX * Copyright (C) 2016 by Colin Durbridge G4EML * * This program is free software; you can redistribute it and/or modify @@ -28,10 +28,8 @@ bool m_dmrEnable = true; bool m_ysfEnable = true; bool m_p25Enable = true; bool m_nxdnEnable = true; -bool m_m17Enable = true; bool m_pocsagEnable = true; bool m_fmEnable = true; -bool m_ax25Enable = true; bool m_duplex = true; @@ -76,13 +74,6 @@ CNXDNTX nxdnTX; CCalNXDN calNXDN; #endif -#if defined(MODE_M17) -CM17RX m17RX; -CM17TX m17TX; - -CCalM17 calM17; -#endif - #if defined(MODE_POCSAG) CPOCSAGTX pocsagTX; CCalPOCSAG calPOCSAG; @@ -93,11 +84,6 @@ CFM fm; CCalFM calFM; #endif -#if defined(MODE_AX25) -CAX25RX ax25RX; -CAX25TX ax25TX; -#endif - CCalRSSI calRSSI; CCWIdTX cwIdTX; @@ -146,21 +132,11 @@ void loop() nxdnTX.process(); #endif -#if defined(MODE_M17) - if (m_m17Enable && m_modemState == STATE_M17) - m17TX.process(); -#endif - #if defined(MODE_POCSAG) if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy())) pocsagTX.process(); #endif -#if defined(MODE_AX25) - if (m_ax25Enable && (m_modemState == STATE_IDLE || m_modemState == STATE_FM)) - ax25TX.process(); -#endif - #if defined(MODE_FM) if (m_fmEnable && m_modemState == STATE_FM) fm.process(); @@ -191,11 +167,6 @@ void loop() calNXDN.process(); #endif -#if defined(MODE_M17) - if (m_modemState == STATE_M17CAL) - calM17.process(); -#endif - #if defined(MODE_POCSAG) if (m_modemState == STATE_POCSAGCAL) calPOCSAG.process(); diff --git a/README.md b/README.md index 535ab8f..986dde0 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, System Fusion, P25, NXDN, M17, POCSAG, AX.25, and FM modes. +This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, POCSAG, and FM modes. It runs on the Arduino Due, the ST-Micro STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3, M4, or M7 processors with a minimum clock speed greater of 80 MHz, and access to at least one analogue to digital converter, one digital to analogue converter, as well as a number of GPIO pins. diff --git a/SerialPort.cpp b/SerialPort.cpp index 755bc67..f182b50 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013,2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2013,2015-2021,2025 by Jonathan Naylor G4KLX * Copyright (C) 2016 by Colin Durbridge G4EML * * This program is free software; you can redistribute it and/or modify @@ -63,16 +63,8 @@ const uint8_t MMDVM_P25_LOST = 0x32U; const uint8_t MMDVM_NXDN_DATA = 0x40U; const uint8_t MMDVM_NXDN_LOST = 0x41U; -const uint8_t MMDVM_M17_LINK_SETUP = 0x45U; -const uint8_t MMDVM_M17_STREAM = 0x46U; -const uint8_t MMDVM_M17_PACKET = 0x47U; -const uint8_t MMDVM_M17_LOST = 0x48U; -const uint8_t MMDVM_M17_EOT = 0x49U; - const uint8_t MMDVM_POCSAG_DATA = 0x50U; -const uint8_t MMDVM_AX25_DATA = 0x55U; - const uint8_t MMDVM_FM_PARAMS1 = 0x60U; const uint8_t MMDVM_FM_PARAMS2 = 0x61U; const uint8_t MMDVM_FM_PARAMS3 = 0x62U; @@ -264,14 +256,7 @@ void CSerialPort::getStatus() reply[11U] = 0U; #endif -#if defined(MODE_M17) - if (m_m17Enable) - reply[12U] = m17TX.getSpace(); - else - reply[12U] = 0U; -#else reply[12U] = 0U; -#endif #if defined(MODE_FM) if (m_fmEnable) @@ -291,15 +276,7 @@ void CSerialPort::getStatus() reply[14U] = 0U; #endif -#if defined(MODE_AX25) - if (m_ax25Enable) - reply[15U] = ax25TX.getSpace(); - else - reply[15U] = 0U; -#else reply[15U] = 0U; -#endif - reply[16U] = 0x00U; reply[17U] = 0x00U; reply[18U] = 0x00U; @@ -335,9 +312,6 @@ void CSerialPort::getVersion() #if defined(MODE_NXDN) reply[4U] |= 0x10U; #endif -#if defined(MODE_M17) - reply[4U] |= 0x20U; -#endif #if defined(MODE_FM) reply[4U] |= 0x40U; #endif @@ -346,9 +320,6 @@ void CSerialPort::getVersion() #if defined(MODE_POCSAG) reply[5U] |= 0x01U; #endif -#if defined(MODE_AX25) - reply[5U] |= 0x02U; -#endif // CPU type/manufacturer. 0=Atmel ARM, 1=NXP ARM, 2=St-Micro ARM reply[6U] = io.getCPU(); @@ -400,15 +371,9 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) #if defined(MODE_FM) bool fmEnable = (data[1U] & 0x20U) == 0x20U; #endif -#if defined(MODE_M17) - bool m17Enable = (data[1U] & 0x40U) == 0x40U; -#endif #if defined(MODE_POCSAG) bool pocsagEnable = (data[2U] & 0x01U) == 0x01U; #endif -#if defined(MODE_AX25) - bool ax25Enable = (data[2U] & 0x02U) == 0x02U; -#endif uint8_t txDelay = data[3U]; if (txDelay > 50U) @@ -416,8 +381,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) MMDVM_STATE modemState = MMDVM_STATE(data[4U]); - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_M17 && modemState != STATE_POCSAG && modemState != STATE_FM && - modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_M17CAL && modemState != STATE_POCSAGCAL && + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_FM && + modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL && modemState != STATE_FMCAL10K && modemState != STATE_FMCAL12K && modemState != STATE_FMCAL15K && modemState != STATE_FMCAL20K && modemState != STATE_FMCAL25K && modemState != STATE_FMCAL30K) return 4U; @@ -461,14 +426,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) return 4U; #endif -#if defined(MODE_M17) - if (modemState == STATE_M17 && !m17Enable) - return 4U; -#else - if (modemState == STATE_M17) - return 4U; -#endif - #if defined(MODE_POCSAG) if (modemState == STATE_POCSAG && !pocsagEnable) return 4U; @@ -496,10 +453,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) uint8_t ysfTXLevel = data[11U]; uint8_t p25TXLevel = data[12U]; uint8_t nxdnTXLevel = data[13U]; - uint8_t m17TXLevel = data[14U]; uint8_t pocsagTXLevel = data[15U]; uint8_t fmTXLevel = data[16U]; - uint8_t ax25TXLevel = data[17U]; #if defined(MODE_YSF) uint8_t ysfTXHang = data[20U]; @@ -510,9 +465,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) #if defined(MODE_NXDN) uint8_t nxdnTXHang = data[22U]; #endif -#if defined(MODE_M17) - uint8_t m17TXHang = data[23U]; -#endif #if defined(MODE_DMR) uint8_t colorCode = data[26U]; @@ -522,16 +474,6 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) uint8_t dmrDelay = data[27U]; #endif -#if defined(MODE_AX25) - int8_t ax25RXTwist = int8_t(data[28U]) - 128; - if (ax25RXTwist < -4 || ax25RXTwist > 10) - return 4U; - - uint8_t ax25TXDelay = data[29U]; - uint8_t ax25SlotTime = data[30U]; - uint8_t ax25PPersist = data[31U]; -#endif - setMode(modemState); m_duplex = !simplex; @@ -565,25 +507,15 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length) nxdnTX.setTXDelay(txDelay); nxdnTX.setParams(nxdnTXHang); #endif -#if defined(MODE_M17) - m_m17Enable = m17Enable; - m17TX.setTXDelay(txDelay); - m17TX.setParams(m17TXHang); -#endif #if defined(MODE_POCSAG) m_pocsagEnable = pocsagEnable; pocsagTX.setTXDelay(txDelay); #endif -#if defined(MODE_AX25) - m_ax25Enable = ax25Enable; - ax25TX.setTXDelay(ax25TXDelay); - ax25RX.setParams(ax25RXTwist, ax25SlotTime, ax25PPersist); -#endif #if defined(MODE_FM) m_fmEnable = fmEnable; #endif - io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel, txDCOffset, rxDCOffset, useCOSAsLockout); + io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset, useCOSAsLockout); io.start(); @@ -697,8 +629,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint16_t length) if (modemState == m_modemState) return 0U; - if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_M17 && modemState != STATE_POCSAG && modemState != STATE_FM && - modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_M17CAL && modemState != STATE_POCSAGCAL && + if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_FM && + modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL && modemState != STATE_FMCAL10K && modemState != STATE_FMCAL12K && modemState != STATE_FMCAL15K && modemState != STATE_FMCAL20K && modemState != STATE_FMCAL25K && modemState != STATE_FMCAL30K) return 4U; @@ -742,14 +674,6 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint16_t length) return 4U; #endif -#if defined(MODE_M17) - if (modemState == STATE_M17 && !m_m17Enable) - return 4U; -#else - if (modemState == STATE_M17) - return 4U; -#endif - #if defined(MODE_POCSAG) if (modemState == STATE_POCSAG && !m_pocsagEnable) return 4U; @@ -789,9 +713,6 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_NXDN: DEBUG1("Mode set to NXDN"); break; - case STATE_M17: - DEBUG1("Mode set to M17"); - break; case STATE_POCSAG: DEBUG1("Mode set to POCSAG"); break; @@ -840,9 +761,6 @@ void CSerialPort::setMode(MMDVM_STATE modemState) case STATE_POCSAGCAL: DEBUG1("Mode set to POCSAG Calibrate"); break; - case STATE_M17CAL: - DEBUG1("Mode set to M17 Calibrate"); - break; default: // STATE_IDLE DEBUG1("Mode set to Idle"); break; @@ -876,11 +794,6 @@ void CSerialPort::setMode(MMDVM_STATE modemState) nxdnRX.reset(); #endif -#if defined(MODE_M17) - if (modemState != STATE_M17) - m17RX.reset(); -#endif - #if defined(MODE_FM) if (modemState != STATE_FM) fm.reset(); @@ -1110,10 +1023,6 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l if (m_modemState == STATE_NXDNCAL1K) err = calNXDN.write(buffer, length); #endif -#if defined(MODE_M17) - if (m_modemState == STATE_M17CAL) - err = calM17.write(buffer, length); -#endif #if defined(MODE_POCSAG) if (m_modemState == STATE_POCSAGCAL) err = calPOCSAG.write(buffer, length); @@ -1317,50 +1226,6 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l break; #endif -#if defined(MODE_M17) - case MMDVM_M17_LINK_SETUP: - if (m_m17Enable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_M17) - err = m17TX.writeData(buffer, length); - } - if (err == 0U) { - if (m_modemState == STATE_IDLE) - setMode(STATE_M17); - } else { - DEBUG2("Received invalid M17 link setup data", err); - sendNAK(type, err); - } - break; - - case MMDVM_M17_STREAM: - if (m_m17Enable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_M17) - err = m17TX.writeData(buffer, length); - } - if (err == 0U) { - if (m_modemState == STATE_IDLE) - setMode(STATE_M17); - } else { - DEBUG2("Received invalid M17 stream data", err); - sendNAK(type, err); - } - break; - - case MMDVM_M17_EOT: - if (m_m17Enable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_M17) - err = m17TX.writeData(buffer, length); - } - if (err == 0U) { - if (m_modemState == STATE_IDLE) - setMode(STATE_M17); - } else { - DEBUG2("Received invalid M17 EOT", err); - sendNAK(type, err); - } - break; -#endif - #if defined(MODE_POCSAG) case MMDVM_POCSAG_DATA: if (m_pocsagEnable) { @@ -1393,19 +1258,6 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l break; #endif -#if defined(MODE_AX25) - case MMDVM_AX25_DATA: - if (m_ax25Enable) { - if (m_modemState == STATE_IDLE || m_modemState == STATE_FM) - err = ax25TX.writeData(buffer, length); - } - if (err != 0U) { - DEBUG2("Received invalid AX.25 data", err); - sendNAK(type, err); - } - break; -#endif - case MMDVM_TRANSPARENT: case MMDVM_QSO_INFO: // Do nothing on the MMDVM. @@ -1709,88 +1561,6 @@ void CSerialPort::writeNXDNLost() } #endif -#if defined(MODE_M17) -void CSerialPort::writeM17LinkSetup(const uint8_t* data, uint8_t length) -{ - if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE) - return; - - if (!m_m17Enable) - return; - - uint8_t reply[130U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 0U; - reply[2U] = MMDVM_M17_LINK_SETUP; - - uint8_t count = 3U; - for (uint8_t i = 0U; i < length; i++, count++) - reply[count] = data[i]; - - reply[1U] = count; - - writeInt(1U, reply, count); -} - -void CSerialPort::writeM17Stream(const uint8_t* data, uint8_t length) -{ - if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE) - return; - - if (!m_m17Enable) - return; - - uint8_t reply[130U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 0U; - reply[2U] = MMDVM_M17_STREAM; - - uint8_t count = 3U; - for (uint8_t i = 0U; i < length; i++, count++) - reply[count] = data[i]; - - reply[1U] = count; - - writeInt(1U, reply, count); -} - -void CSerialPort::writeM17EOT() -{ - if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE) - return; - - if (!m_m17Enable) - return; - - uint8_t reply[3U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 3U; - reply[2U] = MMDVM_M17_EOT; - - writeInt(1U, reply, 3); -} - -void CSerialPort::writeM17Lost() -{ - if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE) - return; - - if (!m_m17Enable) - return; - - uint8_t reply[3U]; - - reply[0U] = MMDVM_FRAME_START; - reply[1U] = 3U; - reply[2U] = MMDVM_M17_LOST; - - writeInt(1U, reply, 3); -} -#endif - #if defined(MODE_FM) void CSerialPort::writeFMData(const uint8_t* data, uint16_t length) { @@ -1860,40 +1630,6 @@ void CSerialPort::writeFMEOT() } #endif -#if defined(MODE_AX25) -void CSerialPort::writeAX25Data(const uint8_t* data, uint16_t length) -{ - if (m_modemState != STATE_FM && m_modemState != STATE_IDLE) - return; - - if (!m_ax25Enable) - return; - - uint8_t reply[512U]; - - reply[0U] = MMDVM_FRAME_START; - - if (length > 252U) { - reply[1U] = 0U; - reply[2U] = (length + 4U) - 255U; - reply[3U] = MMDVM_AX25_DATA; - - for (uint16_t i = 0U; i < length; i++) - reply[i + 4U] = data[i]; - - writeInt(1U, reply, length + 4U); - } else { - reply[1U] = length + 3U; - reply[2U] = MMDVM_AX25_DATA; - - for (uint16_t i = 0U; i < length; i++) - reply[i + 3U] = data[i]; - - writeInt(1U, reply, length + 3U); - } -} -#endif - #if defined(SERIAL_REPEATER) void CSerialPort::writeSerialData(const uint8_t* data, uint8_t length) { diff --git a/SerialPort.h b/SerialPort.h index c013a7f..bd18d51 100644 --- a/SerialPort.h +++ b/SerialPort.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017,2018,2020,2021,2025 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 @@ -64,17 +64,6 @@ public: void writeNXDNLost(); #endif -#if defined(MODE_M17) - void writeM17LinkSetup(const uint8_t* data, uint8_t length); - void writeM17Stream(const uint8_t* data, uint8_t length); - void writeM17Lost(); - void writeM17EOT(); -#endif - -#if defined(MODE_AX25) - void writeAX25Data(const uint8_t* data, uint16_t length); -#endif - #if defined(MODE_FM) void writeFMData(const uint8_t* data, uint16_t length); void writeFMStatus(uint8_t status); @@ -134,3 +123,4 @@ private: }; #endif +