mirror of https://github.com/g4klx/MMDVM.git
Merge pull request #248 from F4FXL/FM
Make the FM chain RX Level independant
This commit is contained in:
commit
5ca9313db8
18
FM.cpp
18
FM.cpp
|
@ -40,13 +40,12 @@ m_hangTimer(),
|
|||
m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz
|
||||
m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
|
||||
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
|
||||
m_preemphasis(32768, 13967, 0, 32768, -18801, 0),//75µS 24kHz sampling rate
|
||||
m_deemphasis (32768, -18801, 0, 32768, 13967, 0),//75µS 24kHz sampling rate
|
||||
m_blanking(),
|
||||
m_useCOS(true),
|
||||
m_cosInvert(false),
|
||||
m_rfAudioBoost(1U),
|
||||
m_downsampler(128)//Size might need adjustement
|
||||
m_downsampler(128),//Size might need adjustement
|
||||
m_rxLevel(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,7 +62,8 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
|||
|
||||
uint8_t i = 0U;
|
||||
for (; i < length; i++) {
|
||||
q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access
|
||||
// ARMv7-M has hardware integer division
|
||||
q15_t currentSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel);
|
||||
|
||||
uint8_t ctcssState = m_ctcssRX.process(currentSample);
|
||||
|
||||
|
@ -90,8 +90,7 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
|||
}
|
||||
|
||||
// Only let audio through when relaying audio
|
||||
if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) {
|
||||
// currentSample = m_deemphasis.filter(currentSample);
|
||||
if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) {
|
||||
// m_downsampler.addSample(currentSample);
|
||||
currentSample = m_blanking.process(currentSample);
|
||||
currentSample *= m_rfAudioBoost;
|
||||
|
@ -114,8 +113,6 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
|||
|
||||
currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample)));
|
||||
|
||||
// currentSample = m_preemphasis.filter(currentSample);
|
||||
|
||||
currentSample += m_ctcssTX.getAudio();
|
||||
|
||||
samples[i] = currentSample;
|
||||
|
@ -188,7 +185,9 @@ uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFreque
|
|||
m_timeoutTone.setParams(timeoutLevel);
|
||||
m_blanking.setParams(maxDev, timeoutLevel);
|
||||
|
||||
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssThreshold, rxLevel);
|
||||
m_rxLevel = rxLevel; //q15_t(255)/q15_t(rxLevel >> 1);
|
||||
|
||||
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssThreshold);
|
||||
if (ret != 0U)
|
||||
return ret;
|
||||
|
||||
|
@ -438,3 +437,4 @@ void CFM::beginRelaying()
|
|||
m_timeoutTimer.start();
|
||||
m_ackMinTimer.start();
|
||||
}
|
||||
|
||||
|
|
3
FM.h
3
FM.h
|
@ -77,13 +77,12 @@ private:
|
|||
CFMDirectFormI m_filterStage1;
|
||||
CFMDirectFormI m_filterStage2;
|
||||
CFMDirectFormI m_filterStage3;
|
||||
CFMDirectFormI m_preemphasis;
|
||||
CFMDirectFormI m_deemphasis;
|
||||
CFMBlanking m_blanking;
|
||||
bool m_useCOS;
|
||||
bool m_cosInvert;
|
||||
q15_t m_rfAudioBoost;
|
||||
CFMDownsampler m_downsampler;
|
||||
q15_t m_rxLevel;
|
||||
|
||||
void stateMachine(bool validSignal);
|
||||
void listeningState(bool validSignal);
|
||||
|
|
|
@ -86,15 +86,12 @@ m_threshold(0),
|
|||
m_count(0U),
|
||||
m_q0(0),
|
||||
m_q1(0),
|
||||
m_result(CTS_NONE),
|
||||
m_rxLevelInverse(1)
|
||||
m_result(CTS_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t level)
|
||||
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold)
|
||||
{
|
||||
m_rxLevelInverse = q15Division(65535, q15_t(level * 128));
|
||||
|
||||
m_coeffDivTwo = 0;
|
||||
|
||||
for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) {
|
||||
|
@ -114,7 +111,8 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t leve
|
|||
|
||||
uint8_t CFMCTCSSRX::process(q15_t sample)
|
||||
{
|
||||
q31_t sample31 = q31_t(sample) * m_rxLevelInverse;
|
||||
//get more dynamic into the decoder by multiplying the sample by 1.5
|
||||
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
|
||||
|
||||
m_result &= ~CTS_READY;
|
||||
|
||||
|
@ -174,16 +172,3 @@ void CFMCTCSSRX::reset()
|
|||
m_result = CTS_NONE;
|
||||
m_count = 0U;
|
||||
}
|
||||
|
||||
//Taken from https://en.wikipedia.org/wiki/Q_(number_format)#Division
|
||||
q15_t CFMCTCSSRX::q15Division(q15_t a, q15_t divisor)
|
||||
{
|
||||
q31_t a31 = q31_t(a) << 16;
|
||||
|
||||
if (((a >> 31) & 1) == ((divisor >> 15) & 1))
|
||||
a31 += divisor >> 1;
|
||||
else
|
||||
a31 -= divisor >> 1;
|
||||
|
||||
return a31 / divisor;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class CFMCTCSSRX {
|
|||
public:
|
||||
CFMCTCSSRX();
|
||||
|
||||
uint8_t setParams(uint8_t frequency, uint8_t threshold, uint8_t level);
|
||||
uint8_t setParams(uint8_t frequency, uint8_t threshold);
|
||||
|
||||
uint8_t process(q15_t sample);
|
||||
|
||||
|
@ -47,9 +47,6 @@ private:
|
|||
q31_t m_q0;
|
||||
q31_t m_q1;
|
||||
uint8_t m_result;
|
||||
q15_t m_rxLevelInverse;
|
||||
|
||||
q15_t q15Division(q15_t a, q15_t divisor);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue