diff --git a/Conf.cpp b/Conf.cpp index 7a78d57..d48aff7 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -35,6 +35,7 @@ enum SECTION { SECTION_CWID, SECTION_DMRID_LOOKUP, SECTION_MODEM, + SECTION_UMP, SECTION_DSTAR, SECTION_DMR, SECTION_FUSION, @@ -93,6 +94,8 @@ m_modemOscOffset(0), m_modemRSSIMultiplier(0), m_modemRSSIOffset(0), m_modemDebug(false), +m_umpEnabled(false), +m_umpPort(), m_dstarEnabled(false), m_dstarModule("C"), m_dstarSelfOnly(false), @@ -207,7 +210,9 @@ bool CConf::read() else if (::strncmp(buffer, "[DMR Id Lookup]", 15U) == 0) section = SECTION_DMRID_LOOKUP; else if (::strncmp(buffer, "[Modem]", 7U) == 0) - section = SECTION_MODEM; + section = SECTION_MODEM; + else if (::strncmp(buffer, "[UMP]", 5U) == 0) + section = SECTION_UMP; else if (::strncmp(buffer, "[D-Star]", 8U) == 0) section = SECTION_DSTAR; else if (::strncmp(buffer, "[DMR]", 5U) == 0) @@ -217,15 +222,15 @@ bool CConf::read() else if (::strncmp(buffer, "[P25]", 5U) == 0) section = SECTION_P25; else if (::strncmp(buffer, "[D-Star Network]", 16U) == 0) - section = SECTION_DSTAR_NETWORK; + section = SECTION_DSTAR_NETWORK; else if (::strncmp(buffer, "[DMR Network]", 13U) == 0) - section = SECTION_DMR_NETWORK; + section = SECTION_DMR_NETWORK; else if (::strncmp(buffer, "[System Fusion Network]", 23U) == 0) - section = SECTION_FUSION_NETWORK; + section = SECTION_FUSION_NETWORK; else if (::strncmp(buffer, "[P25 Network]", 13U) == 0) section = SECTION_P25_NETWORK; else if (::strncmp(buffer, "[TFT Serial]", 12U) == 0) - section = SECTION_TFTSERIAL; + section = SECTION_TFTSERIAL; else if (::strncmp(buffer, "[HD44780]", 9U) == 0) section = SECTION_HD44780; else if (::strncmp(buffer, "[Nextion]", 9U) == 0) @@ -235,7 +240,7 @@ bool CConf::read() else if (::strncmp(buffer, "[LCDproc]", 9U) == 0) section = SECTION_LCDPROC; else - section = SECTION_NONE; + section = SECTION_NONE; continue; } @@ -338,6 +343,11 @@ bool CConf::read() m_modemRSSIOffset = ::atoi(value); else if (::strcmp(key, "Debug") == 0) m_modemDebug = ::atoi(value) == 1; + } else if (section == SECTION_UMP) { + if (::strcmp(key, "Enable") == 0) + m_umpEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Port") == 0) + m_umpPort = value; } else if (section == SECTION_DSTAR) { if (::strcmp(key, "Enable") == 0) m_dstarEnabled = ::atoi(value) == 1; @@ -802,6 +812,16 @@ bool CConf::getModemDebug() const return m_modemDebug; } +bool CConf::getUMPEnabled() const +{ + return m_umpEnabled; +} + +std::string CConf::getUMPPort() const +{ + return m_umpPort; +} + bool CConf::getDStarEnabled() const { return m_dstarEnabled; diff --git a/Conf.h b/Conf.h index 4bf739d..8526acb 100644 --- a/Conf.h +++ b/Conf.h @@ -82,6 +82,10 @@ public: int getModemRSSIOffset() const; bool getModemDebug() const; + // The UMP section + bool getUMPEnabled() const; + std::string getUMPPort() const; + // The D-Star section bool getDStarEnabled() const; std::string getDStarModule() const; @@ -237,6 +241,9 @@ private: int m_modemRSSIOffset; bool m_modemDebug; + bool m_umpEnabled; + std::string m_umpPort; + bool m_dstarEnabled; std::string m_dstarModule; bool m_dstarSelfOnly; diff --git a/MMDVM.ini b/MMDVM.ini index 7df7948..5d38e4c 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -54,6 +54,11 @@ RSSIMultiplier=1 RSSIOffset=10 Debug=0 +[UMP] +Enable=0 +# Port=\\.\COM4 +Port=/dev/ttyACM1 + [D-Star] Enable=1 Module=C diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index dcf4c31..ed107e9 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -127,6 +127,7 @@ m_dmrNetwork(NULL), m_ysfNetwork(NULL), m_p25Network(NULL), m_display(NULL), +m_ump(NULL), m_mode(MODE_IDLE), m_rfModeHang(10U), m_netModeHang(3U), @@ -240,6 +241,20 @@ int CMMDVMHost::run() if (!ret) return 1; + if (m_conf.getUMPEnabled()) { + std::string port = m_conf.getUMPPort(); + + LogInfo("Universal MMDVM Peripheral"); + LogInfo(" Port: %s", port.c_str()); + + m_ump = new CUMP(port); + bool ret = m_ump->open(); + if (!ret) { + delete m_ump; + m_ump = NULL; + } + } + createDisplay(); if (m_dstarEnabled && m_conf.getDStarNetworkEnabled()) { @@ -420,10 +435,13 @@ int CMMDVMHost::run() LogMessage("MMDVMHost-%s is running", VERSION); while (!m_killed) { - bool lockout = m_modem->hasLockout(); - if (lockout && m_mode != MODE_LOCKOUT) + bool lockout1 = m_modem->hasLockout(); + bool lockout2 = false; + if (m_ump != NULL) + lockout2 = m_ump->getLockout(); + if ((lockout1 || lockout2) && m_mode != MODE_LOCKOUT) setMode(MODE_LOCKOUT); - else if (!lockout && m_mode == MODE_LOCKOUT) + else if ((!lockout1 && !lockout2) && m_mode == MODE_LOCKOUT) setMode(MODE_IDLE); bool error = m_modem->hasError(); @@ -432,6 +450,11 @@ int CMMDVMHost::run() else if (!error && m_mode == MODE_ERROR) setMode(MODE_IDLE); + if (m_ump != NULL) { + bool tx = m_modem->hasTX(); + m_ump->setTX(tx); + } + unsigned char data[200U]; unsigned int len; bool ret; @@ -719,6 +742,9 @@ int CMMDVMHost::run() m_dmrTXTimer.stop(); } + if (m_ump != NULL) + m_ump->clock(ms); + if (ms < 5U) CThread::sleep(5U); } @@ -733,6 +759,11 @@ int CMMDVMHost::run() m_display->close(); delete m_display; + if (m_ump != NULL) { + m_ump->close(); + delete m_ump; + } + if (m_lookup != NULL) m_lookup->stop(); @@ -1024,13 +1055,16 @@ void CMMDVMHost::createDisplay() LogInfo(" Display UTC: %s", utc ? "yes" : "no"); LogInfo(" Idle Brightness: %u", idleBrightness); - ISerialPort* serial = NULL; - if (port == "modem") - serial = new CModemSerialPort(m_modem); - else - serial = new CSerialController(port, SERIAL_9600); - - m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness); + if (port == "modem") { + ISerialPort* serial = new CModemSerialPort(m_modem); + m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness); + } else if (port == "ump") { + if (m_ump != NULL) + m_display = new CNextion(m_callsign, dmrid, m_ump, brightness, displayClock, utc, idleBrightness); + } else { + ISerialPort* serial = new CSerialController(port, SERIAL_9600); + m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness); + } } else if (type == "LCDproc") { std::string address = m_conf.getLCDprocAddress(); unsigned int port = m_conf.getLCDprocPort(); @@ -1124,6 +1158,8 @@ void CMMDVMHost::setMode(unsigned char mode) if (m_p25Network != NULL) m_p25Network->enable(false); m_modem->setMode(MODE_DSTAR); + if (m_ump != NULL) + m_ump->setMode(MODE_DSTAR); m_mode = MODE_DSTAR; m_modeTimer.start(); m_cwIdTimer.stop(); @@ -1137,6 +1173,8 @@ void CMMDVMHost::setMode(unsigned char mode) if (m_p25Network != NULL) m_p25Network->enable(false); m_modem->setMode(MODE_DMR); + if (m_ump != NULL) + m_ump->setMode(MODE_DMR); if (m_duplex) { m_modem->writeDMRStart(true); m_dmrTXTimer.start(); @@ -1154,6 +1192,8 @@ void CMMDVMHost::setMode(unsigned char mode) if (m_p25Network != NULL) m_p25Network->enable(false); m_modem->setMode(MODE_YSF); + if (m_ump != NULL) + m_ump->setMode(MODE_YSF); m_mode = MODE_YSF; m_modeTimer.start(); m_cwIdTimer.stop(); @@ -1167,6 +1207,8 @@ void CMMDVMHost::setMode(unsigned char mode) if (m_ysfNetwork != NULL) m_ysfNetwork->enable(false); m_modem->setMode(MODE_P25); + if (m_ump != NULL) + m_ump->setMode(MODE_P25); m_mode = MODE_P25; m_modeTimer.start(); m_cwIdTimer.stop(); @@ -1187,6 +1229,8 @@ void CMMDVMHost::setMode(unsigned char mode) m_dmrTXTimer.stop(); } m_modem->setMode(MODE_IDLE); + if (m_ump != NULL) + m_ump->setMode(MODE_IDLE); m_display->setLockout(); m_mode = MODE_LOCKOUT; m_modeTimer.stop(); @@ -1207,6 +1251,8 @@ void CMMDVMHost::setMode(unsigned char mode) m_modem->writeDMRStart(false); m_dmrTXTimer.stop(); } + if (m_ump != NULL) + m_ump->setMode(MODE_IDLE); m_display->setError("MODEM"); m_mode = MODE_ERROR; m_modeTimer.stop(); @@ -1227,6 +1273,8 @@ void CMMDVMHost::setMode(unsigned char mode) m_dmrTXTimer.stop(); } m_modem->setMode(MODE_IDLE); + if (m_ump != NULL) + m_ump->setMode(MODE_IDLE); if (m_mode == MODE_ERROR || m_mode == MODE_LOCKOUT) { m_modem->sendCWId(m_callsign); m_cwIdTimer.setTimeout(m_cwIdTime); diff --git a/MMDVMHost.h b/MMDVMHost.h index 8206d7d..8608d5d 100644 --- a/MMDVMHost.h +++ b/MMDVMHost.h @@ -28,6 +28,7 @@ #include "Timer.h" #include "Modem.h" #include "Conf.h" +#include "UMP.h" #include @@ -47,6 +48,7 @@ private: CYSFNetwork* m_ysfNetwork; CP25Network* m_p25Network; CDisplay* m_display; + CUMP* m_ump; unsigned char m_mode; unsigned int m_rfModeHang; unsigned int m_netModeHang; diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index 064b5b7..1a43994 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -206,6 +206,7 @@ + @@ -271,6 +272,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 55ff153..476c322 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -215,6 +215,9 @@ Header Files + + Header Files + @@ -400,5 +403,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 15eede6..f41527f 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi b/Makefile.Pi index a83845d..771e62c 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.Adafruit b/Makefile.Pi.Adafruit index a6deba3..cbab68a 100644 --- a/Makefile.Pi.Adafruit +++ b/Makefile.Pi.Adafruit @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \ - Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 4ee0fc5..d52cf36 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index b96e785..0c3fc9b 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index b242148..6d432c7 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/Makefile.Solaris b/Makefile.Solaris index 1def20e..d64df30 100644 --- a/Makefile.Solaris +++ b/Makefile.Solaris @@ -11,7 +11,7 @@ OBJECTS = \ DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \ Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \ P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \ - Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o + UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost diff --git a/UMP.cpp b/UMP.cpp new file mode 100644 index 0000000..a5bdf6a --- /dev/null +++ b/UMP.cpp @@ -0,0 +1,238 @@ +/* +* Copyright (C) 2016 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 "Defines.h" +#include "Utils.h" +#include "Log.h" +#include "UMP.h" + +#include +#include + +const unsigned char UMP_FRAME_START = 0xF0U; + +const unsigned char UMP_HELLO = 0x00U; + +const unsigned char UMP_SET_MODE = 0x01U; +const unsigned char UMP_SET_TX = 0x02U; + +const unsigned char UMP_WRITE_SERIAL = 0x10U; +const unsigned char UMP_READ_SERIAL = 0x11U; + +const unsigned char UMP_STATUS = 0x50U; + +const unsigned int BUFFER_LENGTH = 255U; + +CUMP::CUMP(const std::string& port) : +m_serial(port, SERIAL_115200), +m_buffer(NULL), +m_length(0U), +m_offset(0U), +m_lockout(false), +m_mode(MODE_IDLE), +m_tx(false) +{ + m_buffer = new unsigned char[BUFFER_LENGTH]; +} + +CUMP::~CUMP() +{ + delete[] m_buffer; +} + +bool CUMP::open() +{ + bool ret = m_serial.open(); + if (!ret) + return false; + + unsigned char buffer[3U]; + + buffer[0U] = UMP_FRAME_START; + buffer[1U] = 3U; + buffer[2U] = UMP_HELLO; + + int n = m_serial.write(buffer, 3U); + if (n != 3) { + m_serial.close(); + return false; + } + + return true; +} + +bool CUMP::setMode(unsigned char mode) +{ + if (mode == m_mode) + return true; + + m_mode = mode; + + unsigned char buffer[4U]; + + buffer[0U] = UMP_FRAME_START; + buffer[1U] = 4U; + buffer[2U] = UMP_SET_MODE; + buffer[3U] = mode; + + return m_serial.write(buffer, 4U) == 4; +} + +bool CUMP::setTX(bool on) +{ + if (on == m_tx) + return true; + + m_tx = on; + + unsigned char buffer[4U]; + + buffer[0U] = UMP_FRAME_START; + buffer[1U] = 4U; + buffer[2U] = UMP_SET_TX; + buffer[3U] = on ? 0x01U : 0x00U; + + return m_serial.write(buffer, 4U) == 4; +} + +bool CUMP::getLockout() const +{ + return m_lockout; +} + +int CUMP::write(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[250U]; + + buffer[0U] = UMP_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = UMP_WRITE_SERIAL; + + ::memcpy(buffer + 3U, data, length); + + return m_serial.write(buffer, length + 3U); +} + +// To be implemented later if needed +int CUMP::read(unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + return 0; +} + +void CUMP::clock(unsigned int ms) +{ + if (m_offset == 0U) { + // Get the start of the frame or nothing at all + int ret = m_serial.read(m_buffer + 0U, 1U); + if (ret < 0) { + LogError("Error when reading from the UMP"); + return; + } + + if (ret == 0) + return; + + if (m_buffer[0U] != UMP_FRAME_START) + return; + + m_offset = 1U; + } + + if (m_offset == 1U) { + // Get the length of the frame + int ret = m_serial.read(m_buffer + 1U, 1U); + if (ret < 0) { + LogError("Error when reading from the UMP"); + m_offset = 0U; + return; + } + + if (ret == 0) + return; + + if (m_buffer[1U] >= 250U) { + LogError("Invalid length received from the UMP - %u", m_buffer[1U]); + m_offset = 0U; + return; + } + + m_length = m_buffer[1U]; + m_offset = 2U; + } + + if (m_offset == 2U) { + // Get the frame type + int ret = m_serial.read(m_buffer + 2U, 1U); + if (ret < 0) { + LogError("Error when reading from the UMP"); + m_offset = 0U; + return; + } + + if (ret == 0) + return; + + switch (m_buffer[2U]) { + case UMP_STATUS: + case UMP_READ_SERIAL: + break; + + default: + LogError("Unknown message, type: %02X", m_buffer[2U]); + m_offset = 0U; + return; + } + + m_offset = 3U; + } + + if (m_offset >= 3U) { + while (m_offset < m_length) { + int ret = m_serial.read(m_buffer + m_offset, m_length - m_offset); + if (ret < 0) { + LogError("Error when reading from the UMP"); + m_offset = 0U; + return; + } + + if (ret == 0) + return; + + if (ret > 0) + m_offset += ret; + } + } + + m_offset = 0U; + + // CUtils::dump(1U, "Received", m_buffer, m_length); + + if (m_buffer[2U] == UMP_STATUS) + m_lockout = (m_buffer[3U] & 0x01U) == 0x01U; +} + +void CUMP::close() +{ + m_serial.close(); +} diff --git a/UMP.h b/UMP.h new file mode 100644 index 0000000..17a1e97 --- /dev/null +++ b/UMP.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2016 by Jonathan Naylor G4KLX +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if !defined(UMP_H) +#define UMP_H + +#include "SerialController.h" +#include "SerialPort.h" + +#include + +class CUMP : public ISerialPort +{ +public: + CUMP(const std::string& port); + virtual ~CUMP(); + + virtual bool open(); + + bool setMode(unsigned char mode); + + bool setTX(bool on); + + bool getLockout() const; + + virtual int read(unsigned char* buffer, unsigned int length); + + virtual int write(const unsigned char* buffer, unsigned int length); + + void clock(unsigned int ms); + + virtual void close(); + +private: + CSerialController m_serial; + unsigned char* m_buffer; + unsigned int m_length; + unsigned int m_offset; + bool m_lockout; + unsigned char m_mode; + bool m_tx; +}; + +#endif