More filtering added.

This commit is contained in:
Jonathan Naylor 2020-06-10 16:38:10 +01:00
parent 22cb16f831
commit 121c76f3d8
3 changed files with 103 additions and 18 deletions

View File

@ -30,9 +30,9 @@ 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 = 96;
const uint32_t LPF_FILTER_LEN = 96U;
q15_t lpfCoeffs[] = {
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,
@ -48,7 +48,9 @@ q15_t lpfCoeffs[] = {
// loop_coeffs = firwin(9, [64.0/(1200/2)], width = None,
// pass_zero = True, scale = True, window='hann')
//
float32_t pllLoopCoeffs[] = {3.196252e-02F, 1.204223e-01F, 2.176819e-01F, 2.598666e-01F, 2.176819e-01F, 1.204223e-01F, 3.196252e-02F};
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_audioFilter(),
@ -72,11 +74,11 @@ m_pllCount(0.0F)
m_lpfFilter.numTaps = LPF_FILTER_LEN;
m_lpfFilter.pState = m_lpfState;
m_lpfFilter.pCoeffs = lpfCoeffs;
m_lpfFilter.pCoeffs = LPF_FILTER_COEFFS;
m_pllFilter.numTaps = 7U;
m_pllFilter.numTaps = PLL_FILTER_LEN;
m_pllFilter.pState = m_pllState;
m_pllFilter.pCoeffs = pllLoopCoeffs;
m_pllFilter.pCoeffs = PLL_FILTER_COEFFS;
}
bool CAX25Demodulator::process(const q15_t* samples, uint8_t length, CAX25Frame& frame)

View File

@ -20,19 +20,100 @@
#include "Globals.h"
#include "AX25RX.h"
// XXX There are for the wrong sample rate
// 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 = -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 = -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};
/*
* Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass,
* Hann window, starting and ending 0 value coefficients removed.
*
* np.array(
* firwin2(152,
* [
* 0.0,
* 1000.0/(sample_rate/2),
* 1100.0/(sample_rate/2),
* 2350.0/(sample_rate/2),
* 2500.0/(sample_rate/2),
* 1.0
* ],
* [0,0,1,1,0,0],
* antisymmetric = False,
* window='hann') * 32768,
* dtype=int)[10:-10]
*/
const uint32_t FILTER_LEN = 132U;
// XXX This is for the wrong sample rate
q15_t FILTER_COEFFS[] = {
4, 0, -5, -10, -13, -12, -9, -4, -2, -4, -12, -26,
-41, -52, -51, -35, -3, 39, 83, 117, 131, 118, 83, 36,
-6, -32, -30, -3, 36, 67, 66, 19, -74, -199, -323, -408,
-421, -344, -187, 17, 218, 364, 417, 369, 247, 106, 14, 26,
166, 407, 676, 865, 866, 605, 68, -675, -1484, -2171, -2547, -2471,
-1895, -882, 394, 1692, 2747, 3337, 3337, 2747, 1692, 394, -882, -1895,
-2471, -2547, -2171, -1484, -675, 68, 605, 866, 865, 676, 407, 166,
26, 14, 106, 247, 369, 417, 364, 218, 17, -187, -344, -421,
-408, -323, -199, -74, 19, 66, 67, 36, -3, -30, -32, -6,
36, 83, 118, 131, 117, 83, 39, -3, -35, -51, -52, -41,
-26, -12, -4, -2, -4, -9, -12, -13, -10, -5, 0, 4};
CAX25RX::CAX25RX() :
m_demod1(),
m_demod2(),
m_demod3(),
m_filter(),
m_state(),
m_demod1(dB3, 9U),
m_demod2(dB6, 9U),
m_demod3(dB9, 9U),
m_lastFCS(0U)
{
m_filter.numTaps = FILTER_LEN;
m_filter.pState = m_state;
m_filter.pCoeffs = FILTER_COEFFS;
}
void CAX25RX::samples(const q15_t* samples, uint8_t length)
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);
CAX25Frame frame;
bool ret = m_demod1.process(samples, length, frame);
bool ret = m_demod1.process(output, length, frame);
if (ret) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 1 reported");
@ -41,7 +122,7 @@ void CAX25RX::samples(const q15_t* samples, uint8_t length)
}
}
ret = m_demod2.process(samples, length, frame);
ret = m_demod2.process(output, length, frame);
if (ret) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 2 reported");
@ -50,7 +131,7 @@ void CAX25RX::samples(const q15_t* samples, uint8_t length)
}
}
ret = m_demod3.process(samples, length, frame);
ret = m_demod3.process(output, length, frame);
if (ret) {
if (m_lastFCS != frame.m_fcs) {
DEBUG1("Decoder 3 reported");

View File

@ -27,13 +27,15 @@ class CAX25RX {
public:
CAX25RX();
void samples(const q15_t* samples, uint8_t length);
void samples(q15_t* samples, uint8_t length);
private:
CAX25Demodulator m_demod1;
CAX25Demodulator m_demod2;
CAX25Demodulator m_demod3;
uint16_t m_lastFCS;
arm_fir_instance_q15 m_filter;
q15_t m_state[160U]; // NoTaps + BlockSize - 1, 132 + 20 - 1 plus some spare
CAX25Demodulator m_demod1;
CAX25Demodulator m_demod2;
CAX25Demodulator m_demod3;
uint16_t m_lastFCS;
};
#endif