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 +