mirror of https://github.com/g4klx/MMDVM.git
Code complete, but untested.
This commit is contained in:
parent
121c76f3d8
commit
c2959466fd
|
@ -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};
|
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(float32_t* coeffs, uint16_t length) :
|
||||||
|
m_frame(),
|
||||||
m_audioFilter(),
|
m_audioFilter(),
|
||||||
m_audioState(),
|
m_audioState(),
|
||||||
m_lpfFilter(),
|
m_lpfFilter(),
|
||||||
|
@ -64,7 +65,12 @@ m_pllFilter(),
|
||||||
m_pllState(),
|
m_pllState(),
|
||||||
m_pllLast(false),
|
m_pllLast(false),
|
||||||
m_pllBits(1U),
|
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];
|
m_delayLine = new bool[2U * DELAY_LEN];
|
||||||
|
|
||||||
|
@ -110,10 +116,17 @@ bool CAX25Demodulator::process(const q15_t* samples, uint8_t length, CAX25Frame&
|
||||||
if (sample) {
|
if (sample) {
|
||||||
// We will only ever get one frame because there are
|
// We will only ever get one frame because there are
|
||||||
// not enough bits in a block for more than one.
|
// not enough bits in a block for more than one.
|
||||||
if (result)
|
if (result) {
|
||||||
hdlc_decoder_(NRZI(bit), true);
|
HDLC(NRZI(bit));
|
||||||
else
|
} else {
|
||||||
result = hdlc_decoder_(NRZI(bit), true);
|
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;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
|
|
||||||
#include "AX25Frame.h"
|
#include "AX25Frame.h"
|
||||||
|
|
||||||
|
enum AX25_STATE {
|
||||||
|
AX25_IDLE,
|
||||||
|
AX25_SYNC,
|
||||||
|
AX25_RECEIVE
|
||||||
|
};
|
||||||
|
|
||||||
class CAX25Demodulator {
|
class CAX25Demodulator {
|
||||||
public:
|
public:
|
||||||
|
@ -31,6 +36,7 @@ public:
|
||||||
bool process(const q15_t* samples, uint8_t length, CAX25Frame& frame);
|
bool process(const q15_t* samples, uint8_t length, CAX25Frame& frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CAX25Frame m_frame;
|
||||||
arm_fir_instance_f32 m_audioFilter;
|
arm_fir_instance_f32 m_audioFilter;
|
||||||
float32_t m_audioState[20U];
|
float32_t m_audioState[20U];
|
||||||
arm_fir_instance_q15 m_lpfFilter;
|
arm_fir_instance_q15 m_lpfFilter;
|
||||||
|
@ -43,10 +49,16 @@ private:
|
||||||
bool m_pllLast;
|
bool m_pllLast;
|
||||||
uint8_t m_pllBits;
|
uint8_t m_pllBits;
|
||||||
float32_t m_pllCount;
|
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 delay(bool b);
|
||||||
bool NRZI(bool b);
|
bool NRZI(bool b);
|
||||||
bool PLL(bool b);
|
bool PLL(bool b);
|
||||||
|
bool HDLC(bool b);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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()
|
bool CAX25Frame::checkCRC()
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -21,13 +21,17 @@
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
const uint16_t AX25_MAX_PACKET_LEN = 300U;
|
||||||
|
|
||||||
class CAX25Frame {
|
class CAX25Frame {
|
||||||
public:
|
public:
|
||||||
CAX25Frame();
|
CAX25Frame();
|
||||||
|
|
||||||
|
bool append(uint16_t c);
|
||||||
|
|
||||||
bool checkCRC();
|
bool checkCRC();
|
||||||
|
|
||||||
uint8_t m_data[300U];
|
uint8_t m_data[AX25_MAX_PACKET_LEN];
|
||||||
uint16_t m_length;
|
uint16_t m_length;
|
||||||
uint16_t m_fcs;
|
uint16_t m_fcs;
|
||||||
};
|
};
|
||||||
|
|
12
AX25RX.cpp
12
AX25RX.cpp
|
@ -114,29 +114,29 @@ void CAX25RX::samples(q15_t* samples, uint8_t length)
|
||||||
CAX25Frame frame;
|
CAX25Frame frame;
|
||||||
|
|
||||||
bool ret = m_demod1.process(output, length, frame);
|
bool ret = m_demod1.process(output, length, frame);
|
||||||
if (ret) {
|
if (ret && frame.m_length > 10U) {
|
||||||
if (m_lastFCS != frame.m_fcs) {
|
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);
|
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) {
|
if (ret && frame.m_length > 10U) {
|
||||||
if (m_lastFCS != frame.m_fcs) {
|
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);
|
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) {
|
if (ret && frame.m_length > 10U) {
|
||||||
if (m_lastFCS != frame.m_fcs) {
|
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);
|
serial.writeAX25Data(frame.m_data, frame.m_length - 2U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue