mirror of https://github.com/g4klx/MMDVM.git
Merge remote-tracking branch 'upstream/FM' into bugfix/STM32F1_POG
This commit is contained in:
commit
a4ddc2a060
43
FM.cpp
43
FM.cpp
|
@ -29,6 +29,7 @@ m_timeoutTone(),
|
||||||
m_state(FS_LISTENING),
|
m_state(FS_LISTENING),
|
||||||
m_callsignAtStart(false),
|
m_callsignAtStart(false),
|
||||||
m_callsignAtEnd(false),
|
m_callsignAtEnd(false),
|
||||||
|
m_callsignAtLatch(false),
|
||||||
m_callsignTimer(),
|
m_callsignTimer(),
|
||||||
m_timeoutTimer(),
|
m_timeoutTimer(),
|
||||||
m_holdoffTimer(),
|
m_holdoffTimer(),
|
||||||
|
@ -53,6 +54,8 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||||
if (!m_useCOS)
|
if (!m_useCOS)
|
||||||
cos = true;
|
cos = true;
|
||||||
|
|
||||||
|
clock(length);
|
||||||
|
|
||||||
uint8_t i = 0U;
|
uint8_t i = 0U;
|
||||||
for (; i < length; i++) {
|
for (; i < length; i++) {
|
||||||
q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access
|
q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access
|
||||||
|
@ -65,20 +68,20 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||||
} else if (CTCSS_READY(ctcssState) && m_modemState != STATE_FM) {
|
} else if (CTCSS_READY(ctcssState) && m_modemState != STATE_FM) {
|
||||||
//we had enough samples for CTCSS and we are in some other mode than FM
|
//we had enough samples for CTCSS and we are in some other mode than FM
|
||||||
bool validCTCSS = CTCSS_VALID(ctcssState);
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
stateMachine(validCTCSS && cos, i + 1U);
|
stateMachine(validCTCSS && cos);
|
||||||
if (m_modemState != STATE_FM)
|
if (m_modemState != STATE_FM)
|
||||||
continue;
|
continue;
|
||||||
} else if (CTCSS_READY(ctcssState) && m_modemState == STATE_FM) {
|
} else if (CTCSS_READY(ctcssState) && m_modemState == STATE_FM) {
|
||||||
//We had enough samples for CTCSS and we are in FM mode, trigger the state machine
|
//We had enough samples for CTCSS and we are in FM mode, trigger the state machine
|
||||||
bool validCTCSS = CTCSS_VALID(ctcssState);
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
stateMachine(validCTCSS && cos, i + 1U);
|
stateMachine(validCTCSS && cos);
|
||||||
if (m_modemState != STATE_FM)
|
if (m_modemState != STATE_FM)
|
||||||
break;
|
break;
|
||||||
} else if (CTCSS_NOT_READY(ctcssState) && m_modemState == STATE_FM && i == length - 1) {
|
} else if (CTCSS_NOT_READY(ctcssState) && m_modemState == STATE_FM && i == length - 1) {
|
||||||
//Not enough samples for CTCSS but we already are in FM, trigger the state machine
|
//Not enough samples for CTCSS but we already are in FM, trigger the state machine
|
||||||
//but do not trigger the state machine on every single sample, save CPU!
|
//but do not trigger the state machine on every single sample, save CPU!
|
||||||
bool validCTCSS = CTCSS_VALID(ctcssState);
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
stateMachine(validCTCSS && cos, i + 1U);
|
stateMachine(validCTCSS && cos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only let audio through when relaying audio
|
// Only let audio through when relaying audio
|
||||||
|
@ -138,10 +141,11 @@ void CFM::reset()
|
||||||
m_timeoutTone.stop();
|
m_timeoutTone.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd)
|
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch)
|
||||||
{
|
{
|
||||||
m_callsignAtStart = callsignAtStart;
|
m_callsignAtStart = callsignAtStart;
|
||||||
m_callsignAtEnd = callsignAtEnd;
|
m_callsignAtEnd = callsignAtEnd;
|
||||||
|
m_callsignAtLatch = callsignAtLatch;
|
||||||
|
|
||||||
uint16_t holdoffTime = holdoff * 60U;
|
uint16_t holdoffTime = holdoff * 60U;
|
||||||
uint16_t callsignTime = time * 60U;
|
uint16_t callsignTime = time * 60U;
|
||||||
|
@ -158,7 +162,9 @@ uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency
|
||||||
uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level)
|
uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level)
|
||||||
{
|
{
|
||||||
m_ackDelayTimer.setTimeout(0U, delay);
|
m_ackDelayTimer.setTimeout(0U, delay);
|
||||||
m_ackMinTimer.setTimeout(minTime, 0U);
|
|
||||||
|
if (minTime > 0U)
|
||||||
|
m_ackMinTimer.setTimeout(minTime, delay);
|
||||||
|
|
||||||
return m_rfAck.setParams(rfAck, speed, frequency, level, level);
|
return m_rfAck.setParams(rfAck, speed, frequency, level, level);
|
||||||
}
|
}
|
||||||
|
@ -182,16 +188,8 @@ uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFreque
|
||||||
return m_ctcssTX.setParams(ctcssFrequency, ctcssLevel);
|
return m_ctcssTX.setParams(ctcssFrequency, ctcssLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFM::stateMachine(bool validSignal, uint8_t length)
|
void CFM::stateMachine(bool validSignal)
|
||||||
{
|
{
|
||||||
m_callsignTimer.clock(length);
|
|
||||||
m_timeoutTimer.clock(length);
|
|
||||||
m_holdoffTimer.clock(length);
|
|
||||||
m_kerchunkTimer.clock(length);
|
|
||||||
m_ackMinTimer.clock(length);
|
|
||||||
m_ackDelayTimer.clock(length);
|
|
||||||
m_hangTimer.clock(length);
|
|
||||||
|
|
||||||
switch (m_state) {
|
switch (m_state) {
|
||||||
case FS_LISTENING:
|
case FS_LISTENING:
|
||||||
listeningState(validSignal);
|
listeningState(validSignal);
|
||||||
|
@ -232,6 +230,17 @@ void CFM::stateMachine(bool validSignal, uint8_t length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CFM::clock(uint8_t length)
|
||||||
|
{
|
||||||
|
m_callsignTimer.clock(length);
|
||||||
|
m_timeoutTimer.clock(length);
|
||||||
|
m_holdoffTimer.clock(length);
|
||||||
|
m_kerchunkTimer.clock(length);
|
||||||
|
m_ackMinTimer.clock(length);
|
||||||
|
m_ackDelayTimer.clock(length);
|
||||||
|
m_hangTimer.clock(length);
|
||||||
|
}
|
||||||
|
|
||||||
void CFM::listeningState(bool validSignal)
|
void CFM::listeningState(bool validSignal)
|
||||||
{
|
{
|
||||||
if (validSignal) {
|
if (validSignal) {
|
||||||
|
@ -239,6 +248,8 @@ void CFM::listeningState(bool validSignal)
|
||||||
DEBUG1("State to KERCHUNK");
|
DEBUG1("State to KERCHUNK");
|
||||||
m_state = FS_KERCHUNK;
|
m_state = FS_KERCHUNK;
|
||||||
m_kerchunkTimer.start();
|
m_kerchunkTimer.start();
|
||||||
|
if (m_callsignAtStart && !m_callsignAtLatch)
|
||||||
|
sendCallsign();
|
||||||
} else {
|
} else {
|
||||||
DEBUG1("State to RELAYING");
|
DEBUG1("State to RELAYING");
|
||||||
m_state = FS_RELAYING;
|
m_state = FS_RELAYING;
|
||||||
|
@ -262,6 +273,10 @@ void CFM::kerchunkState(bool validSignal)
|
||||||
DEBUG1("State to RELAYING");
|
DEBUG1("State to RELAYING");
|
||||||
m_state = FS_RELAYING;
|
m_state = FS_RELAYING;
|
||||||
m_kerchunkTimer.stop();
|
m_kerchunkTimer.stop();
|
||||||
|
if (m_callsignAtStart && m_callsignAtLatch) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG1("State to LISTENING");
|
DEBUG1("State to LISTENING");
|
||||||
|
|
7
FM.h
7
FM.h
|
@ -53,7 +53,7 @@ public:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd);
|
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
|
||||||
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
|
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
|
||||||
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ private:
|
||||||
FM_STATE m_state;
|
FM_STATE m_state;
|
||||||
bool m_callsignAtStart;
|
bool m_callsignAtStart;
|
||||||
bool m_callsignAtEnd;
|
bool m_callsignAtEnd;
|
||||||
|
bool m_callsignAtLatch;
|
||||||
CFMTimer m_callsignTimer;
|
CFMTimer m_callsignTimer;
|
||||||
CFMTimer m_timeoutTimer;
|
CFMTimer m_timeoutTimer;
|
||||||
CFMTimer m_holdoffTimer;
|
CFMTimer m_holdoffTimer;
|
||||||
|
@ -83,7 +84,7 @@ private:
|
||||||
q15_t m_rfAudioBoost;
|
q15_t m_rfAudioBoost;
|
||||||
CFMDownsampler m_downsampler;
|
CFMDownsampler m_downsampler;
|
||||||
|
|
||||||
void stateMachine(bool validSignal, uint8_t length);
|
void stateMachine(bool validSignal);
|
||||||
void listeningState(bool validSignal);
|
void listeningState(bool validSignal);
|
||||||
void kerchunkState(bool validSignal);
|
void kerchunkState(bool validSignal);
|
||||||
void relayingState(bool validSignal);
|
void relayingState(bool validSignal);
|
||||||
|
@ -92,6 +93,8 @@ private:
|
||||||
void timeoutWaitState(bool validSignal);
|
void timeoutWaitState(bool validSignal);
|
||||||
void hangState(bool validSignal);
|
void hangState(bool validSignal);
|
||||||
|
|
||||||
|
void clock(uint8_t length);
|
||||||
|
|
||||||
void sendCallsign();
|
void sendCallsign();
|
||||||
void beginRelaying();
|
void beginRelaying();
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,7 +101,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
|
||||||
#define HW_TYPE "MMDVM"
|
#define HW_TYPE "MMDVM"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DESCRIPTION "20200502 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
|
#define DESCRIPTION "20200504 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
|
||||||
|
|
||||||
#if defined(GITVERSION)
|
#if defined(GITVERSION)
|
||||||
#define concat(h, a, b, c) h " " a " " b " GitID #" c ""
|
#define concat(h, a, b, c) h " " a " " b " GitID #" c ""
|
||||||
|
@ -376,6 +376,7 @@ uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length)
|
||||||
|
|
||||||
bool callAtStart = (data[6U] & 0x01U) == 0x01U;
|
bool callAtStart = (data[6U] & 0x01U) == 0x01U;
|
||||||
bool callAtEnd = (data[6U] & 0x02U) == 0x02U;
|
bool callAtEnd = (data[6U] & 0x02U) == 0x02U;
|
||||||
|
bool callAtLatch = (data[6U] & 0x04U) == 0x04U;
|
||||||
|
|
||||||
char callsign[50U];
|
char callsign[50U];
|
||||||
uint8_t n = 0U;
|
uint8_t n = 0U;
|
||||||
|
@ -383,7 +384,7 @@ uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length)
|
||||||
callsign[n] = data[i];
|
callsign[n] = data[i];
|
||||||
callsign[n] = '\0';
|
callsign[n] = '\0';
|
||||||
|
|
||||||
return fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd);
|
return fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd, callAtLatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
|
uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
|
||||||
|
|
Loading…
Reference in New Issue