mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-08-21 22:46:22 +02:00
Merge branch 'FM' into boxcar_fm
This commit is contained in:
+143
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013,2015-2019 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2013,2015-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -65,6 +65,10 @@ const uint8_t MMDVM_NXDN_LOST = 0x41U;
|
||||
|
||||
const uint8_t MMDVM_POCSAG_DATA = 0x50U;
|
||||
|
||||
const uint8_t MMDVM_FM_PARAMS1 = 0x60U;
|
||||
const uint8_t MMDVM_FM_PARAMS2 = 0x61U;
|
||||
const uint8_t MMDVM_FM_PARAMS3 = 0x62U;
|
||||
|
||||
const uint8_t MMDVM_ACK = 0x70U;
|
||||
const uint8_t MMDVM_NAK = 0x7FU;
|
||||
|
||||
@@ -97,7 +101,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
|
||||
#define HW_TYPE "MMDVM"
|
||||
#endif
|
||||
|
||||
#define DESCRIPTION "20190130 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG)"
|
||||
#define DESCRIPTION "20200428 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
|
||||
|
||||
#if defined(GITVERSION)
|
||||
#define concat(h, a, b, c) h " " a " " b " GitID #" c ""
|
||||
@@ -168,6 +172,8 @@ void CSerialPort::getStatus()
|
||||
reply[3U] |= 0x10U;
|
||||
if (m_pocsagEnable)
|
||||
reply[3U] |= 0x20U;
|
||||
if (m_fmEnable)
|
||||
reply[3U] |= 0x40U;
|
||||
|
||||
reply[4U] = uint8_t(m_modemState);
|
||||
|
||||
@@ -256,7 +262,7 @@ void CSerialPort::getVersion()
|
||||
|
||||
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length < 18U)
|
||||
if (length < 19U)
|
||||
return 4U;
|
||||
|
||||
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
|
||||
@@ -273,6 +279,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
bool pocsagEnable = (data[1U] & 0x20U) == 0x20U;
|
||||
bool fmEnable = (data[1U] & 0x40U) == 0x40U;
|
||||
|
||||
uint8_t txDelay = data[2U];
|
||||
if (txDelay > 50U)
|
||||
@@ -280,7 +287,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
|
||||
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
|
||||
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_FM && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL && modemState != STATE_FMCAL10K && modemState != STATE_FMCAL12K && modemState != STATE_FMCAL15K && modemState != STATE_FMCAL20K && modemState != STATE_FMCAL25K && modemState != STATE_FMCAL30K)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !dstarEnable)
|
||||
return 4U;
|
||||
@@ -294,6 +301,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
return 4U;
|
||||
if (modemState == STATE_POCSAG && !pocsagEnable)
|
||||
return 4U;
|
||||
if (modemState == STATE_FM && !fmEnable)
|
||||
return 4U;
|
||||
|
||||
uint8_t rxLevel = data[4U];
|
||||
|
||||
@@ -318,6 +327,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
|
||||
uint8_t pocsagTXLevel = data[17U];
|
||||
|
||||
uint8_t fmTXLevel = data[18U];
|
||||
|
||||
m_modemState = modemState;
|
||||
|
||||
m_dstarEnable = dstarEnable;
|
||||
@@ -326,6 +337,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
m_p25Enable = p25Enable;
|
||||
m_nxdnEnable = nxdnEnable;
|
||||
m_pocsagEnable = pocsagEnable;
|
||||
m_fmEnable = fmEnable;
|
||||
m_duplex = !simplex;
|
||||
|
||||
dstarTX.setTXDelay(txDelay);
|
||||
@@ -343,13 +355,81 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||
|
||||
ysfTX.setParams(ysfLoDev, ysfTXHang);
|
||||
|
||||
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, txDCOffset, rxDCOffset);
|
||||
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, txDCOffset, rxDCOffset);
|
||||
|
||||
io.start();
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setFMParams1(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length < 8U)
|
||||
return 4U;
|
||||
|
||||
uint8_t speed = data[0U];;
|
||||
uint16_t frequency = data[1U] * 10U;
|
||||
uint8_t time = data[2U];
|
||||
uint8_t holdoff = data[3U];
|
||||
uint8_t highLevel = data[4U];
|
||||
uint8_t lowLevel = data[5U];
|
||||
|
||||
bool callAtStart = (data[6U] & 0x01U) == 0x01U;
|
||||
bool callAtEnd = (data[6U] & 0x02U) == 0x02U;
|
||||
|
||||
char callsign[50U];
|
||||
uint8_t n = 0U;
|
||||
for (uint8_t i = 7U; i < length; i++, n++)
|
||||
callsign[n] = data[i];
|
||||
callsign[n] = '\0';
|
||||
|
||||
return fm.setCallsign(callsign, speed, frequency, time, holdoff, highLevel, lowLevel, callAtStart, callAtEnd);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length < 6U)
|
||||
return 4U;
|
||||
|
||||
uint8_t speed = data[0U];
|
||||
uint16_t frequency = data[1U] * 10U;
|
||||
uint8_t minTime = data[2U];
|
||||
uint16_t delay = data[3U] * 10U;
|
||||
uint8_t level = data[4U];
|
||||
|
||||
char ack[50U];
|
||||
uint8_t n = 0U;
|
||||
for (uint8_t i = 5U; i < length; i++, n++)
|
||||
ack[n] = data[i];
|
||||
ack[n] = '\0';
|
||||
|
||||
return fm.setAck(ack, speed, frequency, minTime, delay, level);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length < 11U)
|
||||
return 4U;
|
||||
|
||||
uint16_t timeout = data[0U] * 5U;
|
||||
uint8_t timeoutLevel = data[1U];
|
||||
|
||||
uint8_t ctcssFrequency = data[2U];
|
||||
uint8_t ctcssThreshold = data[3U];
|
||||
uint8_t ctcssLevel = data[4U];
|
||||
|
||||
uint8_t kerchunkTime = data[5U];
|
||||
uint8_t hangTime = data[6U];
|
||||
|
||||
bool useCOS = (data[7U] & 0x01U) == 0x01U;
|
||||
|
||||
uint8_t rfAudioBoost = data[8U];
|
||||
uint8_t maxDev = data[9U];
|
||||
uint8_t rxLevel = data[10U];
|
||||
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, rfAudioBoost, maxDev, rxLevel);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length < 1U)
|
||||
@@ -360,7 +440,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
||||
if (modemState == m_modemState)
|
||||
return 0U;
|
||||
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_FM && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K && modemState != STATE_POCSAGCAL && modemState != STATE_FMCAL10K && modemState != STATE_FMCAL12K && modemState != STATE_FMCAL15K && modemState != STATE_FMCAL20K && modemState != STATE_FMCAL25K && modemState != STATE_FMCAL30K)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
||||
return 4U;
|
||||
@@ -374,6 +454,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
||||
return 4U;
|
||||
if (modemState == STATE_POCSAG && !m_pocsagEnable)
|
||||
return 4U;
|
||||
if (modemState == STATE_FM && !m_fmEnable)
|
||||
return 4U;
|
||||
|
||||
setMode(modemState);
|
||||
|
||||
@@ -401,6 +483,9 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
||||
case STATE_POCSAG:
|
||||
DEBUG1("Mode set to POCSAG");
|
||||
break;
|
||||
case STATE_FM:
|
||||
DEBUG1("Mode set to FM");
|
||||
break;
|
||||
case STATE_DSTARCAL:
|
||||
DEBUG1("Mode set to D-Star Calibrate");
|
||||
break;
|
||||
@@ -413,8 +498,23 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
||||
case STATE_LFCAL:
|
||||
DEBUG1("Mode set to 80 Hz Calibrate");
|
||||
break;
|
||||
case STATE_DMRCAL1K:
|
||||
DEBUG1("Mode set to DMR BS 1031 Hz Calibrate");
|
||||
case STATE_FMCAL10K:
|
||||
DEBUG1("Mode set to FM 10Khz Calibrate");
|
||||
break;
|
||||
case STATE_FMCAL12K:
|
||||
DEBUG1("Mode set to FM 12.5Khz Calibrate");
|
||||
break;
|
||||
case STATE_FMCAL15K:
|
||||
DEBUG1("Mode set to FM 15Khz Calibrate");
|
||||
break;
|
||||
case STATE_FMCAL20K:
|
||||
DEBUG1("Mode set to FM 20Khz Calibrate");
|
||||
break;
|
||||
case STATE_FMCAL25K:
|
||||
DEBUG1("Mode set to FM 10Khz Calibrate");
|
||||
break;
|
||||
case STATE_FMCAL30K:
|
||||
DEBUG1("Mode set to FM 30Khz Calibrate");
|
||||
break;
|
||||
case STATE_P25CAL1K:
|
||||
DEBUG1("Mode set to P25 1011 Hz Calibrate");
|
||||
@@ -451,6 +551,9 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
||||
if (modemState != STATE_NXDN)
|
||||
nxdnRX.reset();
|
||||
|
||||
if (modemState != STATE_FM)
|
||||
fm.reset();
|
||||
|
||||
cwIdTX.reset();
|
||||
|
||||
m_modemState = modemState;
|
||||
@@ -524,11 +627,43 @@ void CSerialPort::process()
|
||||
sendACK();
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS1:
|
||||
err = setFMParams1(m_buffer + 3U, m_len - 3U);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 1", err);
|
||||
sendNAK(err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS2:
|
||||
err = setFMParams2(m_buffer + 3U, m_len - 3U);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 2", err);
|
||||
sendNAK(err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS3:
|
||||
err = setFMParams3(m_buffer + 3U, m_len - 3U);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 3", err);
|
||||
sendNAK(err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_CAL_DATA:
|
||||
if (m_modemState == STATE_DSTARCAL)
|
||||
err = calDStarTX.write(m_buffer + 3U, m_len - 3U);
|
||||
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||
err = calDMR.write(m_buffer + 3U, m_len - 3U);
|
||||
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
|
||||
err = calFM.write(m_buffer + 3U, m_len - 3U);
|
||||
if (m_modemState == STATE_P25CAL1K)
|
||||
err = calP25.write(m_buffer + 3U, m_len - 3U);
|
||||
if (m_modemState == STATE_NXDNCAL1K)
|
||||
|
||||
Reference in New Issue
Block a user