mirror of https://github.com/g4klx/MMDVM.git
Merge branch 'FM' into dstar_correlator_fm
This commit is contained in:
commit
c6485de10c
|
@ -77,6 +77,7 @@ const struct {
|
||||||
{',', 0xEEAEE000U, 22U},
|
{',', 0xEEAEE000U, 22U},
|
||||||
{'-', 0xEAAE0000U, 18U},
|
{'-', 0xEAAE0000U, 18U},
|
||||||
{'=', 0xEAB80000U, 16U},
|
{'=', 0xEAB80000U, 16U},
|
||||||
|
{'.', 0xBAEB8000U, 20U},
|
||||||
{' ', 0x00000000U, 4U},
|
{' ', 0x00000000U, 4U},
|
||||||
{0U, 0x00000000U, 0U}
|
{0U, 0x00000000U, 0U}
|
||||||
};
|
};
|
||||||
|
@ -170,4 +171,3 @@ void CCWIdTX::reset()
|
||||||
m_poPtr = 0U;
|
m_poPtr = 0U;
|
||||||
m_n = 0U;
|
m_n = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
FM.cpp
45
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(),
|
||||||
|
@ -44,7 +45,7 @@ m_deemphasis (32768, -18801, 0, 32768, 13967, 0),//75µS 24kHz sampling rate
|
||||||
m_blanking(),
|
m_blanking(),
|
||||||
m_useCOS(true),
|
m_useCOS(true),
|
||||||
m_rfAudioBoost(1U),
|
m_rfAudioBoost(1U),
|
||||||
m_downsampler(1024)//Size might need adjustement
|
m_downsampler(128)//Size might need adjustement
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,6 +66,7 @@ const struct {
|
||||||
{',', 0xEEAEE000U, 22U},
|
{',', 0xEEAEE000U, 22U},
|
||||||
{'-', 0xEAAE0000U, 18U},
|
{'-', 0xEAAE0000U, 18U},
|
||||||
{'=', 0xEAB80000U, 16U},
|
{'=', 0xEAB80000U, 16U},
|
||||||
|
{'.', 0xBAEB8000U, 20U},
|
||||||
{' ', 0x00000000U, 4U},
|
{' ', 0x00000000U, 4U},
|
||||||
{0U, 0x00000000U, 0U}
|
{0U, 0x00000000U, 0U}
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,7 +85,7 @@ USART1_RXD PA10 input (AF)
|
||||||
#define PIN_POCSAG 11
|
#define PIN_POCSAG 11
|
||||||
#define PORT_POCSAG GPIOB
|
#define PORT_POCSAG GPIOB
|
||||||
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
|
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
|
||||||
#define PIN_FM 12
|
#define PIN_FM 14
|
||||||
#define PORT_FM GPIOB
|
#define PORT_FM GPIOB
|
||||||
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
|
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
|
||||||
|
|
||||||
|
@ -158,16 +158,35 @@ void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value
|
||||||
#if defined(STM32F1_POG)
|
#if defined(STM32F1_POG)
|
||||||
void FancyLEDEffect()
|
void FancyLEDEffect()
|
||||||
{
|
{
|
||||||
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25, &BB_NXDN, &BB_POCSAG, &BB_FM};
|
int ledCount = 10;
|
||||||
|
|
||||||
for(int i=0; i<10; i++){
|
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25,
|
||||||
*foo[i] = 0x01;
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
NULL,
|
||||||
|
#else
|
||||||
|
&BB_NXDN,
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
NULL,
|
||||||
|
#else
|
||||||
|
&BB_POCSAG,
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
NULL};
|
||||||
|
#else
|
||||||
|
&BB_FM};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<ledCount; i++){
|
||||||
|
if(foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
}
|
}
|
||||||
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
|
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
|
||||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||||
delay(SystemCoreClock/1000*100);
|
delay(SystemCoreClock/1000*100);
|
||||||
for(int i=0; i<7; i++){
|
for(int i=0; i<ledCount; i++){
|
||||||
*foo[i] = 0x00;
|
if(foo[i] != NULL)
|
||||||
|
*foo[i] = 0x00;
|
||||||
}
|
}
|
||||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
delay(SystemCoreClock/1000*20);
|
delay(SystemCoreClock/1000*20);
|
||||||
|
@ -176,18 +195,22 @@ void FancyLEDEffect()
|
||||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
|
|
||||||
*foo[0] = 0x01;
|
*foo[0] = 0x01;
|
||||||
for(int i=1; i<10; i++){
|
for(int i=1; i<ledCount; i++){
|
||||||
delay(SystemCoreClock/1000*10);
|
delay(SystemCoreClock/1000*10);
|
||||||
*foo[i-1] = 0x00;
|
if (foo[i-1] != NULL)
|
||||||
*foo[i] = 0x01;
|
*foo[i-1] = 0x00;
|
||||||
|
if (foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
}
|
}
|
||||||
for(int i=10; i>=0; i--){
|
for(int i=ledCount - 2; i>=0; i--) {
|
||||||
delay(SystemCoreClock/1000*10);
|
delay(SystemCoreClock/1000*10);
|
||||||
*foo[i+1] = 0x00;
|
if (foo[i+1] != NULL)
|
||||||
*foo[i] = 0x01;
|
*foo[i+1] = 0x00;
|
||||||
|
if (foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
}
|
}
|
||||||
delay(SystemCoreClock/1000*10);
|
delay(SystemCoreClock/1000*10);
|
||||||
*foo[5+1-6] = 0x00;
|
*foo[0] = 0x00;
|
||||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||||
delay(SystemCoreClock/1000*10);
|
delay(SystemCoreClock/1000*10);
|
||||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
|
|
|
@ -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