MMDVM/SerialPort.cpp

1239 lines
29 KiB
C++
Raw Normal View History

2016-01-14 19:57:21 +01:00
/*
2018-01-10 21:30:35 +01:00
* Copyright (C) 2013,2015,2016,2017,2018 by Jonathan Naylor G4KLX
2016-04-14 18:42:38 +02:00
* Copyright (C) 2016 by Colin Durbridge G4EML
2016-01-14 19:57:21 +01:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
2017-04-12 21:57:32 +02:00
#if defined(MADEBYMAKEFILE)
2017-04-12 11:51:28 +02:00
#include "GitVersion.h"
#endif
2016-01-14 19:57:21 +01:00
#include "SerialPort.h"
const uint8_t MMDVM_FRAME_START = 0xE0U;
const uint8_t MMDVM_GET_VERSION = 0x00U;
const uint8_t MMDVM_GET_STATUS = 0x01U;
const uint8_t MMDVM_SET_CONFIG = 0x02U;
const uint8_t MMDVM_SET_MODE = 0x03U;
const uint8_t MMDVM_SET_FREQ = 0x04U;
2016-01-14 19:57:21 +01:00
const uint8_t MMDVM_CAL_DATA = 0x08U;
2016-12-28 19:07:31 +01:00
const uint8_t MMDVM_RSSI_DATA = 0x09U;
2016-01-14 19:57:21 +01:00
2016-05-09 22:57:14 +02:00
const uint8_t MMDVM_SEND_CWID = 0x0AU;
2016-01-14 19:57:21 +01:00
const uint8_t MMDVM_DSTAR_HEADER = 0x10U;
const uint8_t MMDVM_DSTAR_DATA = 0x11U;
const uint8_t MMDVM_DSTAR_LOST = 0x12U;
const uint8_t MMDVM_DSTAR_EOT = 0x13U;
const uint8_t MMDVM_DMR_DATA1 = 0x18U;
const uint8_t MMDVM_DMR_LOST1 = 0x19U;
const uint8_t MMDVM_DMR_DATA2 = 0x1AU;
const uint8_t MMDVM_DMR_LOST2 = 0x1BU;
const uint8_t MMDVM_DMR_SHORTLC = 0x1CU;
const uint8_t MMDVM_DMR_START = 0x1DU;
2016-06-17 08:47:11 +02:00
const uint8_t MMDVM_DMR_ABORT = 0x1EU;
2016-01-14 19:57:21 +01:00
const uint8_t MMDVM_YSF_DATA = 0x20U;
const uint8_t MMDVM_YSF_LOST = 0x21U;
2016-09-06 20:11:16 +02:00
const uint8_t MMDVM_P25_HDR = 0x30U;
const uint8_t MMDVM_P25_LDU = 0x31U;
const uint8_t MMDVM_P25_LOST = 0x32U;
2018-01-10 21:30:35 +01:00
const uint8_t MMDVM_NXDN_DATA = 0x40U;
const uint8_t MMDVM_NXDN_LOST = 0x41U;
2016-01-14 19:57:21 +01:00
const uint8_t MMDVM_ACK = 0x70U;
const uint8_t MMDVM_NAK = 0x7FU;
const uint8_t MMDVM_SERIAL = 0x80U;
2018-03-21 23:01:35 +01:00
const uint8_t MMDVM_TRANSPARENT = 0x90U;
2016-01-14 19:57:21 +01:00
const uint8_t MMDVM_DEBUG1 = 0xF1U;
const uint8_t MMDVM_DEBUG2 = 0xF2U;
const uint8_t MMDVM_DEBUG3 = 0xF3U;
const uint8_t MMDVM_DEBUG4 = 0xF4U;
const uint8_t MMDVM_DEBUG5 = 0xF5U;
2018-03-27 22:35:38 +02:00
#define DESCRIPTION "MMDVM 20180327 (D-Star/DMR/System Fusion/P25/NXDN)"
2017-04-12 11:51:28 +02:00
#if defined(GITVERSION)
2017-04-13 09:35:21 +02:00
#define concat(a, b) a " GitID #" b ""
2017-04-12 11:51:28 +02:00
const char HARDWARE[] = concat(DESCRIPTION, GITVERSION);
#else
#define concat(a, b, c) a " (Build: " b " " c ")"
const char HARDWARE[] = concat(DESCRIPTION, __TIME__, __DATE__);
2017-04-12 11:51:28 +02:00
#endif
2016-01-14 19:57:21 +01:00
const uint8_t PROTOCOL_VERSION = 1U;
CSerialPort::CSerialPort() :
m_buffer(),
m_ptr(0U),
m_len(0U),
m_debug(false),
m_repeat()
2016-01-14 19:57:21 +01:00
{
}
2016-03-03 20:02:19 +01:00
void CSerialPort::sendACK()
2016-01-14 19:57:21 +01:00
{
uint8_t reply[4U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 4U;
reply[2U] = MMDVM_ACK;
reply[3U] = m_buffer[2U];
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 4);
2016-01-14 19:57:21 +01:00
}
2016-03-03 20:02:19 +01:00
void CSerialPort::sendNAK(uint8_t err)
2016-01-14 19:57:21 +01:00
{
uint8_t reply[5U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 5U;
reply[2U] = MMDVM_NAK;
reply[3U] = m_buffer[2U];
reply[4U] = err;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 5);
2016-01-14 19:57:21 +01:00
}
2016-03-03 20:02:19 +01:00
void CSerialPort::getStatus()
2016-01-14 19:57:21 +01:00
{
2016-02-02 21:23:37 +01:00
io.resetWatchdog();
2016-09-06 20:11:16 +02:00
uint8_t reply[15U];
2016-01-14 19:57:21 +01:00
// Send all sorts of interesting internal values
reply[0U] = MMDVM_FRAME_START;
2016-11-17 17:02:53 +01:00
reply[1U] = 11U;
2016-01-14 19:57:21 +01:00
reply[2U] = MMDVM_GET_STATUS;
reply[3U] = 0x00U;
if (m_dstarEnable)
reply[3U] |= 0x01U;
if (m_dmrEnable)
reply[3U] |= 0x02U;
if (m_ysfEnable)
reply[3U] |= 0x04U;
2016-09-06 20:11:16 +02:00
if (m_p25Enable)
reply[3U] |= 0x08U;
2018-01-10 21:30:35 +01:00
if (m_nxdnEnable)
reply[3U] |= 0x10U;
2016-01-14 19:57:21 +01:00
reply[4U] = uint8_t(m_modemState);
2016-11-17 17:02:53 +01:00
reply[5U] = m_tx ? 0x01U : 0x00U;
2016-01-14 19:57:21 +01:00
2016-06-09 20:50:34 +02:00
bool adcOverflow;
bool dacOverflow;
io.getOverflow(adcOverflow, dacOverflow);
if (adcOverflow)
2016-01-14 19:57:21 +01:00
reply[5U] |= 0x02U;
if (io.hasRXOverflow())
reply[5U] |= 0x04U;
if (io.hasTXOverflow())
reply[5U] |= 0x08U;
if (io.hasLockout())
reply[5U] |= 0x10U;
2016-06-09 20:50:34 +02:00
if (dacOverflow)
reply[5U] |= 0x20U;
2016-11-19 14:54:28 +01:00
reply[5U] |= m_dcd ? 0x40U : 0x00U;
2016-06-09 20:50:34 +02:00
2016-01-14 19:57:21 +01:00
if (m_dstarEnable)
reply[6U] = dstarTX.getSpace();
else
reply[6U] = 0U;
if (m_dmrEnable) {
if (m_duplex) {
reply[7U] = dmrTX.getSpace1();
reply[8U] = dmrTX.getSpace2();
} else {
reply[7U] = 10U;
reply[8U] = dmrDMOTX.getSpace();
}
2016-01-14 19:57:21 +01:00
} else {
reply[7U] = 0U;
reply[8U] = 0U;
}
if (m_ysfEnable)
reply[9U] = ysfTX.getSpace();
else
reply[9U] = 0U;
2016-09-08 18:53:59 +02:00
if (m_p25Enable)
reply[10U] = p25TX.getSpace();
else
reply[10U] = 0U;
2016-09-06 20:11:16 +02:00
2018-01-10 21:30:35 +01:00
if (m_nxdnEnable)
reply[11U] = nxdnTX.getSpace();
else
reply[11U] = 0U;
writeInt(1U, reply, 12);
2016-01-14 19:57:21 +01:00
}
2016-03-03 20:02:19 +01:00
void CSerialPort::getVersion()
2016-01-14 19:57:21 +01:00
{
uint8_t reply[100U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_GET_VERSION;
reply[3U] = PROTOCOL_VERSION;
uint8_t count = 4U;
for (uint8_t i = 0U; HARDWARE[i] != 0x00U; i++, count++)
reply[count] = HARDWARE[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
{
2018-01-10 21:30:35 +01:00
if (length < 16U)
2016-01-14 19:57:21 +01:00
return 4U;
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
bool txInvert = (data[0U] & 0x02U) == 0x02U;
bool pttInvert = (data[0U] & 0x04U) == 0x04U;
2017-03-23 21:27:23 +01:00
bool ysfLoDev = (data[0U] & 0x08U) == 0x08U;
bool simplex = (data[0U] & 0x80U) == 0x80U;
2016-01-14 19:57:21 +01:00
m_debug = (data[0U] & 0x10U) == 0x10U;
2016-01-14 19:57:21 +01:00
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
2016-09-06 20:11:16 +02:00
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
2018-01-10 21:30:35 +01:00
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
2016-01-14 19:57:21 +01:00
uint8_t txDelay = data[2U];
if (txDelay > 50U)
return 4U;
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
2018-02-12 14:34:49 +01:00
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K)
2016-01-14 19:57:21 +01:00
return 4U;
if (modemState == STATE_DSTAR && !dstarEnable)
return 4U;
if (modemState == STATE_DMR && !dmrEnable)
return 4U;
if (modemState == STATE_YSF && !ysfEnable)
return 4U;
2016-09-06 20:11:16 +02:00
if (modemState == STATE_P25 && !p25Enable)
return 4U;
2018-01-10 21:30:35 +01:00
if (modemState == STATE_NXDN && !nxdnEnable)
return 4U;
2016-01-14 19:57:21 +01:00
uint8_t rxLevel = data[4U];
uint8_t colorCode = data[6U];
if (colorCode > 15U)
return 4U;
uint8_t dmrDelay = data[7U];
2016-10-10 18:35:33 +02:00
uint8_t cwIdTXLevel = data[5U];
2016-08-09 08:11:10 +02:00
uint8_t dstarTXLevel = data[9U];
uint8_t dmrTXLevel = data[10U];
uint8_t ysfTXLevel = data[11U];
2016-09-08 18:53:59 +02:00
uint8_t p25TXLevel = data[12U];
2016-08-09 08:11:10 +02:00
2017-08-20 13:07:05 +02:00
int16_t txDCOffset = int16_t(data[13U]) - 128;
2017-10-28 13:45:04 +02:00
int16_t rxDCOffset = int16_t(data[14U]) - 128;
2017-08-20 13:07:05 +02:00
2018-01-10 21:30:35 +01:00
uint8_t nxdnTXLevel = data[15U];
2016-01-14 19:57:21 +01:00
m_modemState = modemState;
m_dstarEnable = dstarEnable;
m_dmrEnable = dmrEnable;
m_ysfEnable = ysfEnable;
2016-09-06 20:11:16 +02:00
m_p25Enable = p25Enable;
2018-01-10 21:30:35 +01:00
m_nxdnEnable = nxdnEnable;
m_duplex = !simplex;
2016-01-14 19:57:21 +01:00
dstarTX.setTXDelay(txDelay);
ysfTX.setTXDelay(txDelay);
2016-09-08 18:53:59 +02:00
p25TX.setTXDelay(txDelay);
dmrDMOTX.setTXDelay(txDelay);
2018-01-10 21:30:35 +01:00
nxdnTX.setTXDelay(txDelay);
2016-01-14 19:57:21 +01:00
dmrTX.setColorCode(colorCode);
dmrRX.setColorCode(colorCode);
dmrRX.setDelay(dmrDelay);
dmrDMORX.setColorCode(colorCode);
2016-01-14 19:57:21 +01:00
dmrIdleRX.setColorCode(colorCode);
2017-03-23 21:27:23 +01:00
ysfTX.setLoDev(ysfLoDev);
2018-01-10 21:30:35 +01:00
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, txDCOffset, rxDCOffset);
2016-01-14 19:57:21 +01:00
io.start();
return 0U;
}
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
{
if (length < 1U)
return 4U;
MMDVM_STATE modemState = MMDVM_STATE(data[0U]);
if (modemState == m_modemState)
return 0U;
2018-02-12 14:34:49 +01:00
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K)
2016-01-14 19:57:21 +01:00
return 4U;
if (modemState == STATE_DSTAR && !m_dstarEnable)
return 4U;
if (modemState == STATE_DMR && !m_dmrEnable)
return 4U;
if (modemState == STATE_YSF && !m_ysfEnable)
return 4U;
2016-09-06 20:11:16 +02:00
if (modemState == STATE_P25 && !m_p25Enable)
return 4U;
2018-01-10 21:30:35 +01:00
if (modemState == STATE_NXDN && !m_nxdnEnable)
return 4U;
2016-01-14 19:57:21 +01:00
setMode(modemState);
return 0U;
}
void CSerialPort::setMode(MMDVM_STATE modemState)
{
switch (modemState) {
case STATE_DMR:
2016-03-14 21:24:51 +01:00
DEBUG1("Mode set to DMR");
2016-01-14 19:57:21 +01:00
dstarRX.reset();
ysfRX.reset();
2016-09-08 18:53:59 +02:00
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-05-10 07:35:53 +02:00
cwIdTX.reset();
2016-01-14 19:57:21 +01:00
break;
case STATE_DSTAR:
2016-03-14 21:24:51 +01:00
DEBUG1("Mode set to D-Star");
2016-01-14 19:57:21 +01:00
dmrIdleRX.reset();
dmrDMORX.reset();
2016-01-14 19:57:21 +01:00
dmrRX.reset();
ysfRX.reset();
2016-09-08 18:53:59 +02:00
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-05-10 07:35:53 +02:00
cwIdTX.reset();
2016-01-14 19:57:21 +01:00
break;
case STATE_YSF:
2016-03-14 21:24:51 +01:00
DEBUG1("Mode set to System Fusion");
2016-01-14 19:57:21 +01:00
dmrIdleRX.reset();
dmrDMORX.reset();
2016-01-14 19:57:21 +01:00
dmrRX.reset();
dstarRX.reset();
2016-09-08 18:53:59 +02:00
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-05-10 07:35:53 +02:00
cwIdTX.reset();
2016-01-14 19:57:21 +01:00
break;
2016-09-06 20:11:16 +02:00
case STATE_P25:
DEBUG1("Mode set to P25");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
cwIdTX.reset();
break;
case STATE_NXDN:
DEBUG1("Mode set to NXDN");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2016-09-06 20:11:16 +02:00
cwIdTX.reset();
break;
2016-04-14 18:42:38 +02:00
case STATE_DSTARCAL:
DEBUG1("Mode set to D-Star Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
2016-04-14 18:42:38 +02:00
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
2016-09-08 18:53:59 +02:00
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-05-10 07:35:53 +02:00
cwIdTX.reset();
2016-04-14 18:42:38 +02:00
break;
case STATE_DMRCAL:
DEBUG1("Mode set to DMR Calibrate");
2016-01-14 19:57:21 +01:00
dmrIdleRX.reset();
dmrDMORX.reset();
2016-01-14 19:57:21 +01:00
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
2016-09-08 18:53:59 +02:00
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-05-10 07:35:53 +02:00
cwIdTX.reset();
2016-01-14 19:57:21 +01:00
break;
2016-12-28 19:07:31 +01:00
case STATE_RSSICAL:
DEBUG1("Mode set to RSSI Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2016-12-28 19:07:31 +01:00
cwIdTX.reset();
break;
case STATE_LFCAL:
DEBUG1("Mode set to 80 Hz Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
cwIdTX.reset();
break;
2018-01-07 04:24:58 +01:00
case STATE_DMRCAL1K:
DEBUG1("Mode set to DMR BS 1031 Hz Calibrate");
2018-01-03 04:55:14 +01:00
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2018-01-03 04:55:14 +01:00
cwIdTX.reset();
break;
2018-01-07 04:06:41 +01:00
case STATE_P25CAL1K:
DEBUG1("Mode set to P25 1011 Hz Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2018-01-10 21:30:35 +01:00
nxdnRX.reset();
2018-01-07 04:06:41 +01:00
cwIdTX.reset();
break;
case STATE_DMRDMO1K:
DEBUG1("Mode set to DMR MS 1031 Hz Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
2018-02-12 14:34:49 +01:00
nxdnRX.reset();
cwIdTX.reset();
break;
case STATE_NXDNCAL1K:
DEBUG1("Mode set to NXDN 1031 Hz Calibrate");
dmrIdleRX.reset();
dmrDMORX.reset();
dmrRX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
nxdnRX.reset();
cwIdTX.reset();
break;
2016-01-14 19:57:21 +01:00
default:
2016-03-14 21:24:51 +01:00
DEBUG1("Mode set to Idle");
2016-01-14 19:57:21 +01:00
// STATE_IDLE
break;
}
m_modemState = modemState;
io.setMode();
2016-01-14 19:57:21 +01:00
}
void CSerialPort::start()
{
2016-11-01 19:01:22 +01:00
beginInt(1U, 115200);
#if defined(SERIAL_REPEATER)
2016-11-01 19:01:22 +01:00
beginInt(3U, 9600);
#endif
2016-01-14 19:57:21 +01:00
}
void CSerialPort::process()
{
2016-11-01 19:01:22 +01:00
while (availableInt(1U)) {
uint8_t c = readInt(1U);
2016-01-14 19:57:21 +01:00
2016-11-04 07:45:12 +01:00
if (m_ptr == 0U) {
if (c == MMDVM_FRAME_START) {
// Handle the frame start correctly
m_buffer[0U] = c;
m_ptr = 1U;
m_len = 0U;
}
2017-08-20 16:19:58 +02:00
else {
m_ptr = 0U;
m_len = 0U;
}
2016-11-04 07:45:12 +01:00
} else if (m_ptr == 1U) {
// Handle the frame length
m_len = m_buffer[m_ptr] = c;
m_ptr = 2U;
} else {
2016-01-14 19:57:21 +01:00
// Any other bytes are added to the buffer
m_buffer[m_ptr] = c;
m_ptr++;
// The full packet has been received, process it
if (m_ptr == m_len) {
uint8_t err = 2U;
switch (m_buffer[2U]) {
case MMDVM_GET_STATUS:
getStatus();
break;
case MMDVM_GET_VERSION:
getVersion();
break;
case MMDVM_SET_CONFIG:
err = setConfig(m_buffer + 3U, m_len - 3U);
if (err == 0U)
sendACK();
else
sendNAK(err);
break;
case MMDVM_SET_MODE:
err = setMode(m_buffer + 3U, m_len - 3U);
if (err == 0U)
sendACK();
else
sendNAK(err);
break;
case MMDVM_SET_FREQ:
sendACK();
break;
2016-01-14 19:57:21 +01:00
case MMDVM_CAL_DATA:
2016-04-14 18:42:38 +02:00
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)
2016-04-14 18:42:38 +02:00
err = calDMR.write(m_buffer + 3U, m_len - 3U);
2018-01-07 04:06:41 +01:00
if (m_modemState == STATE_P25CAL1K)
err = calP25.write(m_buffer + 3U, m_len - 3U);
2018-02-12 14:34:49 +01:00
if (m_modemState == STATE_NXDNCAL1K)
err = calNXDN.write(m_buffer + 3U, m_len - 3U);
2016-01-14 19:57:21 +01:00
if (err == 0U) {
sendACK();
} else {
DEBUG2("Received invalid calibration data", err);
sendNAK(err);
}
break;
2016-05-09 22:57:14 +02:00
case MMDVM_SEND_CWID:
2016-05-12 19:03:12 +02:00
err = 5U;
2016-05-09 22:57:14 +02:00
if (m_modemState == STATE_IDLE)
err = cwIdTX.write(m_buffer + 3U, m_len - 3U);
if (err != 0U) {
DEBUG2("Invalid CW Id data", err);
sendNAK(err);
}
break;
2016-01-14 19:57:21 +01:00
case MMDVM_DSTAR_HEADER:
if (m_dstarEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
err = dstarTX.writeHeader(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_DSTAR);
} else {
DEBUG2("Received invalid D-Star header", err);
sendNAK(err);
}
break;
case MMDVM_DSTAR_DATA:
if (m_dstarEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
err = dstarTX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_DSTAR);
} else {
DEBUG2("Received invalid D-Star data", err);
sendNAK(err);
}
break;
case MMDVM_DSTAR_EOT:
if (m_dstarEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
err = dstarTX.writeEOT();
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_DSTAR);
} else {
DEBUG2("Received invalid D-Star EOT", err);
sendNAK(err);
}
break;
case MMDVM_DMR_DATA1:
if (m_dmrEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) {
if (m_duplex)
err = dmrTX.writeData1(m_buffer + 3U, m_len - 3U);
}
2016-01-14 19:57:21 +01:00
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_DMR);
} else {
DEBUG2("Received invalid DMR data", err);
sendNAK(err);
}
break;
case MMDVM_DMR_DATA2:
if (m_dmrEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) {
if (m_duplex)
err = dmrTX.writeData2(m_buffer + 3U, m_len - 3U);
else
err = dmrDMOTX.writeData(m_buffer + 3U, m_len - 3U);
}
2016-01-14 19:57:21 +01:00
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_DMR);
} else {
DEBUG2("Received invalid DMR data", err);
sendNAK(err);
}
break;
case MMDVM_DMR_START:
if (m_dmrEnable) {
err = 4U;
if (m_len == 4U) {
2016-03-31 12:29:30 +02:00
if (m_buffer[3U] == 0x01U && m_modemState == STATE_DMR) {
if (!m_tx)
dmrTX.setStart(true);
2016-01-14 19:57:21 +01:00
err = 0U;
2016-03-31 12:29:30 +02:00
} else if (m_buffer[3U] == 0x00U && m_modemState == STATE_DMR) {
if (m_tx)
dmrTX.setStart(false);
2016-01-14 19:57:21 +01:00
err = 0U;
}
}
}
if (err != 0U) {
DEBUG2("Received invalid DMR start", err);
sendNAK(err);
}
break;
case MMDVM_DMR_SHORTLC:
if (m_dmrEnable)
err = dmrTX.writeShortLC(m_buffer + 3U, m_len - 3U);
if (err != 0U) {
DEBUG2("Received invalid DMR Short LC", err);
sendNAK(err);
}
break;
2016-06-17 08:47:11 +02:00
case MMDVM_DMR_ABORT:
if (m_dmrEnable)
err = dmrTX.writeAbort(m_buffer + 3U, m_len - 3U);
if (err != 0U) {
DEBUG2("Received invalid DMR Abort", err);
sendNAK(err);
}
break;
2016-01-14 19:57:21 +01:00
case MMDVM_YSF_DATA:
if (m_ysfEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_YSF)
err = ysfTX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_YSF);
} else {
DEBUG2("Received invalid System Fusion data", err);
sendNAK(err);
}
break;
2016-09-08 18:53:59 +02:00
case MMDVM_P25_HDR:
if (m_p25Enable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_P25)
err = p25TX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_P25);
} else {
DEBUG2("Received invalid P25 header", err);
sendNAK(err);
}
break;
case MMDVM_P25_LDU:
if (m_p25Enable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_P25)
err = p25TX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_P25);
} else {
DEBUG2("Received invalid P25 LDU", err);
sendNAK(err);
}
break;
2018-01-10 21:30:35 +01:00
case MMDVM_NXDN_DATA:
if (m_nxdnEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_NXDN)
err = nxdnTX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_NXDN);
} else {
DEBUG2("Received invalid NXDN data", err);
sendNAK(err);
}
break;
2018-03-21 23:01:35 +01:00
case MMDVM_TRANSPARENT:
// Do nothing on the MMDVM.
break;
#if defined(SERIAL_REPEATER)
case MMDVM_SERIAL: {
2017-08-20 16:19:58 +02:00
for (uint8_t i = 3U; i < m_len; i++)
m_repeat.put(m_buffer[i]);
}
break;
#endif
2016-01-14 19:57:21 +01:00
default:
// Handle this, send a NAK back
sendNAK(1U);
break;
}
m_ptr = 0U;
m_len = 0U;
}
}
}
2017-08-20 16:19:58 +02:00
if (io.getWatchdog() >= 48000U) {
m_ptr = 0U;
m_len = 0U;
}
#if defined(SERIAL_REPEATER)
2017-08-20 16:19:58 +02:00
// Write any outgoing serial data
uint16_t space = m_repeat.getData();
if (space > 0U) {
int avail = availableForWriteInt(3U);
if (avail < space)
space = avail;
for (uint16_t i = 0U; i < space; i++) {
uint8_t c = m_repeat.get();
writeInt(3U, &c, 1U);
}
}
// Read any incoming serial data
while (availableInt(3U))
readInt(3U);
#endif
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDStarHeader(const uint8_t* header, uint8_t length)
{
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
return;
if (!m_dstarEnable)
return;
uint8_t reply[50U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DSTAR_HEADER;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = header[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDStarData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
return;
if (!m_dstarEnable)
return;
uint8_t reply[20U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DSTAR_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDStarLost()
{
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
return;
if (!m_dstarEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_DSTAR_LOST;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 3);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDStarEOT()
{
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
return;
if (!m_dstarEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_DSTAR_EOT;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 3);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDMRData(bool slot, const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_DMR && m_modemState != STATE_IDLE)
return;
if (!m_dmrEnable)
return;
uint8_t reply[40U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = slot ? MMDVM_DMR_DATA2 : MMDVM_DMR_DATA1;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDMRLost(bool slot)
{
if (m_modemState != STATE_DMR && m_modemState != STATE_IDLE)
return;
if (!m_dmrEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = slot ? MMDVM_DMR_LOST2 : MMDVM_DMR_LOST1;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 3);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeYSFData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_YSF && m_modemState != STATE_IDLE)
return;
if (!m_ysfEnable)
return;
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_YSF_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeYSFLost()
{
if (m_modemState != STATE_YSF && m_modemState != STATE_IDLE)
return;
if (!m_ysfEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_YSF_LOST;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 3);
2016-01-14 19:57:21 +01:00
}
2016-09-06 20:11:16 +02:00
void CSerialPort::writeP25Hdr(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
return;
if (!m_p25Enable)
return;
uint8_t reply[120U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_P25_HDR;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-09-06 20:11:16 +02:00
}
void CSerialPort::writeP25Ldu(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
return;
if (!m_p25Enable)
return;
uint8_t reply[250U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_P25_LDU;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-09-06 20:11:16 +02:00
}
void CSerialPort::writeP25Lost()
{
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
return;
if (!m_p25Enable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_P25_LOST;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, 3);
2016-09-06 20:11:16 +02:00
}
2018-01-10 21:30:35 +01:00
void CSerialPort::writeNXDNData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
return;
if (!m_nxdnEnable)
return;
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_NXDN_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
writeInt(1U, reply, count);
}
void CSerialPort::writeNXDNLost()
{
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
return;
if (!m_nxdnEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_NXDN_LOST;
writeInt(1U, reply, 3);
}
2016-01-14 19:57:21 +01:00
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
{
2016-04-14 18:42:38 +02:00
if (m_modemState != STATE_DSTARCAL)
2016-01-14 19:57:21 +01:00
return;
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_CAL_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-12-28 19:07:31 +01:00
writeInt(1U, reply, count);
}
void CSerialPort::writeRSSIData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_RSSICAL)
return;
uint8_t reply[30U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_RSSI_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDebug(const char* text)
{
if (!m_debug)
return;
2016-01-14 19:57:21 +01:00
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DEBUG1;
uint8_t count = 3U;
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
reply[count] = text[i];
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count, true);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDebug(const char* text, int16_t n1)
{
if (!m_debug)
return;
2016-01-14 19:57:21 +01:00
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DEBUG2;
uint8_t count = 3U;
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
reply[count] = text[i];
reply[count++] = (n1 >> 8) & 0xFF;
reply[count++] = (n1 >> 0) & 0xFF;
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count, true);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2)
{
if (!m_debug)
return;
2016-01-14 19:57:21 +01:00
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DEBUG3;
uint8_t count = 3U;
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
reply[count] = text[i];
reply[count++] = (n1 >> 8) & 0xFF;
reply[count++] = (n1 >> 0) & 0xFF;
reply[count++] = (n2 >> 8) & 0xFF;
reply[count++] = (n2 >> 0) & 0xFF;
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count, true);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3)
{
if (!m_debug)
return;
2016-01-14 19:57:21 +01:00
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DEBUG4;
uint8_t count = 3U;
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
reply[count] = text[i];
reply[count++] = (n1 >> 8) & 0xFF;
reply[count++] = (n1 >> 0) & 0xFF;
reply[count++] = (n2 >> 8) & 0xFF;
reply[count++] = (n2 >> 0) & 0xFF;
reply[count++] = (n3 >> 8) & 0xFF;
reply[count++] = (n3 >> 0) & 0xFF;
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count, true);
2016-01-14 19:57:21 +01:00
}
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4)
{
if (!m_debug)
return;
2016-01-14 19:57:21 +01:00
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_DEBUG5;
uint8_t count = 3U;
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
reply[count] = text[i];
reply[count++] = (n1 >> 8) & 0xFF;
reply[count++] = (n1 >> 0) & 0xFF;
reply[count++] = (n2 >> 8) & 0xFF;
reply[count++] = (n2 >> 0) & 0xFF;
reply[count++] = (n3 >> 8) & 0xFF;
reply[count++] = (n3 >> 0) & 0xFF;
reply[count++] = (n4 >> 8) & 0xFF;
reply[count++] = (n4 >> 0) & 0xFF;
reply[1U] = count;
2016-11-01 19:01:22 +01:00
writeInt(1U, reply, count, true);
2016-01-14 19:57:21 +01:00
}