Implement an efficient FIR filter.

This commit is contained in:
Jonathan Naylor 2020-04-22 14:37:23 +01:00
parent f936bc6fe8
commit 57730d7f81
2 changed files with 31 additions and 11 deletions

36
FM.cpp
View File

@ -30,8 +30,8 @@ const uint16_t FILTER_COEFFS_LEN = 51U;
CFM::CFM() : CFM::CFM() :
m_filter(), m_filterBuffer(NULL),
m_filterState(), m_filterPosition(0U),
m_callsign(), m_callsign(),
m_rfAck(), m_rfAck(),
m_ctcssRX(), m_ctcssRX(),
@ -48,11 +48,7 @@ m_ackMinTimer(),
m_ackDelayTimer(), m_ackDelayTimer(),
m_hangTimer() m_hangTimer()
{ {
::memset(m_filterState, 0x00U, 230U * sizeof(q15_t)); m_filterBuffer = new q15_t[FILTER_COEFFS_LEN];
m_filter.numTaps = FILTER_COEFFS_LEN;
m_filter.pState = m_filterState;
m_filter.pCoeffs = FILTER_COEFFS;
} }
void CFM::samples(q15_t* samples, uint8_t length) void CFM::samples(q15_t* samples, uint8_t length)
@ -98,8 +94,7 @@ void CFM::samples(q15_t* samples, uint8_t length)
if (!m_callsign.isRunning() && !m_rfAck.isRunning()) if (!m_callsign.isRunning() && !m_rfAck.isRunning())
currentSample += m_timeoutTone.getAudio(); currentSample += m_timeoutTone.getAudio();
//ToDo Filtering currentSample = filter(currentSample);
//::arm_fir_fast_q15(&m_filter, samples + i, &currentSample, 1);
currentSample += m_ctcssTX.getAudio(); currentSample += m_ctcssTX.getAudio();
@ -395,3 +390,26 @@ void CFM::beginRelaying()
m_timeoutTimer.start(); m_timeoutTimer.start();
m_ackMinTimer.start(); m_ackMinTimer.start();
} }
q15_t CFM::filter(q15_t sample)
{
q15_t output = 0;
m_filterBuffer[m_filterPosition] = sample;
uint8_t iTaps = 0U;
for (int8_t i = m_filterPosition; i >= 0; i--) {
q31_t temp = FILTER_COEFFS[iTaps++] * m_filterBuffer[i];
output += q15_t(__SSAT((temp >> 15), 16));
}
for (int8_t i = FILTER_COEFFS_LEN - 1; i >= m_filterPosition; i--) {
q31_t temp = FILTER_COEFFS[iTaps++] * m_filterBuffer[i];
output += q15_t(__SSAT((temp >> 15), 16));
}
m_filterPosition = (m_filterPosition + 1U) % FILTER_COEFFS_LEN;
return output;
}

6
FM.h
View File

@ -52,8 +52,8 @@ public:
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime); uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime);
private: private:
arm_fir_instance_q15 m_filter; q15_t* m_filterBuffer;
q15_t m_filterState[130U]; // NoTaps + BlockSize - 1, 101 + 20 - 1 plus some spare uint8_t m_filterPosition;
CFMKeyer m_callsign; CFMKeyer m_callsign;
CFMKeyer m_rfAck; CFMKeyer m_rfAck;
CFMCTCSSRX m_ctcssRX; CFMCTCSSRX m_ctcssRX;
@ -81,6 +81,8 @@ private:
void sendCallsign(); void sendCallsign();
void beginRelaying(); void beginRelaying();
q15_t filter(q15_t sample);
}; };
#endif #endif