First woring AX.25 decoder (in simulation).

This commit is contained in:
Jonathan Naylor 2020-06-17 15:28:41 +01:00
parent e332dbba8e
commit af11be16dc
4 changed files with 332 additions and 133 deletions

View File

@ -21,27 +21,27 @@
#include "Globals.h" #include "Globals.h"
#include "AX25Demodulator.h" #include "AX25Demodulator.h"
const float32_t DELAY = 0.000448F;
const float32_t SAMPLE_RATE = 24000.0F; const float32_t SAMPLE_RATE = 24000.0F;
const float32_t SYMBOL_RATE = 1200.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 SAMPLES_PER_SYMBOL = SAMPLE_RATE / SYMBOL_RATE;
const float32_t PLL_LIMIT = SAMPLES_PER_SYMBOL / 2.0F; 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; const uint32_t LPF_FILTER_LEN = 96U;
q15_t LPF_FILTER_COEFFS[] = { q15_t LPF_FILTER_COEFFS[] = {
0, 1, 3, 5, 8, 11, 14, 17, 19, 20, 18, 14, 0, 0, 0, 1, 2, 5, 8, 12, 18, 23,
7, -2, -16, -33, -53, -76, -101, -126, -151, -174, -194, -208, 29, 33, 36, 36, 33, 25, 13, -5, -28, -57,
-215, -212, -199, -173, -133, -79, -10, 74, 173, 287, 413, 549, -89, -123, -159, -194, -225, -249, -264, -267, -254, -224,
693, 842, 993, 1142, 1287, 1423, 1547, 1656, 1747, 1817, 1865, 1889, -175, -104, -12, 102, 236, 389, 557, 738, 926, 1117,
1889, 1865, 1817, 1747, 1656, 1547, 1423, 1287, 1142, 993, 842, 693, 1306, 1486, 1654, 1802, 1927, 2025, 2092, 2126, 2126, 2092,
549, 413, 287, 173, 74, -10, -79, -133, -173, -199, -212, -215, 2025, 1927, 1802, 1654, 1486, 1306, 1117, 926, 738, 557,
-208, -194, -174, -151, -126, -101, -76, -53, -33, -16, -2, 7, 389, 236, 102, -12, -104, -175, -224, -254, -267, -264,
14, 18, 20, 19, 17, 14, 11, 8, 5, 3, 1, 0, -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. // 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}; 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_frame(),
m_audioFilter(), m_audioFilter(),
m_audioState(), m_audioState(),
@ -73,7 +73,7 @@ m_hdlcBuffer(0U),
m_hdlcBits(0U), m_hdlcBits(0U),
m_hdlcState(AX25_IDLE) m_hdlcState(AX25_IDLE)
{ {
m_delayLine = new bool[2U * DELAY_LEN]; m_delayLine = new bool[DELAY_LEN];
m_audioFilter.numTaps = length; m_audioFilter.numTaps = length;
m_audioFilter.pState = m_audioState; m_audioFilter.pState = m_audioState;
@ -88,21 +88,16 @@ m_hdlcState(AX25_IDLE)
m_pllFilter.pCoeffs = PLL_FILTER_COEFFS; 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; bool result = false;
float32_t input[RX_BLOCK_SIZE]; q15_t fa[RX_BLOCK_SIZE];
for (size_t i = 0; i < length; i++) ::arm_fir_fast_q15(&m_audioFilter, samples, fa, RX_BLOCK_SIZE);
input[i] = float(samples[i]);
float32_t fa[RX_BLOCK_SIZE];
::arm_fir_f32(&m_audioFilter, input, fa, RX_BLOCK_SIZE);
int16_t buffer[RX_BLOCK_SIZE]; int16_t buffer[RX_BLOCK_SIZE];
for (uint8_t i = 0; i < length; i++) { for (uint8_t i = 0; i < length; i++) {
int16_t sample = int16_t(fa[i]); bool level = (fa[i] >= 0);
bool level = (sample >= 0);
bool delayed = delay(level); bool delayed = delay(level);
buffer[i] = (int16_t(level ^ delayed) << 1) - 1; 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) { if (result) {
// Copy the frame data. // Copy the frame data.
::memcpy(frame.m_data, m_frame.m_data, AX25_MAX_PACKET_LEN); ::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; frame.m_fcs = m_frame.m_fcs;
m_frame.m_length = 0U; m_frame.m_length = 0U;
} }
@ -160,7 +155,7 @@ bool CAX25Demodulator::PLL(bool input)
{ {
bool sample = false; bool sample = false;
if (input != m_pllLast or m_pllBits > 16U) { if (input != m_pllLast || m_pllBits > 16U) {
// Record transition. // Record transition.
m_pllLast = input; m_pllLast = input;
@ -214,10 +209,12 @@ bool CAX25Demodulator::HDLC(bool b)
switch (m_hdlcBuffer) { switch (m_hdlcBuffer) {
case 0x7E: case 0x7E:
if (m_frame.m_length > 2U) { if (m_frame.m_length >= 13U) {
result = m_frame.checkCRC(); result = m_frame.checkCRC();
if (!result) if (!result)
m_frame.m_length = 0U; m_frame.m_length = 0U;
} else {
m_frame.m_length = 0U;
} }
m_hdlcState = AX25_SYNC; m_hdlcState = AX25_SYNC;
m_hdlcFlag = false; m_hdlcFlag = false;

View File

@ -31,21 +31,21 @@ enum AX25_STATE {
class CAX25Demodulator { class CAX25Demodulator {
public: 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: private:
CAX25Frame m_frame; CAX25Frame m_frame;
arm_fir_instance_f32 m_audioFilter; arm_fir_instance_q15 m_audioFilter;
float32_t m_audioState[20U]; q15_t m_audioState[40U]; // NoTaps + BlockSize - 1, 9 + 20 - 1 plus some spare
arm_fir_instance_q15 m_lpfFilter; arm_fir_instance_q15 m_lpfFilter;
q15_t m_lpfState[120U]; // NoTaps + BlockSize - 1, 96 + 20 - 1 plus some spare q15_t m_lpfState[120U]; // NoTaps + BlockSize - 1, 96 + 20 - 1 plus some spare
bool* m_delayLine; bool* m_delayLine;
uint16_t m_delayPos; uint16_t m_delayPos;
bool m_nrziState; bool m_nrziState;
arm_fir_instance_f32 m_pllFilter; 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; bool m_pllLast;
uint8_t m_pllBits; uint8_t m_pllBits;
float32_t m_pllCount; float32_t m_pllCount;

View File

@ -21,38 +21,38 @@
#include "AX25Frame.h" #include "AX25Frame.h"
const uint16_t CCITT_TABLE[] = { const uint16_t CCITT_TABLE[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 };
CAX25Frame::CAX25Frame() : CAX25Frame::CAX25Frame() :
m_data(), m_data(),

View File

@ -20,47 +20,255 @@
#include "Globals.h" #include "Globals.h"
#include "AX25RX.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. // 1200Hz = -11dB, 2200Hz = 0dB; 3258Hz cutoff; cosine.
float32_t dB9[] = { q15_t dB11[] = {
-0.00232554104135, 121,
-0.142858725752, -957,
-0.449053780255, -3959,
-0.770264863826, -7383,
2.77651146344, 23871,
-0.770264863826, -7383,
-0.449053780255, -3959,
-0.142858725752, -957,
-0.00232554104135}; 121
};
// 1200Hz = -6dB, 2200Hz = 0dB; 2640Hz cutoff, 2.59 gain; cosine. // 1200Hz = -10dB, 2200Hz = 0dB; 3118Hz cutoff; cosine.
float32_t dB6[] = { q15_t dB10[] = {
-0.0209448226653, 56,
-0.130107651829, -1110,
-0.299004731072, -3987,
-0.45336946386, -7141,
2.0629448761, 24254,
-0.45336946386, -7141,
-0.299004731072, -3987,
-0.130107651829, -1110,
-0.0209448226653}; 56
};
// 1200Hz = -3dB, 2200Hz = 0dB; 1700Hz cutoff, 1.68 gain; cosine. // 1200Hz = -9dB, 2200Hz = 0dB; 2959Hz cutoff; cosine.
float32_t dB3[] = { q15_t dB9[] = {
-0.0231416146776, -19,
-0.0833375337803, -1268,
-0.147937602401, -3994,
-0.197411259519, -6856,
1.46066084756, 24688,
-0.197411259519, -6856,
-0.147937602401, -3994,
-0.0833375337803, -1268,
-0.0231416146776}; -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, * Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass,
* Hann window. * Hann window, starting and ending 0 value coefficients removed.
* *
* np.array( * np.array(
* firwin2(152, * firwin2(152,
@ -77,24 +285,23 @@ float32_t dB3[] = {
* window='hann') * 32768, * window='hann') * 32768,
* dtype=int)[10:-10] * dtype=int)[10:-10]
*/ */
const uint32_t FILTER_LEN = 132U; const uint32_t FILTER_LEN = 132;
q15_t FILTER_COEFFS[] = { q15_t FILTER_COEFFS[] = {
0, 5, 12, 18, 21, 19, 11, -2, -15, 0, 5, 12, 18, 21, 19, 11, -2, -15, -25,
-25, -27, -21, -11, -3, -5, -19, -43, -69, -27, -21, -11, -3, -5, -19, -43, -69, -83, -73,
-83, -73, -35, 27, 98, 155, 180, 163, 109, -35, 27, 98, 155, 180, 163, 109, 39, -20, -45,
39, -20, -45, -26, 23, 74, 89, 39, -81, -26, 23, 74, 89, 39, -81, -247, -407, -501, -480,
-247, -407, -501, -480, -334, -92, 175, 388, 479, -334, -92, 175, 388, 479, 429, 275, 99, 5, 68,
429, 275, 99, 5, 68, 298, 626, 913, 994, 298, 626, 913, 994, 740, 115, -791, -1770, -2544, -2847,
740, 115, -791, -1770, -2544, -2847, -2509, -1527, -76, -2509, -1527, -76, 1518, 2875, 3653, 3653, 2875, 1518, -76,
1518, 2875, 3653, 3653, 2875, 1518, -76, -1527, -2509, -1527, -2509, -2847, -2544, -1770, -791, 115, 740, 994, 913,
-2847, -2544, -1770, -791, 115, 740, 994, 913, 626, 626, 298, 68, 5, 99, 275, 429, 479, 388, 175,
298, 68, 5, 99, 275, 429, 479, 388, 175, -92, -334, -480, -501, -407, -247, -81, 39, 89, 74,
-92, -334, -480, -501, -407, -247, -81, 39, 89, 23, -26, -45, -20, 39, 109, 163, 180, 155, 98,
74, 23, -26, -45, -20, 39, 109, 163, 180, 27, -35, -73, -83, -69, -43, -19, -5, -3, -11,
155, 98, 27, -35, -73, -83, -69, -43, -19, -21, -27, -25, -15, -2, 11, 19, 21, 18, 12,
-5, -3, -11, -21, -27, -25, -15, -2, 11, 5, 0
19, 21, 18, 12, 5, 0}; };
CAX25RX::CAX25RX() : CAX25RX::CAX25RX() :
m_filter(), m_filter(),
@ -114,33 +321,28 @@ void CAX25RX::samples(q15_t* samples, uint8_t length)
q15_t output[RX_BLOCK_SIZE]; q15_t output[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_filter, samples, output, RX_BLOCK_SIZE); ::arm_fir_fast_q15(&m_filter, samples, output, RX_BLOCK_SIZE);
m_lastFCS = 0U;
CAX25Frame frame; CAX25Frame frame;
bool ret = m_demod1.process(output, length, frame); bool ret = m_demod1.process(output, length, frame);
if (ret && frame.m_length > 10U) { if (ret && frame.m_fcs != m_lastFCS) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 1 reported"); DEBUG1("Decoder 1 reported");
m_lastFCS = frame.m_fcs; m_lastFCS = frame.m_fcs;
serial.writeAX25Data(frame.m_data, frame.m_length - 2U); serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
} }
}
ret = m_demod2.process(output, length, frame); ret = m_demod2.process(output, length, frame);
if (ret && frame.m_length > 10U) { if (ret && frame.m_fcs != m_lastFCS) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 2 reported"); DEBUG1("Decoder 2 reported");
m_lastFCS = frame.m_fcs; m_lastFCS = frame.m_fcs;
serial.writeAX25Data(frame.m_data, frame.m_length - 2U); serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
} }
}
ret = m_demod3.process(output, length, frame); ret = m_demod3.process(output, length, frame);
if (ret && frame.m_length > 10U) { if (ret && frame.m_fcs != m_lastFCS) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 3 reported"); DEBUG1("Decoder 3 reported");
m_lastFCS = frame.m_fcs; m_lastFCS = frame.m_fcs;
serial.writeAX25Data(frame.m_data, frame.m_length - 2U); serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
} }
} }
}