From af11be16dc8417d81dc9d94ae887add4a6ccea62 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 17 Jun 2020 15:28:41 +0100 Subject: [PATCH] First woring AX.25 decoder (in simulation). --- AX25Demodulator.cpp | 49 +++---- AX25Demodulator.h | 10 +- AX25Frame.cpp | 64 ++++----- AX25RX.cpp | 342 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 332 insertions(+), 133 deletions(-) diff --git a/AX25Demodulator.cpp b/AX25Demodulator.cpp index 692a63a..d378e59 100644 --- a/AX25Demodulator.cpp +++ b/AX25Demodulator.cpp @@ -21,27 +21,27 @@ #include "Globals.h" #include "AX25Demodulator.h" -const float32_t DELAY = 0.000448F; const float32_t SAMPLE_RATE = 24000.0F; const float32_t SYMBOL_RATE = 1200.0F; -const uint16_t DELAY_LEN = uint16_t((DELAY / (1.0F / SAMPLE_RATE)) + 0.5F); +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; -// XXX This is for the wrong sample rate const uint32_t LPF_FILTER_LEN = 96U; q15_t LPF_FILTER_COEFFS[] = { - 0, 1, 3, 5, 8, 11, 14, 17, 19, 20, 18, 14, - 7, -2, -16, -33, -53, -76, -101, -126, -151, -174, -194, -208, - -215, -212, -199, -173, -133, -79, -10, 74, 173, 287, 413, 549, - 693, 842, 993, 1142, 1287, 1423, 1547, 1656, 1747, 1817, 1865, 1889, - 1889, 1865, 1817, 1747, 1656, 1547, 1423, 1287, 1142, 993, 842, 693, - 549, 413, 287, 173, 74, -10, -79, -133, -173, -199, -212, -215, - -208, -194, -174, -151, -126, -101, -76, -53, -33, -16, -2, 7, - 14, 18, 20, 19, 17, 14, 11, 8, 5, 3, 1, 0, + 0, 0, 0, 1, 2, 5, 8, 12, 18, 23, + 29, 33, 36, 36, 33, 25, 13, -5, -28, -57, + -89, -123, -159, -194, -225, -249, -264, -267, -254, -224, + -175, -104, -12, 102, 236, 389, 557, 738, 926, 1117, + 1306, 1486, 1654, 1802, 1927, 2025, 2092, 2126, 2126, 2092, + 2025, 1927, 1802, 1654, 1486, 1306, 1117, 926, 738, 557, + 389, 236, 102, -12, -104, -175, -224, -254, -267, -264, + -249, -225, -194, -159, -123, -89, -57, -28, -5, 13, + 25, 33, 36, 36, 33, 29, 23, 18, 12, 8, + 5, 2, 1, 0, 0, 0 }; // 64 Hz loop filter. @@ -53,7 +53,7 @@ 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(float32_t* coeffs, uint16_t length) : +CAX25Demodulator::CAX25Demodulator(q15_t* coeffs, uint16_t length) : m_frame(), m_audioFilter(), m_audioState(), @@ -73,7 +73,7 @@ m_hdlcBuffer(0U), m_hdlcBits(0U), m_hdlcState(AX25_IDLE) { - m_delayLine = new bool[2U * DELAY_LEN]; + m_delayLine = new bool[DELAY_LEN]; m_audioFilter.numTaps = length; m_audioFilter.pState = m_audioState; @@ -88,22 +88,17 @@ m_hdlcState(AX25_IDLE) m_pllFilter.pCoeffs = PLL_FILTER_COEFFS; } -bool CAX25Demodulator::process(const q15_t* samples, uint8_t length, CAX25Frame& frame) +bool CAX25Demodulator::process(q15_t* samples, uint8_t length, CAX25Frame& frame) { bool result = false; - float32_t input[RX_BLOCK_SIZE]; - for (size_t i = 0; i < length; i++) - input[i] = float(samples[i]); - - float32_t fa[RX_BLOCK_SIZE]; - ::arm_fir_f32(&m_audioFilter, input, fa, RX_BLOCK_SIZE); + q15_t fa[RX_BLOCK_SIZE]; + ::arm_fir_fast_q15(&m_audioFilter, samples, fa, RX_BLOCK_SIZE); int16_t buffer[RX_BLOCK_SIZE]; for (uint8_t i = 0; i < length; i++) { - int16_t sample = int16_t(fa[i]); - bool level = (sample >= 0); - bool delayed = delay(level); + bool level = (fa[i] >= 0); + bool delayed = delay(level); buffer[i] = (int16_t(level ^ delayed) << 1) - 1; } @@ -124,7 +119,7 @@ bool CAX25Demodulator::process(const q15_t* samples, uint8_t length, CAX25Frame& if (result) { // Copy the frame data. ::memcpy(frame.m_data, m_frame.m_data, AX25_MAX_PACKET_LEN); - frame.m_length = frame.m_length; + frame.m_length = m_frame.m_length; frame.m_fcs = m_frame.m_fcs; m_frame.m_length = 0U; } @@ -160,7 +155,7 @@ bool CAX25Demodulator::PLL(bool input) { bool sample = false; - if (input != m_pllLast or m_pllBits > 16U) { + if (input != m_pllLast || m_pllBits > 16U) { // Record transition. m_pllLast = input; @@ -214,9 +209,11 @@ bool CAX25Demodulator::HDLC(bool b) switch (m_hdlcBuffer) { case 0x7E: - if (m_frame.m_length > 2U) { + if (m_frame.m_length >= 13U) { result = m_frame.checkCRC(); if (!result) + m_frame.m_length = 0U; + } else { m_frame.m_length = 0U; } m_hdlcState = AX25_SYNC; diff --git a/AX25Demodulator.h b/AX25Demodulator.h index e12d4c6..7e9063e 100644 --- a/AX25Demodulator.h +++ b/AX25Demodulator.h @@ -31,21 +31,21 @@ enum AX25_STATE { class CAX25Demodulator { public: - CAX25Demodulator(float32_t* coeffs, uint16_t length); + CAX25Demodulator(q15_t* coeffs, uint16_t length); - bool process(const q15_t* samples, uint8_t length, CAX25Frame& frame); + bool process(q15_t* samples, uint8_t length, CAX25Frame& frame); private: CAX25Frame m_frame; - arm_fir_instance_f32 m_audioFilter; - float32_t m_audioState[20U]; + arm_fir_instance_q15 m_audioFilter; + q15_t m_audioState[40U]; // NoTaps + BlockSize - 1, 9 + 20 - 1 plus some spare arm_fir_instance_q15 m_lpfFilter; q15_t m_lpfState[120U]; // NoTaps + BlockSize - 1, 96 + 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[7U]; + 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; diff --git a/AX25Frame.cpp b/AX25Frame.cpp index 9740dd5..905682e 100644 --- a/AX25Frame.cpp +++ b/AX25Frame.cpp @@ -21,38 +21,38 @@ #include "AX25Frame.h" const uint16_t CCITT_TABLE[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; + 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() : m_data(), diff --git a/AX25RX.cpp b/AX25RX.cpp index c138333..25b533b 100644 --- a/AX25RX.cpp +++ b/AX25RX.cpp @@ -20,47 +20,255 @@ #include "Globals.h" #include "AX25RX.h" -// XXX There are for the wrong sample rate +// 1200Hz = -12dB, 2200Hz = 0dB; 3381Hz cutoff; cosine. +q15_t dB12[] = { + 176, + -812, + -3916, + -7586, + 23536, + -7586, + -3916, + -812, + 176 +}; -// 1200Hz = -9dB, 2200Hz = 0dB; 3252Hz cutoff, 3.7 gain; cosine. -float32_t dB9[] = { - -0.00232554104135, - -0.142858725752, - -0.449053780255, - -0.770264863826, - 2.77651146344, - -0.770264863826, - -0.449053780255, - -0.142858725752, - -0.00232554104135}; +// 1200Hz = -11dB, 2200Hz = 0dB; 3258Hz cutoff; cosine. +q15_t dB11[] = { + 121, + -957, + -3959, + -7383, + 23871, + -7383, + -3959, + -957, + 121 +}; -// 1200Hz = -6dB, 2200Hz = 0dB; 2640Hz cutoff, 2.59 gain; cosine. -float32_t dB6[] = { - -0.0209448226653, - -0.130107651829, - -0.299004731072, - -0.45336946386, - 2.0629448761, - -0.45336946386, - -0.299004731072, - -0.130107651829, - -0.0209448226653}; +// 1200Hz = -10dB, 2200Hz = 0dB; 3118Hz cutoff; cosine. +q15_t dB10[] = { + 56, + -1110, + -3987, + -7141, + 24254, + -7141, + -3987, + -1110, + 56 +}; -// 1200Hz = -3dB, 2200Hz = 0dB; 1700Hz cutoff, 1.68 gain; cosine. -float32_t dB3[] = { - -0.0231416146776, - -0.0833375337803, - -0.147937602401, - -0.197411259519, - 1.46066084756, - -0.197411259519, - -0.147937602401, - -0.0833375337803, - -0.0231416146776}; +// 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. + * Hann window, starting and ending 0 value coefficients removed. * * np.array( * firwin2(152, @@ -77,24 +285,23 @@ float32_t dB3[] = { * window='hann') * 32768, * dtype=int)[10:-10] */ -const uint32_t FILTER_LEN = 132U; - +const uint32_t FILTER_LEN = 132; q15_t FILTER_COEFFS[] = { - 0, 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, 0}; + 0, 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, 0 +}; CAX25RX::CAX25RX() : m_filter(), @@ -114,33 +321,28 @@ 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_lastFCS = 0U; CAX25Frame frame; bool ret = m_demod1.process(output, length, frame); - if (ret && frame.m_length > 10U) { - if (m_lastFCS != frame.m_fcs) { - DEBUG1("Decoder 1 reported"); - m_lastFCS = frame.m_fcs; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } + if (ret && frame.m_fcs != m_lastFCS) { + DEBUG1("Decoder 1 reported"); + m_lastFCS = frame.m_fcs; + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } ret = m_demod2.process(output, length, frame); - if (ret && frame.m_length > 10U) { - if (m_lastFCS != frame.m_fcs) { - DEBUG1("Decoder 2 reported"); - m_lastFCS = frame.m_fcs; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } + if (ret && frame.m_fcs != m_lastFCS) { + DEBUG1("Decoder 2 reported"); + m_lastFCS = frame.m_fcs; + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } ret = m_demod3.process(output, length, frame); - if (ret && frame.m_length > 10U) { - if (m_lastFCS != frame.m_fcs) { - DEBUG1("Decoder 3 reported"); - m_lastFCS = frame.m_fcs; - serial.writeAX25Data(frame.m_data, frame.m_length - 2U); - } + if (ret && frame.m_fcs != m_lastFCS) { + DEBUG1("Decoder 3 reported"); + m_lastFCS = frame.m_fcs; + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } }