From ff9712b36a1e5f0bb6f9a07728f763c24ec4814d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 16 Feb 2021 20:05:03 +0000 Subject: [PATCH 1/4] Refactored some class names. --- AX25Network.h | 6 +- Display.cpp | 8 +- MMDVMHost.cpp | 6 +- MMDVMHost.vcxproj | 8 +- MMDVMHost.vcxproj.filters | 24 +-- SerialModem.cpp => MMDVMModem.cpp | 176 ++++++++++----------- SerialModem.h => MMDVMModem.h | 12 +- Makefile | 10 +- Makefile.Pi | 10 +- Makefile.Pi.Adafruit | 10 +- Makefile.Pi.HD44780 | 10 +- Makefile.Pi.OLED | 10 +- Makefile.Pi.PCF8574 | 10 +- PseudoTTYController.cpp | 8 +- PseudoTTYController.h | 6 +- SerialController.cpp => UARTController.cpp | 40 ++--- SerialController.h => UARTController.h | 14 +- Version.h | 2 +- 18 files changed, 184 insertions(+), 186 deletions(-) rename SerialModem.cpp => MMDVMModem.cpp (91%) rename SerialModem.h => MMDVMModem.h (97%) rename SerialController.cpp => UARTController.cpp (89%) rename SerialController.h => UARTController.h (80%) diff --git a/AX25Network.h b/AX25Network.h index f46de15..c972ccb 100644 --- a/AX25Network.h +++ b/AX25Network.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 by Jonathan Naylor G4KLX + * Copyright (C) 2020,2021 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 @@ -20,7 +20,7 @@ #define AX25Network_H #if defined(_WIN32) || defined(_WIN64) -#include "SerialController.h" +#include "UARTController.h" #else #include "PseudoTTYController.h" #endif @@ -47,7 +47,7 @@ public: private: #if defined(_WIN32) || defined(_WIN64) - CSerialController m_serial; + CUARTController m_serial; #else CPseudoTTYController m_serial; #endif diff --git a/Display.cpp b/Display.cpp index 7d4b1a9..5170ea0 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2021 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 @@ -18,7 +18,7 @@ #include "Display.h" #include "Defines.h" -#include "SerialController.h" +#include "UARTController.h" #include "ModemSerialPort.h" #include "NullDisplay.h" #include "TFTSurenoo.h" @@ -556,7 +556,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem) if (port == "modem") serial = new IModemSerialPort(modem); else - serial = new CSerialController(port, 115200U); + serial = new CUARTController(port, 115200U); display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex()); } else if (type == "Nextion") { @@ -605,7 +605,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem) baudrate = 115200U; LogInfo(" Display baudrate: %u ", baudrate); - ISerialPort* serial = new CSerialController(port, baudrate); + ISerialPort* serial = new CUARTController(port, baudrate); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF); } } else if (type == "LCDproc") { diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d289353..7929f2d 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -22,8 +22,8 @@ #include "NXDNKenwoodNetwork.h" #include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" -#include "SerialController.h" -#include "SerialModem.h" +#include "UARTController.h" +#include "MMDVMModem.h" #include "NullModem.h" #include "Version.h" #include "StopWatch.h" @@ -1393,7 +1393,7 @@ bool CMMDVMHost::createModem() if (port == "NullModem") m_modem = new CNullModem; else - m_modem = new CSerialModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); + m_modem = new CMMDVMModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); m_modem->setSerialParams(protocol, address, speed); m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled); m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel); diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 95d241f..10ce89c 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -243,8 +243,8 @@ - - + + @@ -347,8 +347,8 @@ - - + + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index d110fc5..52c2b9f 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -74,9 +74,6 @@ Header Files - - Header Files - Header Files @@ -332,9 +329,6 @@ Header Files - - Header Files - Header Files @@ -344,6 +338,12 @@ Header Files + + Header Files + + + Header Files + @@ -397,9 +397,6 @@ Source Files - - Source Files - Source Files @@ -634,9 +631,6 @@ Source Files - - Source Files - Source Files @@ -646,5 +640,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/SerialModem.cpp b/MMDVMModem.cpp similarity index 91% rename from SerialModem.cpp rename to MMDVMModem.cpp index 721c736..e2fd3b9 100644 --- a/SerialModem.cpp +++ b/MMDVMModem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2011-2018,2020,2021 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 @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "SerialController.h" +#include "UARTController.h" #if defined(__linux__) #include "I2CController.h" #endif @@ -29,7 +29,7 @@ #include "POCSAGDefines.h" #include "M17Defines.h" #include "Thread.h" -#include "SerialModem.h" +#include "MMDVMModem.h" #include "NullModem.h" #include "Utils.h" #include "Log.h" @@ -114,7 +114,7 @@ const unsigned int MAX_RESPONSES = 30U; const unsigned int BUFFER_LENGTH = 2000U; -CSerialModem::CSerialModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : +CMMDVMModem::CMMDVMModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : m_port(port), m_protocolVersion(0U), m_dmrColorCode(0U), @@ -251,13 +251,13 @@ m_fmExtEnable(false) assert(!port.empty()); } -CSerialModem::~CSerialModem() +CMMDVMModem::~CMMDVMModem() { delete m_serial; delete[] m_buffer; } -void CSerialModem::setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) +void CMMDVMModem::setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) { // Create the serial controller instance according the protocol specified in conf. #if defined(__linux__) @@ -265,10 +265,10 @@ void CSerialModem::setSerialParams(const std::string& protocol, unsigned int add m_serial = new CI2CController(m_port, address); else #endif - m_serial = new CSerialController(m_port, speed, true); + m_serial = new CUARTController(m_port, speed, true); } -void CSerialModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) +void CMMDVMModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) { m_rxFrequency = rxFrequency + rxOffset; m_txFrequency = txFrequency + txOffset; @@ -278,7 +278,7 @@ void CSerialModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned m_pocsagFrequency = pocsagFrequency + txOffset; } -void CSerialModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) +void CMMDVMModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) { m_dstarEnabled = dstarEnabled; m_dmrEnabled = dmrEnabled; @@ -291,7 +291,7 @@ void CSerialModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEna m_ax25Enabled = ax25Enabled; } -void CSerialModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel) +void CMMDVMModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel) { m_rxLevel = rxLevel; m_cwIdTXLevel = cwIdTXLevel; @@ -306,35 +306,35 @@ void CSerialModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLeve m_ax25TXLevel = ax25TXLevel; } -void CSerialModem::setDMRParams(unsigned int colorCode) +void CMMDVMModem::setDMRParams(unsigned int colorCode) { assert(colorCode < 16U); m_dmrColorCode = colorCode; } -void CSerialModem::setYSFParams(bool loDev, unsigned int txHang) +void CMMDVMModem::setYSFParams(bool loDev, unsigned int txHang) { m_ysfLoDev = loDev; m_ysfTXHang = txHang; } -void CSerialModem::setP25Params(unsigned int txHang) +void CMMDVMModem::setP25Params(unsigned int txHang) { m_p25TXHang = txHang; } -void CSerialModem::setNXDNParams(unsigned int txHang) +void CMMDVMModem::setNXDNParams(unsigned int txHang) { m_nxdnTXHang = txHang; } -void CSerialModem::setM17Params(unsigned int txHang) +void CMMDVMModem::setM17Params(unsigned int txHang) { m_m17TXHang = txHang; } -void CSerialModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) +void CMMDVMModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) { m_ax25RXTwist = rxTwist; m_ax25TXDelay = txDelay; @@ -342,12 +342,12 @@ void CSerialModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int m_ax25PPersist = pPersist; } -void CSerialModem::setTransparentDataParams(unsigned int sendFrameType) +void CMMDVMModem::setTransparentDataParams(unsigned int sendFrameType) { m_sendTransparentDataFrameType = sendFrameType; } -bool CSerialModem::open() +bool CMMDVMModem::open() { ::LogMessage("Opening the MMDVM"); @@ -427,7 +427,7 @@ bool CSerialModem::open() return true; } -void CSerialModem::clock(unsigned int ms) +void CMMDVMModem::clock(unsigned int ms) { assert(m_serial != NULL); @@ -1124,7 +1124,7 @@ void CSerialModem::clock(unsigned int ms) } } -void CSerialModem::close() +void CMMDVMModem::close() { assert(m_serial != NULL); @@ -1133,7 +1133,7 @@ void CSerialModem::close() m_serial->close(); } -unsigned int CSerialModem::readDStarData(unsigned char* data) +unsigned int CMMDVMModem::readDStarData(unsigned char* data) { assert(data != NULL); @@ -1147,7 +1147,7 @@ unsigned int CSerialModem::readDStarData(unsigned char* data) return len; } -unsigned int CSerialModem::readDMRData1(unsigned char* data) +unsigned int CMMDVMModem::readDMRData1(unsigned char* data) { assert(data != NULL); @@ -1161,7 +1161,7 @@ unsigned int CSerialModem::readDMRData1(unsigned char* data) return len; } -unsigned int CSerialModem::readDMRData2(unsigned char* data) +unsigned int CMMDVMModem::readDMRData2(unsigned char* data) { assert(data != NULL); @@ -1175,7 +1175,7 @@ unsigned int CSerialModem::readDMRData2(unsigned char* data) return len; } -unsigned int CSerialModem::readYSFData(unsigned char* data) +unsigned int CMMDVMModem::readYSFData(unsigned char* data) { assert(data != NULL); @@ -1189,7 +1189,7 @@ unsigned int CSerialModem::readYSFData(unsigned char* data) return len; } -unsigned int CSerialModem::readP25Data(unsigned char* data) +unsigned int CMMDVMModem::readP25Data(unsigned char* data) { assert(data != NULL); @@ -1203,7 +1203,7 @@ unsigned int CSerialModem::readP25Data(unsigned char* data) return len; } -unsigned int CSerialModem::readNXDNData(unsigned char* data) +unsigned int CMMDVMModem::readNXDNData(unsigned char* data) { assert(data != NULL); @@ -1217,7 +1217,7 @@ unsigned int CSerialModem::readNXDNData(unsigned char* data) return len; } -unsigned int CSerialModem::readM17Data(unsigned char* data) +unsigned int CMMDVMModem::readM17Data(unsigned char* data) { assert(data != NULL); @@ -1231,7 +1231,7 @@ unsigned int CSerialModem::readM17Data(unsigned char* data) return len; } -unsigned int CSerialModem::readFMData(unsigned char* data) +unsigned int CMMDVMModem::readFMData(unsigned char* data) { assert(data != NULL); @@ -1245,7 +1245,7 @@ unsigned int CSerialModem::readFMData(unsigned char* data) return len; } -unsigned int CSerialModem::readAX25Data(unsigned char* data) +unsigned int CMMDVMModem::readAX25Data(unsigned char* data) { assert(data != NULL); @@ -1259,7 +1259,7 @@ unsigned int CSerialModem::readAX25Data(unsigned char* data) return len; } -unsigned int CSerialModem::readTransparentData(unsigned char* data) +unsigned int CMMDVMModem::readTransparentData(unsigned char* data) { assert(data != NULL); @@ -1273,7 +1273,7 @@ unsigned int CSerialModem::readTransparentData(unsigned char* data) return len; } -unsigned int CSerialModem::readSerial(unsigned char* data, unsigned int length) +unsigned int CMMDVMModem::readSerial(unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1287,14 +1287,14 @@ unsigned int CSerialModem::readSerial(unsigned char* data, unsigned int length) return n; } -bool CSerialModem::hasDStarSpace() const +bool CMMDVMModem::hasDStarSpace() const { unsigned int space = m_txDStarData.freeSpace() / (DSTAR_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeDStarData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeDStarData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1328,21 +1328,21 @@ bool CSerialModem::writeDStarData(const unsigned char* data, unsigned int length return true; } -bool CSerialModem::hasDMRSpace1() const +bool CMMDVMModem::hasDMRSpace1() const { unsigned int space = m_txDMRData1.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::hasDMRSpace2() const +bool CMMDVMModem::hasDMRSpace2() const { unsigned int space = m_txDMRData2.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeDMRData1(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeDMRData1(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1365,7 +1365,7 @@ bool CSerialModem::writeDMRData1(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::writeDMRData2(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeDMRData2(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1388,14 +1388,14 @@ bool CSerialModem::writeDMRData2(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasYSFSpace() const +bool CMMDVMModem::hasYSFSpace() const { unsigned int space = m_txYSFData.freeSpace() / (YSF_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeYSFData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeYSFData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1418,14 +1418,14 @@ bool CSerialModem::writeYSFData(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasP25Space() const +bool CMMDVMModem::hasP25Space() const { unsigned int space = m_txP25Data.freeSpace() / (P25_LDU_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeP25Data(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeP25Data(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1448,14 +1448,14 @@ bool CSerialModem::writeP25Data(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasNXDNSpace() const +bool CMMDVMModem::hasNXDNSpace() const { unsigned int space = m_txNXDNData.freeSpace() / (NXDN_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeNXDNData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeNXDNData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1478,14 +1478,14 @@ bool CSerialModem::writeNXDNData(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasM17Space() const +bool CMMDVMModem::hasM17Space() const { unsigned int space = m_txM17Data.freeSpace() / (M17_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writeM17Data(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeM17Data(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1512,14 +1512,14 @@ bool CSerialModem::writeM17Data(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasPOCSAGSpace() const +bool CMMDVMModem::hasPOCSAGSpace() const { unsigned int space = m_txPOCSAGData.freeSpace() / (POCSAG_FRAME_LENGTH_BYTES + 4U); return space > 1U; } -bool CSerialModem::writePOCSAGData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writePOCSAGData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1539,12 +1539,12 @@ bool CSerialModem::writePOCSAGData(const unsigned char* data, unsigned int lengt return true; } -unsigned int CSerialModem::getFMSpace() const +unsigned int CMMDVMModem::getFMSpace() const { return m_txFMData.freeSpace(); } -bool CSerialModem::writeFMData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeFMData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1573,14 +1573,14 @@ bool CSerialModem::writeFMData(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasAX25Space() const +bool CMMDVMModem::hasAX25Space() const { unsigned int space = m_txAX25Data.freeSpace() / (AX25_MAX_FRAME_LENGTH_BYTES + 5U); return space > 1U; } -bool CSerialModem::writeAX25Data(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeAX25Data(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1609,7 +1609,7 @@ bool CSerialModem::writeAX25Data(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::writeTransparentData(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeTransparentData(const unsigned char* data, unsigned int length) { assert(data != NULL); assert(length > 0U); @@ -1643,7 +1643,7 @@ bool CSerialModem::writeTransparentData(const unsigned char* data, unsigned int return true; } -bool CSerialModem::writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) +bool CMMDVMModem::writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) { assert(m_serial != NULL); assert(my1 != NULL); @@ -1672,7 +1672,7 @@ bool CSerialModem::writeDStarInfo(const char* my1, const char* my2, const char* return m_serial->write(buffer, 33U) != 33; } -bool CSerialModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dest, const char* type) +bool CMMDVMModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dest, const char* type) { assert(m_serial != NULL); assert(type != NULL); @@ -1698,7 +1698,7 @@ bool CSerialModem::writeDMRInfo(unsigned int slotNo, const std::string& src, boo return m_serial->write(buffer, 47U) != 47; } -bool CSerialModem::writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) +bool CMMDVMModem::writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) { assert(m_serial != NULL); assert(source != NULL); @@ -1726,7 +1726,7 @@ bool CSerialModem::writeYSFInfo(const char* source, const char* dest, unsigned c return m_serial->write(buffer, 36U) != 36; } -bool CSerialModem::writeP25Info(const char* source, bool group, unsigned int dest, const char* type) +bool CMMDVMModem::writeP25Info(const char* source, bool group, unsigned int dest, const char* type) { assert(m_serial != NULL); assert(source != NULL); @@ -1751,7 +1751,7 @@ bool CSerialModem::writeP25Info(const char* source, bool group, unsigned int des return m_serial->write(buffer, 31U) != 31; } -bool CSerialModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) +bool CMMDVMModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) { assert(m_serial != NULL); assert(source != NULL); @@ -1776,7 +1776,7 @@ bool CSerialModem::writeNXDNInfo(const char* source, bool group, unsigned int de return m_serial->write(buffer, 31U) != 31; } -bool CSerialModem::writeM17Info(const char* source, const char* dest, const char* type) +bool CMMDVMModem::writeM17Info(const char* source, const char* dest, const char* type) { assert(m_serial != NULL); assert(source != NULL); @@ -1800,7 +1800,7 @@ bool CSerialModem::writeM17Info(const char* source, const char* dest, const char return m_serial->write(buffer, 23U) != 23; } -bool CSerialModem::writePOCSAGInfo(unsigned int ric, const std::string& message) +bool CMMDVMModem::writePOCSAGInfo(unsigned int ric, const std::string& message) { assert(m_serial != NULL); @@ -1823,7 +1823,7 @@ bool CSerialModem::writePOCSAGInfo(unsigned int ric, const std::string& message) return ret != int(length + 11U); } -bool CSerialModem::writeIPInfo(const std::string& address) +bool CMMDVMModem::writeIPInfo(const std::string& address) { assert(m_serial != NULL); @@ -1844,7 +1844,7 @@ bool CSerialModem::writeIPInfo(const std::string& address) return ret != int(length + 4U); } -bool CSerialModem::writeSerial(const unsigned char* data, unsigned int length) +bool CMMDVMModem::writeSerial(const unsigned char* data, unsigned int length) { assert(m_serial != NULL); assert(data != NULL); @@ -1865,27 +1865,27 @@ bool CSerialModem::writeSerial(const unsigned char* data, unsigned int length) return true; } -bool CSerialModem::hasTX() const +bool CMMDVMModem::hasTX() const { return m_tx; } -bool CSerialModem::hasCD() const +bool CMMDVMModem::hasCD() const { return m_cd; } -bool CSerialModem::hasLockout() const +bool CMMDVMModem::hasLockout() const { return m_lockout; } -bool CSerialModem::hasError() const +bool CMMDVMModem::hasError() const { return m_error; } -bool CSerialModem::readVersion() +bool CMMDVMModem::readVersion() { assert(m_serial != NULL); @@ -1998,7 +1998,7 @@ bool CSerialModem::readVersion() return false; } -bool CSerialModem::readStatus() +bool CMMDVMModem::readStatus() { assert(m_serial != NULL); @@ -2013,7 +2013,7 @@ bool CSerialModem::readStatus() return m_serial->write(buffer, 3U) == 3; } -bool CSerialModem::writeConfig() +bool CMMDVMModem::writeConfig() { switch (m_protocolVersion) { case 1U: @@ -2025,7 +2025,7 @@ bool CSerialModem::writeConfig() } } -bool CSerialModem::setConfig1() +bool CMMDVMModem::setConfig1() { assert(m_serial != NULL); @@ -2140,7 +2140,7 @@ bool CSerialModem::setConfig1() return true; } -bool CSerialModem::setConfig2() +bool CMMDVMModem::setConfig2() { assert(m_serial != NULL); @@ -2266,7 +2266,7 @@ bool CSerialModem::setConfig2() return true; } -bool CSerialModem::setFrequency() +bool CMMDVMModem::setFrequency() { assert(m_serial != NULL); @@ -2339,7 +2339,7 @@ bool CSerialModem::setFrequency() return true; } -RESP_TYPE_MMDVM CSerialModem::getResponse() +RESP_TYPE_MMDVM CMMDVMModem::getResponse() { assert(m_serial != NULL); @@ -2441,17 +2441,17 @@ RESP_TYPE_MMDVM CSerialModem::getResponse() return RTM_OK; } -HW_TYPE CSerialModem::getHWType() const +HW_TYPE CMMDVMModem::getHWType() const { return m_hwType; } -unsigned char CSerialModem::getMode() const +unsigned char CMMDVMModem::getMode() const { return m_mode; } -bool CSerialModem::setMode(unsigned char mode) +bool CMMDVMModem::setMode(unsigned char mode) { assert(m_serial != NULL); @@ -2467,7 +2467,7 @@ bool CSerialModem::setMode(unsigned char mode) return m_serial->write(buffer, 4U) == 4; } -bool CSerialModem::sendCWId(const std::string& callsign) +bool CMMDVMModem::sendCWId(const std::string& callsign) { assert(m_serial != NULL); @@ -2489,7 +2489,7 @@ bool CSerialModem::sendCWId(const std::string& callsign) return m_serial->write(buffer, length + 3U) == int(length + 3U); } -bool CSerialModem::writeDMRStart(bool tx) +bool CMMDVMModem::writeDMRStart(bool tx) { assert(m_serial != NULL); @@ -2510,7 +2510,7 @@ bool CSerialModem::writeDMRStart(bool tx) return m_serial->write(buffer, 4U) == 4; } -bool CSerialModem::writeDMRAbort(unsigned int slotNo) +bool CMMDVMModem::writeDMRAbort(unsigned int slotNo) { assert(m_serial != NULL); @@ -2531,7 +2531,7 @@ bool CSerialModem::writeDMRAbort(unsigned int slotNo) return m_serial->write(buffer, 4U) == 4; } -bool CSerialModem::writeDMRShortLC(const unsigned char* lc) +bool CMMDVMModem::writeDMRShortLC(const unsigned char* lc) { assert(m_serial != NULL); assert(lc != NULL); @@ -2556,7 +2556,7 @@ bool CSerialModem::writeDMRShortLC(const unsigned char* lc) return m_serial->write(buffer, 12U) == 12; } -void CSerialModem::setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) +void CMMDVMModem::setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) { m_fmCallsign = callsign; m_fmCallsignSpeed = callsignSpeed; @@ -2570,7 +2570,7 @@ void CSerialModem::setFMCallsignParams(const std::string& callsign, unsigned int m_fmCallsignAtLatch = callsignAtLatch; } -void CSerialModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) +void CMMDVMModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) { m_fmRfAck = rfAck; m_fmAckSpeed = ackSpeed; @@ -2580,7 +2580,7 @@ void CSerialModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpee m_fmAckLevel = ackLevel; } -void CSerialModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) +void CMMDVMModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) { m_fmTimeout = timeout; m_fmTimeoutLevel = timeoutLevel; @@ -2605,14 +2605,14 @@ void CSerialModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, flo m_fmMaxDevLevel = maxDevLevel; } -void CSerialModem::setFMExtParams(const std::string& ack, unsigned int audioBoost) +void CMMDVMModem::setFMExtParams(const std::string& ack, unsigned int audioBoost) { m_fmExtAck = ack; m_fmExtAudioBoost = audioBoost; m_fmExtEnable = true; } -bool CSerialModem::setFMCallsignParams() +bool CMMDVMModem::setFMCallsignParams() { assert(m_serial != NULL); @@ -2673,7 +2673,7 @@ bool CSerialModem::setFMCallsignParams() return true; } -bool CSerialModem::setFMAckParams() +bool CMMDVMModem::setFMAckParams() { assert(m_serial != NULL); @@ -2725,7 +2725,7 @@ bool CSerialModem::setFMAckParams() return true; } -bool CSerialModem::setFMMiscParams() +bool CMMDVMModem::setFMMiscParams() { assert(m_serial != NULL); @@ -2792,7 +2792,7 @@ bool CSerialModem::setFMMiscParams() return true; } -bool CSerialModem::setFMExtParams() +bool CMMDVMModem::setFMExtParams() { assert(m_serial != NULL); @@ -2843,7 +2843,7 @@ bool CSerialModem::setFMExtParams() return true; } -void CSerialModem::printDebug() +void CMMDVMModem::printDebug() { if (m_buffer[2U] == MMDVM_DEBUG1) { LogMessage("Debug: %.*s", m_length - m_offset - 0U, m_buffer + m_offset); diff --git a/SerialModem.h b/MMDVMModem.h similarity index 97% rename from SerialModem.h rename to MMDVMModem.h index 4b56077..6e73ce8 100644 --- a/SerialModem.h +++ b/MMDVMModem.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2011-2018,2020,2021 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 @@ -16,8 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef SERIALMODEM_H -#define SERIALMODEM_H +#ifndef MMDVMMODEM_H +#define MMDVMMODEM_H #include "Modem.h" @@ -42,10 +42,10 @@ enum SERIAL_STATE { SS_DATA }; -class CSerialModem : public IModem { +class CMMDVMModem : public IModem { public: - CSerialModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); - virtual ~CSerialModem(); + CMMDVMModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); + virtual ~CMMDVMModem(); virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed); virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency); diff --git a/Makefile b/Makefile index 85a924a..108776a 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o \ - NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o \ - RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \ - UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ + NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ + P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ + RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ + UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi b/Makefile.Pi index 2880c34..110672b 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o \ - NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o \ - P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o \ - RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \ - UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ + NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ + P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ + RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ + UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 019b46a..2fe7098 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -12,11 +12,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ + POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ + UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 811a0ac..1db3fcf 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ + POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ + UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index a8beaec..5c692ce 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -15,11 +15,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o \ - NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o OLED.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ + NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o OLED.o P25Audio.o \ + P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ + RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ + UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 21d4ed0..8da7d05 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -12,11 +12,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \ - Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ + POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ + UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/PseudoTTYController.cpp b/PseudoTTYController.cpp index 52a4ac9..8c3cd7a 100644 --- a/PseudoTTYController.cpp +++ b/PseudoTTYController.cpp @@ -1,6 +1,5 @@ /* - * Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020 by Jonathan Naylor G4KLX - * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX + * Copyright (C) 2020,2021 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 @@ -37,7 +36,7 @@ CPseudoTTYController::CPseudoTTYController(const std::string& symlink, unsigned int speed, bool assertRTS) : -CSerialController(speed, assertRTS), +CUARTController(speed, assertRTS), m_symlink(symlink) { } @@ -77,10 +76,9 @@ bool CPseudoTTYController::open() void CPseudoTTYController::close() { - CSerialController::close(); + CUARTController::close(); ::unlink(m_symlink.c_str()); } #endif - diff --git a/PseudoTTYController.h b/PseudoTTYController.h index ccf6ba1..228f153 100644 --- a/PseudoTTYController.h +++ b/PseudoTTYController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 by Jonathan Naylor G4KLX + * Copyright (C) 2020,2021 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 @@ -23,9 +23,9 @@ #include -#include "SerialController.h" +#include "UARTController.h" -class CPseudoTTYController : public CSerialController { +class CPseudoTTYController : public CUARTController { public: CPseudoTTYController(const std::string& symlink, unsigned int speed, bool assertRTS = false); virtual ~CPseudoTTYController(); diff --git a/SerialController.cpp b/UARTController.cpp similarity index 89% rename from SerialController.cpp rename to UARTController.cpp index 99fe576..cc748b1 100644 --- a/SerialController.cpp +++ b/UARTController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020,2021 by Jonathan Naylor G4KLX * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "SerialController.h" +#include "UARTController.h" #include "Log.h" #include @@ -39,7 +39,7 @@ #if defined(_WIN32) || defined(_WIN64) -CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) : +CUARTController::CUARTController(const std::string& device, unsigned int speed, bool assertRTS) : m_device(device), m_speed(speed), m_assertRTS(assertRTS), @@ -48,7 +48,7 @@ m_handle(INVALID_HANDLE_VALUE) assert(!device.empty()); } -CSerialController::CSerialController(unsigned int speed, bool assertRTS) : +CUARTController::CUARTController(unsigned int speed, bool assertRTS) : m_device(), m_speed(speed), m_assertRTS(assertRTS), @@ -56,11 +56,11 @@ m_handle(INVALID_HANDLE_VALUE) { } -CSerialController::~CSerialController() +CUARTController::~CUARTController() { } -bool CSerialController::open() +bool CUARTController::open() { assert(m_handle == INVALID_HANDLE_VALUE); @@ -140,7 +140,7 @@ bool CSerialController::open() return true; } -int CSerialController::read(unsigned char* buffer, unsigned int length) +int CUARTController::read(unsigned char* buffer, unsigned int length) { assert(m_handle != INVALID_HANDLE_VALUE); assert(buffer != NULL); @@ -162,7 +162,7 @@ int CSerialController::read(unsigned char* buffer, unsigned int length) return int(length); } -int CSerialController::readNonblock(unsigned char* buffer, unsigned int length) +int CUARTController::readNonblock(unsigned char* buffer, unsigned int length) { assert(m_handle != INVALID_HANDLE_VALUE); assert(buffer != NULL); @@ -194,7 +194,7 @@ int CSerialController::readNonblock(unsigned char* buffer, unsigned int length) return int(bytes); } -int CSerialController::write(const unsigned char* buffer, unsigned int length) +int CUARTController::write(const unsigned char* buffer, unsigned int length) { assert(m_handle != INVALID_HANDLE_VALUE); assert(buffer != NULL); @@ -218,7 +218,7 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length) return int(length); } -void CSerialController::close() +void CUARTController::close() { assert(m_handle != INVALID_HANDLE_VALUE); @@ -228,7 +228,7 @@ void CSerialController::close() #else -CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) : +CUARTController::CUARTController(const std::string& device, unsigned int speed, bool assertRTS) : m_device(device), m_speed(speed), m_assertRTS(assertRTS), @@ -237,7 +237,7 @@ m_fd(-1) assert(!device.empty()); } -CSerialController::CSerialController(unsigned int speed, bool assertRTS) : +CUARTController::CUARTController(unsigned int speed, bool assertRTS) : m_device(), m_speed(speed), m_assertRTS(assertRTS), @@ -245,11 +245,11 @@ m_fd(-1) { } -CSerialController::~CSerialController() +CUARTController::~CUARTController() { } -bool CSerialController::open() +bool CUARTController::open() { assert(m_fd == -1); @@ -269,7 +269,7 @@ bool CSerialController::open() return true; } -bool CSerialController::setRaw() +bool CUARTController::setRaw() { termios termios; if (::tcgetattr(m_fd, &termios) < 0) { @@ -368,7 +368,7 @@ bool CSerialController::setRaw() } #if defined(__APPLE__) -int CSerialController::setNonblock(bool nonblock) +int CUARTController::setNonblock(bool nonblock) { int flag = ::fcntl(m_fd, F_GETFD, 0); @@ -381,7 +381,7 @@ int CSerialController::setNonblock(bool nonblock) } #endif -int CSerialController::read(unsigned char* buffer, unsigned int length) +int CUARTController::read(unsigned char* buffer, unsigned int length) { assert(buffer != NULL); assert(m_fd != -1); @@ -429,7 +429,7 @@ int CSerialController::read(unsigned char* buffer, unsigned int length) return length; } -bool CSerialController::canWrite(){ +bool CUARTController::canWrite(){ #if defined(__APPLE__) fd_set wset; FD_ZERO(&wset); @@ -449,7 +449,7 @@ bool CSerialController::canWrite(){ #endif } -int CSerialController::write(const unsigned char* buffer, unsigned int length) +int CUARTController::write(const unsigned char* buffer, unsigned int length) { assert(buffer != NULL); assert(m_fd != -1); @@ -476,7 +476,7 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length) return length; } -void CSerialController::close() +void CUARTController::close() { assert(m_fd != -1); diff --git a/SerialController.h b/UARTController.h similarity index 80% rename from SerialController.h rename to UARTController.h index e4adb7d..e1e245f 100644 --- a/SerialController.h +++ b/UARTController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020,2021 by Jonathan Naylor G4KLX * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef SerialController_H -#define SerialController_H +#ifndef UARTController_H +#define UARTController_H #include "SerialPort.h" @@ -28,10 +28,10 @@ #include #endif -class CSerialController : public ISerialPort { +class CUARTController : public ISerialPort { public: - CSerialController(const std::string& device, unsigned int speed, bool assertRTS = false); - virtual ~CSerialController(); + CUARTController(const std::string& device, unsigned int speed, bool assertRTS = false); + virtual ~CUARTController(); virtual bool open(); @@ -46,7 +46,7 @@ public: #endif protected: - CSerialController(unsigned int speed, bool assertRTS = false); + CUARTController(unsigned int speed, bool assertRTS = false); std::string m_device; unsigned int m_speed; diff --git a/Version.h b/Version.h index 2dedd19..50453e8 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20210101"; +const char* VERSION = "20210216"; #endif From 8ace65b86d3944a9ebe90b768c8514b8c2de88fa Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 16 Feb 2021 22:34:25 +0000 Subject: [PATCH 2/4] More sane modem port protocol handling. --- Conf.cpp | 72 ++++++++++---- Conf.h | 22 +++-- I2CController.h | 5 +- MMDVM.ini | 16 ++- MMDVMHost.cpp | 53 +++++++--- MMDVMHost.vcxproj | 4 + MMDVMHost.vcxproj.filters | 12 +++ MMDVMModem.cpp | 199 ++++++++++++++++++-------------------- MMDVMModem.h | 9 +- MMDVMModemPort.cpp | 23 +++++ MMDVMModemPort.h | 37 +++++++ Makefile | 10 +- Makefile.Pi | 10 +- Makefile.Pi.Adafruit | 4 +- Makefile.Pi.HD44780 | 4 +- Makefile.Pi.OLED | 11 ++- Makefile.Pi.PCF8574 | 4 +- Modem.h | 5 +- NullModem.h | 4 +- UARTController.h | 3 +- UDPController.cpp | 79 +++++++++++++++ UDPController.h | 49 ++++++++++ 22 files changed, 454 insertions(+), 181 deletions(-) create mode 100644 MMDVMModemPort.cpp create mode 100644 MMDVMModemPort.h create mode 100644 UDPController.cpp create mode 100644 UDPController.h diff --git a/Conf.cpp b/Conf.cpp index 4dbafbf..1c4985b 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021 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 @@ -93,10 +93,14 @@ m_dmrIdLookupFile(), m_dmrIdLookupTime(0U), m_nxdnIdLookupFile(), m_nxdnIdLookupTime(0U), -m_modemPort(), m_modemProtocol("uart"), -m_modemSpeed(115200U), -m_modemAddress(0x22), +m_modemUARTPort(), +m_modemUARTSpeed(115200U), +m_modemI2CPort(), +m_modemI2CAddress(0x22U), +m_modemModemAddress(), +m_modemModemPort(0U), +m_modemLocalPort(0U), m_modemRXInvert(false), m_modemTXInvert(false), m_modemPTTInvert(false), @@ -514,14 +518,22 @@ bool CConf::read() else if (::strcmp(key, "Time") == 0) m_nxdnIdLookupTime = (unsigned int)::atoi(value); } else if (section == SECTION_MODEM) { - if (::strcmp(key, "Port") == 0) - m_modemPort = value; - else if (::strcmp(key, "Protocol") == 0) + if (::strcmp(key, "Protocol") == 0) m_modemProtocol = value; - else if (::strcmp(key, "Speed") == 0) - m_modemSpeed = (unsigned int)::atoi(value); - else if (::strcmp(key, "Address") == 0) - m_modemAddress = (unsigned int)::strtoul(value, NULL, 16); + else if (::strcmp(key, "UARTPort") == 0) + m_modemUARTPort = value; + else if (::strcmp(key, "UARTSpeed") == 0) + m_modemUARTSpeed = (unsigned int)::atoi(value); + else if (::strcmp(key, "I2CPort") == 0) + m_modemI2CPort = value; + else if (::strcmp(key, "I2CAddress") == 0) + m_modemI2CAddress = (unsigned int)::strtoul(value, NULL, 16); + else if (::strcmp(key, "ModemAddress") == 0) + m_modemModemAddress = value; + else if (::strcmp(key, "ModemPort") == 0) + m_modemModemPort = (unsigned int)::atoi(value); + else if (::strcmp(key, "LocalPort") == 0) + m_modemLocalPort = (unsigned int)::atoi(value); else if (::strcmp(key, "RXInvert") == 0) m_modemRXInvert = ::atoi(value) == 1; else if (::strcmp(key, "TXInvert") == 0) @@ -1232,24 +1244,44 @@ unsigned int CConf::getNXDNIdLookupTime() const return m_nxdnIdLookupTime; } -std::string CConf::getModemPort() const -{ - return m_modemPort; -} - std::string CConf::getModemProtocol() const { return m_modemProtocol; } -unsigned int CConf::getModemSpeed() const +std::string CConf::getModemUARTPort() const { - return m_modemSpeed; + return m_modemUARTPort; } -unsigned int CConf::getModemAddress() const +unsigned int CConf::getModemUARTSpeed() const { - return m_modemAddress; + return m_modemUARTSpeed; +} + +std::string CConf::getModemI2CPort() const +{ + return m_modemI2CPort; +} + +unsigned int CConf::getModemI2CAddress() const +{ + return m_modemI2CAddress; +} + +std::string CConf::getModemModemAddress() const +{ + return m_modemModemAddress; +} + +unsigned int CConf::getModemModemPort() const +{ + return m_modemModemPort; +} + +unsigned int CConf::getModemLocalPort() const +{ + return m_modemLocalPort; } bool CConf::getModemRXInvert() const diff --git a/Conf.h b/Conf.h index 92fa8ce..430bbeb 100644 --- a/Conf.h +++ b/Conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021 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 @@ -70,10 +70,14 @@ public: unsigned int getNXDNIdLookupTime() const; // The Modem section - std::string getModemPort() const; std::string getModemProtocol() const; - unsigned int getModemSpeed() const; - unsigned int getModemAddress() const; + std::string getModemUARTPort() const; + unsigned int getModemUARTSpeed() const; + std::string getModemI2CPort() const; + unsigned int getModemI2CAddress() const; + std::string getModemModemAddress() const; + unsigned int getModemModemPort() const; + unsigned int getModemLocalPort() const; bool getModemRXInvert() const; bool getModemTXInvert() const; bool getModemPTTInvert() const; @@ -391,10 +395,14 @@ private: std::string m_nxdnIdLookupFile; unsigned int m_nxdnIdLookupTime; - std::string m_modemPort; std::string m_modemProtocol; - unsigned int m_modemSpeed; - unsigned int m_modemAddress; + std::string m_modemUARTPort; + unsigned int m_modemUARTSpeed; + std::string m_modemI2CPort; + unsigned int m_modemI2CAddress; + std::string m_modemModemAddress; + unsigned int m_modemModemPort; + unsigned int m_modemLocalPort; bool m_modemRXInvert; bool m_modemTXInvert; bool m_modemPTTInvert; diff --git a/I2CController.h b/I2CController.h index 281c587..19298ca 100644 --- a/I2CController.h +++ b/I2CController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020,2021 by Jonathan Naylor G4KLX * Copyright (C) 1999-2001 by Thomas Sailor HB9JNX * * This program is free software; you can redistribute it and/or modify @@ -22,11 +22,12 @@ #if defined(__linux__) +#include "MMDVMModemPort.h" #include "SerialPort.h" #include -class CI2CController : public ISerialPort { +class CI2CController : public ISerialPort, public IMMDVMModemPort { public: CI2CController(const std::string& device, unsigned int address = 0x22U); virtual ~CI2CController(); diff --git a/MMDVM.ini b/MMDVM.ini index 7810965..638118f 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -43,12 +43,18 @@ File=NXDN.csv Time=24 [Modem] -# Port=/dev/ttyACM0 -Port=/dev/ttyAMA0 -# Port=\\.\COM4 +# Valid values are "uart", "udp", and (on Linux) "i2c" Protocol=uart -Speed=460800 -# Address=0x22 +# The port and speed used for a UART connection +# UARTPort=\\.\COM4 +# UARTPort=/dev/ttyACM0 +UARTPort=/dev/ttyAMA0 +UARTSpeed=460800 +# The port and address for an I2C connection +I2CPort=/dev/i2c +I2CAddress=0x22 +# IP parameters for UDP connection + TXInvert=1 RXInvert=0 PTTInvert=0 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 7929f2d..a03fa70 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -23,6 +23,7 @@ #include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" #include "UARTController.h" +#include "UDPController.h" #include "MMDVMModem.h" #include "NullModem.h" #include "Version.h" @@ -1315,10 +1316,14 @@ int CMMDVMHost::run() bool CMMDVMHost::createModem() { - std::string port = m_conf.getModemPort(); - std::string protocol = m_conf.getModemProtocol(); - unsigned int speed = m_conf.getModemSpeed(); - unsigned int address = m_conf.getModemAddress(); + std::string protocol = m_conf.getModemProtocol(); + std::string uartPort = m_conf.getModemUARTPort(); + unsigned int uartSpeed = m_conf.getModemUARTSpeed(); + std::string i2cPort = m_conf.getModemI2CPort(); + unsigned int i2cAddress = m_conf.getModemI2CAddress(); + std::string modemAddress = m_conf.getModemModemAddress(); + unsigned int modemPort = m_conf.getModemModemPort(); + unsigned int localPort = m_conf.getModemLocalPort(); bool rxInvert = m_conf.getModemRXInvert(); bool txInvert = m_conf.getModemTXInvert(); bool pttInvert = m_conf.getModemPTTInvert(); @@ -1358,14 +1363,23 @@ bool CMMDVMHost::createModem() bool useCOSAsLockout = m_conf.getModemUseCOSAsLockout(); LogInfo("Modem Parameters"); - LogInfo(" Port: %s", port.c_str()); -#if defined(__linux__) LogInfo(" Protocol: %s", protocol.c_str()); - if (protocol == "i2c") - LogInfo(" I2C Address: %02X", address); - else + + if (protocol == "uart") { + LogInfo(" UART Port: %s", uartPort.c_str()); + LogInfo(" UART Speed: %u", uartSpeed); + } else if (protocol == "udp") { + LogInfo(" Modem Address: %s", modemAddress.c_str()); + LogInfo(" Modem Port: %u", modemPort); + LogInfo(" Local Port: %u", localPort); + } +#if defined(__linux__) + else if (protocol == "i2c") { + LogInfo(" I2C Port: %s", i2cPort.c_str()); + LogInfo(" I2C Address: %02X", i2cAddress); + } #endif - LogInfo(" Speed: %u", speed); + LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no"); LogInfo(" TX Invert: %s", txInvert ? "yes" : "no"); LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no"); @@ -1390,11 +1404,24 @@ bool CMMDVMHost::createModem() LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset); LogInfo(" Use COS as Lockout: %s", useCOSAsLockout ? "yes" : "no"); - if (port == "NullModem") + if (protocol == "null") m_modem = new CNullModem; else - m_modem = new CMMDVMModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); - m_modem->setSerialParams(protocol, address, speed); + m_modem = new CMMDVMModem(m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); + + IMMDVMModemPort* modem = NULL; + if (protocol == "uart") + modem = new CUARTController(uartPort, uartSpeed, true); + else if (protocol == "udp") + modem = new CUDPController(modemAddress, modemPort, localPort); +#if defined(__linux__) + else if (protocol == "i2c") + modem = new CI2CController(i2cPort, i2cAddress); +#endif + else + return false; + + m_modem->setModem(modem); m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled); m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel); m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency); diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 10ce89c..1067b2b 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -203,6 +203,7 @@ + @@ -252,6 +253,7 @@ + @@ -311,6 +313,7 @@ + @@ -356,6 +359,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 52c2b9f..0a1e4bf 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -344,6 +344,12 @@ Header Files + + Header Files + + + Header Files + @@ -646,5 +652,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/MMDVMModem.cpp b/MMDVMModem.cpp index e2fd3b9..bb14094 100644 --- a/MMDVMModem.cpp +++ b/MMDVMModem.cpp @@ -114,8 +114,7 @@ const unsigned int MAX_RESPONSES = 30U; const unsigned int BUFFER_LENGTH = 2000U; -CMMDVMModem::CMMDVMModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : -m_port(port), +CMMDVMModem::CMMDVMModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : m_protocolVersion(0U), m_dmrColorCode(0U), m_ysfLoDev(false), @@ -158,7 +157,7 @@ m_fmEnabled(false), m_ax25Enabled(false), m_rxDCOffset(0), m_txDCOffset(0), -m_serial(NULL), +m_port(NULL), m_buffer(NULL), m_length(0U), m_offset(0U), @@ -247,25 +246,19 @@ m_fmMaxDevLevel(90.0F), m_fmExtEnable(false) { m_buffer = new unsigned char[BUFFER_LENGTH]; - - assert(!port.empty()); } CMMDVMModem::~CMMDVMModem() { - delete m_serial; + delete m_port; delete[] m_buffer; } -void CMMDVMModem::setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) +void CMMDVMModem::setModem(IMMDVMModemPort* port) { - // Create the serial controller instance according the protocol specified in conf. -#if defined(__linux__) - if (protocol == "i2c") - m_serial = new CI2CController(m_port, address); - else -#endif - m_serial = new CUARTController(m_port, speed, true); + assert(port != NULL); + + m_port = port; } void CMMDVMModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) @@ -351,15 +344,15 @@ bool CMMDVMModem::open() { ::LogMessage("Opening the MMDVM"); - bool ret = m_serial->open(); + bool ret = m_port->open(); if (!ret) return false; ret = readVersion(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } else { /* Stopping the inactivity timer here when a firmware version has been @@ -369,51 +362,51 @@ bool CMMDVMModem::open() ret = setFrequency(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } ret = writeConfig(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } if (m_fmEnabled && m_duplex) { ret = setFMCallsignParams(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } ret = setFMAckParams(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } ret = setFMMiscParams(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } if (m_fmExtEnable) { ret = setFMExtParams(); if (!ret) { - m_serial->close(); - delete m_serial; - m_serial = NULL; + m_port->close(); + delete m_port; + m_port = NULL; return false; } } @@ -429,7 +422,7 @@ bool CMMDVMModem::open() void CMMDVMModem::clock(unsigned int ms) { - assert(m_serial != NULL); + assert(m_port != NULL); // Poll the modem status every 250ms m_statusTimer.clock(ms); @@ -928,7 +921,7 @@ void CMMDVMModem::clock(unsigned int ms) break; } - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing D-Star data to the MMDVM"); @@ -944,7 +937,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX DMR Data 1", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing DMR data to the MMDVM"); @@ -961,7 +954,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX DMR Data 2", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing DMR data to the MMDVM"); @@ -978,7 +971,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX YSF Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing YSF data to the MMDVM"); @@ -999,7 +992,7 @@ void CMMDVMModem::clock(unsigned int ms) CUtils::dump(1U, "TX P25 LDU", m_buffer, len); } - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing P25 data to the MMDVM"); @@ -1016,7 +1009,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX NXDN Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing NXDN data to the MMDVM"); @@ -1037,7 +1030,7 @@ void CMMDVMModem::clock(unsigned int ms) CUtils::dump(1U, "TX M17 Data", m_buffer, len); } - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing M17 data to the MMDVM"); @@ -1054,7 +1047,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX POCSAG Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing POCSAG data to the MMDVM"); @@ -1071,7 +1064,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX FM Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing FM data to the MMDVM"); @@ -1088,7 +1081,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX AX.25 Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing AX.25 data to the MMDVM"); @@ -1105,7 +1098,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX Transparent Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing Transparent data to the MMDVM"); } @@ -1118,7 +1111,7 @@ void CMMDVMModem::clock(unsigned int ms) if (m_trace) CUtils::dump(1U, "TX Serial Data", m_buffer, len); - int ret = m_serial->write(m_buffer, len); + int ret = m_port->write(m_buffer, len); if (ret != int(len)) LogWarning("Error when writing Serial data to the MMDVM"); } @@ -1126,11 +1119,11 @@ void CMMDVMModem::clock(unsigned int ms) void CMMDVMModem::close() { - assert(m_serial != NULL); + assert(m_port != NULL); ::LogMessage("Closing the MMDVM"); - m_serial->close(); + m_port->close(); } unsigned int CMMDVMModem::readDStarData(unsigned char* data) @@ -1645,7 +1638,7 @@ bool CMMDVMModem::writeTransparentData(const unsigned char* data, unsigned int l bool CMMDVMModem::writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(my1 != NULL); assert(my2 != NULL); assert(your != NULL); @@ -1669,12 +1662,12 @@ bool CMMDVMModem::writeDStarInfo(const char* my1, const char* my2, const char* y ::memcpy(buffer + 25U, reflector, DSTAR_LONG_CALLSIGN_LENGTH); - return m_serial->write(buffer, 33U) != 33; + return m_port->write(buffer, 33U) != 33; } bool CMMDVMModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dest, const char* type) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(type != NULL); unsigned char buffer[50U]; @@ -1695,12 +1688,12 @@ bool CMMDVMModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool ::memcpy(buffer + 46U, type, 1U); - return m_serial->write(buffer, 47U) != 47; + return m_port->write(buffer, 47U) != 47; } bool CMMDVMModem::writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(source != NULL); assert(dest != NULL); assert(type != NULL); @@ -1723,12 +1716,12 @@ bool CMMDVMModem::writeYSFInfo(const char* source, const char* dest, unsigned ch buffer[35U] = dgid; - return m_serial->write(buffer, 36U) != 36; + return m_port->write(buffer, 36U) != 36; } bool CMMDVMModem::writeP25Info(const char* source, bool group, unsigned int dest, const char* type) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(source != NULL); assert(type != NULL); @@ -1748,12 +1741,12 @@ bool CMMDVMModem::writeP25Info(const char* source, bool group, unsigned int dest ::memcpy(buffer + 30U, type, 1U); - return m_serial->write(buffer, 31U) != 31; + return m_port->write(buffer, 31U) != 31; } bool CMMDVMModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(source != NULL); assert(type != NULL); @@ -1773,12 +1766,12 @@ bool CMMDVMModem::writeNXDNInfo(const char* source, bool group, unsigned int des ::memcpy(buffer + 30U, type, 1U); - return m_serial->write(buffer, 31U) != 31; + return m_port->write(buffer, 31U) != 31; } bool CMMDVMModem::writeM17Info(const char* source, const char* dest, const char* type) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(source != NULL); assert(dest != NULL); assert(type != NULL); @@ -1797,12 +1790,12 @@ bool CMMDVMModem::writeM17Info(const char* source, const char* dest, const char* ::memcpy(buffer + 22U, type, 1U); - return m_serial->write(buffer, 23U) != 23; + return m_port->write(buffer, 23U) != 23; } bool CMMDVMModem::writePOCSAGInfo(unsigned int ric, const std::string& message) { - assert(m_serial != NULL); + assert(m_port != NULL); size_t length = message.size(); @@ -1818,14 +1811,14 @@ bool CMMDVMModem::writePOCSAGInfo(unsigned int ric, const std::string& message) ::memcpy(buffer + 11U, message.c_str(), length); - int ret = m_serial->write(buffer, length + 11U); + int ret = m_port->write(buffer, length + 11U); return ret != int(length + 11U); } bool CMMDVMModem::writeIPInfo(const std::string& address) { - assert(m_serial != NULL); + assert(m_port != NULL); size_t length = address.size(); @@ -1839,14 +1832,14 @@ bool CMMDVMModem::writeIPInfo(const std::string& address) ::memcpy(buffer + 4U, address.c_str(), length); - int ret = m_serial->write(buffer, length + 4U); + int ret = m_port->write(buffer, length + 4U); return ret != int(length + 4U); } bool CMMDVMModem::writeSerial(const unsigned char* data, unsigned int length) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(data != NULL); assert(length > 0U); @@ -1887,7 +1880,7 @@ bool CMMDVMModem::hasError() const bool CMMDVMModem::readVersion() { - assert(m_serial != NULL); + assert(m_port != NULL); CThread::sleep(2000U); // 2s @@ -1900,12 +1893,12 @@ bool CMMDVMModem::readVersion() // CUtils::dump(1U, "Written", buffer, 3U); - int ret = m_serial->write(buffer, 3U); + int ret = m_port->write(buffer, 3U); if (ret != 3) return false; #if defined(__APPLE__) - m_serial->setNonblock(true); + m_port->setNonblock(true); #endif for (unsigned int count = 0U; count < MAX_RESPONSES; count++) { @@ -2000,7 +1993,7 @@ bool CMMDVMModem::readVersion() bool CMMDVMModem::readStatus() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[3U]; @@ -2010,7 +2003,7 @@ bool CMMDVMModem::readStatus() // CUtils::dump(1U, "Written", buffer, 3U); - return m_serial->write(buffer, 3U) == 3; + return m_port->write(buffer, 3U) == 3; } bool CMMDVMModem::writeConfig() @@ -2027,7 +2020,7 @@ bool CMMDVMModem::writeConfig() bool CMMDVMModem::setConfig1() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[30U]; @@ -2109,7 +2102,7 @@ bool CMMDVMModem::setConfig1() // CUtils::dump(1U, "Written", buffer, 26U); - int ret = m_serial->write(buffer, 26U); + int ret = m_port->write(buffer, 26U); if (ret != 26) return false; @@ -2142,7 +2135,7 @@ bool CMMDVMModem::setConfig1() bool CMMDVMModem::setConfig2() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[50U]; @@ -2235,7 +2228,7 @@ bool CMMDVMModem::setConfig2() // CUtils::dump(1U, "Written", buffer, 40U); - int ret = m_serial->write(buffer, 40U); + int ret = m_port->write(buffer, 40U); if (ret != 40) return false; @@ -2268,7 +2261,7 @@ bool CMMDVMModem::setConfig2() bool CMMDVMModem::setFrequency() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[20U]; unsigned char len; @@ -2310,7 +2303,7 @@ bool CMMDVMModem::setFrequency() // CUtils::dump(1U, "Written", buffer, len); - int ret = m_serial->write(buffer, len); + int ret = m_port->write(buffer, len); if (ret != len) return false; @@ -2341,11 +2334,11 @@ bool CMMDVMModem::setFrequency() RESP_TYPE_MMDVM CMMDVMModem::getResponse() { - assert(m_serial != NULL); + assert(m_port != NULL); if (m_state == SS_START) { // Get the start of the frame or nothing at all - int ret = m_serial->read(m_buffer + 0U, 1U); + int ret = m_port->read(m_buffer + 0U, 1U); if (ret < 0) { LogError("Error when reading from the modem"); return RTM_ERROR; @@ -2363,7 +2356,7 @@ RESP_TYPE_MMDVM CMMDVMModem::getResponse() if (m_state == SS_LENGTH1) { // Get the length of the frame, 1/2 - int ret = m_serial->read(m_buffer + 1U, 1U); + int ret = m_port->read(m_buffer + 1U, 1U); if (ret < 0) { LogError("Error when reading from the modem"); m_state = SS_START; @@ -2384,7 +2377,7 @@ RESP_TYPE_MMDVM CMMDVMModem::getResponse() if (m_state == SS_LENGTH2) { // Get the length of the frane, 2/2 - int ret = m_serial->read(m_buffer + 2U, 1U); + int ret = m_port->read(m_buffer + 2U, 1U); if (ret < 0) { LogError("Error when reading from the modem"); m_state = SS_START; @@ -2401,7 +2394,7 @@ RESP_TYPE_MMDVM CMMDVMModem::getResponse() if (m_state == SS_TYPE) { // Get the frame type - int ret = m_serial->read(&m_type, 1U); + int ret = m_port->read(&m_type, 1U); if (ret < 0) { LogError("Error when reading from the modem"); m_state = SS_START; @@ -2418,7 +2411,7 @@ RESP_TYPE_MMDVM CMMDVMModem::getResponse() if (m_state == SS_DATA) { while (m_offset < m_length) { - int ret = m_serial->read(m_buffer + m_offset, m_length - m_offset); + int ret = m_port->read(m_buffer + m_offset, m_length - m_offset); if (ret < 0) { LogError("Error when reading from the modem"); m_state = SS_START; @@ -2453,7 +2446,7 @@ unsigned char CMMDVMModem::getMode() const bool CMMDVMModem::setMode(unsigned char mode) { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[4U]; @@ -2464,12 +2457,12 @@ bool CMMDVMModem::setMode(unsigned char mode) // CUtils::dump(1U, "Written", buffer, 4U); - return m_serial->write(buffer, 4U) == 4; + return m_port->write(buffer, 4U) == 4; } bool CMMDVMModem::sendCWId(const std::string& callsign) { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned int length = callsign.length(); if (length > 200U) @@ -2486,12 +2479,12 @@ bool CMMDVMModem::sendCWId(const std::string& callsign) // CUtils::dump(1U, "Written", buffer, length + 3U); - return m_serial->write(buffer, length + 3U) == int(length + 3U); + return m_port->write(buffer, length + 3U) == int(length + 3U); } bool CMMDVMModem::writeDMRStart(bool tx) { - assert(m_serial != NULL); + assert(m_port != NULL); if (tx && m_tx) return true; @@ -2507,12 +2500,12 @@ bool CMMDVMModem::writeDMRStart(bool tx) // CUtils::dump(1U, "Written", buffer, 4U); - return m_serial->write(buffer, 4U) == 4; + return m_port->write(buffer, 4U) == 4; } bool CMMDVMModem::writeDMRAbort(unsigned int slotNo) { - assert(m_serial != NULL); + assert(m_port != NULL); if (slotNo == 1U) m_txDMRData1.clear(); @@ -2528,12 +2521,12 @@ bool CMMDVMModem::writeDMRAbort(unsigned int slotNo) // CUtils::dump(1U, "Written", buffer, 4U); - return m_serial->write(buffer, 4U) == 4; + return m_port->write(buffer, 4U) == 4; } bool CMMDVMModem::writeDMRShortLC(const unsigned char* lc) { - assert(m_serial != NULL); + assert(m_port != NULL); assert(lc != NULL); unsigned char buffer[12U]; @@ -2553,7 +2546,7 @@ bool CMMDVMModem::writeDMRShortLC(const unsigned char* lc) // CUtils::dump(1U, "Written", buffer, 12U); - return m_serial->write(buffer, 12U) == 12; + return m_port->write(buffer, 12U) == 12; } void CMMDVMModem::setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) @@ -2614,7 +2607,7 @@ void CMMDVMModem::setFMExtParams(const std::string& ack, unsigned int audioBoost bool CMMDVMModem::setFMCallsignParams() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[80U]; unsigned char len = 10U + m_fmCallsign.size(); @@ -2644,7 +2637,7 @@ bool CMMDVMModem::setFMCallsignParams() // CUtils::dump(1U, "Written", buffer, len); - int ret = m_serial->write(buffer, len); + int ret = m_port->write(buffer, len); if (ret != len) return false; @@ -2675,7 +2668,7 @@ bool CMMDVMModem::setFMCallsignParams() bool CMMDVMModem::setFMAckParams() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[80U]; unsigned char len = 8U + m_fmRfAck.size(); @@ -2696,7 +2689,7 @@ bool CMMDVMModem::setFMAckParams() // CUtils::dump(1U, "Written", buffer, len); - int ret = m_serial->write(buffer, len); + int ret = m_port->write(buffer, len); if (ret != len) return false; @@ -2727,7 +2720,7 @@ bool CMMDVMModem::setFMAckParams() bool CMMDVMModem::setFMMiscParams() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[20U]; @@ -2763,7 +2756,7 @@ bool CMMDVMModem::setFMMiscParams() // CUtils::dump(1U, "Written", buffer, 17U); - int ret = m_serial->write(buffer, 17U); + int ret = m_port->write(buffer, 17U); if (ret != 17) return false; @@ -2794,7 +2787,7 @@ bool CMMDVMModem::setFMMiscParams() bool CMMDVMModem::setFMExtParams() { - assert(m_serial != NULL); + assert(m_port != NULL); unsigned char buffer[80U]; unsigned char len = 7U + m_fmExtAck.size(); @@ -2814,7 +2807,7 @@ bool CMMDVMModem::setFMExtParams() // CUtils::dump(1U, "Written", buffer, len); - int ret = m_serial->write(buffer, len); + int ret = m_port->write(buffer, len); if (ret != len) return false; diff --git a/MMDVMModem.h b/MMDVMModem.h index 6e73ce8..5670d28 100644 --- a/MMDVMModem.h +++ b/MMDVMModem.h @@ -21,7 +21,7 @@ #include "Modem.h" -#include "SerialPort.h" +#include "MMDVMModemPort.h" #include "RingBuffer.h" #include "Defines.h" #include "Timer.h" @@ -44,10 +44,10 @@ enum SERIAL_STATE { class CMMDVMModem : public IModem { public: - CMMDVMModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); + CMMDVMModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); virtual ~CMMDVMModem(); - virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed); + virtual void setModem(IMMDVMModemPort* port); virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency); virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled); virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel); @@ -136,7 +136,6 @@ public: virtual void close(); private: - std::string m_port; unsigned int m_protocolVersion; unsigned int m_dmrColorCode; bool m_ysfLoDev; @@ -179,7 +178,7 @@ private: bool m_ax25Enabled; int m_rxDCOffset; int m_txDCOffset; - ISerialPort* m_serial; + IMMDVMModemPort* m_port; unsigned char* m_buffer; unsigned int m_length; unsigned int m_offset; diff --git a/MMDVMModemPort.cpp b/MMDVMModemPort.cpp new file mode 100644 index 0000000..5b60b74 --- /dev/null +++ b/MMDVMModemPort.cpp @@ -0,0 +1,23 @@ +/* +* Copyright (C) 2016,2021 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. +*/ + +#include "MMDVMModemPort.h" + +IMMDVMModemPort::~IMMDVMModemPort() +{ +} diff --git a/MMDVMModemPort.h b/MMDVMModemPort.h new file mode 100644 index 0000000..565708c --- /dev/null +++ b/MMDVMModemPort.h @@ -0,0 +1,37 @@ +/* +* Copyright (C) 2016,2021 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. +*/ + +#ifndef MMDVMModemPort_H +#define MMDVMModemPort_H + +class IMMDVMModemPort { +public: + virtual ~IMMDVMModemPort() = 0; + + virtual bool open() = 0; + + virtual int read(unsigned char* buffer, unsigned int length) = 0; + + virtual int write(const unsigned char* buffer, unsigned int length) = 0; + + virtual void close() = 0; + +private: +}; + +#endif diff --git a/Makefile b/Makefile index 108776a..d26be33 100644 --- a/Makefile +++ b/Makefile @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ - UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ + POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ + UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi b/Makefile.Pi index 110672b..0662f57 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ - P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ - UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ + POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ + UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 2fe7098..eeb192a 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -12,11 +12,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 1db3fcf..92a7b58 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -11,11 +11,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 5c692ce..42c584d 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -15,11 +15,12 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ - NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o OLED.o P25Audio.o \ - P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o POCSAGNetwork.o QR1676.o \ - RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UARTController.o \ - UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ + NXDNUDCH.o OLED.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ + POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ + Thread.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 8da7d05..0c54640 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -12,11 +12,11 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Modem.h b/Modem.h index faf0917..896e5de 100644 --- a/Modem.h +++ b/Modem.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2011-2018,2020,2021 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 @@ -20,6 +20,7 @@ #define MODEM_H #include "Defines.h" +#include "MMDVMModemPort.h" #include @@ -27,7 +28,7 @@ class IModem { public: virtual ~IModem() = 0; - virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) = 0; + virtual void setModem(IMMDVMModemPort* port) = 0; virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) = 0; virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17ENabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) = 0; virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) = 0; diff --git a/NullModem.h b/NullModem.h index 83e60d6..442b13e 100644 --- a/NullModem.h +++ b/NullModem.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2011-2018,2020,2021 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 @@ -29,7 +29,7 @@ public: CNullModem(); virtual ~CNullModem(); - virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) {}; + virtual void setModem(IMMDVMModemPort* port) {}; virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) {}; virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) {}; virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) {}; diff --git a/UARTController.h b/UARTController.h index e1e245f..bd7d133 100644 --- a/UARTController.h +++ b/UARTController.h @@ -20,6 +20,7 @@ #ifndef UARTController_H #define UARTController_H +#include "MMDVMModemPort.h" #include "SerialPort.h" #include @@ -28,7 +29,7 @@ #include #endif -class CUARTController : public ISerialPort { +class CUARTController : public ISerialPort, public IMMDVMModemPort { public: CUARTController(const std::string& device, unsigned int speed, bool assertRTS = false); virtual ~CUARTController(); diff --git a/UDPController.cpp b/UDPController.cpp new file mode 100644 index 0000000..7e38d7c --- /dev/null +++ b/UDPController.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2021 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. + */ + +#include "UDPController.h" +#include "Log.h" + +#include +#include + +const unsigned int BUFFER_LENGTH = 600U; + +CUDPController::CUDPController(const std::string& modemAddress, unsigned int modemPort, unsigned int localPort) : +m_socket(localPort), +m_addr(), +m_addrLen(0U), +m_buffer(NULL), +m_length(0U), +m_offset(0U) +{ + assert(!modemAddress.empty()); + assert(modemPort > 0U); + assert(localPort > 0U); + + if (CUDPSocket::lookup(modemAddress, modemPort, m_addr, m_addrLen) != 0) + m_addrLen = 0U; + + m_buffer = new unsigned char[BUFFER_LENGTH]; +} + +CUDPController::~CUDPController() +{ + delete[] m_buffer; +} + +bool CUDPController::open() +{ + if (m_addrLen == 0U) { + LogError("Unable to resolve the address of the modem"); + return false; + } + + return m_socket.open(m_addr); +} + +int CUDPController::read(unsigned char* buffer, unsigned int length) +{ + assert(buffer != NULL); + assert(length > 0U); + + return 0; +} + +int CUDPController::write(const unsigned char* buffer, unsigned int length) +{ + assert(buffer != NULL); + assert(length > 0U); + + return m_socket.write(buffer, length, m_addr, m_addrLen) ? int(length) : -1; +} + +void CUDPController::close() +{ + m_socket.close(); +} diff --git a/UDPController.h b/UDPController.h new file mode 100644 index 0000000..6e24eca --- /dev/null +++ b/UDPController.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 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. + */ + +#ifndef UDPController_H +#define UDPController_H + +#include "MMDVMModemPort.h" +#include "UDPSocket.h" + +#include + +class CUDPController : public IMMDVMModemPort { +public: + CUDPController(const std::string& modemAddress, unsigned int modemPort, unsigned int localPort); + virtual ~CUDPController(); + + virtual bool open(); + + virtual int read(unsigned char* buffer, unsigned int length); + + virtual int write(const unsigned char* buffer, unsigned int length); + + virtual void close(); + +protected: + CUDPSocket m_socket; + sockaddr_storage m_addr; + unsigned int m_addrLen; + unsigned char* m_buffer; + unsigned int m_length; + unsigned int m_offset; +}; + +#endif From 279afb75f36082be34358843573757eb5147d66a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 17 Feb 2021 19:35:28 +0000 Subject: [PATCH 3/4] Finish off the UDP Controller and more clean-ups. --- MMDVM.ini | 2 +- MMDVMHost.cpp | 12 ++-- MMDVMHost.vcxproj | 4 +- MMDVMHost.vcxproj.filters | 12 ++-- MMDVMModem.cpp | 5 -- Makefile | 2 +- Makefile.Pi | 2 +- Makefile.Pi.Adafruit | 11 ++-- Makefile.Pi.HD44780 | 11 ++-- Makefile.Pi.OLED | 2 +- Makefile.Pi.PCF8574 | 11 ++-- NullController.cpp | 47 +++++++++++++++ NullController.h | 40 +++++++++++++ NullModem.cpp | 35 ----------- NullModem.h | 123 -------------------------------------- README.md | 2 +- UDPController.cpp | 35 ++++++++--- UDPController.h | 5 +- Version.h | 2 +- 19 files changed, 154 insertions(+), 209 deletions(-) create mode 100644 NullController.cpp create mode 100644 NullController.h delete mode 100644 NullModem.cpp delete mode 100644 NullModem.h diff --git a/MMDVM.ini b/MMDVM.ini index 638118f..a75af4b 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -43,7 +43,7 @@ File=NXDN.csv Time=24 [Modem] -# Valid values are "uart", "udp", and (on Linux) "i2c" +# Valid values are "null", "uart", "udp", and (on Linux) "i2c" Protocol=uart # The port and speed used for a UART connection # UARTPort=\\.\COM4 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index a03fa70..f662289 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -22,10 +22,13 @@ #include "NXDNKenwoodNetwork.h" #include "NXDNIcomNetwork.h" #include "RSSIInterpolator.h" +#include "NullController.h" #include "UARTController.h" +#if defined(__linux__) +#include "I2CController.h" +#endif #include "UDPController.h" #include "MMDVMModem.h" -#include "NullModem.h" #include "Version.h" #include "StopWatch.h" #include "Defines.h" @@ -1404,10 +1407,7 @@ bool CMMDVMHost::createModem() LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset); LogInfo(" Use COS as Lockout: %s", useCOSAsLockout ? "yes" : "no"); - if (protocol == "null") - m_modem = new CNullModem; - else - m_modem = new CMMDVMModem(m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); + m_modem = new CMMDVMModem(m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); IMMDVMModemPort* modem = NULL; if (protocol == "uart") @@ -1418,6 +1418,8 @@ bool CMMDVMHost::createModem() else if (protocol == "i2c") modem = new CI2CController(i2cPort, i2cAddress); #endif + else if (protocol == "null") + modem = new CNullController; else return false; diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 1067b2b..f6a0920 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -209,8 +209,8 @@ + - @@ -319,8 +319,8 @@ + - diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 0a1e4bf..b6efac7 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -263,9 +263,6 @@ Header Files - - Header Files - Header Files @@ -350,6 +347,9 @@ Header Files + + Header Files + @@ -577,9 +577,6 @@ Source Files - - Source Files - Source Files @@ -658,5 +655,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/MMDVMModem.cpp b/MMDVMModem.cpp index bb14094..c6c98c8 100644 --- a/MMDVMModem.cpp +++ b/MMDVMModem.cpp @@ -16,10 +16,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "UARTController.h" -#if defined(__linux__) -#include "I2CController.h" -#endif #include "DStarDefines.h" #include "DMRDefines.h" #include "YSFDefines.h" @@ -30,7 +26,6 @@ #include "M17Defines.h" #include "Thread.h" #include "MMDVMModem.h" -#include "NullModem.h" #include "Utils.h" #include "Log.h" diff --git a/Makefile b/Makefile index d26be33..6ff0e76 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ diff --git a/Makefile.Pi b/Makefile.Pi index 0662f57..ee7be86 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -11,7 +11,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index eeb192a..53cef93 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -12,11 +12,12 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ - NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ - NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ + NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ + POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ + Thread.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 92a7b58..cf4f3cb 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -11,11 +11,12 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ - NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ - NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ + NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ + POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ + Thread.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 42c584d..63a1d52 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -15,7 +15,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ + MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o OLED.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index 0c54640..cce0546 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -12,11 +12,12 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o \ - NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ - NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ - POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ - UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ + NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ + POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ + Thread.o Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o \ + YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/NullController.cpp b/NullController.cpp new file mode 100644 index 0000000..fb48a04 --- /dev/null +++ b/NullController.cpp @@ -0,0 +1,47 @@ +/* +* Copyright (C) 2021 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. +*/ + +#include "NullController.h" + +CNullController::CNullController() +{ +} + +CNullController::~CNullController() +{ +} + +bool CNullController::open() +{ + return true; +} + +int CNullController::read(unsigned char* buffer, unsigned int length) +{ + return 0; +} + +int CNullController::write(const unsigned char* buffer, unsigned int length) +{ + return length; +} + + +void CNullController::close() +{ +} diff --git a/NullController.h b/NullController.h new file mode 100644 index 0000000..5cb39c8 --- /dev/null +++ b/NullController.h @@ -0,0 +1,40 @@ +/* +* Copyright (C) 2021 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. +*/ + +#ifndef NullController_H +#define NullController_H + +#include "MMDVMModemPort.h" + +class CNullController : public IMMDVMModemPort { +public: + CNullController(); + virtual ~CNullController(); + + virtual bool open(); + + virtual int read(unsigned char* buffer, unsigned int length); + + virtual int write(const unsigned char* buffer, unsigned int length); + + virtual void close(); + +private: +}; + +#endif diff --git a/NullModem.cpp b/NullModem.cpp deleted file mode 100644 index 40e3fdd..0000000 --- a/NullModem.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011-2018,2020 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. - */ - -#include "NullModem.h" -#include "Log.h" - -CNullModem::CNullModem() -{ -} - -CNullModem::~CNullModem() -{ -} - -bool CNullModem::open() -{ - ::LogMessage("Opening the MMDVM Null Modem"); - - return true; -} diff --git a/NullModem.h b/NullModem.h deleted file mode 100644 index 442b13e..0000000 --- a/NullModem.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2011-2018,2020,2021 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. - */ - -#ifndef NULLMODEM_H -#define NULLMODEM_H - -#include "Modem.h" -#include "Defines.h" - -#include - -class CNullModem : public IModem { -public: - CNullModem(); - virtual ~CNullModem(); - - virtual void setModem(IMMDVMModemPort* port) {}; - virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) {}; - virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) {}; - virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) {}; - virtual void setDMRParams(unsigned int colorCode) {}; - virtual void setYSFParams(bool loDev, unsigned int txHang) {}; - virtual void setP25Params(unsigned int txHang) {}; - virtual void setNXDNParams(unsigned int txHang) {}; - virtual void setM17Params(unsigned int txHang) {}; - virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) {}; - virtual void setTransparentDataParams(unsigned int sendFrameType) {}; - - virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) {}; - virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) {}; - virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) {}; - virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost) {}; - - virtual bool open(); - - virtual unsigned int readDStarData(unsigned char* data) { return 0U; }; - virtual unsigned int readDMRData1(unsigned char* data) { return 0U; }; - virtual unsigned int readDMRData2(unsigned char* data) { return 0U; }; - virtual unsigned int readYSFData(unsigned char* data) { return 0U; }; - virtual unsigned int readP25Data(unsigned char* data) { return 0U; }; - virtual unsigned int readNXDNData(unsigned char* data) { return 0U; }; - virtual unsigned int readM17Data(unsigned char* data) { return 0U; }; - virtual unsigned int readFMData(unsigned char* data) { return 0U; }; - virtual unsigned int readAX25Data(unsigned char* data) { return 0U; }; - - virtual bool hasDStarSpace()const { return true; }; - virtual bool hasDMRSpace1() const { return true; }; - virtual bool hasDMRSpace2() const { return true; }; - virtual bool hasYSFSpace() const { return true; }; - virtual bool hasP25Space() const { return true; }; - virtual bool hasNXDNSpace() const { return true; }; - virtual bool hasM17Space() const { return true; }; - virtual bool hasPOCSAGSpace() const { return true; }; - virtual unsigned int getFMSpace() const { return true; }; - virtual bool hasAX25Space() const { return true; }; - - virtual bool hasTX() const { return false; }; - virtual bool hasCD() const { return false; }; - - virtual bool hasLockout() const { return false; }; - virtual bool hasError() const { return false; }; - - virtual bool writeDStarData(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeDMRData1(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeDMRData2(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeYSFData(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeP25Data(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeNXDNData(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeM17Data(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writePOCSAGData(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeFMData(const unsigned char* data, unsigned int length) { return true; }; - virtual bool writeAX25Data(const unsigned char* data, unsigned int length) { return true; }; - - virtual bool writeConfig() { return true; }; - virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) { return true; }; - virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) { return true; }; - virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) { return true; }; - virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type) { return true; }; - virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) { return true; }; - virtual bool writeM17Info(const char* source, const char* dest, const char* type) { return true; }; - virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message) { return true; }; - virtual bool writeIPInfo(const std::string& address) { return true; }; - - virtual bool writeDMRStart(bool tx) { return true; }; - virtual bool writeDMRShortLC(const unsigned char* lc) { return true; }; - virtual bool writeDMRAbort(unsigned int slotNo) { return true; }; - - virtual bool writeTransparentData(const unsigned char* data, unsigned int length) { return true; }; - virtual unsigned int readTransparentData(unsigned char* data) { return 0U; }; - - virtual bool writeSerial(const unsigned char* data, unsigned int length) { return true; }; - virtual unsigned int readSerial(unsigned char* data, unsigned int length) { return 0U; }; - - virtual unsigned char getMode() const { return MODE_IDLE; }; - virtual bool setMode(unsigned char mode) { return true; }; - - virtual bool sendCWId(const std::string& callsign) { return true; }; - - virtual HW_TYPE getHWType() const { return HWT_MMDVM; }; - - virtual void clock(unsigned int ms) {}; - - virtual void close() {}; - -private: -}; - -#endif diff --git a/README.md b/README.md index 0b6fe0b..5fe08f0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ POCSAG, FM, and AX.25 on the MMDVM, and D-Star, DMR, and System Fusion on the DV On the D-Star side the MMDVMHost interfaces with the ircDDB Gateway, on DMR it connects to the DMR Gateway to allow for connection to multiple DMR networks, -on System Fusion it connects to the YSF Gateway to allow +or a single network directly. on System Fusion it connects to the YSF Gateway to allow access to the FCS and YSF networks. On P25 it connects to the P25 Gateway. On NXDN it connects to the NXDN Gateway which provides access to the NXDN and NXCore talk groups. On M17 it uses the M17 Gateway to access the M17 reflector system. diff --git a/UDPController.cpp b/UDPController.cpp index 7e38d7c..c8f4b6f 100644 --- a/UDPController.cpp +++ b/UDPController.cpp @@ -28,9 +28,7 @@ CUDPController::CUDPController(const std::string& modemAddress, unsigned int mod m_socket(localPort), m_addr(), m_addrLen(0U), -m_buffer(NULL), -m_length(0U), -m_offset(0U) +m_buffer(2000U, "UDP Controller Ring Buffer") { assert(!modemAddress.empty()); assert(modemPort > 0U); @@ -38,13 +36,10 @@ m_offset(0U) if (CUDPSocket::lookup(modemAddress, modemPort, m_addr, m_addrLen) != 0) m_addrLen = 0U; - - m_buffer = new unsigned char[BUFFER_LENGTH]; } CUDPController::~CUDPController() { - delete[] m_buffer; } bool CUDPController::open() @@ -59,10 +54,32 @@ bool CUDPController::open() int CUDPController::read(unsigned char* buffer, unsigned int length) { - assert(buffer != NULL); - assert(length > 0U); + assert(buffer != NULL); + assert(length > 0U); - return 0; + unsigned char data[BUFFER_LENGTH]; + sockaddr_storage addr; + unsigned int addrLen; + int ret = m_socket.read(data, BUFFER_LENGTH, addr, addrLen); + + // An error occurred on the socket + if (ret < 0) + return ret; + + // Add new data to the ring buffer + if (ret > 0) { + if (CUDPSocket::match(addr, m_addr)) + m_buffer.addData(data, ret); + } + + // Get required data from the ring buffer + unsigned int avail = m_buffer.dataSize(); + if (avail < length) + length = avail; + + m_buffer.getData(buffer, length); + + return int(length); } int CUDPController::write(const unsigned char* buffer, unsigned int length) diff --git a/UDPController.h b/UDPController.h index 6e24eca..acb19e4 100644 --- a/UDPController.h +++ b/UDPController.h @@ -20,6 +20,7 @@ #define UDPController_H #include "MMDVMModemPort.h" +#include "RingBuffer.h" #include "UDPSocket.h" #include @@ -41,9 +42,7 @@ protected: CUDPSocket m_socket; sockaddr_storage m_addr; unsigned int m_addrLen; - unsigned char* m_buffer; - unsigned int m_length; - unsigned int m_offset; + CRingBuffer m_buffer; }; #endif diff --git a/Version.h b/Version.h index 50453e8..f707967 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20210216"; +const char* VERSION = "20210217"; #endif From e291096d227871721f4a89f8bed9f8fb85c28d5d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Wed, 17 Feb 2021 21:36:47 +0000 Subject: [PATCH 4/4] Final modem refactoring. --- CASTInfo.cpp | 4 +- CASTInfo.h | 7 +- DMRControl.cpp | 4 +- DMRControl.h | 6 +- DMRSlot.cpp | 6 +- DMRSlot.h | 6 +- Display.cpp | 2 +- Display.h | 6 +- I2CController.h | 4 +- MMDVMHost.cpp | 15 +- MMDVMHost.h | 4 +- MMDVMHost.vcxproj | 10 +- MMDVMHost.vcxproj.filters | 30 +- MMDVMModem.cpp | 2857 --------------------------- MMDVMModem.h | 285 --- Makefile | 2 +- Makefile.Pi | 2 +- Makefile.Pi.Adafruit | 2 +- Makefile.Pi.HD44780 | 2 +- Makefile.Pi.OLED | 2 +- Makefile.Pi.PCF8574 | 2 +- Modem.cpp | 2838 +++++++++++++++++++++++++- Modem.h | 313 ++- MMDVMModemPort.cpp => ModemPort.cpp | 4 +- MMDVMModemPort.h => ModemPort.h | 8 +- ModemSerialPort.cpp | 4 +- ModemSerialPort.h | 6 +- NullController.h | 4 +- UARTController.h | 4 +- UDPController.h | 4 +- 30 files changed, 3144 insertions(+), 3299 deletions(-) delete mode 100644 MMDVMModem.cpp delete mode 100644 MMDVMModem.h rename MMDVMModemPort.cpp => ModemPort.cpp (92%) rename MMDVMModemPort.h => ModemPort.h (90%) diff --git a/CASTInfo.cpp b/CASTInfo.cpp index 4078d2d..071f320 100644 --- a/CASTInfo.cpp +++ b/CASTInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2018,2020,2021 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 @@ -21,7 +21,7 @@ static bool networkInfoInitialized = false; static unsigned char passCounter = 0; -CCASTInfo::CCASTInfo(IModem* modem) : +CCASTInfo::CCASTInfo(CModem* modem) : CDisplay(), m_modem(modem), m_ipaddress() diff --git a/CASTInfo.h b/CASTInfo.h index 38092b7..41e3955 100644 --- a/CASTInfo.h +++ b/CASTInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2018,2020,2021 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 @@ -25,10 +25,11 @@ #include "NetworkInfo.h" #include "Modem.h" + class CCASTInfo : public CDisplay { public: - CCASTInfo(IModem* modem); + CCASTInfo(CModem* modem); virtual ~CCASTInfo(); virtual bool open(); @@ -67,7 +68,7 @@ protected: virtual void clearCWInt(); private: - IModem* m_modem; + CModem* m_modem; std::string m_ipaddress; }; diff --git a/DMRControl.cpp b/DMRControl.cpp index a5efb21..5761080 100644 --- a/DMRControl.cpp +++ b/DMRControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2021 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 @@ -21,7 +21,7 @@ #include #include -CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) : +CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) : m_colorCode(colorCode), m_modem(modem), m_network(network), diff --git a/DMRControl.h b/DMRControl.h index 31f5f7f..9144194 100644 --- a/DMRControl.h +++ b/DMRControl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021 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 @@ -31,7 +31,7 @@ class CDMRControl { public: - CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm); + CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector& prefixes, const std::vector& blacklist, const std::vector& whitelist, const std::vector& slot1TGWhitelist, const std::vector& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm); ~CDMRControl(); bool processWakeup(const unsigned char* data); @@ -50,7 +50,7 @@ public: private: unsigned int m_colorCode; - IModem* m_modem; + CModem* m_modem; IDMRNetwork* m_network; CDMRSlot m_slot1; CDMRSlot m_slot2; diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 4209860..ea06464 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 Jonathan Naylor, G4KLX + * Copyright (C) 2015-2021 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 @@ -37,7 +37,7 @@ unsigned int CDMRSlot::m_colorCode = 0U; bool CDMRSlot::m_embeddedLCOnly = false; bool CDMRSlot::m_dumpTAData = true; -IModem* CDMRSlot::m_modem = NULL; +CModem* CDMRSlot::m_modem = NULL; IDMRNetwork* CDMRSlot::m_network = NULL; CDisplay* CDMRSlot::m_display = NULL; bool CDMRSlot::m_duplex = true; @@ -1896,7 +1896,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data) m_queue.addData(data, len); } -void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm) +void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm) { assert(modem != NULL); assert(display != NULL); diff --git a/DMRSlot.h b/DMRSlot.h index 789e6ce..62bcc91 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021 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 @@ -62,7 +62,7 @@ public: void enable(bool enabled); - static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm); + static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm); private: unsigned int m_slotNo; @@ -117,7 +117,7 @@ private: static bool m_embeddedLCOnly; static bool m_dumpTAData; - static IModem* m_modem; + static CModem* m_modem; static IDMRNetwork* m_network; static CDisplay* m_display; static bool m_duplex; diff --git a/Display.cpp b/Display.cpp index 5170ea0..16d34ea 100644 --- a/Display.cpp +++ b/Display.cpp @@ -535,7 +535,7 @@ int CDisplay::writeNXDNIntEx(const class CUserDBentry& source, bool group, unsig /* Factory method extracted from MMDVMHost.cpp - BG5HHP */ -CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem) +CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem) { CDisplay *display = NULL; diff --git a/Display.h b/Display.h index c5e7d72..fae929b 100644 --- a/Display.h +++ b/Display.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2021 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 @@ -28,7 +28,7 @@ #include class CConf; -class IModem; +class CModem; class CDisplay { @@ -86,7 +86,7 @@ public: void clock(unsigned int ms); - static CDisplay* createDisplay(const CConf& conf, IModem* modem); + static CDisplay* createDisplay(const CConf& conf, CModem* modem); protected: virtual void setIdleInt() = 0; diff --git a/I2CController.h b/I2CController.h index 19298ca..b178af3 100644 --- a/I2CController.h +++ b/I2CController.h @@ -22,12 +22,12 @@ #if defined(__linux__) -#include "MMDVMModemPort.h" +#include "ModemPort.h" #include "SerialPort.h" #include -class CI2CController : public ISerialPort, public IMMDVMModemPort { +class CI2CController : public ISerialPort, public IModemPort { public: CI2CController(const std::string& device, unsigned int address = 0x22U); virtual ~CI2CController(); diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index f662289..b4d9a4a 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -28,7 +28,6 @@ #include "I2CController.h" #endif #include "UDPController.h" -#include "MMDVMModem.h" #include "Version.h" #include "StopWatch.h" #include "Defines.h" @@ -1407,23 +1406,23 @@ bool CMMDVMHost::createModem() LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset); LogInfo(" Use COS as Lockout: %s", useCOSAsLockout ? "yes" : "no"); - m_modem = new CMMDVMModem(m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); + m_modem = new CModem(m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug); - IMMDVMModemPort* modem = NULL; + IModemPort* port = NULL; if (protocol == "uart") - modem = new CUARTController(uartPort, uartSpeed, true); + port = new CUARTController(uartPort, uartSpeed, true); else if (protocol == "udp") - modem = new CUDPController(modemAddress, modemPort, localPort); + port = new CUDPController(modemAddress, modemPort, localPort); #if defined(__linux__) else if (protocol == "i2c") - modem = new CI2CController(i2cPort, i2cAddress); + port = new CI2CController(i2cPort, i2cAddress); #endif else if (protocol == "null") - modem = new CNullController; + port = new CNullController; else return false; - m_modem->setModem(modem); + m_modem->setPort(port); m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled); m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel); m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency); diff --git a/MMDVMHost.h b/MMDVMHost.h index c69318c..aeb02ef 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 by Jonathan Naylor G4KLX + * Copyright (C) 2015-2021 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 @@ -58,7 +58,7 @@ public: private: CConf m_conf; - IModem* m_modem; + CModem* m_modem; CDStarControl* m_dstar; CDMRControl* m_dmr; CYSFControl* m_ysf; diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index f6a0920..182f62a 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -203,8 +203,7 @@ - - + @@ -245,7 +244,7 @@ - + @@ -313,8 +312,7 @@ - - + @@ -351,7 +349,7 @@ - + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index b6efac7..36320cd 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -56,9 +56,6 @@ Header Files - - Header Files - Header Files @@ -335,21 +332,21 @@ Header Files - - Header Files - Header Files - - Header Files - Header Files Header Files + + Header Files + + + Header Files + @@ -388,9 +385,6 @@ Source Files - - Source Files - Source Files @@ -643,20 +637,20 @@ Source Files - - Source Files - Source Files - - Source Files - Source Files Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/MMDVMModem.cpp b/MMDVMModem.cpp deleted file mode 100644 index c6c98c8..0000000 --- a/MMDVMModem.cpp +++ /dev/null @@ -1,2857 +0,0 @@ -/* - * Copyright (C) 2011-2018,2020,2021 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. - */ - -#include "DStarDefines.h" -#include "DMRDefines.h" -#include "YSFDefines.h" -#include "P25Defines.h" -#include "NXDNDefines.h" -#include "AX25Defines.h" -#include "POCSAGDefines.h" -#include "M17Defines.h" -#include "Thread.h" -#include "MMDVMModem.h" -#include "Utils.h" -#include "Log.h" - -#include -#include -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) -#include -#else -#include -#endif - -const unsigned char MMDVM_FRAME_START = 0xE0U; - -const unsigned char MMDVM_GET_VERSION = 0x00U; -const unsigned char MMDVM_GET_STATUS = 0x01U; -const unsigned char MMDVM_SET_CONFIG = 0x02U; -const unsigned char MMDVM_SET_MODE = 0x03U; -const unsigned char MMDVM_SET_FREQ = 0x04U; - -const unsigned char MMDVM_SEND_CWID = 0x0AU; - -const unsigned char MMDVM_DSTAR_HEADER = 0x10U; -const unsigned char MMDVM_DSTAR_DATA = 0x11U; -const unsigned char MMDVM_DSTAR_LOST = 0x12U; -const unsigned char MMDVM_DSTAR_EOT = 0x13U; - -const unsigned char MMDVM_DMR_DATA1 = 0x18U; -const unsigned char MMDVM_DMR_LOST1 = 0x19U; -const unsigned char MMDVM_DMR_DATA2 = 0x1AU; -const unsigned char MMDVM_DMR_LOST2 = 0x1BU; -const unsigned char MMDVM_DMR_SHORTLC = 0x1CU; -const unsigned char MMDVM_DMR_START = 0x1DU; -const unsigned char MMDVM_DMR_ABORT = 0x1EU; - -const unsigned char MMDVM_YSF_DATA = 0x20U; -const unsigned char MMDVM_YSF_LOST = 0x21U; - -const unsigned char MMDVM_P25_HDR = 0x30U; -const unsigned char MMDVM_P25_LDU = 0x31U; -const unsigned char MMDVM_P25_LOST = 0x32U; - -const unsigned char MMDVM_NXDN_DATA = 0x40U; -const unsigned char MMDVM_NXDN_LOST = 0x41U; - -const unsigned char MMDVM_M17_HEADER = 0x45U; -const unsigned char MMDVM_M17_DATA = 0x46U; -const unsigned char MMDVM_M17_LOST = 0x47U; - -const unsigned char MMDVM_POCSAG_DATA = 0x50U; - -const unsigned char MMDVM_AX25_DATA = 0x55U; - -const unsigned char MMDVM_FM_PARAMS1 = 0x60U; -const unsigned char MMDVM_FM_PARAMS2 = 0x61U; -const unsigned char MMDVM_FM_PARAMS3 = 0x62U; -const unsigned char MMDVM_FM_PARAMS4 = 0x63U; -const unsigned char MMDVM_FM_DATA = 0x65U; -const unsigned char MMDVM_FM_CONTROL = 0x66U; -const unsigned char MMDVM_FM_EOT = 0x67U; - -const unsigned char MMDVM_ACK = 0x70U; -const unsigned char MMDVM_NAK = 0x7FU; - -const unsigned char MMDVM_SERIAL_DATA = 0x80U; - -const unsigned char MMDVM_TRANSPARENT = 0x90U; -const unsigned char MMDVM_QSO_INFO = 0x91U; - -const unsigned char MMDVM_DEBUG1 = 0xF1U; -const unsigned char MMDVM_DEBUG2 = 0xF2U; -const unsigned char MMDVM_DEBUG3 = 0xF3U; -const unsigned char MMDVM_DEBUG4 = 0xF4U; -const unsigned char MMDVM_DEBUG5 = 0xF5U; - -const unsigned int MAX_RESPONSES = 30U; - -const unsigned int BUFFER_LENGTH = 2000U; - - -CMMDVMModem::CMMDVMModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : -m_protocolVersion(0U), -m_dmrColorCode(0U), -m_ysfLoDev(false), -m_ysfTXHang(4U), -m_p25TXHang(5U), -m_nxdnTXHang(5U), -m_m17TXHang(5U), -m_duplex(duplex), -m_rxInvert(rxInvert), -m_txInvert(txInvert), -m_pttInvert(pttInvert), -m_txDelay(txDelay), -m_dmrDelay(dmrDelay), -m_rxLevel(0.0F), -m_cwIdTXLevel(0.0F), -m_dstarTXLevel(0.0F), -m_dmrTXLevel(0.0F), -m_ysfTXLevel(0.0F), -m_p25TXLevel(0.0F), -m_nxdnTXLevel(0.0F), -m_m17TXLevel(0.0F), -m_pocsagTXLevel(0.0F), -m_fmTXLevel(0.0F), -m_ax25TXLevel(0.0F), -m_rfLevel(0.0F), -m_useCOSAsLockout(useCOSAsLockout), -m_trace(trace), -m_debug(debug), -m_rxFrequency(0U), -m_txFrequency(0U), -m_pocsagFrequency(0U), -m_dstarEnabled(false), -m_dmrEnabled(false), -m_ysfEnabled(false), -m_p25Enabled(false), -m_nxdnEnabled(false), -m_m17Enabled(false), -m_pocsagEnabled(false), -m_fmEnabled(false), -m_ax25Enabled(false), -m_rxDCOffset(0), -m_txDCOffset(0), -m_port(NULL), -m_buffer(NULL), -m_length(0U), -m_offset(0U), -m_state(SS_START), -m_type(0U), -m_rxDStarData(1000U, "Modem RX D-Star"), -m_txDStarData(1000U, "Modem TX D-Star"), -m_rxDMRData1(1000U, "Modem RX DMR1"), -m_rxDMRData2(1000U, "Modem RX DMR2"), -m_txDMRData1(1000U, "Modem TX DMR1"), -m_txDMRData2(1000U, "Modem TX DMR2"), -m_rxYSFData(1000U, "Modem RX YSF"), -m_txYSFData(1000U, "Modem TX YSF"), -m_rxP25Data(1000U, "Modem RX P25"), -m_txP25Data(1000U, "Modem TX P25"), -m_rxNXDNData(1000U, "Modem RX NXDN"), -m_txNXDNData(1000U, "Modem TX NXDN"), -m_rxM17Data(1000U, "Modem RX M17"), -m_txM17Data(1000U, "Modem TX M17"), -m_txPOCSAGData(1000U, "Modem TX POCSAG"), -m_rxFMData(5000U, "Modem RX FM"), -m_txFMData(5000U, "Modem TX FM"), -m_rxAX25Data(1000U, "Modem RX AX.25"), -m_txAX25Data(1000U, "Modem TX AX.25"), -m_rxSerialData(1000U, "Modem RX Serial"), -m_txSerialData(1000U, "Modem TX Serial"), -m_rxTransparentData(1000U, "Modem RX Transparent"), -m_txTransparentData(1000U, "Modem TX Transparent"), -m_sendTransparentDataFrameType(0U), -m_statusTimer(1000U, 0U, 250U), -m_inactivityTimer(1000U, 2U), -m_playoutTimer(1000U, 0U, 10U), -m_dstarSpace(0U), -m_dmrSpace1(0U), -m_dmrSpace2(0U), -m_ysfSpace(0U), -m_p25Space(0U), -m_nxdnSpace(0U), -m_m17Space(0U), -m_pocsagSpace(0U), -m_fmSpace(0U), -m_ax25Space(0U), -m_tx(false), -m_cd(false), -m_lockout(false), -m_error(false), -m_mode(MODE_IDLE), -m_hwType(HWT_UNKNOWN), -m_ax25RXTwist(0), -m_ax25TXDelay(300U), -m_ax25SlotTime(30U), -m_ax25PPersist(128U), -m_fmCallsign(), -m_fmCallsignSpeed(20U), -m_fmCallsignFrequency(1000U), -m_fmCallsignTime(600U), -m_fmCallsignHoldoff(0U), -m_fmCallsignHighLevel(35.0F), -m_fmCallsignLowLevel(15.0F), -m_fmCallsignAtStart(true), -m_fmCallsignAtEnd(true), -m_fmCallsignAtLatch(true), -m_fmRfAck("K"), -m_fmExtAck("N"), -m_fmAckSpeed(20U), -m_fmAckFrequency(1750U), -m_fmAckMinTime(4U), -m_fmAckDelay(1000U), -m_fmAckLevel(80.0F), -m_fmTimeout(120U), -m_fmTimeoutLevel(80.0F), -m_fmCtcssFrequency(88.4F), -m_fmCtcssHighThreshold(30U), -m_fmCtcssLowThreshold(20U), -m_fmCtcssLevel(10.0F), -m_fmKerchunkTime(0U), -m_fmHangTime(5U), -m_fmAccessMode(1U), -m_fmCOSInvert(false), -m_fmNoiseSquelch(false), -m_fmSquelchHighThreshold(30U), -m_fmSquelchLowThreshold(20U), -m_fmRFAudioBoost(1U), -m_fmExtAudioBoost(1U), -m_fmMaxDevLevel(90.0F), -m_fmExtEnable(false) -{ - m_buffer = new unsigned char[BUFFER_LENGTH]; -} - -CMMDVMModem::~CMMDVMModem() -{ - delete m_port; - delete[] m_buffer; -} - -void CMMDVMModem::setModem(IMMDVMModemPort* port) -{ - assert(port != NULL); - - m_port = port; -} - -void CMMDVMModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) -{ - m_rxFrequency = rxFrequency + rxOffset; - m_txFrequency = txFrequency + txOffset; - m_txDCOffset = txDCOffset; - m_rxDCOffset = rxDCOffset; - m_rfLevel = rfLevel; - m_pocsagFrequency = pocsagFrequency + txOffset; -} - -void CMMDVMModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) -{ - m_dstarEnabled = dstarEnabled; - m_dmrEnabled = dmrEnabled; - m_ysfEnabled = ysfEnabled; - m_p25Enabled = p25Enabled; - m_nxdnEnabled = nxdnEnabled; - m_m17Enabled = m17Enabled; - m_pocsagEnabled = pocsagEnabled; - m_fmEnabled = fmEnabled; - m_ax25Enabled = ax25Enabled; -} - -void CMMDVMModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel) -{ - m_rxLevel = rxLevel; - m_cwIdTXLevel = cwIdTXLevel; - m_dstarTXLevel = dstarTXLevel; - m_dmrTXLevel = dmrTXLevel; - m_ysfTXLevel = ysfTXLevel; - m_p25TXLevel = p25TXLevel; - m_nxdnTXLevel = nxdnTXLevel; - m_m17TXLevel = m17TXLevel; - m_pocsagTXLevel = pocsagTXLevel; - m_fmTXLevel = fmTXLevel; - m_ax25TXLevel = ax25TXLevel; -} - -void CMMDVMModem::setDMRParams(unsigned int colorCode) -{ - assert(colorCode < 16U); - - m_dmrColorCode = colorCode; -} - -void CMMDVMModem::setYSFParams(bool loDev, unsigned int txHang) -{ - m_ysfLoDev = loDev; - m_ysfTXHang = txHang; -} - -void CMMDVMModem::setP25Params(unsigned int txHang) -{ - m_p25TXHang = txHang; -} - -void CMMDVMModem::setNXDNParams(unsigned int txHang) -{ - m_nxdnTXHang = txHang; -} - -void CMMDVMModem::setM17Params(unsigned int txHang) -{ - m_m17TXHang = txHang; -} - -void CMMDVMModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) -{ - m_ax25RXTwist = rxTwist; - m_ax25TXDelay = txDelay; - m_ax25SlotTime = slotTime; - m_ax25PPersist = pPersist; -} - -void CMMDVMModem::setTransparentDataParams(unsigned int sendFrameType) -{ - m_sendTransparentDataFrameType = sendFrameType; -} - -bool CMMDVMModem::open() -{ - ::LogMessage("Opening the MMDVM"); - - bool ret = m_port->open(); - if (!ret) - return false; - - ret = readVersion(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } else { - /* Stopping the inactivity timer here when a firmware version has been - successfuly read prevents the death spiral of "no reply from modem..." */ - m_inactivityTimer.stop(); - } - - ret = setFrequency(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - - ret = writeConfig(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - - if (m_fmEnabled && m_duplex) { - ret = setFMCallsignParams(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - - ret = setFMAckParams(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - - ret = setFMMiscParams(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - - if (m_fmExtEnable) { - ret = setFMExtParams(); - if (!ret) { - m_port->close(); - delete m_port; - m_port = NULL; - return false; - } - } - } - - m_statusTimer.start(); - - m_error = false; - m_offset = 0U; - - return true; -} - -void CMMDVMModem::clock(unsigned int ms) -{ - assert(m_port != NULL); - - // Poll the modem status every 250ms - m_statusTimer.clock(ms); - if (m_statusTimer.hasExpired()) { - readStatus(); - m_statusTimer.start(); - } - - m_inactivityTimer.clock(ms); - if (m_inactivityTimer.hasExpired()) { - LogError("No reply from the modem for some time, resetting it"); - m_error = true; - close(); - - CThread::sleep(2000U); // 2s - while (!open()) - CThread::sleep(5000U); // 5s - } - - RESP_TYPE_MMDVM type = getResponse(); - - if (type == RTM_TIMEOUT) { - // Nothing to do - } else if (type == RTM_ERROR) { - // Nothing to do - } else { - // type == RTM_OK - switch (m_type) { - case MMDVM_DSTAR_HEADER: { - if (m_trace) - CUtils::dump(1U, "RX D-Star Header", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxDStarData.addData(&data, 1U); - - data = TAG_HEADER; - m_rxDStarData.addData(&data, 1U); - - m_rxDStarData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_DSTAR_DATA: { - if (m_trace) - CUtils::dump(1U, "RX D-Star Data", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxDStarData.addData(&data, 1U); - - data = TAG_DATA; - m_rxDStarData.addData(&data, 1U); - - m_rxDStarData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_DSTAR_LOST: { - if (m_trace) - CUtils::dump(1U, "RX D-Star Lost", m_buffer, m_length); - - unsigned char data = 1U; - m_rxDStarData.addData(&data, 1U); - - data = TAG_LOST; - m_rxDStarData.addData(&data, 1U); - } - break; - - case MMDVM_DSTAR_EOT: { - if (m_trace) - CUtils::dump(1U, "RX D-Star EOT", m_buffer, m_length); - - unsigned char data = 1U; - m_rxDStarData.addData(&data, 1U); - - data = TAG_EOT; - m_rxDStarData.addData(&data, 1U); - } - break; - - case MMDVM_DMR_DATA1: { - if (m_trace) - CUtils::dump(1U, "RX DMR Data 1", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxDMRData1.addData(&data, 1U); - - if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC)) - data = TAG_EOT; - else - data = TAG_DATA; - m_rxDMRData1.addData(&data, 1U); - - m_rxDMRData1.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_DMR_DATA2: { - if (m_trace) - CUtils::dump(1U, "RX DMR Data 2", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxDMRData2.addData(&data, 1U); - - if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC)) - data = TAG_EOT; - else - data = TAG_DATA; - m_rxDMRData2.addData(&data, 1U); - - m_rxDMRData2.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_DMR_LOST1: { - if (m_trace) - CUtils::dump(1U, "RX DMR Lost 1", m_buffer, m_length); - - unsigned char data = 1U; - m_rxDMRData1.addData(&data, 1U); - - data = TAG_LOST; - m_rxDMRData1.addData(&data, 1U); - } - break; - - case MMDVM_DMR_LOST2: { - if (m_trace) - CUtils::dump(1U, "RX DMR Lost 2", m_buffer, m_length); - - unsigned char data = 1U; - m_rxDMRData2.addData(&data, 1U); - - data = TAG_LOST; - m_rxDMRData2.addData(&data, 1U); - } - break; - - case MMDVM_YSF_DATA: { - if (m_trace) - CUtils::dump(1U, "RX YSF Data", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxYSFData.addData(&data, 1U); - - data = TAG_DATA; - m_rxYSFData.addData(&data, 1U); - - m_rxYSFData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_YSF_LOST: { - if (m_trace) - CUtils::dump(1U, "RX YSF Lost", m_buffer, m_length); - - unsigned char data = 1U; - m_rxYSFData.addData(&data, 1U); - - data = TAG_LOST; - m_rxYSFData.addData(&data, 1U); - } - break; - - case MMDVM_P25_HDR: { - if (m_trace) - CUtils::dump(1U, "RX P25 Header", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxP25Data.addData(&data, 1U); - - data = TAG_HEADER; - m_rxP25Data.addData(&data, 1U); - - m_rxP25Data.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_P25_LDU: { - if (m_trace) - CUtils::dump(1U, "RX P25 LDU", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxP25Data.addData(&data, 1U); - - data = TAG_DATA; - m_rxP25Data.addData(&data, 1U); - - m_rxP25Data.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_P25_LOST: { - if (m_trace) - CUtils::dump(1U, "RX P25 Lost", m_buffer, m_length); - - unsigned char data = 1U; - m_rxP25Data.addData(&data, 1U); - - data = TAG_LOST; - m_rxP25Data.addData(&data, 1U); - } - break; - - case MMDVM_NXDN_DATA: { - if (m_trace) - CUtils::dump(1U, "RX NXDN Data", m_buffer, m_length); - - unsigned char data = m_length - m_offset + 1U; - m_rxNXDNData.addData(&data, 1U); - - data = TAG_DATA; - m_rxNXDNData.addData(&data, 1U); - - m_rxNXDNData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_NXDN_LOST: { - if (m_trace) - CUtils::dump(1U, "RX NXDN Lost", m_buffer, m_length); - - unsigned char data = 1U; - m_rxNXDNData.addData(&data, 1U); - - data = TAG_LOST; - m_rxNXDNData.addData(&data, 1U); - } - break; - - case MMDVM_M17_HEADER: { - if (m_trace) - CUtils::dump(1U, "RX M17 Header", m_buffer, m_length); - - unsigned char data = m_length - 2U; - m_rxM17Data.addData(&data, 1U); - - data = TAG_HEADER; - m_rxM17Data.addData(&data, 1U); - - m_rxM17Data.addData(m_buffer + 3U, m_length - 3U); - } - break; - - case MMDVM_M17_DATA: { - if (m_trace) - CUtils::dump(1U, "RX M17 Data", m_buffer, m_length); - - unsigned char data = m_length - 2U; - m_rxM17Data.addData(&data, 1U); - - data = TAG_DATA; - m_rxM17Data.addData(&data, 1U); - - m_rxM17Data.addData(m_buffer + 3U, m_length - 3U); - } - break; - - case MMDVM_M17_LOST: { - if (m_trace) - CUtils::dump(1U, "RX M17 Lost", m_buffer, m_length); - - unsigned char data = 1U; - m_rxM17Data.addData(&data, 1U); - - data = TAG_LOST; - m_rxM17Data.addData(&data, 1U); - } - break; - - case MMDVM_FM_DATA: { - if (m_trace) - CUtils::dump(1U, "RX FM Data", m_buffer, m_length); - - unsigned int data1 = m_length - m_offset + 1U; - m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); - - unsigned char data2 = TAG_DATA; - m_rxFMData.addData(&data2, 1U); - - m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_FM_CONTROL: { - if (m_trace) - CUtils::dump(1U, "RX FM Control", m_buffer, m_length); - - unsigned int data1 = m_length - m_offset + 1U; - m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); - - unsigned char data2= TAG_HEADER; - m_rxFMData.addData(&data2, 1U); - - m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_FM_EOT: { - if(m_trace) - CUtils::dump(1U, "RX FM End of transmission", m_buffer, m_length); - - unsigned int data1 = m_length - m_offset + 1U; - m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); - - unsigned char data2 = TAG_EOT; - m_rxFMData.addData(&data2, 1U); - - m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_AX25_DATA: { - if (m_trace) - CUtils::dump(1U, "RX AX.25 Data", m_buffer, m_length); - - unsigned int data = m_length - m_offset; - m_rxAX25Data.addData((unsigned char*)&data, sizeof(unsigned int)); - - m_rxAX25Data.addData(m_buffer + m_offset, m_length - m_offset); - } - break; - - case MMDVM_GET_STATUS: - // if (m_trace) - // CUtils::dump(1U, "GET_STATUS", m_buffer, m_length); - - switch (m_protocolVersion) { - case 1U: { - m_mode = m_buffer[m_offset + 1U]; - - m_tx = (m_buffer[m_offset + 2U] & 0x01U) == 0x01U; - bool adcOverflow = (m_buffer[m_offset + 2U] & 0x02U) == 0x02U; - if (adcOverflow) - LogError("MMDVM ADC levels have overflowed"); - bool rxOverflow = (m_buffer[m_offset + 2U] & 0x04U) == 0x04U; - if (rxOverflow) - LogError("MMDVM RX buffer has overflowed"); - bool txOverflow = (m_buffer[m_offset + 2U] & 0x08U) == 0x08U; - if (txOverflow) - LogError("MMDVM TX buffer has overflowed"); - m_lockout = (m_buffer[m_offset + 2U] & 0x10U) == 0x10U; - bool dacOverflow = (m_buffer[m_offset + 2U] & 0x20U) == 0x20U; - if (dacOverflow) - LogError("MMDVM DAC levels have overflowed"); - m_cd = (m_buffer[m_offset + 2U] & 0x40U) == 0x40U; - - m_p25Space = 0U; - m_nxdnSpace = 0U; - m_m17Space = 0U; - m_pocsagSpace = 0U; - m_fmSpace = 0U; - m_ax25Space = 0U; - - m_dstarSpace = m_buffer[m_offset + 3U]; - m_dmrSpace1 = m_buffer[m_offset + 4U]; - m_dmrSpace2 = m_buffer[m_offset + 5U]; - m_ysfSpace = m_buffer[m_offset + 6U]; - - // The following depend on the version of the firmware - if (m_length > (m_offset + 7U)) - m_p25Space = m_buffer[m_offset + 7U]; - if (m_length > (m_offset + 8U)) - m_nxdnSpace = m_buffer[m_offset + 8U]; - if (m_length > (m_offset + 9U)) - m_pocsagSpace = m_buffer[m_offset + 9U]; - if (m_length > (m_offset + 10U)) - m_m17Space = m_buffer[m_offset + 10U]; - } - break; - - case 2U: { - m_mode = m_buffer[m_offset + 0U]; - - m_tx = (m_buffer[m_offset + 1U] & 0x01U) == 0x01U; - bool adcOverflow = (m_buffer[m_offset + 1U] & 0x02U) == 0x02U; - if (adcOverflow) - LogError("MMDVM ADC levels have overflowed"); - bool rxOverflow = (m_buffer[m_offset + 1U] & 0x04U) == 0x04U; - if (rxOverflow) - LogError("MMDVM RX buffer has overflowed"); - bool txOverflow = (m_buffer[m_offset + 1U] & 0x08U) == 0x08U; - if (txOverflow) - LogError("MMDVM TX buffer has overflowed"); - m_lockout = (m_buffer[m_offset + 1U] & 0x10U) == 0x10U; - bool dacOverflow = (m_buffer[m_offset + 1U] & 0x20U) == 0x20U; - if (dacOverflow) - LogError("MMDVM DAC levels have overflowed"); - m_cd = (m_buffer[m_offset + 1U] & 0x40U) == 0x40U; - - m_dstarSpace = m_buffer[m_offset + 3U]; - m_dmrSpace1 = m_buffer[m_offset + 4U]; - m_dmrSpace2 = m_buffer[m_offset + 5U]; - m_ysfSpace = m_buffer[m_offset + 6U]; - m_p25Space = m_buffer[m_offset + 7U]; - m_nxdnSpace = m_buffer[m_offset + 8U]; - m_m17Space = m_buffer[m_offset + 9U]; - m_fmSpace = m_buffer[m_offset + 10U]; - m_pocsagSpace = m_buffer[m_offset + 11U]; - m_ax25Space = m_buffer[m_offset + 12U]; - } - break; - - default: - m_dstarSpace = 0U; - m_dmrSpace1 = 0U; - m_dmrSpace2 = 0U; - m_ysfSpace = 0U; - m_p25Space = 0U; - m_nxdnSpace = 0U; - m_m17Space = 0U; - m_pocsagSpace = 0U; - m_fmSpace = 0U; - m_ax25Space = 0U; - break; - } - - m_inactivityTimer.start(); - // LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_m17Space, m_pocsagSpace, m_fmSpace, m_ax25Space, int(m_lockout), int(m_cd)); - break; - - case MMDVM_TRANSPARENT: { - if (m_trace) - CUtils::dump(1U, "RX Transparent Data", m_buffer, m_length); - - unsigned char offset = m_sendTransparentDataFrameType; - if (offset > 1U) offset = 1U; - unsigned char data = m_length - m_offset + offset; - m_rxTransparentData.addData(&data, 1U); - - m_rxTransparentData.addData(m_buffer + m_offset - offset, m_length - m_offset + offset); - } - break; - - // These should not be received, but don't complain if we do - case MMDVM_GET_VERSION: - case MMDVM_ACK: - break; - - case MMDVM_NAK: - LogWarning("Received a NAK from the MMDVM, command = 0x%02X, reason = %u", m_buffer[m_offset], m_buffer[m_offset + 1U]); - break; - - case MMDVM_DEBUG1: - case MMDVM_DEBUG2: - case MMDVM_DEBUG3: - case MMDVM_DEBUG4: - case MMDVM_DEBUG5: - printDebug(); - break; - - case MMDVM_SERIAL_DATA: - if (m_trace) - CUtils::dump(1U, "RX Serial Data", m_buffer, m_length); - m_rxSerialData.addData(m_buffer + m_offset, m_length - m_offset); - break; - - default: - LogMessage("Unknown message, type: %02X", m_type); - CUtils::dump("Buffer dump", m_buffer, m_length); - break; - } - } - - // Only feed data to the modem if the playout timer has expired - m_playoutTimer.clock(ms); - if (!m_playoutTimer.hasExpired()) - return; - - if (m_dstarSpace > 1U && !m_txDStarData.isEmpty()) { - unsigned char buffer[4U]; - m_txDStarData.peek(buffer, 4U); - - if ((buffer[3U] == MMDVM_DSTAR_HEADER && m_dstarSpace > 4U) || - (buffer[3U] == MMDVM_DSTAR_DATA && m_dstarSpace > 1U) || - (buffer[3U] == MMDVM_DSTAR_EOT && m_dstarSpace > 1U)) { - unsigned char len = 0U; - m_txDStarData.getData(&len, 1U); - m_txDStarData.getData(m_buffer, len); - - switch (buffer[3U]) { - case MMDVM_DSTAR_HEADER: - if (m_trace) - CUtils::dump(1U, "TX D-Star Header", m_buffer, len); - m_dstarSpace -= 4U; - break; - case MMDVM_DSTAR_DATA: - if (m_trace) - CUtils::dump(1U, "TX D-Star Data", m_buffer, len); - m_dstarSpace -= 1U; - break; - default: - if (m_trace) - CUtils::dump(1U, "TX D-Star EOT", m_buffer, len); - m_dstarSpace -= 1U; - break; - } - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing D-Star data to the MMDVM"); - - m_playoutTimer.start(); - } - } - - if (m_dmrSpace1 > 1U && !m_txDMRData1.isEmpty()) { - unsigned char len = 0U; - m_txDMRData1.getData(&len, 1U); - m_txDMRData1.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX DMR Data 1", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing DMR data to the MMDVM"); - - m_playoutTimer.start(); - - m_dmrSpace1--; - } - - if (m_dmrSpace2 > 1U && !m_txDMRData2.isEmpty()) { - unsigned char len = 0U; - m_txDMRData2.getData(&len, 1U); - m_txDMRData2.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX DMR Data 2", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing DMR data to the MMDVM"); - - m_playoutTimer.start(); - - m_dmrSpace2--; - } - - if (m_ysfSpace > 1U && !m_txYSFData.isEmpty()) { - unsigned char len = 0U; - m_txYSFData.getData(&len, 1U); - m_txYSFData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX YSF Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing YSF data to the MMDVM"); - - m_playoutTimer.start(); - - m_ysfSpace--; - } - - if (m_p25Space > 1U && !m_txP25Data.isEmpty()) { - unsigned char len = 0U; - m_txP25Data.getData(&len, 1U); - m_txP25Data.getData(m_buffer, len); - - if (m_trace) { - if (m_buffer[2U] == MMDVM_P25_HDR) - CUtils::dump(1U, "TX P25 HDR", m_buffer, len); - else - CUtils::dump(1U, "TX P25 LDU", m_buffer, len); - } - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing P25 data to the MMDVM"); - - m_playoutTimer.start(); - - m_p25Space--; - } - - if (m_nxdnSpace > 1U && !m_txNXDNData.isEmpty()) { - unsigned char len = 0U; - m_txNXDNData.getData(&len, 1U); - m_txNXDNData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX NXDN Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing NXDN data to the MMDVM"); - - m_playoutTimer.start(); - - m_nxdnSpace--; - } - - if (m_m17Space > 1U && !m_txM17Data.isEmpty()) { - unsigned char len = 0U; - m_txM17Data.getData(&len, 1U); - m_txM17Data.getData(m_buffer, len); - - if (m_trace) { - if (m_buffer[2U] == MMDVM_M17_HEADER) - CUtils::dump(1U, "TX M17 Header", m_buffer, len); - else - CUtils::dump(1U, "TX M17 Data", m_buffer, len); - } - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing M17 data to the MMDVM"); - - m_playoutTimer.start(); - - m_m17Space--; - } - - if (m_pocsagSpace > 1U && !m_txPOCSAGData.isEmpty()) { - unsigned char len = 0U; - m_txPOCSAGData.getData(&len, 1U); - m_txPOCSAGData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX POCSAG Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing POCSAG data to the MMDVM"); - - m_playoutTimer.start(); - - m_pocsagSpace--; - } - - if (m_fmSpace > 1U && !m_txFMData.isEmpty()) { - unsigned int len = 0U; - m_txFMData.getData((unsigned char*)&len, sizeof(unsigned int)); - m_txFMData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX FM Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing FM data to the MMDVM"); - - m_playoutTimer.start(); - - m_fmSpace--; - } - - if (m_ax25Space > 0U && !m_txAX25Data.isEmpty()) { - unsigned int len = 0U; - m_txAX25Data.getData((unsigned char*)&len, sizeof(unsigned int)); - m_txAX25Data.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX AX.25 Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing AX.25 data to the MMDVM"); - - m_playoutTimer.start(); - - m_ax25Space = 0U; - } - - if (!m_txTransparentData.isEmpty()) { - unsigned char len = 0U; - m_txTransparentData.getData(&len, 1U); - m_txTransparentData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX Transparent Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing Transparent data to the MMDVM"); - } - - if (!m_txSerialData.isEmpty()) { - unsigned char len = 0U; - m_txSerialData.getData(&len, 1U); - m_txSerialData.getData(m_buffer, len); - - if (m_trace) - CUtils::dump(1U, "TX Serial Data", m_buffer, len); - - int ret = m_port->write(m_buffer, len); - if (ret != int(len)) - LogWarning("Error when writing Serial data to the MMDVM"); - } -} - -void CMMDVMModem::close() -{ - assert(m_port != NULL); - - ::LogMessage("Closing the MMDVM"); - - m_port->close(); -} - -unsigned int CMMDVMModem::readDStarData(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxDStarData.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxDStarData.getData(&len, 1U); - m_rxDStarData.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readDMRData1(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxDMRData1.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxDMRData1.getData(&len, 1U); - m_rxDMRData1.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readDMRData2(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxDMRData2.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxDMRData2.getData(&len, 1U); - m_rxDMRData2.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readYSFData(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxYSFData.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxYSFData.getData(&len, 1U); - m_rxYSFData.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readP25Data(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxP25Data.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxP25Data.getData(&len, 1U); - m_rxP25Data.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readNXDNData(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxNXDNData.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxNXDNData.getData(&len, 1U); - m_rxNXDNData.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readM17Data(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxM17Data.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxM17Data.getData(&len, 1U); - m_rxM17Data.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readFMData(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxFMData.isEmpty()) - return 0U; - - unsigned int len = 0U; - m_rxFMData.getData((unsigned char*)&len, sizeof(unsigned int)); - m_rxFMData.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readAX25Data(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxAX25Data.isEmpty()) - return 0U; - - unsigned int len = 0U; - m_rxAX25Data.getData((unsigned char*)&len, sizeof(unsigned int)); - m_rxAX25Data.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readTransparentData(unsigned char* data) -{ - assert(data != NULL); - - if (m_rxTransparentData.isEmpty()) - return 0U; - - unsigned char len = 0U; - m_rxTransparentData.getData(&len, 1U); - m_rxTransparentData.getData(data, len); - - return len; -} - -unsigned int CMMDVMModem::readSerial(unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned int n = 0U; - while (!m_rxSerialData.isEmpty() && n < length) { - m_rxSerialData.getData(data + n, 1U); - n++; - } - - return n; -} - -bool CMMDVMModem::hasDStarSpace() const -{ - unsigned int space = m_txDStarData.freeSpace() / (DSTAR_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeDStarData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[50U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - - switch (data[0U]) { - case TAG_HEADER: - buffer[2U] = MMDVM_DSTAR_HEADER; - break; - case TAG_DATA: - buffer[2U] = MMDVM_DSTAR_DATA; - break; - case TAG_EOT: - buffer[2U] = MMDVM_DSTAR_EOT; - break; - default: - CUtils::dump(2U, "Unknown D-Star packet type", data, length); - return false; - } - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txDStarData.addData(&len, 1U); - m_txDStarData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasDMRSpace1() const -{ - unsigned int space = m_txDMRData1.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::hasDMRSpace2() const -{ - unsigned int space = m_txDMRData2.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeDMRData1(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = MMDVM_DMR_DATA1; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txDMRData1.addData(&len, 1U); - m_txDMRData1.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::writeDMRData2(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = MMDVM_DMR_DATA2; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txDMRData2.addData(&len, 1U); - m_txDMRData2.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasYSFSpace() const -{ - unsigned int space = m_txYSFData.freeSpace() / (YSF_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeYSFData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[130U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = MMDVM_YSF_DATA; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txYSFData.addData(&len, 1U); - m_txYSFData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasP25Space() const -{ - unsigned int space = m_txP25Data.freeSpace() / (P25_LDU_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeP25Data(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_HEADER && data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[250U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = (data[0U] == TAG_HEADER) ? MMDVM_P25_HDR : MMDVM_P25_LDU; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txP25Data.addData(&len, 1U); - m_txP25Data.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasNXDNSpace() const -{ - unsigned int space = m_txNXDNData.freeSpace() / (NXDN_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeNXDNData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[130U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - buffer[2U] = MMDVM_NXDN_DATA; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txNXDNData.addData(&len, 1U); - m_txNXDNData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasM17Space() const -{ - unsigned int space = m_txM17Data.freeSpace() / (M17_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writeM17Data(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - if (data[0U] != TAG_HEADER && data[0U] != TAG_DATA && data[0U] != TAG_EOT) - return false; - - unsigned char buffer[130U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 2U; - - if (data[0U] == TAG_HEADER) - buffer[2U] = MMDVM_M17_HEADER; - else - buffer[2U] = MMDVM_M17_DATA; - - ::memcpy(buffer + 3U, data + 1U, length - 1U); - - unsigned char len = length + 2U; - m_txM17Data.addData(&len, 1U); - m_txM17Data.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasPOCSAGSpace() const -{ - unsigned int space = m_txPOCSAGData.freeSpace() / (POCSAG_FRAME_LENGTH_BYTES + 4U); - - return space > 1U; -} - -bool CMMDVMModem::writePOCSAGData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[130U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_POCSAG_DATA; - - ::memcpy(buffer + 3U, data, length); - - unsigned char len = length + 3U; - m_txPOCSAGData.addData(&len, 1U); - m_txPOCSAGData.addData(buffer, len); - - return true; -} - -unsigned int CMMDVMModem::getFMSpace() const -{ - return m_txFMData.freeSpace(); -} - -bool CMMDVMModem::writeFMData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[500U]; - - unsigned int len; - if (length > 252U) { - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 0U; - buffer[2U] = (length + 4U) - 255U; - buffer[3U] = MMDVM_FM_DATA; - ::memcpy(buffer + 4U, data, length); - len = length + 4U; - } else { - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_FM_DATA; - ::memcpy(buffer + 3U, data, length); - len = length + 3U; - } - - m_txFMData.addData((unsigned char*)&len, sizeof(unsigned int)); - m_txFMData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasAX25Space() const -{ - unsigned int space = m_txAX25Data.freeSpace() / (AX25_MAX_FRAME_LENGTH_BYTES + 5U); - - return space > 1U; -} - -bool CMMDVMModem::writeAX25Data(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[500U]; - - unsigned int len; - if (length > 252U) { - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 0U; - buffer[2U] = (length + 4U) - 255U; - buffer[3U] = MMDVM_AX25_DATA; - ::memcpy(buffer + 4U, data, length); - len = length + 4U; - } else { - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_AX25_DATA; - ::memcpy(buffer + 3U, data, length); - len = length + 3U; - } - - m_txAX25Data.addData((unsigned char*)&len, sizeof(unsigned int)); - m_txAX25Data.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::writeTransparentData(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[250U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_TRANSPARENT; - - if (m_sendTransparentDataFrameType > 0U) { - ::memcpy(buffer + 2U, data, length); - length--; - buffer[1U]--; - - //when sendFrameType==1 , only 0x80 and 0x90 (MMDVM_SERIAL and MMDVM_TRANSPARENT) are allowed - // and reverted to default (MMDVM_TRANSPARENT) for any other value - //when >1, frame type is not checked - if (m_sendTransparentDataFrameType == 1U) { - if ((buffer[2U] & 0xE0) != 0x80) - buffer[2U] = MMDVM_TRANSPARENT; - } - } else { - ::memcpy(buffer + 3U, data, length); - } - - unsigned char len = length + 3U; - m_txTransparentData.addData(&len, 1U); - m_txTransparentData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) -{ - assert(m_port != NULL); - assert(my1 != NULL); - assert(my2 != NULL); - assert(your != NULL); - assert(type != NULL); - assert(reflector != NULL); - - unsigned char buffer[50U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 33U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_DSTAR; - - ::memcpy(buffer + 4U, my1, DSTAR_LONG_CALLSIGN_LENGTH); - ::memcpy(buffer + 12U, my2, DSTAR_SHORT_CALLSIGN_LENGTH); - - ::memcpy(buffer + 16U, your, DSTAR_LONG_CALLSIGN_LENGTH); - - ::memcpy(buffer + 24U, type, 1U); - - ::memcpy(buffer + 25U, reflector, DSTAR_LONG_CALLSIGN_LENGTH); - - return m_port->write(buffer, 33U) != 33; -} - -bool CMMDVMModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dest, const char* type) -{ - assert(m_port != NULL); - assert(type != NULL); - - unsigned char buffer[50U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 47U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_DMR; - - buffer[4U] = slotNo; - - ::sprintf((char*)(buffer + 5U), "%20.20s", src.c_str()); - - buffer[25U] = group ? 'G' : 'I'; - - ::sprintf((char*)(buffer + 26U), "%20.20s", dest.c_str()); - - ::memcpy(buffer + 46U, type, 1U); - - return m_port->write(buffer, 47U) != 47; -} - -bool CMMDVMModem::writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) -{ - assert(m_port != NULL); - assert(source != NULL); - assert(dest != NULL); - assert(type != NULL); - assert(origin != NULL); - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 36U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_YSF; - - ::memcpy(buffer + 4U, source, YSF_CALLSIGN_LENGTH); - ::memcpy(buffer + 14U, dest, YSF_CALLSIGN_LENGTH); - - ::memcpy(buffer + 24U, type, 1U); - - ::memcpy(buffer + 25U, origin, YSF_CALLSIGN_LENGTH); - - buffer[35U] = dgid; - - return m_port->write(buffer, 36U) != 36; -} - -bool CMMDVMModem::writeP25Info(const char* source, bool group, unsigned int dest, const char* type) -{ - assert(m_port != NULL); - assert(source != NULL); - assert(type != NULL); - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 31U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_DMR; - - ::sprintf((char*)(buffer + 4U), "%20.20s", source); - - buffer[24U] = group ? 'G' : 'I'; - - ::sprintf((char*)(buffer + 25U), "%05u", dest); // 16-bits - - ::memcpy(buffer + 30U, type, 1U); - - return m_port->write(buffer, 31U) != 31; -} - -bool CMMDVMModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) -{ - assert(m_port != NULL); - assert(source != NULL); - assert(type != NULL); - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 31U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_NXDN; - - ::sprintf((char*)(buffer + 4U), "%20.20s", source); - - buffer[24U] = group ? 'G' : 'I'; - - ::sprintf((char*)(buffer + 25U), "%05u", dest); // 16-bits - - ::memcpy(buffer + 30U, type, 1U); - - return m_port->write(buffer, 31U) != 31; -} - -bool CMMDVMModem::writeM17Info(const char* source, const char* dest, const char* type) -{ - assert(m_port != NULL); - assert(source != NULL); - assert(dest != NULL); - assert(type != NULL); - - unsigned char buffer[40U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 31U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_M17; - - ::sprintf((char*)(buffer + 4U), "%9.9s", source); - - ::sprintf((char*)(buffer + 13U), "%9.9s", dest); - - ::memcpy(buffer + 22U, type, 1U); - - return m_port->write(buffer, 23U) != 23; -} - -bool CMMDVMModem::writePOCSAGInfo(unsigned int ric, const std::string& message) -{ - assert(m_port != NULL); - - size_t length = message.size(); - - unsigned char buffer[250U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 11U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = MODE_POCSAG; - - ::sprintf((char*)(buffer + 4U), "%07u", ric); // 21-bits - - ::memcpy(buffer + 11U, message.c_str(), length); - - int ret = m_port->write(buffer, length + 11U); - - return ret != int(length + 11U); -} - -bool CMMDVMModem::writeIPInfo(const std::string& address) -{ - assert(m_port != NULL); - - size_t length = address.size(); - - unsigned char buffer[25U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 4U; - buffer[2U] = MMDVM_QSO_INFO; - - buffer[3U] = 250U; - - ::memcpy(buffer + 4U, address.c_str(), length); - - int ret = m_port->write(buffer, length + 4U); - - return ret != int(length + 4U); -} - -bool CMMDVMModem::writeSerial(const unsigned char* data, unsigned int length) -{ - assert(m_port != NULL); - assert(data != NULL); - assert(length > 0U); - - unsigned char buffer[255U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_SERIAL_DATA; - - ::memcpy(buffer + 3U, data, length); - - unsigned char len = length + 3U; - m_txSerialData.addData(&len, 1U); - m_txSerialData.addData(buffer, len); - - return true; -} - -bool CMMDVMModem::hasTX() const -{ - return m_tx; -} - -bool CMMDVMModem::hasCD() const -{ - return m_cd; -} - -bool CMMDVMModem::hasLockout() const -{ - return m_lockout; -} - -bool CMMDVMModem::hasError() const -{ - return m_error; -} - -bool CMMDVMModem::readVersion() -{ - assert(m_port != NULL); - - CThread::sleep(2000U); // 2s - - for (unsigned int i = 0U; i < 6U; i++) { - unsigned char buffer[3U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 3U; - buffer[2U] = MMDVM_GET_VERSION; - - // CUtils::dump(1U, "Written", buffer, 3U); - - int ret = m_port->write(buffer, 3U); - if (ret != 3) - return false; - -#if defined(__APPLE__) - m_port->setNonblock(true); -#endif - - for (unsigned int count = 0U; count < MAX_RESPONSES; count++) { - CThread::sleep(10U); - RESP_TYPE_MMDVM resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] == MMDVM_GET_VERSION) { - if (::memcmp(m_buffer + 4U, "MMDVM ", 6U) == 0) - m_hwType = HWT_MMDVM; - else if (::memcmp(m_buffer + 4U, "DVMEGA", 6U) == 0) - m_hwType = HWT_DVMEGA; - else if (::memcmp(m_buffer + 4U, "ZUMspot", 7U) == 0) - m_hwType = HWT_MMDVM_ZUMSPOT; - else if (::memcmp(m_buffer + 4U, "MMDVM_HS_Hat", 12U) == 0) - m_hwType = HWT_MMDVM_HS_HAT; - else if (::memcmp(m_buffer + 4U, "MMDVM_HS_Dual_Hat", 17U) == 0) - m_hwType = HWT_MMDVM_HS_DUAL_HAT; - else if (::memcmp(m_buffer + 4U, "Nano_hotSPOT", 12U) == 0) - m_hwType = HWT_NANO_HOTSPOT; - else if (::memcmp(m_buffer + 4U, "Nano_DV", 7U) == 0) - m_hwType = HWT_NANO_DV; - else if (::memcmp(m_buffer + 4U, "D2RG_MMDVM_HS", 13U) == 0) - m_hwType = HWT_D2RG_MMDVM_HS; - else if (::memcmp(m_buffer + 4U, "MMDVM_HS-", 9U) == 0) - m_hwType = HWT_MMDVM_HS; - else if (::memcmp(m_buffer + 4U, "OpenGD77_HS", 11U) == 0) - m_hwType = HWT_OPENGD77_HS; - else if (::memcmp(m_buffer + 4U, "SkyBridge", 9U) == 0) - m_hwType = HWT_SKYBRIDGE; - - m_protocolVersion = m_buffer[3U]; - - switch (m_protocolVersion) { - case 1U: - LogInfo("MMDVM protocol version: %u, description: %.*s", m_protocolVersion, m_length - 4U, m_buffer + 4U); - return true; - - case 2U: - LogInfo("MMDVM protocol version: %u, description: %.*s", m_protocolVersion, m_length - 23U, m_buffer + 23U); - switch (m_buffer[6U]) { - case 0U: - LogInfo("CPU: Atmel ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]); - break; - case 1U: - LogInfo("CPU: NXP ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]); - break; - case 2U: - LogInfo("CPU: ST-Micro ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U]); - break; - default: - LogInfo("CPU: Unknown type: %u", m_buffer[6U]); - break; - } - char modeText[100U]; - ::strcpy(modeText, "Modes:"); - if ((m_buffer[4U] & 0x01U) == 0x01U) - ::strcat(modeText, " D-Star"); - if ((m_buffer[4U] & 0x02U) == 0x02U) - ::strcat(modeText, " DMR"); - if ((m_buffer[4U] & 0x04U) == 0x04U) - ::strcat(modeText, " YSF"); - if ((m_buffer[4U] & 0x08U) == 0x08U) - ::strcat(modeText, " P25"); - if ((m_buffer[4U] & 0x10U) == 0x10U) - ::strcat(modeText, " NXDN"); - if ((m_buffer[4U] & 0x20U) == 0x20U) - ::strcat(modeText, " M17"); - if ((m_buffer[4U] & 0x40U) == 0x40U) - ::strcat(modeText, " FM"); - if ((m_buffer[5U] & 0x01U) == 0x01U) - ::strcat(modeText, " POCSAG"); - if ((m_buffer[5U] & 0x02U) == 0x02U) - ::strcat(modeText, " AX.25"); - LogInfo(modeText); - return true; - - default: - LogError("MMDVM protocol version: %u, unsupported by this version of the MMDVM Host", m_protocolVersion); - return false; - } - - return true; - } - } - - CThread::sleep(1500U); - } - - LogError("Unable to read the firmware version after six attempts"); - - return false; -} - -bool CMMDVMModem::readStatus() -{ - assert(m_port != NULL); - - unsigned char buffer[3U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 3U; - buffer[2U] = MMDVM_GET_STATUS; - - // CUtils::dump(1U, "Written", buffer, 3U); - - return m_port->write(buffer, 3U) == 3; -} - -bool CMMDVMModem::writeConfig() -{ - switch (m_protocolVersion) { - case 1U: - return setConfig1(); - case 2U: - return setConfig2(); - default: - return false; - } -} - -bool CMMDVMModem::setConfig1() -{ - assert(m_port != NULL); - - unsigned char buffer[30U]; - - buffer[0U] = MMDVM_FRAME_START; - - buffer[1U] = 26U; - - buffer[2U] = MMDVM_SET_CONFIG; - - buffer[3U] = 0x00U; - if (m_rxInvert) - buffer[3U] |= 0x01U; - if (m_txInvert) - buffer[3U] |= 0x02U; - if (m_pttInvert) - buffer[3U] |= 0x04U; - if (m_ysfLoDev) - buffer[3U] |= 0x08U; - if (m_debug) - buffer[3U] |= 0x10U; - if (m_useCOSAsLockout) - buffer[3U] |= 0x20U; - if (!m_duplex) - buffer[3U] |= 0x80U; - - buffer[4U] = 0x00U; - if (m_dstarEnabled) - buffer[4U] |= 0x01U; - if (m_dmrEnabled) - buffer[4U] |= 0x02U; - if (m_ysfEnabled) - buffer[4U] |= 0x04U; - if (m_p25Enabled) - buffer[4U] |= 0x08U; - if (m_nxdnEnabled) - buffer[4U] |= 0x10U; - if (m_pocsagEnabled) - buffer[4U] |= 0x20U; - if (m_m17Enabled) - buffer[4U] |= 0x40U; - - buffer[5U] = m_txDelay / 10U; // In 10ms units - - buffer[6U] = MODE_IDLE; - - buffer[7U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); - - buffer[8U] = (unsigned char)(m_cwIdTXLevel * 2.55F + 0.5F); - - buffer[9U] = m_dmrColorCode; - - buffer[10U] = m_dmrDelay; - - buffer[11U] = 128U; // Was OscOffset - - buffer[12U] = (unsigned char)(m_dstarTXLevel * 2.55F + 0.5F); - buffer[13U] = (unsigned char)(m_dmrTXLevel * 2.55F + 0.5F); - buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F); - buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F); - - buffer[16U] = (unsigned char)(m_txDCOffset + 128); - buffer[17U] = (unsigned char)(m_rxDCOffset + 128); - - buffer[18U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F); - - buffer[19U] = (unsigned char)m_ysfTXHang; - - buffer[20U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F); - - buffer[21U] = (unsigned char)(m_fmTXLevel * 2.55F + 0.5F); - - buffer[22U] = (unsigned char)m_p25TXHang; - - buffer[23U] = (unsigned char)m_nxdnTXHang; - - buffer[24U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F); - - buffer[25U] = (unsigned char)m_m17TXHang; - - // CUtils::dump(1U, "Written", buffer, 26U); - - int ret = m_port->write(buffer, 26U); - if (ret != 26) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_CONFIG command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_CONFIG command from the modem"); - return false; - } - - m_playoutTimer.start(); - - return true; -} - -bool CMMDVMModem::setConfig2() -{ - assert(m_port != NULL); - - unsigned char buffer[50U]; - - buffer[0U] = MMDVM_FRAME_START; - - buffer[1U] = 40U; - - buffer[2U] = MMDVM_SET_CONFIG; - - buffer[3U] = 0x00U; - if (m_rxInvert) - buffer[3U] |= 0x01U; - if (m_txInvert) - buffer[3U] |= 0x02U; - if (m_pttInvert) - buffer[3U] |= 0x04U; - if (m_ysfLoDev) - buffer[3U] |= 0x08U; - if (m_debug) - buffer[3U] |= 0x10U; - if (m_useCOSAsLockout) - buffer[3U] |= 0x20U; - if (!m_duplex) - buffer[3U] |= 0x80U; - - buffer[4U] = 0x00U; - if (m_dstarEnabled) - buffer[4U] |= 0x01U; - if (m_dmrEnabled) - buffer[4U] |= 0x02U; - if (m_ysfEnabled) - buffer[4U] |= 0x04U; - if (m_p25Enabled) - buffer[4U] |= 0x08U; - if (m_nxdnEnabled) - buffer[4U] |= 0x10U; - if (m_fmEnabled) - buffer[4U] |= 0x20U; - if (m_m17Enabled) - buffer[4U] |= 0x40U; - - buffer[5U] = 0x00U; - if (m_pocsagEnabled) - buffer[5U] |= 0x01U; - if (m_ax25Enabled) - buffer[5U] |= 0x02U; - - buffer[6U] = m_txDelay / 10U; // In 10ms units - - buffer[7U] = MODE_IDLE; - - buffer[8U] = (unsigned char)(m_txDCOffset + 128); - buffer[9U] = (unsigned char)(m_rxDCOffset + 128); - - buffer[10U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); - - buffer[11U] = (unsigned char)(m_cwIdTXLevel * 2.55F + 0.5F); - buffer[12U] = (unsigned char)(m_dstarTXLevel * 2.55F + 0.5F); - buffer[13U] = (unsigned char)(m_dmrTXLevel * 2.55F + 0.5F); - buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F); - buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F); - buffer[16U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F); - buffer[17U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F); - buffer[18U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F); - buffer[19U] = (unsigned char)(m_fmTXLevel * 2.55F + 0.5F); - buffer[20U] = (unsigned char)(m_ax25TXLevel * 2.55F + 0.5F); - buffer[21U] = 0x00U; - buffer[22U] = 0x00U; - - buffer[23U] = (unsigned char)m_ysfTXHang; - buffer[24U] = (unsigned char)m_p25TXHang; - buffer[25U] = (unsigned char)m_nxdnTXHang; - buffer[26U] = (unsigned char)m_m17TXHang; - buffer[27U] = 0x00U; - buffer[28U] = 0x00U; - - buffer[29U] = m_dmrColorCode; - buffer[30U] = m_dmrDelay; - - buffer[31U] = (unsigned char)(m_ax25RXTwist + 128); - buffer[32U] = m_ax25TXDelay / 10U; // In 10ms units - buffer[33U] = m_ax25SlotTime / 10U; // In 10ms units - buffer[34U] = m_ax25PPersist; - - buffer[35U] = 0x00U; - buffer[36U] = 0x00U; - buffer[37U] = 0x00U; - buffer[38U] = 0x00U; - buffer[39U] = 0x00U; - - // CUtils::dump(1U, "Written", buffer, 40U); - - int ret = m_port->write(buffer, 40U); - if (ret != 40) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_CONFIG command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_CONFIG command from the modem"); - return false; - } - - m_playoutTimer.start(); - - return true; -} - -bool CMMDVMModem::setFrequency() -{ - assert(m_port != NULL); - - unsigned char buffer[20U]; - unsigned char len; - unsigned int pocsagFrequency = 433000000U; - - if (m_pocsagEnabled) - pocsagFrequency = m_pocsagFrequency; - - if (m_hwType == HWT_DVMEGA) - len = 12U; - else { - buffer[12U] = (unsigned char)(m_rfLevel * 2.55F + 0.5F); - - buffer[13U] = (pocsagFrequency >> 0) & 0xFFU; - buffer[14U] = (pocsagFrequency >> 8) & 0xFFU; - buffer[15U] = (pocsagFrequency >> 16) & 0xFFU; - buffer[16U] = (pocsagFrequency >> 24) & 0xFFU; - - len = 17U; - } - - buffer[0U] = MMDVM_FRAME_START; - - buffer[1U] = len; - - buffer[2U] = MMDVM_SET_FREQ; - - buffer[3U] = 0x00U; - - buffer[4U] = (m_rxFrequency >> 0) & 0xFFU; - buffer[5U] = (m_rxFrequency >> 8) & 0xFFU; - buffer[6U] = (m_rxFrequency >> 16) & 0xFFU; - buffer[7U] = (m_rxFrequency >> 24) & 0xFFU; - - buffer[8U] = (m_txFrequency >> 0) & 0xFFU; - buffer[9U] = (m_txFrequency >> 8) & 0xFFU; - buffer[10U] = (m_txFrequency >> 16) & 0xFFU; - buffer[11U] = (m_txFrequency >> 24) & 0xFFU; - - // CUtils::dump(1U, "Written", buffer, len); - - int ret = m_port->write(buffer, len); - if (ret != len) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_FREQ command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_FREQ command from the modem"); - return false; - } - - return true; -} - -RESP_TYPE_MMDVM CMMDVMModem::getResponse() -{ - assert(m_port != NULL); - - if (m_state == SS_START) { - // Get the start of the frame or nothing at all - int ret = m_port->read(m_buffer + 0U, 1U); - if (ret < 0) { - LogError("Error when reading from the modem"); - return RTM_ERROR; - } - - if (ret == 0) - return RTM_TIMEOUT; - - if (m_buffer[0U] != MMDVM_FRAME_START) - return RTM_TIMEOUT; - - m_state = SS_LENGTH1; - m_length = 1U; - } - - if (m_state == SS_LENGTH1) { - // Get the length of the frame, 1/2 - int ret = m_port->read(m_buffer + 1U, 1U); - if (ret < 0) { - LogError("Error when reading from the modem"); - m_state = SS_START; - return RTM_ERROR; - } - - if (ret == 0) - return RTM_TIMEOUT; - - m_length = m_buffer[1U]; - m_offset = 2U; - - if (m_length == 0U) - m_state = SS_LENGTH2; - else - m_state = SS_TYPE; - } - - if (m_state == SS_LENGTH2) { - // Get the length of the frane, 2/2 - int ret = m_port->read(m_buffer + 2U, 1U); - if (ret < 0) { - LogError("Error when reading from the modem"); - m_state = SS_START; - return RTM_ERROR; - } - - if (ret == 0) - return RTM_TIMEOUT; - - m_length = m_buffer[2U] + 255U; - m_offset = 3U; - m_state = SS_TYPE; - } - - if (m_state == SS_TYPE) { - // Get the frame type - int ret = m_port->read(&m_type, 1U); - if (ret < 0) { - LogError("Error when reading from the modem"); - m_state = SS_START; - return RTM_ERROR; - } - - if (ret == 0) - return RTM_TIMEOUT; - - m_buffer[m_offset++] = m_type; - - m_state = SS_DATA; - } - - if (m_state == SS_DATA) { - while (m_offset < m_length) { - int ret = m_port->read(m_buffer + m_offset, m_length - m_offset); - if (ret < 0) { - LogError("Error when reading from the modem"); - m_state = SS_START; - return RTM_ERROR; - } - - if (ret == 0) - return RTM_TIMEOUT; - - if (ret > 0) - m_offset += ret; - } - } - - // CUtils::dump(1U, "Received", m_buffer, m_length); - - m_offset = m_length > 255U ? 4U : 3U; - m_state = SS_START; - - return RTM_OK; -} - -HW_TYPE CMMDVMModem::getHWType() const -{ - return m_hwType; -} - -unsigned char CMMDVMModem::getMode() const -{ - return m_mode; -} - -bool CMMDVMModem::setMode(unsigned char mode) -{ - assert(m_port != NULL); - - unsigned char buffer[4U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 4U; - buffer[2U] = MMDVM_SET_MODE; - buffer[3U] = mode; - - // CUtils::dump(1U, "Written", buffer, 4U); - - return m_port->write(buffer, 4U) == 4; -} - -bool CMMDVMModem::sendCWId(const std::string& callsign) -{ - assert(m_port != NULL); - - unsigned int length = callsign.length(); - if (length > 200U) - length = 200U; - - unsigned char buffer[205U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = length + 3U; - buffer[2U] = MMDVM_SEND_CWID; - - for (unsigned int i = 0U; i < length; i++) - buffer[i + 3U] = callsign.at(i); - - // CUtils::dump(1U, "Written", buffer, length + 3U); - - return m_port->write(buffer, length + 3U) == int(length + 3U); -} - -bool CMMDVMModem::writeDMRStart(bool tx) -{ - assert(m_port != NULL); - - if (tx && m_tx) - return true; - if (!tx && !m_tx) - return true; - - unsigned char buffer[4U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 4U; - buffer[2U] = MMDVM_DMR_START; - buffer[3U] = tx ? 0x01U : 0x00U; - - // CUtils::dump(1U, "Written", buffer, 4U); - - return m_port->write(buffer, 4U) == 4; -} - -bool CMMDVMModem::writeDMRAbort(unsigned int slotNo) -{ - assert(m_port != NULL); - - if (slotNo == 1U) - m_txDMRData1.clear(); - else - m_txDMRData2.clear(); - - unsigned char buffer[4U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 4U; - buffer[2U] = MMDVM_DMR_ABORT; - buffer[3U] = slotNo; - - // CUtils::dump(1U, "Written", buffer, 4U); - - return m_port->write(buffer, 4U) == 4; -} - -bool CMMDVMModem::writeDMRShortLC(const unsigned char* lc) -{ - assert(m_port != NULL); - assert(lc != NULL); - - unsigned char buffer[12U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 12U; - buffer[2U] = MMDVM_DMR_SHORTLC; - buffer[3U] = lc[0U]; - buffer[4U] = lc[1U]; - buffer[5U] = lc[2U]; - buffer[6U] = lc[3U]; - buffer[7U] = lc[4U]; - buffer[8U] = lc[5U]; - buffer[9U] = lc[6U]; - buffer[10U] = lc[7U]; - buffer[11U] = lc[8U]; - - // CUtils::dump(1U, "Written", buffer, 12U); - - return m_port->write(buffer, 12U) == 12; -} - -void CMMDVMModem::setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) -{ - m_fmCallsign = callsign; - m_fmCallsignSpeed = callsignSpeed; - m_fmCallsignFrequency = callsignFrequency; - m_fmCallsignTime = callsignTime; - m_fmCallsignHoldoff = callsignHoldoff; - m_fmCallsignHighLevel = callsignHighLevel; - m_fmCallsignLowLevel = callsignLowLevel; - m_fmCallsignAtStart = callsignAtStart; - m_fmCallsignAtEnd = callsignAtEnd; - m_fmCallsignAtLatch = callsignAtLatch; -} - -void CMMDVMModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) -{ - m_fmRfAck = rfAck; - m_fmAckSpeed = ackSpeed; - m_fmAckFrequency = ackFrequency; - m_fmAckMinTime = ackMinTime; - m_fmAckDelay = ackDelay; - m_fmAckLevel = ackLevel; -} - -void CMMDVMModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) -{ - m_fmTimeout = timeout; - m_fmTimeoutLevel = timeoutLevel; - - m_fmCtcssFrequency = ctcssFrequency; - m_fmCtcssHighThreshold = ctcssHighThreshold; - m_fmCtcssLowThreshold = ctcssLowThreshold; - m_fmCtcssLevel = ctcssLevel; - - m_fmKerchunkTime = kerchunkTime; - - m_fmHangTime = hangTime; - - m_fmAccessMode = accessMode; - m_fmCOSInvert = cosInvert; - - m_fmNoiseSquelch = noiseSquelch; - m_fmSquelchHighThreshold = squelchHighThreshold; - m_fmSquelchLowThreshold = squelchLowThreshold; - - m_fmRFAudioBoost = rfAudioBoost; - m_fmMaxDevLevel = maxDevLevel; -} - -void CMMDVMModem::setFMExtParams(const std::string& ack, unsigned int audioBoost) -{ - m_fmExtAck = ack; - m_fmExtAudioBoost = audioBoost; - m_fmExtEnable = true; -} - -bool CMMDVMModem::setFMCallsignParams() -{ - assert(m_port != NULL); - - unsigned char buffer[80U]; - unsigned char len = 10U + m_fmCallsign.size(); - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = len; - buffer[2U] = MMDVM_FM_PARAMS1; - - buffer[3U] = m_fmCallsignSpeed; - buffer[4U] = m_fmCallsignFrequency / 10U; - buffer[5U] = m_fmCallsignTime; - buffer[6U] = m_fmCallsignHoldoff; - - buffer[7U] = (unsigned char)(m_fmCallsignHighLevel * 2.55F + 0.5F); - buffer[8U] = (unsigned char)(m_fmCallsignLowLevel * 2.55F + 0.5F); - - buffer[9U] = 0x00U; - if (m_fmCallsignAtStart) - buffer[9U] |= 0x01U; - if (m_fmCallsignAtEnd) - buffer[9U] |= 0x02U; - if (m_fmCallsignAtLatch) - buffer[9U] |= 0x04U; - - for (unsigned int i = 0U; i < m_fmCallsign.size(); i++) - buffer[10U + i] = m_fmCallsign.at(i); - - // CUtils::dump(1U, "Written", buffer, len); - - int ret = m_port->write(buffer, len); - if (ret != len) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_FM_PARAMS1 command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_FM_PARAMS1 command from the modem"); - return false; - } - - return true; -} - -bool CMMDVMModem::setFMAckParams() -{ - assert(m_port != NULL); - - unsigned char buffer[80U]; - unsigned char len = 8U + m_fmRfAck.size(); - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = len; - buffer[2U] = MMDVM_FM_PARAMS2; - - buffer[3U] = m_fmAckSpeed; - buffer[4U] = m_fmAckFrequency / 10U; - buffer[5U] = m_fmAckMinTime; - buffer[6U] = m_fmAckDelay / 10U; - - buffer[7U] = (unsigned char)(m_fmAckLevel * 2.55F + 0.5F); - - for (unsigned int i = 0U; i < m_fmRfAck.size(); i++) - buffer[8U + i] = m_fmRfAck.at(i); - - // CUtils::dump(1U, "Written", buffer, len); - - int ret = m_port->write(buffer, len); - if (ret != len) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_FM_PARAMS2 command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_FM_PARAMS2 command from the modem"); - return false; - } - - return true; -} - -bool CMMDVMModem::setFMMiscParams() -{ - assert(m_port != NULL); - - unsigned char buffer[20U]; - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = 17U; - buffer[2U] = MMDVM_FM_PARAMS3; - - buffer[3U] = m_fmTimeout / 5U; - buffer[4U] = (unsigned char)(m_fmTimeoutLevel * 2.55F + 0.5F); - - buffer[5U] = (unsigned char)m_fmCtcssFrequency; - buffer[6U] = m_fmCtcssHighThreshold; - buffer[7U] = m_fmCtcssLowThreshold; - buffer[8U] = (unsigned char)(m_fmCtcssLevel * 2.55F + 0.5F); - - buffer[9U] = m_fmKerchunkTime; - buffer[10U] = m_fmHangTime; - - buffer[11U] = m_fmAccessMode & 0x0FU; - if (m_fmNoiseSquelch) - buffer[11U] |= 0x40U; - if (m_fmCOSInvert) - buffer[11U] |= 0x80U; - - buffer[12U] = m_fmRFAudioBoost; - - buffer[13U] = (unsigned char)(m_fmMaxDevLevel * 2.55F + 0.5F); - - buffer[14U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); - - buffer[15U] = m_fmSquelchHighThreshold; - buffer[16U] = m_fmSquelchLowThreshold; - - // CUtils::dump(1U, "Written", buffer, 17U); - - int ret = m_port->write(buffer, 17U); - if (ret != 17) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_FM_PARAMS3 command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_FM_PARAMS3 command from the modem"); - return false; - } - - return true; -} - -bool CMMDVMModem::setFMExtParams() -{ - assert(m_port != NULL); - - unsigned char buffer[80U]; - unsigned char len = 7U + m_fmExtAck.size(); - - buffer[0U] = MMDVM_FRAME_START; - buffer[1U] = len; - buffer[2U] = MMDVM_FM_PARAMS4; - - buffer[3U] = m_fmExtAudioBoost; - buffer[4U] = m_fmAckSpeed; - buffer[5U] = m_fmAckFrequency / 10U; - - buffer[6U] = (unsigned char)(m_fmAckLevel * 2.55F + 0.5F); - - for (unsigned int i = 0U; i < m_fmExtAck.size(); i++) - buffer[7U + i] = m_fmExtAck.at(i); - - // CUtils::dump(1U, "Written", buffer, len); - - int ret = m_port->write(buffer, len); - if (ret != len) - return false; - - unsigned int count = 0U; - RESP_TYPE_MMDVM resp; - do { - CThread::sleep(10U); - - resp = getResponse(); - if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { - count++; - if (count >= MAX_RESPONSES) { - LogError("The MMDVM is not responding to the SET_FM_PARAMS4 command"); - return false; - } - } - } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); - - // CUtils::dump(1U, "Response", m_buffer, m_length); - - if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { - LogError("Received a NAK to the SET_FM_PARAMS4 command from the modem"); - return false; - } - - return true; -} - -void CMMDVMModem::printDebug() -{ - if (m_buffer[2U] == MMDVM_DEBUG1) { - LogMessage("Debug: %.*s", m_length - m_offset - 0U, m_buffer + m_offset); - } else if (m_buffer[2U] == MMDVM_DEBUG2) { - short val1 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; - LogMessage("Debug: %.*s %d", m_length - m_offset - 2U, m_buffer + m_offset, val1); - } else if (m_buffer[2U] == MMDVM_DEBUG3) { - short val1 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; - short val2 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; - LogMessage("Debug: %.*s %d %d", m_length - m_offset - 4U, m_buffer + m_offset, val1, val2); - } else if (m_buffer[2U] == MMDVM_DEBUG4) { - short val1 = (m_buffer[m_length - 6U] << 8) | m_buffer[m_length - 5U]; - short val2 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; - short val3 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; - LogMessage("Debug: %.*s %d %d %d", m_length - m_offset - 6U, m_buffer + m_offset, val1, val2, val3); - } else if (m_buffer[2U] == MMDVM_DEBUG5) { - short val1 = (m_buffer[m_length - 8U] << 8) | m_buffer[m_length - 7U]; - short val2 = (m_buffer[m_length - 6U] << 8) | m_buffer[m_length - 5U]; - short val3 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; - short val4 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; - LogMessage("Debug: %.*s %d %d %d %d", m_length - m_offset - 8U, m_buffer + m_offset, val1, val2, val3, val4); - } -} diff --git a/MMDVMModem.h b/MMDVMModem.h deleted file mode 100644 index 5670d28..0000000 --- a/MMDVMModem.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2011-2018,2020,2021 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. - */ - -#ifndef MMDVMMODEM_H -#define MMDVMMODEM_H - -#include "Modem.h" - -#include "MMDVMModemPort.h" -#include "RingBuffer.h" -#include "Defines.h" -#include "Timer.h" - -#include - -enum RESP_TYPE_MMDVM { - RTM_OK, - RTM_TIMEOUT, - RTM_ERROR -}; - -enum SERIAL_STATE { - SS_START, - SS_LENGTH1, - SS_LENGTH2, - SS_TYPE, - SS_DATA -}; - -class CMMDVMModem : public IModem { -public: - CMMDVMModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); - virtual ~CMMDVMModem(); - - virtual void setModem(IMMDVMModemPort* port); - virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency); - virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled); - virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel); - virtual void setDMRParams(unsigned int colorCode); - virtual void setYSFParams(bool loDev, unsigned int txHang); - virtual void setP25Params(unsigned int txHang); - virtual void setNXDNParams(unsigned int txHang); - virtual void setM17Params(unsigned int txHang); - virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist); - virtual void setTransparentDataParams(unsigned int sendFrameType); - - virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch); - virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel); - virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel); - virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost); - - virtual bool open(); - - virtual unsigned int readDStarData(unsigned char* data); - virtual unsigned int readDMRData1(unsigned char* data); - virtual unsigned int readDMRData2(unsigned char* data); - virtual unsigned int readYSFData(unsigned char* data); - virtual unsigned int readP25Data(unsigned char* data); - virtual unsigned int readNXDNData(unsigned char* data); - virtual unsigned int readM17Data(unsigned char* data); - virtual unsigned int readFMData(unsigned char* data); - virtual unsigned int readAX25Data(unsigned char* data); - - virtual bool hasDStarSpace() const; - virtual bool hasDMRSpace1() const; - virtual bool hasDMRSpace2() const; - virtual bool hasYSFSpace() const; - virtual bool hasP25Space() const; - virtual bool hasNXDNSpace() const; - virtual bool hasM17Space() const; - virtual bool hasPOCSAGSpace() const; - virtual unsigned int getFMSpace() const; - virtual bool hasAX25Space() const; - - virtual bool hasTX() const; - virtual bool hasCD() const; - - virtual bool hasLockout() const; - virtual bool hasError() const; - - virtual bool writeConfig(); - virtual bool writeDStarData(const unsigned char* data, unsigned int length); - virtual bool writeDMRData1(const unsigned char* data, unsigned int length); - virtual bool writeDMRData2(const unsigned char* data, unsigned int length); - virtual bool writeYSFData(const unsigned char* data, unsigned int length); - virtual bool writeP25Data(const unsigned char* data, unsigned int length); - virtual bool writeNXDNData(const unsigned char* data, unsigned int length); - virtual bool writeM17Data(const unsigned char* data, unsigned int length); - virtual bool writePOCSAGData(const unsigned char* data, unsigned int length); - virtual bool writeFMData(const unsigned char* data, unsigned int length); - virtual bool writeAX25Data(const unsigned char* data, unsigned int length); - - virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); - virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); - virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin); - virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type); - virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type); - virtual bool writeM17Info(const char* source, const char* dest, const char* type); - virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message); - virtual bool writeIPInfo(const std::string& address); - - virtual bool writeDMRStart(bool tx); - virtual bool writeDMRShortLC(const unsigned char* lc); - virtual bool writeDMRAbort(unsigned int slotNo); - - virtual bool writeTransparentData(const unsigned char* data, unsigned int length); - virtual unsigned int readTransparentData(unsigned char* data); - - virtual bool writeSerial(const unsigned char* data, unsigned int length); - virtual unsigned int readSerial(unsigned char* data, unsigned int length); - - virtual unsigned char getMode() const; - virtual bool setMode(unsigned char mode); - - virtual bool sendCWId(const std::string& callsign); - - virtual HW_TYPE getHWType() const; - - virtual void clock(unsigned int ms); - - virtual void close(); - -private: - unsigned int m_protocolVersion; - unsigned int m_dmrColorCode; - bool m_ysfLoDev; - unsigned int m_ysfTXHang; - unsigned int m_p25TXHang; - unsigned int m_nxdnTXHang; - unsigned int m_m17TXHang; - bool m_duplex; - bool m_rxInvert; - bool m_txInvert; - bool m_pttInvert; - unsigned int m_txDelay; - unsigned int m_dmrDelay; - float m_rxLevel; - float m_cwIdTXLevel; - float m_dstarTXLevel; - float m_dmrTXLevel; - float m_ysfTXLevel; - float m_p25TXLevel; - float m_nxdnTXLevel; - float m_m17TXLevel; - float m_pocsagTXLevel; - float m_fmTXLevel; - float m_ax25TXLevel; - float m_rfLevel; - bool m_useCOSAsLockout; - bool m_trace; - bool m_debug; - unsigned int m_rxFrequency; - unsigned int m_txFrequency; - unsigned int m_pocsagFrequency; - bool m_dstarEnabled; - bool m_dmrEnabled; - bool m_ysfEnabled; - bool m_p25Enabled; - bool m_nxdnEnabled; - bool m_m17Enabled; - bool m_pocsagEnabled; - bool m_fmEnabled; - bool m_ax25Enabled; - int m_rxDCOffset; - int m_txDCOffset; - IMMDVMModemPort* m_port; - unsigned char* m_buffer; - unsigned int m_length; - unsigned int m_offset; - SERIAL_STATE m_state; - unsigned char m_type; - CRingBuffer m_rxDStarData; - CRingBuffer m_txDStarData; - CRingBuffer m_rxDMRData1; - CRingBuffer m_rxDMRData2; - CRingBuffer m_txDMRData1; - CRingBuffer m_txDMRData2; - CRingBuffer m_rxYSFData; - CRingBuffer m_txYSFData; - CRingBuffer m_rxP25Data; - CRingBuffer m_txP25Data; - CRingBuffer m_rxNXDNData; - CRingBuffer m_txNXDNData; - CRingBuffer m_rxM17Data; - CRingBuffer m_txM17Data; - CRingBuffer m_txPOCSAGData; - CRingBuffer m_rxFMData; - CRingBuffer m_txFMData; - CRingBuffer m_rxAX25Data; - CRingBuffer m_txAX25Data; - CRingBuffer m_rxSerialData; - CRingBuffer m_txSerialData; - CRingBuffer m_rxTransparentData; - CRingBuffer m_txTransparentData; - unsigned int m_sendTransparentDataFrameType; - CTimer m_statusTimer; - CTimer m_inactivityTimer; - CTimer m_playoutTimer; - unsigned int m_dstarSpace; - unsigned int m_dmrSpace1; - unsigned int m_dmrSpace2; - unsigned int m_ysfSpace; - unsigned int m_p25Space; - unsigned int m_nxdnSpace; - unsigned int m_m17Space; - unsigned int m_pocsagSpace; - unsigned int m_fmSpace; - unsigned int m_ax25Space; - bool m_tx; - bool m_cd; - bool m_lockout; - bool m_error; - unsigned char m_mode; - HW_TYPE m_hwType; - int m_ax25RXTwist; - unsigned int m_ax25TXDelay; - unsigned int m_ax25SlotTime; - unsigned int m_ax25PPersist; - - std::string m_fmCallsign; - unsigned int m_fmCallsignSpeed; - unsigned int m_fmCallsignFrequency; - unsigned int m_fmCallsignTime; - unsigned int m_fmCallsignHoldoff; - float m_fmCallsignHighLevel; - float m_fmCallsignLowLevel; - bool m_fmCallsignAtStart; - bool m_fmCallsignAtEnd; - bool m_fmCallsignAtLatch; - std::string m_fmRfAck; - std::string m_fmExtAck; - unsigned int m_fmAckSpeed; - unsigned int m_fmAckFrequency; - unsigned int m_fmAckMinTime; - unsigned int m_fmAckDelay; - float m_fmAckLevel; - unsigned int m_fmTimeout; - float m_fmTimeoutLevel; - float m_fmCtcssFrequency; - unsigned int m_fmCtcssHighThreshold; - unsigned int m_fmCtcssLowThreshold; - float m_fmCtcssLevel; - unsigned int m_fmKerchunkTime; - unsigned int m_fmHangTime; - unsigned int m_fmAccessMode; - bool m_fmCOSInvert; - bool m_fmNoiseSquelch; - unsigned int m_fmSquelchHighThreshold; - unsigned int m_fmSquelchLowThreshold; - unsigned int m_fmRFAudioBoost; - unsigned int m_fmExtAudioBoost; - float m_fmMaxDevLevel; - bool m_fmExtEnable; - - bool readVersion(); - bool readStatus(); - bool setConfig1(); - bool setConfig2(); - bool setFrequency(); - bool setFMCallsignParams(); - bool setFMAckParams(); - bool setFMMiscParams(); - bool setFMExtParams(); - - void printDebug(); - - RESP_TYPE_MMDVM getResponse(); -}; - -#endif diff --git a/Makefile b/Makefile index 6ff0e76..901697a 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ + Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ diff --git a/Makefile.Pi b/Makefile.Pi index ee7be86..528c972 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -11,7 +11,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ + Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o POCSAGControl.o \ POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o \ diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index 53cef93..d4e75dd 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -12,7 +12,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index cf4f3cb..215d9f1 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -11,7 +11,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index 63a1d52..889c72d 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -15,7 +15,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \ - MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ + Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \ NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \ NXDNUDCH.o OLED.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index cce0546..ce09839 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -12,7 +12,7 @@ OBJECTS = \ DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \ DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \ Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LICH.o M17Network.o M17Utils.o \ - MMDVMHost.o MMDVMModem.o MMDVMModemPort.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ + MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \ NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \ NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \ POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o \ diff --git a/Modem.cpp b/Modem.cpp index 75c65dc..d6ed93f 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 by Jonathan Naylor G4KLX + * Copyright (C) 2011-2018,2020,2021 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 @@ -16,8 +16,2842 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "DStarDefines.h" +#include "DMRDefines.h" +#include "YSFDefines.h" +#include "P25Defines.h" +#include "NXDNDefines.h" +#include "AX25Defines.h" +#include "POCSAGDefines.h" +#include "M17Defines.h" +#include "Thread.h" #include "Modem.h" +#include "Utils.h" +#include "Log.h" -IModem::~IModem() +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#else +#include +#endif + +const unsigned char MMDVM_FRAME_START = 0xE0U; + +const unsigned char MMDVM_GET_VERSION = 0x00U; +const unsigned char MMDVM_GET_STATUS = 0x01U; +const unsigned char MMDVM_SET_CONFIG = 0x02U; +const unsigned char MMDVM_SET_MODE = 0x03U; +const unsigned char MMDVM_SET_FREQ = 0x04U; + +const unsigned char MMDVM_SEND_CWID = 0x0AU; + +const unsigned char MMDVM_DSTAR_HEADER = 0x10U; +const unsigned char MMDVM_DSTAR_DATA = 0x11U; +const unsigned char MMDVM_DSTAR_LOST = 0x12U; +const unsigned char MMDVM_DSTAR_EOT = 0x13U; + +const unsigned char MMDVM_DMR_DATA1 = 0x18U; +const unsigned char MMDVM_DMR_LOST1 = 0x19U; +const unsigned char MMDVM_DMR_DATA2 = 0x1AU; +const unsigned char MMDVM_DMR_LOST2 = 0x1BU; +const unsigned char MMDVM_DMR_SHORTLC = 0x1CU; +const unsigned char MMDVM_DMR_START = 0x1DU; +const unsigned char MMDVM_DMR_ABORT = 0x1EU; + +const unsigned char MMDVM_YSF_DATA = 0x20U; +const unsigned char MMDVM_YSF_LOST = 0x21U; + +const unsigned char MMDVM_P25_HDR = 0x30U; +const unsigned char MMDVM_P25_LDU = 0x31U; +const unsigned char MMDVM_P25_LOST = 0x32U; + +const unsigned char MMDVM_NXDN_DATA = 0x40U; +const unsigned char MMDVM_NXDN_LOST = 0x41U; + +const unsigned char MMDVM_M17_HEADER = 0x45U; +const unsigned char MMDVM_M17_DATA = 0x46U; +const unsigned char MMDVM_M17_LOST = 0x47U; + +const unsigned char MMDVM_POCSAG_DATA = 0x50U; + +const unsigned char MMDVM_AX25_DATA = 0x55U; + +const unsigned char MMDVM_FM_PARAMS1 = 0x60U; +const unsigned char MMDVM_FM_PARAMS2 = 0x61U; +const unsigned char MMDVM_FM_PARAMS3 = 0x62U; +const unsigned char MMDVM_FM_PARAMS4 = 0x63U; +const unsigned char MMDVM_FM_DATA = 0x65U; +const unsigned char MMDVM_FM_CONTROL = 0x66U; +const unsigned char MMDVM_FM_EOT = 0x67U; + +const unsigned char MMDVM_ACK = 0x70U; +const unsigned char MMDVM_NAK = 0x7FU; + +const unsigned char MMDVM_SERIAL_DATA = 0x80U; + +const unsigned char MMDVM_TRANSPARENT = 0x90U; +const unsigned char MMDVM_QSO_INFO = 0x91U; + +const unsigned char MMDVM_DEBUG1 = 0xF1U; +const unsigned char MMDVM_DEBUG2 = 0xF2U; +const unsigned char MMDVM_DEBUG3 = 0xF3U; +const unsigned char MMDVM_DEBUG4 = 0xF4U; +const unsigned char MMDVM_DEBUG5 = 0xF5U; + +const unsigned int MAX_RESPONSES = 30U; + +const unsigned int BUFFER_LENGTH = 2000U; + + +CModem::CModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) : +m_protocolVersion(0U), +m_dmrColorCode(0U), +m_ysfLoDev(false), +m_ysfTXHang(4U), +m_p25TXHang(5U), +m_nxdnTXHang(5U), +m_m17TXHang(5U), +m_duplex(duplex), +m_rxInvert(rxInvert), +m_txInvert(txInvert), +m_pttInvert(pttInvert), +m_txDelay(txDelay), +m_dmrDelay(dmrDelay), +m_rxLevel(0.0F), +m_cwIdTXLevel(0.0F), +m_dstarTXLevel(0.0F), +m_dmrTXLevel(0.0F), +m_ysfTXLevel(0.0F), +m_p25TXLevel(0.0F), +m_nxdnTXLevel(0.0F), +m_m17TXLevel(0.0F), +m_pocsagTXLevel(0.0F), +m_fmTXLevel(0.0F), +m_ax25TXLevel(0.0F), +m_rfLevel(0.0F), +m_useCOSAsLockout(useCOSAsLockout), +m_trace(trace), +m_debug(debug), +m_rxFrequency(0U), +m_txFrequency(0U), +m_pocsagFrequency(0U), +m_dstarEnabled(false), +m_dmrEnabled(false), +m_ysfEnabled(false), +m_p25Enabled(false), +m_nxdnEnabled(false), +m_m17Enabled(false), +m_pocsagEnabled(false), +m_fmEnabled(false), +m_ax25Enabled(false), +m_rxDCOffset(0), +m_txDCOffset(0), +m_port(NULL), +m_buffer(NULL), +m_length(0U), +m_offset(0U), +m_state(SS_START), +m_type(0U), +m_rxDStarData(1000U, "Modem RX D-Star"), +m_txDStarData(1000U, "Modem TX D-Star"), +m_rxDMRData1(1000U, "Modem RX DMR1"), +m_rxDMRData2(1000U, "Modem RX DMR2"), +m_txDMRData1(1000U, "Modem TX DMR1"), +m_txDMRData2(1000U, "Modem TX DMR2"), +m_rxYSFData(1000U, "Modem RX YSF"), +m_txYSFData(1000U, "Modem TX YSF"), +m_rxP25Data(1000U, "Modem RX P25"), +m_txP25Data(1000U, "Modem TX P25"), +m_rxNXDNData(1000U, "Modem RX NXDN"), +m_txNXDNData(1000U, "Modem TX NXDN"), +m_rxM17Data(1000U, "Modem RX M17"), +m_txM17Data(1000U, "Modem TX M17"), +m_txPOCSAGData(1000U, "Modem TX POCSAG"), +m_rxFMData(5000U, "Modem RX FM"), +m_txFMData(5000U, "Modem TX FM"), +m_rxAX25Data(1000U, "Modem RX AX.25"), +m_txAX25Data(1000U, "Modem TX AX.25"), +m_rxSerialData(1000U, "Modem RX Serial"), +m_txSerialData(1000U, "Modem TX Serial"), +m_rxTransparentData(1000U, "Modem RX Transparent"), +m_txTransparentData(1000U, "Modem TX Transparent"), +m_sendTransparentDataFrameType(0U), +m_statusTimer(1000U, 0U, 250U), +m_inactivityTimer(1000U, 2U), +m_playoutTimer(1000U, 0U, 10U), +m_dstarSpace(0U), +m_dmrSpace1(0U), +m_dmrSpace2(0U), +m_ysfSpace(0U), +m_p25Space(0U), +m_nxdnSpace(0U), +m_m17Space(0U), +m_pocsagSpace(0U), +m_fmSpace(0U), +m_ax25Space(0U), +m_tx(false), +m_cd(false), +m_lockout(false), +m_error(false), +m_mode(MODE_IDLE), +m_hwType(HWT_UNKNOWN), +m_ax25RXTwist(0), +m_ax25TXDelay(300U), +m_ax25SlotTime(30U), +m_ax25PPersist(128U), +m_fmCallsign(), +m_fmCallsignSpeed(20U), +m_fmCallsignFrequency(1000U), +m_fmCallsignTime(600U), +m_fmCallsignHoldoff(0U), +m_fmCallsignHighLevel(35.0F), +m_fmCallsignLowLevel(15.0F), +m_fmCallsignAtStart(true), +m_fmCallsignAtEnd(true), +m_fmCallsignAtLatch(true), +m_fmRfAck("K"), +m_fmExtAck("N"), +m_fmAckSpeed(20U), +m_fmAckFrequency(1750U), +m_fmAckMinTime(4U), +m_fmAckDelay(1000U), +m_fmAckLevel(80.0F), +m_fmTimeout(120U), +m_fmTimeoutLevel(80.0F), +m_fmCtcssFrequency(88.4F), +m_fmCtcssHighThreshold(30U), +m_fmCtcssLowThreshold(20U), +m_fmCtcssLevel(10.0F), +m_fmKerchunkTime(0U), +m_fmHangTime(5U), +m_fmAccessMode(1U), +m_fmCOSInvert(false), +m_fmNoiseSquelch(false), +m_fmSquelchHighThreshold(30U), +m_fmSquelchLowThreshold(20U), +m_fmRFAudioBoost(1U), +m_fmExtAudioBoost(1U), +m_fmMaxDevLevel(90.0F), +m_fmExtEnable(false) { + m_buffer = new unsigned char[BUFFER_LENGTH]; +} + +CModem::~CModem() +{ + delete m_port; + delete[] m_buffer; +} + +void CModem::setPort(IModemPort* port) +{ + assert(port != NULL); + + m_port = port; +} + +void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) +{ + m_rxFrequency = rxFrequency + rxOffset; + m_txFrequency = txFrequency + txOffset; + m_txDCOffset = txDCOffset; + m_rxDCOffset = rxDCOffset; + m_rfLevel = rfLevel; + m_pocsagFrequency = pocsagFrequency + txOffset; +} + +void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) +{ + m_dstarEnabled = dstarEnabled; + m_dmrEnabled = dmrEnabled; + m_ysfEnabled = ysfEnabled; + m_p25Enabled = p25Enabled; + m_nxdnEnabled = nxdnEnabled; + m_m17Enabled = m17Enabled; + m_pocsagEnabled = pocsagEnabled; + m_fmEnabled = fmEnabled; + m_ax25Enabled = ax25Enabled; +} + +void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel) +{ + m_rxLevel = rxLevel; + m_cwIdTXLevel = cwIdTXLevel; + m_dstarTXLevel = dstarTXLevel; + m_dmrTXLevel = dmrTXLevel; + m_ysfTXLevel = ysfTXLevel; + m_p25TXLevel = p25TXLevel; + m_nxdnTXLevel = nxdnTXLevel; + m_m17TXLevel = m17TXLevel; + m_pocsagTXLevel = pocsagTXLevel; + m_fmTXLevel = fmTXLevel; + m_ax25TXLevel = ax25TXLevel; +} + +void CModem::setDMRParams(unsigned int colorCode) +{ + assert(colorCode < 16U); + + m_dmrColorCode = colorCode; +} + +void CModem::setYSFParams(bool loDev, unsigned int txHang) +{ + m_ysfLoDev = loDev; + m_ysfTXHang = txHang; +} + +void CModem::setP25Params(unsigned int txHang) +{ + m_p25TXHang = txHang; +} + +void CModem::setNXDNParams(unsigned int txHang) +{ + m_nxdnTXHang = txHang; +} + +void CModem::setM17Params(unsigned int txHang) +{ + m_m17TXHang = txHang; +} + +void CModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) +{ + m_ax25RXTwist = rxTwist; + m_ax25TXDelay = txDelay; + m_ax25SlotTime = slotTime; + m_ax25PPersist = pPersist; +} + +void CModem::setTransparentDataParams(unsigned int sendFrameType) +{ + m_sendTransparentDataFrameType = sendFrameType; +} + +bool CModem::open() +{ + ::LogMessage("Opening the MMDVM"); + + bool ret = m_port->open(); + if (!ret) + return false; + + ret = readVersion(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } else { + /* Stopping the inactivity timer here when a firmware version has been + successfuly read prevents the death spiral of "no reply from modem..." */ + m_inactivityTimer.stop(); + } + + ret = setFrequency(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + + ret = writeConfig(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + + if (m_fmEnabled && m_duplex) { + ret = setFMCallsignParams(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + + ret = setFMAckParams(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + + ret = setFMMiscParams(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + + if (m_fmExtEnable) { + ret = setFMExtParams(); + if (!ret) { + m_port->close(); + delete m_port; + m_port = NULL; + return false; + } + } + } + + m_statusTimer.start(); + + m_error = false; + m_offset = 0U; + + return true; +} + +void CModem::clock(unsigned int ms) +{ + assert(m_port != NULL); + + // Poll the modem status every 250ms + m_statusTimer.clock(ms); + if (m_statusTimer.hasExpired()) { + readStatus(); + m_statusTimer.start(); + } + + m_inactivityTimer.clock(ms); + if (m_inactivityTimer.hasExpired()) { + LogError("No reply from the modem for some time, resetting it"); + m_error = true; + close(); + + CThread::sleep(2000U); // 2s + while (!open()) + CThread::sleep(5000U); // 5s + } + + RESP_TYPE_MMDVM type = getResponse(); + + if (type == RTM_TIMEOUT) { + // Nothing to do + } else if (type == RTM_ERROR) { + // Nothing to do + } else { + // type == RTM_OK + switch (m_type) { + case MMDVM_DSTAR_HEADER: { + if (m_trace) + CUtils::dump(1U, "RX D-Star Header", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxDStarData.addData(&data, 1U); + + data = TAG_HEADER; + m_rxDStarData.addData(&data, 1U); + + m_rxDStarData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_DSTAR_DATA: { + if (m_trace) + CUtils::dump(1U, "RX D-Star Data", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxDStarData.addData(&data, 1U); + + data = TAG_DATA; + m_rxDStarData.addData(&data, 1U); + + m_rxDStarData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_DSTAR_LOST: { + if (m_trace) + CUtils::dump(1U, "RX D-Star Lost", m_buffer, m_length); + + unsigned char data = 1U; + m_rxDStarData.addData(&data, 1U); + + data = TAG_LOST; + m_rxDStarData.addData(&data, 1U); + } + break; + + case MMDVM_DSTAR_EOT: { + if (m_trace) + CUtils::dump(1U, "RX D-Star EOT", m_buffer, m_length); + + unsigned char data = 1U; + m_rxDStarData.addData(&data, 1U); + + data = TAG_EOT; + m_rxDStarData.addData(&data, 1U); + } + break; + + case MMDVM_DMR_DATA1: { + if (m_trace) + CUtils::dump(1U, "RX DMR Data 1", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxDMRData1.addData(&data, 1U); + + if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC)) + data = TAG_EOT; + else + data = TAG_DATA; + m_rxDMRData1.addData(&data, 1U); + + m_rxDMRData1.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_DMR_DATA2: { + if (m_trace) + CUtils::dump(1U, "RX DMR Data 2", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxDMRData2.addData(&data, 1U); + + if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC)) + data = TAG_EOT; + else + data = TAG_DATA; + m_rxDMRData2.addData(&data, 1U); + + m_rxDMRData2.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_DMR_LOST1: { + if (m_trace) + CUtils::dump(1U, "RX DMR Lost 1", m_buffer, m_length); + + unsigned char data = 1U; + m_rxDMRData1.addData(&data, 1U); + + data = TAG_LOST; + m_rxDMRData1.addData(&data, 1U); + } + break; + + case MMDVM_DMR_LOST2: { + if (m_trace) + CUtils::dump(1U, "RX DMR Lost 2", m_buffer, m_length); + + unsigned char data = 1U; + m_rxDMRData2.addData(&data, 1U); + + data = TAG_LOST; + m_rxDMRData2.addData(&data, 1U); + } + break; + + case MMDVM_YSF_DATA: { + if (m_trace) + CUtils::dump(1U, "RX YSF Data", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxYSFData.addData(&data, 1U); + + data = TAG_DATA; + m_rxYSFData.addData(&data, 1U); + + m_rxYSFData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_YSF_LOST: { + if (m_trace) + CUtils::dump(1U, "RX YSF Lost", m_buffer, m_length); + + unsigned char data = 1U; + m_rxYSFData.addData(&data, 1U); + + data = TAG_LOST; + m_rxYSFData.addData(&data, 1U); + } + break; + + case MMDVM_P25_HDR: { + if (m_trace) + CUtils::dump(1U, "RX P25 Header", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxP25Data.addData(&data, 1U); + + data = TAG_HEADER; + m_rxP25Data.addData(&data, 1U); + + m_rxP25Data.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_P25_LDU: { + if (m_trace) + CUtils::dump(1U, "RX P25 LDU", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxP25Data.addData(&data, 1U); + + data = TAG_DATA; + m_rxP25Data.addData(&data, 1U); + + m_rxP25Data.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_P25_LOST: { + if (m_trace) + CUtils::dump(1U, "RX P25 Lost", m_buffer, m_length); + + unsigned char data = 1U; + m_rxP25Data.addData(&data, 1U); + + data = TAG_LOST; + m_rxP25Data.addData(&data, 1U); + } + break; + + case MMDVM_NXDN_DATA: { + if (m_trace) + CUtils::dump(1U, "RX NXDN Data", m_buffer, m_length); + + unsigned char data = m_length - m_offset + 1U; + m_rxNXDNData.addData(&data, 1U); + + data = TAG_DATA; + m_rxNXDNData.addData(&data, 1U); + + m_rxNXDNData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_NXDN_LOST: { + if (m_trace) + CUtils::dump(1U, "RX NXDN Lost", m_buffer, m_length); + + unsigned char data = 1U; + m_rxNXDNData.addData(&data, 1U); + + data = TAG_LOST; + m_rxNXDNData.addData(&data, 1U); + } + break; + + case MMDVM_M17_HEADER: { + if (m_trace) + CUtils::dump(1U, "RX M17 Header", m_buffer, m_length); + + unsigned char data = m_length - 2U; + m_rxM17Data.addData(&data, 1U); + + data = TAG_HEADER; + m_rxM17Data.addData(&data, 1U); + + m_rxM17Data.addData(m_buffer + 3U, m_length - 3U); + } + break; + + case MMDVM_M17_DATA: { + if (m_trace) + CUtils::dump(1U, "RX M17 Data", m_buffer, m_length); + + unsigned char data = m_length - 2U; + m_rxM17Data.addData(&data, 1U); + + data = TAG_DATA; + m_rxM17Data.addData(&data, 1U); + + m_rxM17Data.addData(m_buffer + 3U, m_length - 3U); + } + break; + + case MMDVM_M17_LOST: { + if (m_trace) + CUtils::dump(1U, "RX M17 Lost", m_buffer, m_length); + + unsigned char data = 1U; + m_rxM17Data.addData(&data, 1U); + + data = TAG_LOST; + m_rxM17Data.addData(&data, 1U); + } + break; + + case MMDVM_FM_DATA: { + if (m_trace) + CUtils::dump(1U, "RX FM Data", m_buffer, m_length); + + unsigned int data1 = m_length - m_offset + 1U; + m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); + + unsigned char data2 = TAG_DATA; + m_rxFMData.addData(&data2, 1U); + + m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_FM_CONTROL: { + if (m_trace) + CUtils::dump(1U, "RX FM Control", m_buffer, m_length); + + unsigned int data1 = m_length - m_offset + 1U; + m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); + + unsigned char data2= TAG_HEADER; + m_rxFMData.addData(&data2, 1U); + + m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_FM_EOT: { + if(m_trace) + CUtils::dump(1U, "RX FM End of transmission", m_buffer, m_length); + + unsigned int data1 = m_length - m_offset + 1U; + m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int)); + + unsigned char data2 = TAG_EOT; + m_rxFMData.addData(&data2, 1U); + + m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_AX25_DATA: { + if (m_trace) + CUtils::dump(1U, "RX AX.25 Data", m_buffer, m_length); + + unsigned int data = m_length - m_offset; + m_rxAX25Data.addData((unsigned char*)&data, sizeof(unsigned int)); + + m_rxAX25Data.addData(m_buffer + m_offset, m_length - m_offset); + } + break; + + case MMDVM_GET_STATUS: + // if (m_trace) + // CUtils::dump(1U, "GET_STATUS", m_buffer, m_length); + + switch (m_protocolVersion) { + case 1U: { + m_mode = m_buffer[m_offset + 1U]; + + m_tx = (m_buffer[m_offset + 2U] & 0x01U) == 0x01U; + bool adcOverflow = (m_buffer[m_offset + 2U] & 0x02U) == 0x02U; + if (adcOverflow) + LogError("MMDVM ADC levels have overflowed"); + bool rxOverflow = (m_buffer[m_offset + 2U] & 0x04U) == 0x04U; + if (rxOverflow) + LogError("MMDVM RX buffer has overflowed"); + bool txOverflow = (m_buffer[m_offset + 2U] & 0x08U) == 0x08U; + if (txOverflow) + LogError("MMDVM TX buffer has overflowed"); + m_lockout = (m_buffer[m_offset + 2U] & 0x10U) == 0x10U; + bool dacOverflow = (m_buffer[m_offset + 2U] & 0x20U) == 0x20U; + if (dacOverflow) + LogError("MMDVM DAC levels have overflowed"); + m_cd = (m_buffer[m_offset + 2U] & 0x40U) == 0x40U; + + m_p25Space = 0U; + m_nxdnSpace = 0U; + m_m17Space = 0U; + m_pocsagSpace = 0U; + m_fmSpace = 0U; + m_ax25Space = 0U; + + m_dstarSpace = m_buffer[m_offset + 3U]; + m_dmrSpace1 = m_buffer[m_offset + 4U]; + m_dmrSpace2 = m_buffer[m_offset + 5U]; + m_ysfSpace = m_buffer[m_offset + 6U]; + + // The following depend on the version of the firmware + if (m_length > (m_offset + 7U)) + m_p25Space = m_buffer[m_offset + 7U]; + if (m_length > (m_offset + 8U)) + m_nxdnSpace = m_buffer[m_offset + 8U]; + if (m_length > (m_offset + 9U)) + m_pocsagSpace = m_buffer[m_offset + 9U]; + if (m_length > (m_offset + 10U)) + m_m17Space = m_buffer[m_offset + 10U]; + } + break; + + case 2U: { + m_mode = m_buffer[m_offset + 0U]; + + m_tx = (m_buffer[m_offset + 1U] & 0x01U) == 0x01U; + bool adcOverflow = (m_buffer[m_offset + 1U] & 0x02U) == 0x02U; + if (adcOverflow) + LogError("MMDVM ADC levels have overflowed"); + bool rxOverflow = (m_buffer[m_offset + 1U] & 0x04U) == 0x04U; + if (rxOverflow) + LogError("MMDVM RX buffer has overflowed"); + bool txOverflow = (m_buffer[m_offset + 1U] & 0x08U) == 0x08U; + if (txOverflow) + LogError("MMDVM TX buffer has overflowed"); + m_lockout = (m_buffer[m_offset + 1U] & 0x10U) == 0x10U; + bool dacOverflow = (m_buffer[m_offset + 1U] & 0x20U) == 0x20U; + if (dacOverflow) + LogError("MMDVM DAC levels have overflowed"); + m_cd = (m_buffer[m_offset + 1U] & 0x40U) == 0x40U; + + m_dstarSpace = m_buffer[m_offset + 3U]; + m_dmrSpace1 = m_buffer[m_offset + 4U]; + m_dmrSpace2 = m_buffer[m_offset + 5U]; + m_ysfSpace = m_buffer[m_offset + 6U]; + m_p25Space = m_buffer[m_offset + 7U]; + m_nxdnSpace = m_buffer[m_offset + 8U]; + m_m17Space = m_buffer[m_offset + 9U]; + m_fmSpace = m_buffer[m_offset + 10U]; + m_pocsagSpace = m_buffer[m_offset + 11U]; + m_ax25Space = m_buffer[m_offset + 12U]; + } + break; + + default: + m_dstarSpace = 0U; + m_dmrSpace1 = 0U; + m_dmrSpace2 = 0U; + m_ysfSpace = 0U; + m_p25Space = 0U; + m_nxdnSpace = 0U; + m_m17Space = 0U; + m_pocsagSpace = 0U; + m_fmSpace = 0U; + m_ax25Space = 0U; + break; + } + + m_inactivityTimer.start(); + // LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_m17Space, m_pocsagSpace, m_fmSpace, m_ax25Space, int(m_lockout), int(m_cd)); + break; + + case MMDVM_TRANSPARENT: { + if (m_trace) + CUtils::dump(1U, "RX Transparent Data", m_buffer, m_length); + + unsigned char offset = m_sendTransparentDataFrameType; + if (offset > 1U) offset = 1U; + unsigned char data = m_length - m_offset + offset; + m_rxTransparentData.addData(&data, 1U); + + m_rxTransparentData.addData(m_buffer + m_offset - offset, m_length - m_offset + offset); + } + break; + + // These should not be received, but don't complain if we do + case MMDVM_GET_VERSION: + case MMDVM_ACK: + break; + + case MMDVM_NAK: + LogWarning("Received a NAK from the MMDVM, command = 0x%02X, reason = %u", m_buffer[m_offset], m_buffer[m_offset + 1U]); + break; + + case MMDVM_DEBUG1: + case MMDVM_DEBUG2: + case MMDVM_DEBUG3: + case MMDVM_DEBUG4: + case MMDVM_DEBUG5: + printDebug(); + break; + + case MMDVM_SERIAL_DATA: + if (m_trace) + CUtils::dump(1U, "RX Serial Data", m_buffer, m_length); + m_rxSerialData.addData(m_buffer + m_offset, m_length - m_offset); + break; + + default: + LogMessage("Unknown message, type: %02X", m_type); + CUtils::dump("Buffer dump", m_buffer, m_length); + break; + } + } + + // Only feed data to the modem if the playout timer has expired + m_playoutTimer.clock(ms); + if (!m_playoutTimer.hasExpired()) + return; + + if (m_dstarSpace > 1U && !m_txDStarData.isEmpty()) { + unsigned char buffer[4U]; + m_txDStarData.peek(buffer, 4U); + + if ((buffer[3U] == MMDVM_DSTAR_HEADER && m_dstarSpace > 4U) || + (buffer[3U] == MMDVM_DSTAR_DATA && m_dstarSpace > 1U) || + (buffer[3U] == MMDVM_DSTAR_EOT && m_dstarSpace > 1U)) { + unsigned char len = 0U; + m_txDStarData.getData(&len, 1U); + m_txDStarData.getData(m_buffer, len); + + switch (buffer[3U]) { + case MMDVM_DSTAR_HEADER: + if (m_trace) + CUtils::dump(1U, "TX D-Star Header", m_buffer, len); + m_dstarSpace -= 4U; + break; + case MMDVM_DSTAR_DATA: + if (m_trace) + CUtils::dump(1U, "TX D-Star Data", m_buffer, len); + m_dstarSpace -= 1U; + break; + default: + if (m_trace) + CUtils::dump(1U, "TX D-Star EOT", m_buffer, len); + m_dstarSpace -= 1U; + break; + } + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing D-Star data to the MMDVM"); + + m_playoutTimer.start(); + } + } + + if (m_dmrSpace1 > 1U && !m_txDMRData1.isEmpty()) { + unsigned char len = 0U; + m_txDMRData1.getData(&len, 1U); + m_txDMRData1.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX DMR Data 1", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing DMR data to the MMDVM"); + + m_playoutTimer.start(); + + m_dmrSpace1--; + } + + if (m_dmrSpace2 > 1U && !m_txDMRData2.isEmpty()) { + unsigned char len = 0U; + m_txDMRData2.getData(&len, 1U); + m_txDMRData2.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX DMR Data 2", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing DMR data to the MMDVM"); + + m_playoutTimer.start(); + + m_dmrSpace2--; + } + + if (m_ysfSpace > 1U && !m_txYSFData.isEmpty()) { + unsigned char len = 0U; + m_txYSFData.getData(&len, 1U); + m_txYSFData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX YSF Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing YSF data to the MMDVM"); + + m_playoutTimer.start(); + + m_ysfSpace--; + } + + if (m_p25Space > 1U && !m_txP25Data.isEmpty()) { + unsigned char len = 0U; + m_txP25Data.getData(&len, 1U); + m_txP25Data.getData(m_buffer, len); + + if (m_trace) { + if (m_buffer[2U] == MMDVM_P25_HDR) + CUtils::dump(1U, "TX P25 HDR", m_buffer, len); + else + CUtils::dump(1U, "TX P25 LDU", m_buffer, len); + } + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing P25 data to the MMDVM"); + + m_playoutTimer.start(); + + m_p25Space--; + } + + if (m_nxdnSpace > 1U && !m_txNXDNData.isEmpty()) { + unsigned char len = 0U; + m_txNXDNData.getData(&len, 1U); + m_txNXDNData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX NXDN Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing NXDN data to the MMDVM"); + + m_playoutTimer.start(); + + m_nxdnSpace--; + } + + if (m_m17Space > 1U && !m_txM17Data.isEmpty()) { + unsigned char len = 0U; + m_txM17Data.getData(&len, 1U); + m_txM17Data.getData(m_buffer, len); + + if (m_trace) { + if (m_buffer[2U] == MMDVM_M17_HEADER) + CUtils::dump(1U, "TX M17 Header", m_buffer, len); + else + CUtils::dump(1U, "TX M17 Data", m_buffer, len); + } + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing M17 data to the MMDVM"); + + m_playoutTimer.start(); + + m_m17Space--; + } + + if (m_pocsagSpace > 1U && !m_txPOCSAGData.isEmpty()) { + unsigned char len = 0U; + m_txPOCSAGData.getData(&len, 1U); + m_txPOCSAGData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX POCSAG Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing POCSAG data to the MMDVM"); + + m_playoutTimer.start(); + + m_pocsagSpace--; + } + + if (m_fmSpace > 1U && !m_txFMData.isEmpty()) { + unsigned int len = 0U; + m_txFMData.getData((unsigned char*)&len, sizeof(unsigned int)); + m_txFMData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX FM Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing FM data to the MMDVM"); + + m_playoutTimer.start(); + + m_fmSpace--; + } + + if (m_ax25Space > 0U && !m_txAX25Data.isEmpty()) { + unsigned int len = 0U; + m_txAX25Data.getData((unsigned char*)&len, sizeof(unsigned int)); + m_txAX25Data.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX AX.25 Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing AX.25 data to the MMDVM"); + + m_playoutTimer.start(); + + m_ax25Space = 0U; + } + + if (!m_txTransparentData.isEmpty()) { + unsigned char len = 0U; + m_txTransparentData.getData(&len, 1U); + m_txTransparentData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX Transparent Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing Transparent data to the MMDVM"); + } + + if (!m_txSerialData.isEmpty()) { + unsigned char len = 0U; + m_txSerialData.getData(&len, 1U); + m_txSerialData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX Serial Data", m_buffer, len); + + int ret = m_port->write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing Serial data to the MMDVM"); + } +} + +void CModem::close() +{ + assert(m_port != NULL); + + ::LogMessage("Closing the MMDVM"); + + m_port->close(); +} + +unsigned int CModem::readDStarData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxDStarData.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxDStarData.getData(&len, 1U); + m_rxDStarData.getData(data, len); + + return len; +} + +unsigned int CModem::readDMRData1(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxDMRData1.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxDMRData1.getData(&len, 1U); + m_rxDMRData1.getData(data, len); + + return len; +} + +unsigned int CModem::readDMRData2(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxDMRData2.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxDMRData2.getData(&len, 1U); + m_rxDMRData2.getData(data, len); + + return len; +} + +unsigned int CModem::readYSFData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxYSFData.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxYSFData.getData(&len, 1U); + m_rxYSFData.getData(data, len); + + return len; +} + +unsigned int CModem::readP25Data(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxP25Data.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxP25Data.getData(&len, 1U); + m_rxP25Data.getData(data, len); + + return len; +} + +unsigned int CModem::readNXDNData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxNXDNData.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxNXDNData.getData(&len, 1U); + m_rxNXDNData.getData(data, len); + + return len; +} + +unsigned int CModem::readM17Data(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxM17Data.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxM17Data.getData(&len, 1U); + m_rxM17Data.getData(data, len); + + return len; +} + +unsigned int CModem::readFMData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxFMData.isEmpty()) + return 0U; + + unsigned int len = 0U; + m_rxFMData.getData((unsigned char*)&len, sizeof(unsigned int)); + m_rxFMData.getData(data, len); + + return len; +} + +unsigned int CModem::readAX25Data(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxAX25Data.isEmpty()) + return 0U; + + unsigned int len = 0U; + m_rxAX25Data.getData((unsigned char*)&len, sizeof(unsigned int)); + m_rxAX25Data.getData(data, len); + + return len; +} + +unsigned int CModem::readTransparentData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxTransparentData.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxTransparentData.getData(&len, 1U); + m_rxTransparentData.getData(data, len); + + return len; +} + +unsigned int CModem::readSerial(unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned int n = 0U; + while (!m_rxSerialData.isEmpty() && n < length) { + m_rxSerialData.getData(data + n, 1U); + n++; + } + + return n; +} + +bool CModem::hasDStarSpace() const +{ + unsigned int space = m_txDStarData.freeSpace() / (DSTAR_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeDStarData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[50U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + + switch (data[0U]) { + case TAG_HEADER: + buffer[2U] = MMDVM_DSTAR_HEADER; + break; + case TAG_DATA: + buffer[2U] = MMDVM_DSTAR_DATA; + break; + case TAG_EOT: + buffer[2U] = MMDVM_DSTAR_EOT; + break; + default: + CUtils::dump(2U, "Unknown D-Star packet type", data, length); + return false; + } + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txDStarData.addData(&len, 1U); + m_txDStarData.addData(buffer, len); + + return true; +} + +bool CModem::hasDMRSpace1() const +{ + unsigned int space = m_txDMRData1.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::hasDMRSpace2() const +{ + unsigned int space = m_txDMRData2.freeSpace() / (DMR_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeDMRData1(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = MMDVM_DMR_DATA1; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txDMRData1.addData(&len, 1U); + m_txDMRData1.addData(buffer, len); + + return true; +} + +bool CModem::writeDMRData2(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = MMDVM_DMR_DATA2; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txDMRData2.addData(&len, 1U); + m_txDMRData2.addData(buffer, len); + + return true; +} + +bool CModem::hasYSFSpace() const +{ + unsigned int space = m_txYSFData.freeSpace() / (YSF_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeYSFData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[130U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = MMDVM_YSF_DATA; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txYSFData.addData(&len, 1U); + m_txYSFData.addData(buffer, len); + + return true; +} + +bool CModem::hasP25Space() const +{ + unsigned int space = m_txP25Data.freeSpace() / (P25_LDU_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeP25Data(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_HEADER && data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[250U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = (data[0U] == TAG_HEADER) ? MMDVM_P25_HDR : MMDVM_P25_LDU; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txP25Data.addData(&len, 1U); + m_txP25Data.addData(buffer, len); + + return true; +} + +bool CModem::hasNXDNSpace() const +{ + unsigned int space = m_txNXDNData.freeSpace() / (NXDN_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeNXDNData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[130U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + buffer[2U] = MMDVM_NXDN_DATA; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txNXDNData.addData(&len, 1U); + m_txNXDNData.addData(buffer, len); + + return true; +} + +bool CModem::hasM17Space() const +{ + unsigned int space = m_txM17Data.freeSpace() / (M17_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writeM17Data(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + if (data[0U] != TAG_HEADER && data[0U] != TAG_DATA && data[0U] != TAG_EOT) + return false; + + unsigned char buffer[130U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 2U; + + if (data[0U] == TAG_HEADER) + buffer[2U] = MMDVM_M17_HEADER; + else + buffer[2U] = MMDVM_M17_DATA; + + ::memcpy(buffer + 3U, data + 1U, length - 1U); + + unsigned char len = length + 2U; + m_txM17Data.addData(&len, 1U); + m_txM17Data.addData(buffer, len); + + return true; +} + +bool CModem::hasPOCSAGSpace() const +{ + unsigned int space = m_txPOCSAGData.freeSpace() / (POCSAG_FRAME_LENGTH_BYTES + 4U); + + return space > 1U; +} + +bool CModem::writePOCSAGData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[130U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_POCSAG_DATA; + + ::memcpy(buffer + 3U, data, length); + + unsigned char len = length + 3U; + m_txPOCSAGData.addData(&len, 1U); + m_txPOCSAGData.addData(buffer, len); + + return true; +} + +unsigned int CModem::getFMSpace() const +{ + return m_txFMData.freeSpace(); +} + +bool CModem::writeFMData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[500U]; + + unsigned int len; + if (length > 252U) { + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 0U; + buffer[2U] = (length + 4U) - 255U; + buffer[3U] = MMDVM_FM_DATA; + ::memcpy(buffer + 4U, data, length); + len = length + 4U; + } else { + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_FM_DATA; + ::memcpy(buffer + 3U, data, length); + len = length + 3U; + } + + m_txFMData.addData((unsigned char*)&len, sizeof(unsigned int)); + m_txFMData.addData(buffer, len); + + return true; +} + +bool CModem::hasAX25Space() const +{ + unsigned int space = m_txAX25Data.freeSpace() / (AX25_MAX_FRAME_LENGTH_BYTES + 5U); + + return space > 1U; +} + +bool CModem::writeAX25Data(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[500U]; + + unsigned int len; + if (length > 252U) { + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 0U; + buffer[2U] = (length + 4U) - 255U; + buffer[3U] = MMDVM_AX25_DATA; + ::memcpy(buffer + 4U, data, length); + len = length + 4U; + } else { + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_AX25_DATA; + ::memcpy(buffer + 3U, data, length); + len = length + 3U; + } + + m_txAX25Data.addData((unsigned char*)&len, sizeof(unsigned int)); + m_txAX25Data.addData(buffer, len); + + return true; +} + +bool CModem::writeTransparentData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[250U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_TRANSPARENT; + + if (m_sendTransparentDataFrameType > 0U) { + ::memcpy(buffer + 2U, data, length); + length--; + buffer[1U]--; + + //when sendFrameType==1 , only 0x80 and 0x90 (MMDVM_SERIAL and MMDVM_TRANSPARENT) are allowed + // and reverted to default (MMDVM_TRANSPARENT) for any other value + //when >1, frame type is not checked + if (m_sendTransparentDataFrameType == 1U) { + if ((buffer[2U] & 0xE0) != 0x80) + buffer[2U] = MMDVM_TRANSPARENT; + } + } else { + ::memcpy(buffer + 3U, data, length); + } + + unsigned char len = length + 3U; + m_txTransparentData.addData(&len, 1U); + m_txTransparentData.addData(buffer, len); + + return true; +} + +bool CModem::writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) +{ + assert(m_port != NULL); + assert(my1 != NULL); + assert(my2 != NULL); + assert(your != NULL); + assert(type != NULL); + assert(reflector != NULL); + + unsigned char buffer[50U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 33U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_DSTAR; + + ::memcpy(buffer + 4U, my1, DSTAR_LONG_CALLSIGN_LENGTH); + ::memcpy(buffer + 12U, my2, DSTAR_SHORT_CALLSIGN_LENGTH); + + ::memcpy(buffer + 16U, your, DSTAR_LONG_CALLSIGN_LENGTH); + + ::memcpy(buffer + 24U, type, 1U); + + ::memcpy(buffer + 25U, reflector, DSTAR_LONG_CALLSIGN_LENGTH); + + return m_port->write(buffer, 33U) != 33; +} + +bool CModem::writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dest, const char* type) +{ + assert(m_port != NULL); + assert(type != NULL); + + unsigned char buffer[50U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 47U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_DMR; + + buffer[4U] = slotNo; + + ::sprintf((char*)(buffer + 5U), "%20.20s", src.c_str()); + + buffer[25U] = group ? 'G' : 'I'; + + ::sprintf((char*)(buffer + 26U), "%20.20s", dest.c_str()); + + ::memcpy(buffer + 46U, type, 1U); + + return m_port->write(buffer, 47U) != 47; +} + +bool CModem::writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) +{ + assert(m_port != NULL); + assert(source != NULL); + assert(dest != NULL); + assert(type != NULL); + assert(origin != NULL); + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 36U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_YSF; + + ::memcpy(buffer + 4U, source, YSF_CALLSIGN_LENGTH); + ::memcpy(buffer + 14U, dest, YSF_CALLSIGN_LENGTH); + + ::memcpy(buffer + 24U, type, 1U); + + ::memcpy(buffer + 25U, origin, YSF_CALLSIGN_LENGTH); + + buffer[35U] = dgid; + + return m_port->write(buffer, 36U) != 36; +} + +bool CModem::writeP25Info(const char* source, bool group, unsigned int dest, const char* type) +{ + assert(m_port != NULL); + assert(source != NULL); + assert(type != NULL); + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 31U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_DMR; + + ::sprintf((char*)(buffer + 4U), "%20.20s", source); + + buffer[24U] = group ? 'G' : 'I'; + + ::sprintf((char*)(buffer + 25U), "%05u", dest); // 16-bits + + ::memcpy(buffer + 30U, type, 1U); + + return m_port->write(buffer, 31U) != 31; +} + +bool CModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) +{ + assert(m_port != NULL); + assert(source != NULL); + assert(type != NULL); + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 31U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_NXDN; + + ::sprintf((char*)(buffer + 4U), "%20.20s", source); + + buffer[24U] = group ? 'G' : 'I'; + + ::sprintf((char*)(buffer + 25U), "%05u", dest); // 16-bits + + ::memcpy(buffer + 30U, type, 1U); + + return m_port->write(buffer, 31U) != 31; +} + +bool CModem::writeM17Info(const char* source, const char* dest, const char* type) +{ + assert(m_port != NULL); + assert(source != NULL); + assert(dest != NULL); + assert(type != NULL); + + unsigned char buffer[40U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 31U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_M17; + + ::sprintf((char*)(buffer + 4U), "%9.9s", source); + + ::sprintf((char*)(buffer + 13U), "%9.9s", dest); + + ::memcpy(buffer + 22U, type, 1U); + + return m_port->write(buffer, 23U) != 23; +} + +bool CModem::writePOCSAGInfo(unsigned int ric, const std::string& message) +{ + assert(m_port != NULL); + + size_t length = message.size(); + + unsigned char buffer[250U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 11U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = MODE_POCSAG; + + ::sprintf((char*)(buffer + 4U), "%07u", ric); // 21-bits + + ::memcpy(buffer + 11U, message.c_str(), length); + + int ret = m_port->write(buffer, length + 11U); + + return ret != int(length + 11U); +} + +bool CModem::writeIPInfo(const std::string& address) +{ + assert(m_port != NULL); + + size_t length = address.size(); + + unsigned char buffer[25U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 4U; + buffer[2U] = MMDVM_QSO_INFO; + + buffer[3U] = 250U; + + ::memcpy(buffer + 4U, address.c_str(), length); + + int ret = m_port->write(buffer, length + 4U); + + return ret != int(length + 4U); +} + +bool CModem::writeSerial(const unsigned char* data, unsigned int length) +{ + assert(m_port != NULL); + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[255U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_SERIAL_DATA; + + ::memcpy(buffer + 3U, data, length); + + unsigned char len = length + 3U; + m_txSerialData.addData(&len, 1U); + m_txSerialData.addData(buffer, len); + + return true; +} + +bool CModem::hasTX() const +{ + return m_tx; +} + +bool CModem::hasCD() const +{ + return m_cd; +} + +bool CModem::hasLockout() const +{ + return m_lockout; +} + +bool CModem::hasError() const +{ + return m_error; +} + +bool CModem::readVersion() +{ + assert(m_port != NULL); + + CThread::sleep(2000U); // 2s + + for (unsigned int i = 0U; i < 6U; i++) { + unsigned char buffer[3U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = MMDVM_GET_VERSION; + + // CUtils::dump(1U, "Written", buffer, 3U); + + int ret = m_port->write(buffer, 3U); + if (ret != 3) + return false; + +#if defined(__APPLE__) + m_port->setNonblock(true); +#endif + + for (unsigned int count = 0U; count < MAX_RESPONSES; count++) { + CThread::sleep(10U); + RESP_TYPE_MMDVM resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] == MMDVM_GET_VERSION) { + if (::memcmp(m_buffer + 4U, "MMDVM ", 6U) == 0) + m_hwType = HWT_MMDVM; + else if (::memcmp(m_buffer + 4U, "DVMEGA", 6U) == 0) + m_hwType = HWT_DVMEGA; + else if (::memcmp(m_buffer + 4U, "ZUMspot", 7U) == 0) + m_hwType = HWT_MMDVM_ZUMSPOT; + else if (::memcmp(m_buffer + 4U, "MMDVM_HS_Hat", 12U) == 0) + m_hwType = HWT_MMDVM_HS_HAT; + else if (::memcmp(m_buffer + 4U, "MMDVM_HS_Dual_Hat", 17U) == 0) + m_hwType = HWT_MMDVM_HS_DUAL_HAT; + else if (::memcmp(m_buffer + 4U, "Nano_hotSPOT", 12U) == 0) + m_hwType = HWT_NANO_HOTSPOT; + else if (::memcmp(m_buffer + 4U, "Nano_DV", 7U) == 0) + m_hwType = HWT_NANO_DV; + else if (::memcmp(m_buffer + 4U, "D2RG_MMDVM_HS", 13U) == 0) + m_hwType = HWT_D2RG_MMDVM_HS; + else if (::memcmp(m_buffer + 4U, "MMDVM_HS-", 9U) == 0) + m_hwType = HWT_MMDVM_HS; + else if (::memcmp(m_buffer + 4U, "OpenGD77_HS", 11U) == 0) + m_hwType = HWT_OPENGD77_HS; + else if (::memcmp(m_buffer + 4U, "SkyBridge", 9U) == 0) + m_hwType = HWT_SKYBRIDGE; + + m_protocolVersion = m_buffer[3U]; + + switch (m_protocolVersion) { + case 1U: + LogInfo("MMDVM protocol version: %u, description: %.*s", m_protocolVersion, m_length - 4U, m_buffer + 4U); + return true; + + case 2U: + LogInfo("MMDVM protocol version: %u, description: %.*s", m_protocolVersion, m_length - 23U, m_buffer + 23U); + switch (m_buffer[6U]) { + case 0U: + LogInfo("CPU: Atmel ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]); + break; + case 1U: + LogInfo("CPU: NXP ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U], m_buffer[19U], m_buffer[20U], m_buffer[21U], m_buffer[22U]); + break; + case 2U: + LogInfo("CPU: ST-Micro ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", m_buffer[7U], m_buffer[8U], m_buffer[9U], m_buffer[10U], m_buffer[11U], m_buffer[12U], m_buffer[13U], m_buffer[14U], m_buffer[15U], m_buffer[16U], m_buffer[17U], m_buffer[18U]); + break; + default: + LogInfo("CPU: Unknown type: %u", m_buffer[6U]); + break; + } + char modeText[100U]; + ::strcpy(modeText, "Modes:"); + if ((m_buffer[4U] & 0x01U) == 0x01U) + ::strcat(modeText, " D-Star"); + if ((m_buffer[4U] & 0x02U) == 0x02U) + ::strcat(modeText, " DMR"); + if ((m_buffer[4U] & 0x04U) == 0x04U) + ::strcat(modeText, " YSF"); + if ((m_buffer[4U] & 0x08U) == 0x08U) + ::strcat(modeText, " P25"); + if ((m_buffer[4U] & 0x10U) == 0x10U) + ::strcat(modeText, " NXDN"); + if ((m_buffer[4U] & 0x20U) == 0x20U) + ::strcat(modeText, " M17"); + if ((m_buffer[4U] & 0x40U) == 0x40U) + ::strcat(modeText, " FM"); + if ((m_buffer[5U] & 0x01U) == 0x01U) + ::strcat(modeText, " POCSAG"); + if ((m_buffer[5U] & 0x02U) == 0x02U) + ::strcat(modeText, " AX.25"); + LogInfo(modeText); + return true; + + default: + LogError("MMDVM protocol version: %u, unsupported by this version of the MMDVM Host", m_protocolVersion); + return false; + } + + return true; + } + } + + CThread::sleep(1500U); + } + + LogError("Unable to read the firmware version after six attempts"); + + return false; +} + +bool CModem::readStatus() +{ + assert(m_port != NULL); + + unsigned char buffer[3U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = MMDVM_GET_STATUS; + + // CUtils::dump(1U, "Written", buffer, 3U); + + return m_port->write(buffer, 3U) == 3; +} + +bool CModem::writeConfig() +{ + switch (m_protocolVersion) { + case 1U: + return setConfig1(); + case 2U: + return setConfig2(); + default: + return false; + } +} + +bool CModem::setConfig1() +{ + assert(m_port != NULL); + + unsigned char buffer[30U]; + + buffer[0U] = MMDVM_FRAME_START; + + buffer[1U] = 26U; + + buffer[2U] = MMDVM_SET_CONFIG; + + buffer[3U] = 0x00U; + if (m_rxInvert) + buffer[3U] |= 0x01U; + if (m_txInvert) + buffer[3U] |= 0x02U; + if (m_pttInvert) + buffer[3U] |= 0x04U; + if (m_ysfLoDev) + buffer[3U] |= 0x08U; + if (m_debug) + buffer[3U] |= 0x10U; + if (m_useCOSAsLockout) + buffer[3U] |= 0x20U; + if (!m_duplex) + buffer[3U] |= 0x80U; + + buffer[4U] = 0x00U; + if (m_dstarEnabled) + buffer[4U] |= 0x01U; + if (m_dmrEnabled) + buffer[4U] |= 0x02U; + if (m_ysfEnabled) + buffer[4U] |= 0x04U; + if (m_p25Enabled) + buffer[4U] |= 0x08U; + if (m_nxdnEnabled) + buffer[4U] |= 0x10U; + if (m_pocsagEnabled) + buffer[4U] |= 0x20U; + if (m_m17Enabled) + buffer[4U] |= 0x40U; + + buffer[5U] = m_txDelay / 10U; // In 10ms units + + buffer[6U] = MODE_IDLE; + + buffer[7U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); + + buffer[8U] = (unsigned char)(m_cwIdTXLevel * 2.55F + 0.5F); + + buffer[9U] = m_dmrColorCode; + + buffer[10U] = m_dmrDelay; + + buffer[11U] = 128U; // Was OscOffset + + buffer[12U] = (unsigned char)(m_dstarTXLevel * 2.55F + 0.5F); + buffer[13U] = (unsigned char)(m_dmrTXLevel * 2.55F + 0.5F); + buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F); + buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F); + + buffer[16U] = (unsigned char)(m_txDCOffset + 128); + buffer[17U] = (unsigned char)(m_rxDCOffset + 128); + + buffer[18U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F); + + buffer[19U] = (unsigned char)m_ysfTXHang; + + buffer[20U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F); + + buffer[21U] = (unsigned char)(m_fmTXLevel * 2.55F + 0.5F); + + buffer[22U] = (unsigned char)m_p25TXHang; + + buffer[23U] = (unsigned char)m_nxdnTXHang; + + buffer[24U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F); + + buffer[25U] = (unsigned char)m_m17TXHang; + + // CUtils::dump(1U, "Written", buffer, 26U); + + int ret = m_port->write(buffer, 26U); + if (ret != 26) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_CONFIG command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_CONFIG command from the modem"); + return false; + } + + m_playoutTimer.start(); + + return true; +} + +bool CModem::setConfig2() +{ + assert(m_port != NULL); + + unsigned char buffer[50U]; + + buffer[0U] = MMDVM_FRAME_START; + + buffer[1U] = 40U; + + buffer[2U] = MMDVM_SET_CONFIG; + + buffer[3U] = 0x00U; + if (m_rxInvert) + buffer[3U] |= 0x01U; + if (m_txInvert) + buffer[3U] |= 0x02U; + if (m_pttInvert) + buffer[3U] |= 0x04U; + if (m_ysfLoDev) + buffer[3U] |= 0x08U; + if (m_debug) + buffer[3U] |= 0x10U; + if (m_useCOSAsLockout) + buffer[3U] |= 0x20U; + if (!m_duplex) + buffer[3U] |= 0x80U; + + buffer[4U] = 0x00U; + if (m_dstarEnabled) + buffer[4U] |= 0x01U; + if (m_dmrEnabled) + buffer[4U] |= 0x02U; + if (m_ysfEnabled) + buffer[4U] |= 0x04U; + if (m_p25Enabled) + buffer[4U] |= 0x08U; + if (m_nxdnEnabled) + buffer[4U] |= 0x10U; + if (m_fmEnabled) + buffer[4U] |= 0x20U; + if (m_m17Enabled) + buffer[4U] |= 0x40U; + + buffer[5U] = 0x00U; + if (m_pocsagEnabled) + buffer[5U] |= 0x01U; + if (m_ax25Enabled) + buffer[5U] |= 0x02U; + + buffer[6U] = m_txDelay / 10U; // In 10ms units + + buffer[7U] = MODE_IDLE; + + buffer[8U] = (unsigned char)(m_txDCOffset + 128); + buffer[9U] = (unsigned char)(m_rxDCOffset + 128); + + buffer[10U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); + + buffer[11U] = (unsigned char)(m_cwIdTXLevel * 2.55F + 0.5F); + buffer[12U] = (unsigned char)(m_dstarTXLevel * 2.55F + 0.5F); + buffer[13U] = (unsigned char)(m_dmrTXLevel * 2.55F + 0.5F); + buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F); + buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F); + buffer[16U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F); + buffer[17U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F); + buffer[18U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F); + buffer[19U] = (unsigned char)(m_fmTXLevel * 2.55F + 0.5F); + buffer[20U] = (unsigned char)(m_ax25TXLevel * 2.55F + 0.5F); + buffer[21U] = 0x00U; + buffer[22U] = 0x00U; + + buffer[23U] = (unsigned char)m_ysfTXHang; + buffer[24U] = (unsigned char)m_p25TXHang; + buffer[25U] = (unsigned char)m_nxdnTXHang; + buffer[26U] = (unsigned char)m_m17TXHang; + buffer[27U] = 0x00U; + buffer[28U] = 0x00U; + + buffer[29U] = m_dmrColorCode; + buffer[30U] = m_dmrDelay; + + buffer[31U] = (unsigned char)(m_ax25RXTwist + 128); + buffer[32U] = m_ax25TXDelay / 10U; // In 10ms units + buffer[33U] = m_ax25SlotTime / 10U; // In 10ms units + buffer[34U] = m_ax25PPersist; + + buffer[35U] = 0x00U; + buffer[36U] = 0x00U; + buffer[37U] = 0x00U; + buffer[38U] = 0x00U; + buffer[39U] = 0x00U; + + // CUtils::dump(1U, "Written", buffer, 40U); + + int ret = m_port->write(buffer, 40U); + if (ret != 40) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_CONFIG command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_CONFIG command from the modem"); + return false; + } + + m_playoutTimer.start(); + + return true; +} + +bool CModem::setFrequency() +{ + assert(m_port != NULL); + + unsigned char buffer[20U]; + unsigned char len; + unsigned int pocsagFrequency = 433000000U; + + if (m_pocsagEnabled) + pocsagFrequency = m_pocsagFrequency; + + if (m_hwType == HWT_DVMEGA) + len = 12U; + else { + buffer[12U] = (unsigned char)(m_rfLevel * 2.55F + 0.5F); + + buffer[13U] = (pocsagFrequency >> 0) & 0xFFU; + buffer[14U] = (pocsagFrequency >> 8) & 0xFFU; + buffer[15U] = (pocsagFrequency >> 16) & 0xFFU; + buffer[16U] = (pocsagFrequency >> 24) & 0xFFU; + + len = 17U; + } + + buffer[0U] = MMDVM_FRAME_START; + + buffer[1U] = len; + + buffer[2U] = MMDVM_SET_FREQ; + + buffer[3U] = 0x00U; + + buffer[4U] = (m_rxFrequency >> 0) & 0xFFU; + buffer[5U] = (m_rxFrequency >> 8) & 0xFFU; + buffer[6U] = (m_rxFrequency >> 16) & 0xFFU; + buffer[7U] = (m_rxFrequency >> 24) & 0xFFU; + + buffer[8U] = (m_txFrequency >> 0) & 0xFFU; + buffer[9U] = (m_txFrequency >> 8) & 0xFFU; + buffer[10U] = (m_txFrequency >> 16) & 0xFFU; + buffer[11U] = (m_txFrequency >> 24) & 0xFFU; + + // CUtils::dump(1U, "Written", buffer, len); + + int ret = m_port->write(buffer, len); + if (ret != len) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_FREQ command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_FREQ command from the modem"); + return false; + } + + return true; +} + +RESP_TYPE_MMDVM CModem::getResponse() +{ + assert(m_port != NULL); + + if (m_state == SS_START) { + // Get the start of the frame or nothing at all + int ret = m_port->read(m_buffer + 0U, 1U); + if (ret < 0) { + LogError("Error when reading from the modem"); + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + if (m_buffer[0U] != MMDVM_FRAME_START) + return RTM_TIMEOUT; + + m_state = SS_LENGTH1; + m_length = 1U; + } + + if (m_state == SS_LENGTH1) { + // Get the length of the frame, 1/2 + int ret = m_port->read(m_buffer + 1U, 1U); + if (ret < 0) { + LogError("Error when reading from the modem"); + m_state = SS_START; + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + m_length = m_buffer[1U]; + m_offset = 2U; + + if (m_length == 0U) + m_state = SS_LENGTH2; + else + m_state = SS_TYPE; + } + + if (m_state == SS_LENGTH2) { + // Get the length of the frane, 2/2 + int ret = m_port->read(m_buffer + 2U, 1U); + if (ret < 0) { + LogError("Error when reading from the modem"); + m_state = SS_START; + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + m_length = m_buffer[2U] + 255U; + m_offset = 3U; + m_state = SS_TYPE; + } + + if (m_state == SS_TYPE) { + // Get the frame type + int ret = m_port->read(&m_type, 1U); + if (ret < 0) { + LogError("Error when reading from the modem"); + m_state = SS_START; + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + m_buffer[m_offset++] = m_type; + + m_state = SS_DATA; + } + + if (m_state == SS_DATA) { + while (m_offset < m_length) { + int ret = m_port->read(m_buffer + m_offset, m_length - m_offset); + if (ret < 0) { + LogError("Error when reading from the modem"); + m_state = SS_START; + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + if (ret > 0) + m_offset += ret; + } + } + + // CUtils::dump(1U, "Received", m_buffer, m_length); + + m_offset = m_length > 255U ? 4U : 3U; + m_state = SS_START; + + return RTM_OK; +} + +HW_TYPE CModem::getHWType() const +{ + return m_hwType; +} + +unsigned char CModem::getMode() const +{ + return m_mode; +} + +bool CModem::setMode(unsigned char mode) +{ + assert(m_port != NULL); + + unsigned char buffer[4U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 4U; + buffer[2U] = MMDVM_SET_MODE; + buffer[3U] = mode; + + // CUtils::dump(1U, "Written", buffer, 4U); + + return m_port->write(buffer, 4U) == 4; +} + +bool CModem::sendCWId(const std::string& callsign) +{ + assert(m_port != NULL); + + unsigned int length = callsign.length(); + if (length > 200U) + length = 200U; + + unsigned char buffer[205U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_SEND_CWID; + + for (unsigned int i = 0U; i < length; i++) + buffer[i + 3U] = callsign.at(i); + + // CUtils::dump(1U, "Written", buffer, length + 3U); + + return m_port->write(buffer, length + 3U) == int(length + 3U); +} + +bool CModem::writeDMRStart(bool tx) +{ + assert(m_port != NULL); + + if (tx && m_tx) + return true; + if (!tx && !m_tx) + return true; + + unsigned char buffer[4U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 4U; + buffer[2U] = MMDVM_DMR_START; + buffer[3U] = tx ? 0x01U : 0x00U; + + // CUtils::dump(1U, "Written", buffer, 4U); + + return m_port->write(buffer, 4U) == 4; +} + +bool CModem::writeDMRAbort(unsigned int slotNo) +{ + assert(m_port != NULL); + + if (slotNo == 1U) + m_txDMRData1.clear(); + else + m_txDMRData2.clear(); + + unsigned char buffer[4U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 4U; + buffer[2U] = MMDVM_DMR_ABORT; + buffer[3U] = slotNo; + + // CUtils::dump(1U, "Written", buffer, 4U); + + return m_port->write(buffer, 4U) == 4; +} + +bool CModem::writeDMRShortLC(const unsigned char* lc) +{ + assert(m_port != NULL); + assert(lc != NULL); + + unsigned char buffer[12U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 12U; + buffer[2U] = MMDVM_DMR_SHORTLC; + buffer[3U] = lc[0U]; + buffer[4U] = lc[1U]; + buffer[5U] = lc[2U]; + buffer[6U] = lc[3U]; + buffer[7U] = lc[4U]; + buffer[8U] = lc[5U]; + buffer[9U] = lc[6U]; + buffer[10U] = lc[7U]; + buffer[11U] = lc[8U]; + + // CUtils::dump(1U, "Written", buffer, 12U); + + return m_port->write(buffer, 12U) == 12; +} + +void CModem::setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) +{ + m_fmCallsign = callsign; + m_fmCallsignSpeed = callsignSpeed; + m_fmCallsignFrequency = callsignFrequency; + m_fmCallsignTime = callsignTime; + m_fmCallsignHoldoff = callsignHoldoff; + m_fmCallsignHighLevel = callsignHighLevel; + m_fmCallsignLowLevel = callsignLowLevel; + m_fmCallsignAtStart = callsignAtStart; + m_fmCallsignAtEnd = callsignAtEnd; + m_fmCallsignAtLatch = callsignAtLatch; +} + +void CModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) +{ + m_fmRfAck = rfAck; + m_fmAckSpeed = ackSpeed; + m_fmAckFrequency = ackFrequency; + m_fmAckMinTime = ackMinTime; + m_fmAckDelay = ackDelay; + m_fmAckLevel = ackLevel; +} + +void CModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) +{ + m_fmTimeout = timeout; + m_fmTimeoutLevel = timeoutLevel; + + m_fmCtcssFrequency = ctcssFrequency; + m_fmCtcssHighThreshold = ctcssHighThreshold; + m_fmCtcssLowThreshold = ctcssLowThreshold; + m_fmCtcssLevel = ctcssLevel; + + m_fmKerchunkTime = kerchunkTime; + + m_fmHangTime = hangTime; + + m_fmAccessMode = accessMode; + m_fmCOSInvert = cosInvert; + + m_fmNoiseSquelch = noiseSquelch; + m_fmSquelchHighThreshold = squelchHighThreshold; + m_fmSquelchLowThreshold = squelchLowThreshold; + + m_fmRFAudioBoost = rfAudioBoost; + m_fmMaxDevLevel = maxDevLevel; +} + +void CModem::setFMExtParams(const std::string& ack, unsigned int audioBoost) +{ + m_fmExtAck = ack; + m_fmExtAudioBoost = audioBoost; + m_fmExtEnable = true; +} + +bool CModem::setFMCallsignParams() +{ + assert(m_port != NULL); + + unsigned char buffer[80U]; + unsigned char len = 10U + m_fmCallsign.size(); + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = len; + buffer[2U] = MMDVM_FM_PARAMS1; + + buffer[3U] = m_fmCallsignSpeed; + buffer[4U] = m_fmCallsignFrequency / 10U; + buffer[5U] = m_fmCallsignTime; + buffer[6U] = m_fmCallsignHoldoff; + + buffer[7U] = (unsigned char)(m_fmCallsignHighLevel * 2.55F + 0.5F); + buffer[8U] = (unsigned char)(m_fmCallsignLowLevel * 2.55F + 0.5F); + + buffer[9U] = 0x00U; + if (m_fmCallsignAtStart) + buffer[9U] |= 0x01U; + if (m_fmCallsignAtEnd) + buffer[9U] |= 0x02U; + if (m_fmCallsignAtLatch) + buffer[9U] |= 0x04U; + + for (unsigned int i = 0U; i < m_fmCallsign.size(); i++) + buffer[10U + i] = m_fmCallsign.at(i); + + // CUtils::dump(1U, "Written", buffer, len); + + int ret = m_port->write(buffer, len); + if (ret != len) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_FM_PARAMS1 command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_FM_PARAMS1 command from the modem"); + return false; + } + + return true; +} + +bool CModem::setFMAckParams() +{ + assert(m_port != NULL); + + unsigned char buffer[80U]; + unsigned char len = 8U + m_fmRfAck.size(); + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = len; + buffer[2U] = MMDVM_FM_PARAMS2; + + buffer[3U] = m_fmAckSpeed; + buffer[4U] = m_fmAckFrequency / 10U; + buffer[5U] = m_fmAckMinTime; + buffer[6U] = m_fmAckDelay / 10U; + + buffer[7U] = (unsigned char)(m_fmAckLevel * 2.55F + 0.5F); + + for (unsigned int i = 0U; i < m_fmRfAck.size(); i++) + buffer[8U + i] = m_fmRfAck.at(i); + + // CUtils::dump(1U, "Written", buffer, len); + + int ret = m_port->write(buffer, len); + if (ret != len) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_FM_PARAMS2 command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_FM_PARAMS2 command from the modem"); + return false; + } + + return true; +} + +bool CModem::setFMMiscParams() +{ + assert(m_port != NULL); + + unsigned char buffer[20U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = 17U; + buffer[2U] = MMDVM_FM_PARAMS3; + + buffer[3U] = m_fmTimeout / 5U; + buffer[4U] = (unsigned char)(m_fmTimeoutLevel * 2.55F + 0.5F); + + buffer[5U] = (unsigned char)m_fmCtcssFrequency; + buffer[6U] = m_fmCtcssHighThreshold; + buffer[7U] = m_fmCtcssLowThreshold; + buffer[8U] = (unsigned char)(m_fmCtcssLevel * 2.55F + 0.5F); + + buffer[9U] = m_fmKerchunkTime; + buffer[10U] = m_fmHangTime; + + buffer[11U] = m_fmAccessMode & 0x0FU; + if (m_fmNoiseSquelch) + buffer[11U] |= 0x40U; + if (m_fmCOSInvert) + buffer[11U] |= 0x80U; + + buffer[12U] = m_fmRFAudioBoost; + + buffer[13U] = (unsigned char)(m_fmMaxDevLevel * 2.55F + 0.5F); + + buffer[14U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F); + + buffer[15U] = m_fmSquelchHighThreshold; + buffer[16U] = m_fmSquelchLowThreshold; + + // CUtils::dump(1U, "Written", buffer, 17U); + + int ret = m_port->write(buffer, 17U); + if (ret != 17) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_FM_PARAMS3 command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_FM_PARAMS3 command from the modem"); + return false; + } + + return true; +} + +bool CModem::setFMExtParams() +{ + assert(m_port != NULL); + + unsigned char buffer[80U]; + unsigned char len = 7U + m_fmExtAck.size(); + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = len; + buffer[2U] = MMDVM_FM_PARAMS4; + + buffer[3U] = m_fmExtAudioBoost; + buffer[4U] = m_fmAckSpeed; + buffer[5U] = m_fmAckFrequency / 10U; + + buffer[6U] = (unsigned char)(m_fmAckLevel * 2.55F + 0.5F); + + for (unsigned int i = 0U; i < m_fmExtAck.size(); i++) + buffer[7U + i] = m_fmExtAck.at(i); + + // CUtils::dump(1U, "Written", buffer, len); + + int ret = m_port->write(buffer, len); + if (ret != len) + return false; + + unsigned int count = 0U; + RESP_TYPE_MMDVM resp; + do { + CThread::sleep(10U); + + resp = getResponse(); + if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) { + count++; + if (count >= MAX_RESPONSES) { + LogError("The MMDVM is not responding to the SET_FM_PARAMS4 command"); + return false; + } + } + } while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK); + + // CUtils::dump(1U, "Response", m_buffer, m_length); + + if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) { + LogError("Received a NAK to the SET_FM_PARAMS4 command from the modem"); + return false; + } + + return true; +} + +void CModem::printDebug() +{ + if (m_buffer[2U] == MMDVM_DEBUG1) { + LogMessage("Debug: %.*s", m_length - m_offset - 0U, m_buffer + m_offset); + } else if (m_buffer[2U] == MMDVM_DEBUG2) { + short val1 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; + LogMessage("Debug: %.*s %d", m_length - m_offset - 2U, m_buffer + m_offset, val1); + } else if (m_buffer[2U] == MMDVM_DEBUG3) { + short val1 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; + short val2 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; + LogMessage("Debug: %.*s %d %d", m_length - m_offset - 4U, m_buffer + m_offset, val1, val2); + } else if (m_buffer[2U] == MMDVM_DEBUG4) { + short val1 = (m_buffer[m_length - 6U] << 8) | m_buffer[m_length - 5U]; + short val2 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; + short val3 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; + LogMessage("Debug: %.*s %d %d %d", m_length - m_offset - 6U, m_buffer + m_offset, val1, val2, val3); + } else if (m_buffer[2U] == MMDVM_DEBUG5) { + short val1 = (m_buffer[m_length - 8U] << 8) | m_buffer[m_length - 7U]; + short val2 = (m_buffer[m_length - 6U] << 8) | m_buffer[m_length - 5U]; + short val3 = (m_buffer[m_length - 4U] << 8) | m_buffer[m_length - 3U]; + short val4 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; + LogMessage("Debug: %.*s %d %d %d %d", m_length - m_offset - 8U, m_buffer + m_offset, val1, val2, val3, val4); + } } diff --git a/Modem.h b/Modem.h index 896e5de..fe9dfb7 100644 --- a/Modem.h +++ b/Modem.h @@ -16,107 +16,268 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef MODEM_H -#define MODEM_H +#ifndef Modem_H +#define Modem_H +#include "ModemPort.h" +#include "RingBuffer.h" #include "Defines.h" -#include "MMDVMModemPort.h" +#include "Timer.h" #include -class IModem { +enum RESP_TYPE_MMDVM { + RTM_OK, + RTM_TIMEOUT, + RTM_ERROR +}; + +enum SERIAL_STATE { + SS_START, + SS_LENGTH1, + SS_LENGTH2, + SS_TYPE, + SS_DATA +}; + +class CModem { public: - virtual ~IModem() = 0; + CModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug); + ~CModem(); - virtual void setModem(IMMDVMModemPort* port) = 0; - virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) = 0; - virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17ENabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) = 0; - virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) = 0; - virtual void setDMRParams(unsigned int colorCode) = 0; - virtual void setYSFParams(bool loDev, unsigned int txHang) = 0; - virtual void setP25Params(unsigned int txHang) = 0; - virtual void setNXDNParams(unsigned int txHang) = 0; - virtual void setM17Params(unsigned int txHang) = 0; - virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) = 0; - virtual void setTransparentDataParams(unsigned int sendFrameType) = 0; + void setPort(IModemPort* port); + void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency); + void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled); + void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel); + void setDMRParams(unsigned int colorCode); + void setYSFParams(bool loDev, unsigned int txHang); + void setP25Params(unsigned int txHang); + void setNXDNParams(unsigned int txHang); + void setM17Params(unsigned int txHang); + void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist); + void setTransparentDataParams(unsigned int sendFrameType); - virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) = 0; - virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) = 0; - virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) = 0; - virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost) = 0; + void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch); + void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel); + void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel); + void setFMExtParams(const std::string& ack, unsigned int audioBoost); - virtual bool open() = 0; + bool open(); - virtual unsigned int readDStarData(unsigned char* data) = 0; - virtual unsigned int readDMRData1(unsigned char* data) = 0; - virtual unsigned int readDMRData2(unsigned char* data) = 0; - virtual unsigned int readYSFData(unsigned char* data) = 0; - virtual unsigned int readP25Data(unsigned char* data) = 0; - virtual unsigned int readNXDNData(unsigned char* data) = 0; - virtual unsigned int readM17Data(unsigned char* data) = 0; - virtual unsigned int readFMData(unsigned char* data) = 0; - virtual unsigned int readAX25Data(unsigned char* data) = 0; + unsigned int readDStarData(unsigned char* data); + unsigned int readDMRData1(unsigned char* data); + unsigned int readDMRData2(unsigned char* data); + unsigned int readYSFData(unsigned char* data); + unsigned int readP25Data(unsigned char* data); + unsigned int readNXDNData(unsigned char* data); + unsigned int readM17Data(unsigned char* data); + unsigned int readFMData(unsigned char* data); + unsigned int readAX25Data(unsigned char* data); - virtual bool hasDStarSpace() const = 0; - virtual bool hasDMRSpace1() const = 0; - virtual bool hasDMRSpace2() const = 0; - virtual bool hasYSFSpace() const = 0; - virtual bool hasP25Space() const = 0; - virtual bool hasNXDNSpace() const = 0; - virtual bool hasM17Space() const = 0; - virtual bool hasPOCSAGSpace() const = 0; - virtual unsigned int getFMSpace() const = 0; - virtual bool hasAX25Space() const = 0; + bool hasDStarSpace() const; + bool hasDMRSpace1() const; + bool hasDMRSpace2() const; + bool hasYSFSpace() const; + bool hasP25Space() const; + bool hasNXDNSpace() const; + bool hasM17Space() const; + bool hasPOCSAGSpace() const; + unsigned int getFMSpace() const; + bool hasAX25Space() const; - virtual bool hasTX() const = 0; - virtual bool hasCD() const = 0; + bool hasTX() const; + bool hasCD() const; - virtual bool hasLockout() const = 0; - virtual bool hasError() const = 0; + bool hasLockout() const; + bool hasError() const; - virtual bool writeConfig() = 0; - virtual bool writeDStarData(const unsigned char* data, unsigned int length) = 0; - virtual bool writeDMRData1(const unsigned char* data, unsigned int length) = 0; - virtual bool writeDMRData2(const unsigned char* data, unsigned int length) = 0; - virtual bool writeYSFData(const unsigned char* data, unsigned int length) = 0; - virtual bool writeP25Data(const unsigned char* data, unsigned int length) = 0; - virtual bool writeNXDNData(const unsigned char* data, unsigned int length) = 0; - virtual bool writeM17Data(const unsigned char* data, unsigned int length) = 0; - virtual bool writePOCSAGData(const unsigned char* data, unsigned int length) = 0; - virtual bool writeFMData(const unsigned char* data, unsigned int length) = 0; - virtual bool writeAX25Data(const unsigned char* data, unsigned int length) = 0; + bool writeConfig(); + bool writeDStarData(const unsigned char* data, unsigned int length); + bool writeDMRData1(const unsigned char* data, unsigned int length); + bool writeDMRData2(const unsigned char* data, unsigned int length); + bool writeYSFData(const unsigned char* data, unsigned int length); + bool writeP25Data(const unsigned char* data, unsigned int length); + bool writeNXDNData(const unsigned char* data, unsigned int length); + bool writeM17Data(const unsigned char* data, unsigned int length); + bool writePOCSAGData(const unsigned char* data, unsigned int length); + bool writeFMData(const unsigned char* data, unsigned int length); + bool writeAX25Data(const unsigned char* data, unsigned int length); - virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0; - virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0; - virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) = 0; - virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type) = 0; - virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) = 0; - virtual bool writeM17Info(const char* source, const char* dest, const char* type) = 0; - virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message) = 0; - virtual bool writeIPInfo(const std::string& address) = 0; + bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); + bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); + bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin); + bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type); + bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type); + bool writeM17Info(const char* source, const char* dest, const char* type); + bool writePOCSAGInfo(unsigned int ric, const std::string& message); + bool writeIPInfo(const std::string& address); - virtual bool writeDMRStart(bool tx) = 0; - virtual bool writeDMRShortLC(const unsigned char* lc) = 0; - virtual bool writeDMRAbort(unsigned int slotNo) = 0; + bool writeDMRStart(bool tx); + bool writeDMRShortLC(const unsigned char* lc); + bool writeDMRAbort(unsigned int slotNo); - virtual bool writeTransparentData(const unsigned char* data, unsigned int length) = 0; - virtual unsigned int readTransparentData(unsigned char* data) = 0; + bool writeTransparentData(const unsigned char* data, unsigned int length); + unsigned int readTransparentData(unsigned char* data); - virtual bool writeSerial(const unsigned char* data, unsigned int length) = 0; - virtual unsigned int readSerial(unsigned char* data, unsigned int length) = 0; + bool writeSerial(const unsigned char* data, unsigned int length); + unsigned int readSerial(unsigned char* data, unsigned int length); - virtual unsigned char getMode() const = 0; - virtual bool setMode(unsigned char mode) = 0; + unsigned char getMode() const; + bool setMode(unsigned char mode); - virtual bool sendCWId(const std::string& callsign) = 0; + bool sendCWId(const std::string& callsign); - virtual HW_TYPE getHWType() const = 0; + HW_TYPE getHWType() const; - virtual void clock(unsigned int ms) = 0; + void clock(unsigned int ms); - virtual void close() = 0; + void close(); private: + unsigned int m_protocolVersion; + unsigned int m_dmrColorCode; + bool m_ysfLoDev; + unsigned int m_ysfTXHang; + unsigned int m_p25TXHang; + unsigned int m_nxdnTXHang; + unsigned int m_m17TXHang; + bool m_duplex; + bool m_rxInvert; + bool m_txInvert; + bool m_pttInvert; + unsigned int m_txDelay; + unsigned int m_dmrDelay; + float m_rxLevel; + float m_cwIdTXLevel; + float m_dstarTXLevel; + float m_dmrTXLevel; + float m_ysfTXLevel; + float m_p25TXLevel; + float m_nxdnTXLevel; + float m_m17TXLevel; + float m_pocsagTXLevel; + float m_fmTXLevel; + float m_ax25TXLevel; + float m_rfLevel; + bool m_useCOSAsLockout; + bool m_trace; + bool m_debug; + unsigned int m_rxFrequency; + unsigned int m_txFrequency; + unsigned int m_pocsagFrequency; + bool m_dstarEnabled; + bool m_dmrEnabled; + bool m_ysfEnabled; + bool m_p25Enabled; + bool m_nxdnEnabled; + bool m_m17Enabled; + bool m_pocsagEnabled; + bool m_fmEnabled; + bool m_ax25Enabled; + int m_rxDCOffset; + int m_txDCOffset; + IModemPort* m_port; + unsigned char* m_buffer; + unsigned int m_length; + unsigned int m_offset; + SERIAL_STATE m_state; + unsigned char m_type; + CRingBuffer m_rxDStarData; + CRingBuffer m_txDStarData; + CRingBuffer m_rxDMRData1; + CRingBuffer m_rxDMRData2; + CRingBuffer m_txDMRData1; + CRingBuffer m_txDMRData2; + CRingBuffer m_rxYSFData; + CRingBuffer m_txYSFData; + CRingBuffer m_rxP25Data; + CRingBuffer m_txP25Data; + CRingBuffer m_rxNXDNData; + CRingBuffer m_txNXDNData; + CRingBuffer m_rxM17Data; + CRingBuffer m_txM17Data; + CRingBuffer m_txPOCSAGData; + CRingBuffer m_rxFMData; + CRingBuffer m_txFMData; + CRingBuffer m_rxAX25Data; + CRingBuffer m_txAX25Data; + CRingBuffer m_rxSerialData; + CRingBuffer m_txSerialData; + CRingBuffer m_rxTransparentData; + CRingBuffer m_txTransparentData; + unsigned int m_sendTransparentDataFrameType; + CTimer m_statusTimer; + CTimer m_inactivityTimer; + CTimer m_playoutTimer; + unsigned int m_dstarSpace; + unsigned int m_dmrSpace1; + unsigned int m_dmrSpace2; + unsigned int m_ysfSpace; + unsigned int m_p25Space; + unsigned int m_nxdnSpace; + unsigned int m_m17Space; + unsigned int m_pocsagSpace; + unsigned int m_fmSpace; + unsigned int m_ax25Space; + bool m_tx; + bool m_cd; + bool m_lockout; + bool m_error; + unsigned char m_mode; + HW_TYPE m_hwType; + int m_ax25RXTwist; + unsigned int m_ax25TXDelay; + unsigned int m_ax25SlotTime; + unsigned int m_ax25PPersist; + + std::string m_fmCallsign; + unsigned int m_fmCallsignSpeed; + unsigned int m_fmCallsignFrequency; + unsigned int m_fmCallsignTime; + unsigned int m_fmCallsignHoldoff; + float m_fmCallsignHighLevel; + float m_fmCallsignLowLevel; + bool m_fmCallsignAtStart; + bool m_fmCallsignAtEnd; + bool m_fmCallsignAtLatch; + std::string m_fmRfAck; + std::string m_fmExtAck; + unsigned int m_fmAckSpeed; + unsigned int m_fmAckFrequency; + unsigned int m_fmAckMinTime; + unsigned int m_fmAckDelay; + float m_fmAckLevel; + unsigned int m_fmTimeout; + float m_fmTimeoutLevel; + float m_fmCtcssFrequency; + unsigned int m_fmCtcssHighThreshold; + unsigned int m_fmCtcssLowThreshold; + float m_fmCtcssLevel; + unsigned int m_fmKerchunkTime; + unsigned int m_fmHangTime; + unsigned int m_fmAccessMode; + bool m_fmCOSInvert; + bool m_fmNoiseSquelch; + unsigned int m_fmSquelchHighThreshold; + unsigned int m_fmSquelchLowThreshold; + unsigned int m_fmRFAudioBoost; + unsigned int m_fmExtAudioBoost; + float m_fmMaxDevLevel; + bool m_fmExtEnable; + + bool readVersion(); + bool readStatus(); + bool setConfig1(); + bool setConfig2(); + bool setFrequency(); + bool setFMCallsignParams(); + bool setFMAckParams(); + bool setFMMiscParams(); + bool setFMExtParams(); + + void printDebug(); + + RESP_TYPE_MMDVM getResponse(); }; #endif diff --git a/MMDVMModemPort.cpp b/ModemPort.cpp similarity index 92% rename from MMDVMModemPort.cpp rename to ModemPort.cpp index 5b60b74..6a675e6 100644 --- a/MMDVMModemPort.cpp +++ b/ModemPort.cpp @@ -16,8 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "MMDVMModemPort.h" +#include "ModemPort.h" -IMMDVMModemPort::~IMMDVMModemPort() +IModemPort::~IModemPort() { } diff --git a/MMDVMModemPort.h b/ModemPort.h similarity index 90% rename from MMDVMModemPort.h rename to ModemPort.h index 565708c..c537f9e 100644 --- a/MMDVMModemPort.h +++ b/ModemPort.h @@ -16,12 +16,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef MMDVMModemPort_H -#define MMDVMModemPort_H +#ifndef ModemPort_H +#define ModemPort_H -class IMMDVMModemPort { +class IModemPort { public: - virtual ~IMMDVMModemPort() = 0; + virtual ~IModemPort() = 0; virtual bool open() = 0; diff --git a/ModemSerialPort.cpp b/ModemSerialPort.cpp index c34cb3d..aa0a194 100644 --- a/ModemSerialPort.cpp +++ b/ModemSerialPort.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016,2020 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2020,2021 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 @@ -21,7 +21,7 @@ #include #include -IModemSerialPort::IModemSerialPort(IModem* modem) : +IModemSerialPort::IModemSerialPort(CModem* modem) : m_modem(modem) { assert(modem != NULL); diff --git a/ModemSerialPort.h b/ModemSerialPort.h index 6de56a7..9a64426 100644 --- a/ModemSerialPort.h +++ b/ModemSerialPort.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016,2020 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2020,2021 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 @@ -24,7 +24,7 @@ class IModemSerialPort : public ISerialPort { public: - IModemSerialPort(IModem* modem); + IModemSerialPort(CModem* modem); virtual ~IModemSerialPort(); virtual bool open(); @@ -36,7 +36,7 @@ public: virtual void close(); private: - IModem* m_modem; + CModem* m_modem; }; #endif diff --git a/NullController.h b/NullController.h index 5cb39c8..bbf0681 100644 --- a/NullController.h +++ b/NullController.h @@ -19,9 +19,9 @@ #ifndef NullController_H #define NullController_H -#include "MMDVMModemPort.h" +#include "ModemPort.h" -class CNullController : public IMMDVMModemPort { +class CNullController : public IModemPort { public: CNullController(); virtual ~CNullController(); diff --git a/UARTController.h b/UARTController.h index bd7d133..bdb9bd9 100644 --- a/UARTController.h +++ b/UARTController.h @@ -20,7 +20,7 @@ #ifndef UARTController_H #define UARTController_H -#include "MMDVMModemPort.h" +#include "ModemPort.h" #include "SerialPort.h" #include @@ -29,7 +29,7 @@ #include #endif -class CUARTController : public ISerialPort, public IMMDVMModemPort { +class CUARTController : public ISerialPort, public IModemPort { public: CUARTController(const std::string& device, unsigned int speed, bool assertRTS = false); virtual ~CUARTController(); diff --git a/UDPController.h b/UDPController.h index acb19e4..ee10cb3 100644 --- a/UDPController.h +++ b/UDPController.h @@ -19,13 +19,13 @@ #ifndef UDPController_H #define UDPController_H -#include "MMDVMModemPort.h" +#include "ModemPort.h" #include "RingBuffer.h" #include "UDPSocket.h" #include -class CUDPController : public IMMDVMModemPort { +class CUDPController : public IModemPort { public: CUDPController(const std::string& modemAddress, unsigned int modemPort, unsigned int localPort); virtual ~CUDPController();