From e21006236596ef5a009624df0058a33990ff0f2a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 21 Jun 2020 21:40:40 +0100 Subject: [PATCH] Add the twist processing to the AX25 RX. --- AX25Demodulator.cpp | 16 +-- AX25Demodulator.h | 8 +- AX25RX.cpp | 259 ++---------------------------------- AX25Twist.cpp | 311 ++++++++++++++++++++++++++++++++++++++++++++ AX25Twist.h | 39 ++++++ 5 files changed, 373 insertions(+), 260 deletions(-) create mode 100644 AX25Twist.cpp create mode 100644 AX25Twist.h diff --git a/AX25Demodulator.cpp b/AX25Demodulator.cpp index 14f1415..7ffb99c 100644 --- a/AX25Demodulator.cpp +++ b/AX25Demodulator.cpp @@ -53,10 +53,9 @@ 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(q15_t* coeffs, uint16_t length) : +CAX25Demodulator::CAX25Demodulator(int8_t n) : m_frame(), -m_audioFilter(), -m_audioState(), +m_twist(n), m_lpfFilter(), m_lpfState(), m_delayLine(NULL), @@ -75,10 +74,6 @@ m_hdlcState(AX25_IDLE) { m_delayLine = new bool[DELAY_LEN]; - m_audioFilter.numTaps = length; - m_audioFilter.pState = m_audioState; - m_audioFilter.pCoeffs = coeffs; - m_lpfFilter.numTaps = LPF_FILTER_LEN; m_lpfFilter.pState = m_lpfState; m_lpfFilter.pCoeffs = LPF_FILTER_COEFFS; @@ -93,7 +88,7 @@ bool CAX25Demodulator::process(q15_t* samples, uint8_t length, CAX25Frame& frame bool result = false; q15_t fa[RX_BLOCK_SIZE]; - ::arm_fir_fast_q15(&m_audioFilter, samples, 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++) { @@ -263,3 +258,8 @@ bool CAX25Demodulator::HDLC(bool b) return false; } +void CAX25Demodulator::setTwist(int8_t n) +{ + m_twist.setTwist(n); +} + diff --git a/AX25Demodulator.h b/AX25Demodulator.h index 7e9063e..84a98d6 100644 --- a/AX25Demodulator.h +++ b/AX25Demodulator.h @@ -22,6 +22,7 @@ #include "Config.h" #include "AX25Frame.h" +#include "AX25Twist.h" enum AX25_STATE { AX25_IDLE, @@ -31,14 +32,15 @@ enum AX25_STATE { class CAX25Demodulator { public: - CAX25Demodulator(q15_t* coeffs, uint16_t length); + CAX25Demodulator(int8_t n); bool process(q15_t* samples, uint8_t length, CAX25Frame& frame); + void setTwist(int8_t n); + private: CAX25Frame m_frame; - arm_fir_instance_q15 m_audioFilter; - q15_t m_audioState[40U]; // NoTaps + BlockSize - 1, 9 + 20 - 1 plus some spare + CAX25Twist m_twist; arm_fir_instance_q15 m_lpfFilter; q15_t m_lpfState[120U]; // NoTaps + BlockSize - 1, 96 + 20 - 1 plus some spare bool* m_delayLine; diff --git a/AX25RX.cpp b/AX25RX.cpp index 25b533b..7a6b166 100644 --- a/AX25RX.cpp +++ b/AX25RX.cpp @@ -20,252 +20,6 @@ #include "Globals.h" #include "AX25RX.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 -}; - /* * Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass, * Hann window, starting and ending 0 value coefficients removed. @@ -306,9 +60,9 @@ q15_t FILTER_COEFFS[] = { CAX25RX::CAX25RX() : m_filter(), m_state(), -m_demod1(dB3, 9U), -m_demod2(dB6, 9U), -m_demod3(dB9, 9U), +m_demod1(3), +m_demod2(6), +m_demod3(9), m_lastFCS(0U) { m_filter.numTaps = FILTER_LEN; @@ -346,3 +100,10 @@ void CAX25RX::samples(q15_t* samples, uint8_t length) } } +void CAX25RX::setParams(int8_t twist) +{ + m_demod1.setTwist(twist - 3); + m_demod2.setTwist(twist); + m_demod3.setTwist(twist + 3); +} + diff --git a/AX25Twist.cpp b/AX25Twist.cpp new file mode 100644 index 0000000..bf0c534 --- /dev/null +++ b/AX25Twist.cpp @@ -0,0 +1,311 @@ +/* + * 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" +#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]; +} + diff --git a/AX25Twist.h b/AX25Twist.h new file mode 100644 index 0000000..ea1c6de --- /dev/null +++ b/AX25Twist.h @@ -0,0 +1,39 @@ +/* + * 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(AX25Twist_H) +#define AX25Twist_H + +#include "Config.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 +