From c2959466fd806524dca9158fd87924df864e41bc Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 11 Jun 2020 10:02:11 +0100 Subject: [PATCH] Code complete, but untested. --- AX25Demodulator.cpp | 103 +++++++++++++++++++++++++++++++++++++++++--- AX25Demodulator.h | 12 ++++++ AX25Frame.cpp | 10 +++++ AX25Frame.h | 6 ++- AX25RX.cpp | 12 +++--- 5 files changed, 131 insertions(+), 12 deletions(-) diff --git a/AX25Demodulator.cpp b/AX25Demodulator.cpp index 71e61ee..32dbcb4 100644 --- a/AX25Demodulator.cpp +++ b/AX25Demodulator.cpp @@ -53,6 +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) : +m_frame(), m_audioFilter(), m_audioState(), m_lpfFilter(), @@ -64,7 +65,12 @@ m_pllFilter(), m_pllState(), m_pllLast(false), m_pllBits(1U), -m_pllCount(0.0F) +m_pllCount(0.0F), +m_hdlcOnes(0U), +m_hdlcFlag(false), +m_hdlcBuffer(0U), +m_hdlcBits(0U), +m_hdlcState(AX25_IDLE) { m_delayLine = new bool[2U * DELAY_LEN]; @@ -110,10 +116,17 @@ bool CAX25Demodulator::process(const q15_t* samples, uint8_t length, CAX25Frame& 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_decoder_(NRZI(bit), true); - else - result = hdlc_decoder_(NRZI(bit), true); + if (result) { + HDLC(NRZI(bit)); + } else { + result = HDLC(NRZI(bit)); + if (result) { + ::memcpy(frame.m_data, m_frame.m_data, AX25_MAX_PACKET_LEN); + frame.m_length = frame.m_length; + frame.m_fcs = m_frame.m_fcs; + m_frame.m_length = 0U; + } + } } } @@ -171,3 +184,83 @@ bool CAX25Demodulator::PLL(bool input) return sample; } +bool CAX25Demodulator::HDLC(bool b) +{ + bool result = false; + + if (m_hdlcOnes == 5U) { + if (b) { + // flag byte + m_hdlcFlag = true; + } else { + // bit stuffing... + m_hdlcFlag = false; + m_hdlcOnes = 0U; + return result; + } + } + + 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) { + switch (m_hdlcBuffer) { + case 0x7E: + if (m_frame.m_length > 0U) { + result = m_frame.checkCRC(); + if (!result) + m_frame.m_length = 0U; + } + m_hdlcState = AX25_SYNC; + m_hdlcFlag = false; + m_hdlcBits = 0U; + break; + + case 0xFE: + // 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 result; +} + diff --git a/AX25Demodulator.h b/AX25Demodulator.h index c897c24..e12d4c6 100644 --- a/AX25Demodulator.h +++ b/AX25Demodulator.h @@ -23,6 +23,11 @@ #include "AX25Frame.h" +enum AX25_STATE { + AX25_IDLE, + AX25_SYNC, + AX25_RECEIVE +}; class CAX25Demodulator { public: @@ -31,6 +36,7 @@ public: bool process(const 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_lpfFilter; @@ -43,10 +49,16 @@ private: bool m_pllLast; uint8_t m_pllBits; float32_t m_pllCount; + 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); }; #endif diff --git a/AX25Frame.cpp b/AX25Frame.cpp index 2540cb3..3d3bb9f 100644 --- a/AX25Frame.cpp +++ b/AX25Frame.cpp @@ -61,6 +61,16 @@ 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 { diff --git a/AX25Frame.h b/AX25Frame.h index 30e08f7..eaf770c 100644 --- a/AX25Frame.h +++ b/AX25Frame.h @@ -21,13 +21,17 @@ #include "Config.h" +const uint16_t AX25_MAX_PACKET_LEN = 300U; + class CAX25Frame { public: CAX25Frame(); + bool append(uint16_t c); + bool checkCRC(); - uint8_t m_data[300U]; + uint8_t m_data[AX25_MAX_PACKET_LEN]; uint16_t m_length; uint16_t m_fcs; }; diff --git a/AX25RX.cpp b/AX25RX.cpp index 99aa1a5..de20709 100644 --- a/AX25RX.cpp +++ b/AX25RX.cpp @@ -114,29 +114,29 @@ void CAX25RX::samples(q15_t* samples, uint8_t length) CAX25Frame frame; bool ret = m_demod1.process(output, length, frame); - if (ret) { + 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); + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } } ret = m_demod2.process(output, length, frame); - if (ret) { + 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); + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } } ret = m_demod3.process(output, length, frame); - if (ret) { + 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); + serial.writeAX25Data(frame.m_data, frame.m_length - 2U); } } }