mirror of
https://github.com/g4klx/MMDVM_HS.git
synced 2026-01-10 02:30:08 +01:00
Add NXDN, first commit
This commit is contained in:
parent
84d3258a5d
commit
3788ad540f
|
|
@ -33,6 +33,7 @@ enum MMDVM_STATE {
|
|||
STATE_DMR = 2,
|
||||
STATE_YSF = 3,
|
||||
STATE_P25 = 4,
|
||||
STATE_NXDN = 5,
|
||||
|
||||
// Dummy states start at 90
|
||||
STATE_CWID = 97
|
||||
|
|
@ -62,6 +63,8 @@ const uint8_t MARK_NONE = 0x00U;
|
|||
#include "YSFTX.h"
|
||||
#include "P25RX.h"
|
||||
#include "P25TX.h"
|
||||
#include "NXDNRX.h"
|
||||
#include "NXDNTX.h"
|
||||
#include "CWIdTX.h"
|
||||
#include "Debug.h"
|
||||
#include "Utils.h"
|
||||
|
|
@ -81,6 +84,7 @@ extern bool m_dstarEnable;
|
|||
extern bool m_dmrEnable;
|
||||
extern bool m_ysfEnable;
|
||||
extern bool m_p25Enable;
|
||||
extern bool m_nxdnEnable;
|
||||
|
||||
extern bool m_duplex;
|
||||
|
||||
|
|
@ -110,6 +114,9 @@ extern CYSFTX ysfTX;
|
|||
extern CP25RX p25RX;
|
||||
extern CP25TX p25TX;
|
||||
|
||||
extern CNXDNRX nxdnRX;
|
||||
extern CNXDNTX nxdnTX;
|
||||
|
||||
extern CCWIdTX cwIdTX;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ bool m_dstarEnable = true;
|
|||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
|
||||
bool m_duplex = false;
|
||||
|
||||
|
|
@ -64,6 +65,9 @@ CYSFTX ysfTX;
|
|||
CP25RX p25RX;
|
||||
CP25TX p25TX;
|
||||
|
||||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CCWIdTX cwIdTX;
|
||||
|
||||
CSerialPort serial;
|
||||
|
|
@ -101,6 +105,9 @@ void loop()
|
|||
if (m_p25Enable && m_modemState == STATE_P25)
|
||||
p25TX.process();
|
||||
|
||||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
|
||||
if (m_modemState == STATE_IDLE)
|
||||
cwIdTX.process();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ bool m_dstarEnable = true;
|
|||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
|
||||
bool m_duplex = false;
|
||||
|
||||
|
|
@ -60,6 +61,9 @@ CYSFTX ysfTX;
|
|||
CP25RX p25RX;
|
||||
CP25TX p25TX;
|
||||
|
||||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CCWIdTX cwIdTX;
|
||||
|
||||
CSerialPort serial;
|
||||
|
|
@ -96,6 +100,9 @@ void loop()
|
|||
if (m_p25Enable && m_modemState == STATE_P25)
|
||||
p25TX.process();
|
||||
|
||||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
|
||||
if (m_modemState == STATE_IDLE)
|
||||
cwIdTX.process();
|
||||
}
|
||||
|
|
|
|||
50
NXDNDefines.h
Normal file
50
NXDNDefines.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNDEFINES_H)
|
||||
#define NXDNDEFINES_H
|
||||
|
||||
const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 10U; // At 24 kHz sample rate
|
||||
|
||||
const unsigned int NXDN_FRAME_LENGTH_BITS = 384U;
|
||||
const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
|
||||
const unsigned int NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
|
||||
const unsigned int NXDN_FRAME_LENGTH_SAMPLES = NXDN_FRAME_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const unsigned int NXDN_FSW_LENGTH_BITS = 20U;
|
||||
const unsigned int NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
|
||||
const unsigned int NXDN_FSW_LENGTH_SAMPLES = NXDN_FSW_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U};
|
||||
const uint8_t NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U};
|
||||
const uint8_t NXDN_FSW_BYTES_LENGTH = 3U;
|
||||
|
||||
const uint32_t NXDN_FSW_BITS = 0x000CDF59U;
|
||||
const uint32_t NXDN_FSW_BITS_MASK = 0x000FFFFFU;
|
||||
|
||||
// C D F 5 9
|
||||
// 11 00 11 01 11 11 01 01 10 01
|
||||
// -3 +1 -3 +3 -3 -3 +3 +3 -1 +3
|
||||
|
||||
const int8_t NXDN_FSW_SYMBOLS_VALUES[] = {-3, +1, -3, +3, -3, -3, +3, +3, -1, +3};
|
||||
|
||||
const uint16_t NXDN_FSW_SYMBOLS = 0x014DU;
|
||||
const uint16_t NXDN_FSW_SYMBOLS_MASK = 0x03FFU;
|
||||
|
||||
#endif
|
||||
|
||||
139
NXDNRX.cpp
Normal file
139
NXDNRX.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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"
|
||||
#include "NXDNRX.h"
|
||||
#include "Utils.h"
|
||||
|
||||
const uint8_t MAX_FSW_BIT_START_ERRS = 1U;
|
||||
const uint8_t MAX_FSW_BIT_RUN_ERRS = 3U;
|
||||
|
||||
const unsigned int MAX_FSW_FRAMES = 5U + 1U;
|
||||
|
||||
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNRX::CNXDNRX() :
|
||||
m_prev(false),
|
||||
m_state(NXDNRXS_NONE),
|
||||
m_bitBuffer(0x00U),
|
||||
m_outBuffer(),
|
||||
m_buffer(NULL),
|
||||
m_bufferPtr(0U),
|
||||
m_lostCount(0U)
|
||||
{
|
||||
m_buffer = m_outBuffer + 1U;
|
||||
}
|
||||
|
||||
void CNXDNRX::reset()
|
||||
{
|
||||
m_prev = false;
|
||||
m_state = NXDNRXS_NONE;
|
||||
m_bitBuffer = 0x00U;
|
||||
m_bufferPtr = 0U;
|
||||
m_lostCount = 0U;
|
||||
}
|
||||
|
||||
void CNXDNRX::databit(bool bit)
|
||||
{
|
||||
if (m_state == NXDNRXS_NONE)
|
||||
processNone(bit);
|
||||
else
|
||||
processData(bit);
|
||||
}
|
||||
|
||||
void CNXDNRX::processNone(bool bit)
|
||||
{
|
||||
m_bitBuffer <<= 1;
|
||||
if (bit)
|
||||
m_bitBuffer |= 0x01U;
|
||||
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
if (countBits64((m_bitBuffer & NXDN_FSW_BITS_MASK) ^ NXDN_FSW_BITS) <= MAX_FSW_BIT_START_ERRS) {
|
||||
DEBUG1("NXDNRX: sync found in None");
|
||||
for (uint8_t i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++)
|
||||
m_buffer[i] = NXDN_FSW_BYTES[i];
|
||||
|
||||
m_lostCount = MAX_FSW_FRAMES;
|
||||
m_bufferPtr = NXDN_FSW_LENGTH_BITS;
|
||||
m_state = NXDNRXS_DATA;
|
||||
|
||||
io.setDecode(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CNXDNRX::processData(bool bit)
|
||||
{
|
||||
m_bitBuffer <<= 1;
|
||||
if (bit)
|
||||
m_bitBuffer |= 0x01U;
|
||||
|
||||
WRITE_BIT1(m_buffer, m_bufferPtr, bit);
|
||||
m_bufferPtr++;
|
||||
|
||||
// Only search for a sync in the right place +-2 symbols
|
||||
if (m_bufferPtr >= (NXDN_FSW_LENGTH_BITS - 2U) && m_bufferPtr <= (NXDN_FSW_LENGTH_BITS + 2U)) {
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
if (countBits64((m_bitBuffer & NXDN_FSW_BITS_MASK) ^ NXDN_FSW_BITS) <= MAX_FSW_BIT_RUN_ERRS) {
|
||||
DEBUG2("NXDNRX: found sync in Data, pos", m_bufferPtr - NXDN_FSW_LENGTH_BITS);
|
||||
m_lostCount = MAX_FSW_FRAMES;
|
||||
m_bufferPtr = NXDN_FSW_LENGTH_BITS;
|
||||
}
|
||||
}
|
||||
|
||||
// Send a data frame to the host if the required number of bits have been received
|
||||
if (m_bufferPtr == NXDN_FRAME_LENGTH_BITS) {
|
||||
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||
m_lostCount--;
|
||||
if (m_lostCount == 0U) {
|
||||
DEBUG1("NXDNRX: sync timed out, lost lock");
|
||||
io.setDecode(false);
|
||||
|
||||
serial.writeNXDNLost();
|
||||
|
||||
m_state = NXDNRXS_NONE;
|
||||
} else {
|
||||
m_outBuffer[0U] = m_lostCount == (MAX_FSW_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
|
||||
writeRSSIData(m_outBuffer);
|
||||
|
||||
// Start the next frame
|
||||
::memset(m_outBuffer, 0x00U, NXDN_FRAME_LENGTH_BYTES + 3U);
|
||||
m_bufferPtr = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNRX::writeRSSIData(uint8_t* data)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
uint16_t rssi = io.readRSSI();
|
||||
|
||||
data[49U] = (rssi >> 8) & 0xFFU;
|
||||
data[50U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 3U);
|
||||
#else
|
||||
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
54
NXDNRX.h
Normal file
54
NXDNRX.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNRX_H)
|
||||
#define NXDNRX_H
|
||||
|
||||
#include "NXDNDefines.h"
|
||||
|
||||
enum NXDNRX_STATE {
|
||||
NXDNRXS_NONE,
|
||||
NXDNRXS_DATA
|
||||
};
|
||||
|
||||
class CNXDNRX {
|
||||
public:
|
||||
CNXDNRX();
|
||||
|
||||
void databit(bool bit);
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
bool m_prev;
|
||||
NXDNRX_STATE m_state;
|
||||
uint64_t m_bitBuffer;
|
||||
uint8_t m_outBuffer[NXDN_FRAME_LENGTH_BYTES + 3U];
|
||||
uint8_t* m_buffer;
|
||||
uint16_t m_bufferPtr;
|
||||
uint16_t m_lostCount;
|
||||
|
||||
void processNone(bool bit);
|
||||
void processData(bool bit);
|
||||
void writeRSSIData(uint8_t* data);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
120
NXDNTX.cpp
Normal file
120
NXDNTX.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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"
|
||||
#include "NXDNTX.h"
|
||||
|
||||
#include "NXDNDefines.h"
|
||||
|
||||
const uint8_t NXDN_PREAMBLE[] = {0x57U, 0x75U, 0xFDU};
|
||||
const uint8_t NXDN_SYNC = 0x5FU;
|
||||
|
||||
CNXDNTX::CNXDNTX() :
|
||||
m_buffer(1500U),
|
||||
m_poBuffer(),
|
||||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(240U), // 200ms
|
||||
m_count(0U)
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNTX::process()
|
||||
{
|
||||
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||
return;
|
||||
|
||||
if (m_poLen == 0U) {
|
||||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_count = 0U;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
m_delay = false;
|
||||
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||
}
|
||||
|
||||
m_poPtr = 0U;
|
||||
}
|
||||
|
||||
if (m_poLen > 0U) {
|
||||
uint16_t space = io.getSpace();
|
||||
|
||||
while (space > 8U) {
|
||||
if (m_delay) {
|
||||
m_poPtr++;
|
||||
writeByte(NXDN_SYNC);
|
||||
}
|
||||
else
|
||||
writeByte(m_poBuffer[m_poPtr++]);
|
||||
|
||||
space -= 8U;
|
||||
|
||||
if (m_poPtr >= m_poLen) {
|
||||
m_poPtr = 0U;
|
||||
m_poLen = 0U;
|
||||
m_delay = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
|
||||
uint16_t space = m_buffer.getSpace();
|
||||
if (space < NXDN_FRAME_LENGTH_BYTES)
|
||||
return 5U;
|
||||
|
||||
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++)
|
||||
m_buffer.put(data[i + 1U]);
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void CNXDNTX::writeByte(uint8_t c)
|
||||
{
|
||||
uint8_t bit;
|
||||
uint8_t mask = 0x80U;
|
||||
|
||||
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
|
||||
if ((c & mask) == mask)
|
||||
bit = 1U;
|
||||
else
|
||||
bit = 0U;
|
||||
|
||||
io.write(&bit, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNTX::setTXDelay(uint8_t delay)
|
||||
{
|
||||
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
|
||||
}
|
||||
|
||||
uint16_t CNXDNTX::getSpace() const
|
||||
{
|
||||
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
|
||||
}
|
||||
|
||||
50
NXDNTX.h
Normal file
50
NXDNTX.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(NXDNTX_H)
|
||||
#define NXDNTX_H
|
||||
|
||||
#include "SerialRB.h"
|
||||
|
||||
class CNXDNTX {
|
||||
public:
|
||||
CNXDNTX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
|
||||
void process();
|
||||
|
||||
void setTXDelay(uint8_t delay);
|
||||
|
||||
uint16_t getSpace() const;
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
uint8_t m_poBuffer[60U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
|
||||
void writeByte(uint8_t c);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2013,2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2013,2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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
|
||||
|
|
@ -55,6 +55,9 @@ const uint8_t MMDVM_P25_HDR = 0x30U;
|
|||
const uint8_t MMDVM_P25_LDU = 0x31U;
|
||||
const uint8_t MMDVM_P25_LOST = 0x32U;
|
||||
|
||||
const uint8_t MMDVM_NXDN_DATA = 0x40U;
|
||||
const uint8_t MMDVM_NXDN_LOST = 0x41U;
|
||||
|
||||
const uint8_t MMDVM_ACK = 0x70U;
|
||||
const uint8_t MMDVM_NAK = 0x7FU;
|
||||
|
||||
|
|
@ -201,6 +204,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
|
||||
uint8_t txDelay = data[2U];
|
||||
if (txDelay > 50U)
|
||||
|
|
@ -208,7 +212,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)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !dstarEnable)
|
||||
return 4U;
|
||||
|
|
@ -218,6 +222,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
return 4U;
|
||||
if (modemState == STATE_P25 && !p25Enable)
|
||||
return 4U;
|
||||
if (modemState == STATE_NXDN && !nxdnEnable)
|
||||
return 4U;
|
||||
|
||||
uint8_t colorCode = data[6U];
|
||||
if (colorCode > 15U)
|
||||
|
|
@ -279,7 +285,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)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
||||
return 4U;
|
||||
|
|
@ -289,7 +295,9 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||
return 4U;
|
||||
if (modemState == STATE_P25 && !m_p25Enable)
|
||||
return 4U;
|
||||
|
||||
if (modemState == STATE_NXDN && !m_nxdnEnable)
|
||||
return 4U;
|
||||
|
||||
setMode(modemState);
|
||||
|
||||
return 0U;
|
||||
|
|
@ -367,6 +375,18 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||
ysfRX.reset();
|
||||
cwIdTX.reset();
|
||||
break;
|
||||
case STATE_NXDN:
|
||||
DEBUG1("Mode set to NXDN");
|
||||
#if defined(DUPLEX)
|
||||
dmrIdleRX.reset();
|
||||
dmrRX.reset();
|
||||
#endif
|
||||
dmrDMORX.reset();
|
||||
dstarRX.reset();
|
||||
ysfRX.reset();
|
||||
p25RX.reset();
|
||||
cwIdTX.reset();
|
||||
break;
|
||||
default:
|
||||
DEBUG1("Mode set to Idle");
|
||||
// STATE_IDLE
|
||||
|
|
@ -639,6 +659,20 @@ void CSerialPort::process()
|
|||
}
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
#if defined(SERIAL_REPEATER) || defined(SERIAL_REPEATER_USART1)
|
||||
case MMDVM_SERIAL:
|
||||
writeInt(3U, m_buffer + 3U, m_len - 3U);
|
||||
|
|
@ -891,6 +925,46 @@ void CSerialPort::writeP25Lost()
|
|||
writeInt(1U, reply, 3);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CSerialPort::writeDebug(const char* text)
|
||||
{
|
||||
if (!m_debug)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* 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
|
||||
|
|
@ -44,6 +45,9 @@ public:
|
|||
void writeP25Ldu(const uint8_t* data, uint8_t length);
|
||||
void writeP25Lost();
|
||||
|
||||
void writeNXDNData(const uint8_t* data, uint8_t length);
|
||||
void writeNXDNLost();
|
||||
|
||||
void writeDebug(const char* text);
|
||||
void writeDebug(const char* text, int16_t n1);
|
||||
void writeDebugI(const char* text, int32_t n1);
|
||||
|
|
|
|||
Loading…
Reference in a new issue