From 266680f39b00db8a60e7756a4a25ac794c9f8fa4 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Wed, 14 Apr 2021 23:44:49 +0000 Subject: [PATCH] refactor Modem further to allow custom entry points for "user" handlers for modem open, close and clock (HostCal and Host use this); refactor "remote mode" in Host to use Modem custom entry points; correct some issues with the port of UARTPort from upstream (revert some changes back to pre-UARTPort from the old SerialController class); rework HostCal to use the new custom entry points; rework HostCal for better consistency and class use; correct and rename some misleading class variables and functions; --- host/Host.cpp | 301 +++++++++++------ host/Host.h | 15 +- host/calibrate/HostCal.cpp | 529 ++++++++++------------------- host/calibrate/HostCal.h | 21 +- modem/Modem.cpp | 675 +++++++++++++++++++++---------------- modem/Modem.h | 64 +++- modem/port/UARTPort.cpp | 246 +++++++------- modem/port/UARTPort.h | 5 +- network/RemoteControl.cpp | 18 +- 9 files changed, 959 insertions(+), 915 deletions(-) diff --git a/host/Host.cpp b/host/Host.cpp index 0d01d5ac..9bc2f777 100644 --- a/host/Host.cpp +++ b/host/Host.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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 @@ -50,6 +50,7 @@ using namespace lookups; #include #include #include +#include #include #if !defined(_WIN32) && !defined(_WIN64) @@ -73,7 +74,8 @@ Host::Host(const std::string& confFile) : m_modem(NULL), m_modemRemote(false), m_network(NULL), - m_mode(STATE_IDLE), + m_modemRemotePort(NULL), + m_state(STATE_IDLE), m_modeTimer(1000U), m_dmrTXTimer(1000U), m_cwIdTimer(1000U), @@ -210,15 +212,15 @@ int Host::run() // main execution loop while (!killed) { - if (m_modem->hasLockout() && m_mode != HOST_STATE_LOCKOUT) - setMode(HOST_STATE_LOCKOUT); - else if (!m_modem->hasLockout() && m_mode == HOST_STATE_LOCKOUT) - setMode(STATE_IDLE); + if (m_modem->hasLockout() && m_state != HOST_STATE_LOCKOUT) + setState(HOST_STATE_LOCKOUT); + else if (!m_modem->hasLockout() && m_state == HOST_STATE_LOCKOUT) + setState(STATE_IDLE); - if (m_modem->hasError() && m_mode != HOST_STATE_ERROR) - setMode(HOST_STATE_ERROR); - else if (!m_modem->hasError() && m_mode == HOST_STATE_ERROR) - setMode(STATE_IDLE); + if (m_modem->hasError() && m_state != HOST_STATE_ERROR) + setState(HOST_STATE_ERROR); + else if (!m_modem->hasError() && m_state == HOST_STATE_ERROR) + setState(STATE_IDLE); uint32_t ms = stopWatch.elapsed(); if (ms > 1U) @@ -245,7 +247,7 @@ int Host::run() Thread::sleep(1U); } - setMode(HOST_STATE_QUIT); + setState(HOST_STATE_QUIT); return EXIT_SUCCESS; } @@ -474,7 +476,7 @@ int Host::run() } if (m_fixedMode && m_dmrEnabled && m_p25Enabled) { - ::LogError(LOG_HOST, "Cannot have DMR enabled and P25 enabled when using fixed mode! Choose one protocol for fixed mode operation."); + ::LogError(LOG_HOST, "Cannot have DMR enabled and P25 enabled when using fixed state! Choose one protocol for fixed state operation."); g_killed = true; } @@ -489,19 +491,19 @@ int Host::run() } if (!g_killed) { - // fixed more or P25 control channel will force a mode change + // fixed more or P25 control channel will force a state change if (m_fixedMode || m_p25CtrlChannel) { if (m_p25CtrlChannel) { m_fixedMode = true; } if (dmr != NULL) - setMode(STATE_DMR); + setState(STATE_DMR); if (p25 != NULL) - setMode(STATE_P25); + setState(STATE_P25); } else { - setMode(STATE_IDLE); + setState(STATE_IDLE); } ::LogInfoEx(LOG_HOST, "Host is performing late initialization and warmup"); @@ -545,15 +547,15 @@ int Host::run() // main execution loop while (!killed) { - if (m_modem->hasLockout() && m_mode != HOST_STATE_LOCKOUT) - setMode(HOST_STATE_LOCKOUT); - else if (!m_modem->hasLockout() && m_mode == HOST_STATE_LOCKOUT) - setMode(STATE_IDLE); + if (m_modem->hasLockout() && m_state != HOST_STATE_LOCKOUT) + setState(HOST_STATE_LOCKOUT); + else if (!m_modem->hasLockout() && m_state == HOST_STATE_LOCKOUT) + setState(STATE_IDLE); - if (m_modem->hasError() && m_mode != HOST_STATE_ERROR) - setMode(HOST_STATE_ERROR); - else if (!m_modem->hasError() && m_mode == HOST_STATE_ERROR) - setMode(STATE_IDLE); + if (m_modem->hasError() && m_state != HOST_STATE_ERROR) + setState(HOST_STATE_ERROR); + else if (!m_modem->hasError() && m_state == HOST_STATE_ERROR) + setState(STATE_IDLE); uint32_t ms = stopWatch.elapsed(); if (ms > 1U) @@ -574,13 +576,13 @@ int Host::run() // write those frames to the DMR controller len = m_modem->readDMRData1(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { // if the modem is in duplex -- process wakeup CSBKs if (m_duplex) { bool ret = dmr->processWakeup(data); if (ret) { m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); dmrBeaconDurationTimer.stop(); INTERRUPT_P25_CONTROL; @@ -589,14 +591,14 @@ int Host::run() else { // in simplex directly process slot 1 frames m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); dmr->processFrame1(data, len); dmrBeaconDurationTimer.stop(); p25CCDurationTimer.stop(); } } - else if (m_mode == STATE_DMR) { + else if (m_state == STATE_DMR) { // if the modem is in duplex, and hasn't started transmitting // process wakeup CSBKs if (m_duplex && !m_modem->hasTX()) { @@ -619,8 +621,8 @@ int Host::run() } } } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR modem data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR modem data received, state = %u", m_state); } } @@ -628,13 +630,13 @@ int Host::run() // write those frames to the DMR controller len = m_modem->readDMRData2(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { // if the modem is in duplex -- process wakeup CSBKs if (m_duplex) { bool ret = dmr->processWakeup(data); if (ret) { m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); dmrBeaconDurationTimer.stop(); INTERRUPT_P25_CONTROL; @@ -643,14 +645,14 @@ int Host::run() else { // in simplex -- directly process slot 2 frames m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); dmr->processFrame2(data, len); dmrBeaconDurationTimer.stop(); INTERRUPT_P25_CONTROL; } } - else if (m_mode == STATE_DMR) { + else if (m_state == STATE_DMR) { // if the modem is in duplex, and hasn't started transmitting // process wakeup CSBKs if (m_duplex && !m_modem->hasTX()) { @@ -673,8 +675,8 @@ int Host::run() } } } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR modem data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR modem data received, state = %u", m_state); } } } @@ -685,11 +687,11 @@ int Host::run() if (p25 != NULL) { len = m_modem->readP25Data(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { bool ret = p25->processFrame(data, len); if (ret) { m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_P25); + setState(STATE_P25); dmrBeaconDurationTimer.stop(); INTERRUPT_P25_CONTROL; @@ -699,12 +701,12 @@ int Host::run() if (ret) { dmrBeaconDurationTimer.stop(); - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_P25); + setState(STATE_P25); } - if (m_mode == STATE_P25) { + if (m_state == STATE_P25) { m_modeTimer.start(); } @@ -730,7 +732,7 @@ int Host::run() } } } - else if (m_mode == STATE_P25) { + else if (m_state == STATE_P25) { bool ret = p25->processFrame(data, len); if (ret) { m_modeTimer.start(); @@ -739,19 +741,19 @@ int Host::run() else { ret = p25->writeEndRF(); if (ret) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_rfModeHang); - setMode(STATE_P25); + setState(STATE_P25); } - if (m_mode == STATE_P25) { + if (m_state == STATE_P25) { m_modeTimer.start(); } } } } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "P25 modem data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "P25 modem data received, state = %u", m_state); } } } @@ -762,12 +764,12 @@ int Host::run() if (m_modeTimer.isRunning() && m_modeTimer.hasExpired()) { if (!m_fixedMode) { - setMode(STATE_IDLE); + setState(STATE_IDLE); } else { if (dmr != NULL) - setMode(STATE_DMR); + setState(STATE_DMR); if (p25 != NULL) - setMode(STATE_P25); + setState(STATE_P25); } } @@ -780,11 +782,11 @@ int Host::run() if (ret) { len = dmr->getFrame1(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_netModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); } - if (m_mode == STATE_DMR) { + if (m_state == STATE_DMR) { // if the modem is in duplex -- write DMR sync start if (m_duplex) { m_modem->writeDMRStart(true); @@ -799,8 +801,8 @@ int Host::run() } m_modeTimer.start(); } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); } } } @@ -812,11 +814,11 @@ int Host::run() if (ret) { len = dmr->getFrame2(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_netModeHang); - setMode(STATE_DMR); + setState(STATE_DMR); } - if (m_mode == STATE_DMR) { + if (m_state == STATE_DMR) { // if the modem is in duplex -- write DMR sync start if (m_duplex) { m_modem->writeDMRStart(true); @@ -831,8 +833,8 @@ int Host::run() } m_modeTimer.start(); } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); } } } @@ -847,12 +849,12 @@ int Host::run() if (ret) { len = p25->getFrame(data); if (len > 0U) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_netModeHang); - setMode(STATE_P25); + setState(STATE_P25); } - if (m_mode == STATE_P25) { + if (m_state == STATE_P25) { m_modem->writeP25Data(data, len); dmrBeaconDurationTimer.stop(); @@ -862,12 +864,12 @@ int Host::run() m_modeTimer.start(); } - else if (m_mode != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "P25 data received, mode = %u", m_mode); + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "P25 data received, state = %u", m_state); } } else { - if (m_mode == STATE_IDLE || m_mode == STATE_P25) { + if (m_state == STATE_IDLE || m_state == STATE_P25) { // P25 control data, if control data is being transmitted if (p25CCDurationTimer.isRunning() && !p25CCDurationTimer.hasExpired()) { p25->setCCRunning(true); @@ -877,12 +879,12 @@ int Host::run() // P25 status data, tail on idle ret = p25->writeEndRF(); if (ret) { - if (m_mode == STATE_IDLE) { + if (m_state == STATE_IDLE) { m_modeTimer.setTimeout(m_netModeHang); - setMode(STATE_P25); + setState(STATE_P25); } - if (m_mode == STATE_P25) { + if (m_state == STATE_P25) { m_modeTimer.start(); } } @@ -943,14 +945,14 @@ int Host::run() if (dmrBeaconDurationTimer.isRunning() || p25CCDurationTimer.isRunning()) { LogDebug(LOG_HOST, "CW, beacon or CC timer running, ceasing"); - setMode(STATE_IDLE); + setState(STATE_IDLE); dmrBeaconDurationTimer.stop(); p25CCDurationTimer.stop(); //g_interruptP25Control = true; } - if (m_mode == STATE_IDLE && !m_modem->hasTX()) { + if (m_state == STATE_IDLE && !m_modem->hasTX()) { hasCw = true; m_modem->sendCWId(m_cwCallsign); @@ -969,13 +971,13 @@ int Host::run() dmrBeaconIntervalTimer.start(); } else { - if ((m_mode == STATE_IDLE || m_mode == STATE_DMR) && !m_modem->hasTX()) { + if ((m_state == STATE_IDLE || m_state == STATE_DMR) && !m_modem->hasTX()) { if (m_modeTimer.isRunning()) { m_modeTimer.stop(); } - if (m_mode != STATE_DMR) - setMode(STATE_DMR); + if (m_state != STATE_DMR) + setState(STATE_DMR); g_fireDMRBeacon = false; LogDebug(LOG_HOST, "DMR, roaming beacon burst"); @@ -990,7 +992,7 @@ int Host::run() if (dmrBeaconDurationTimer.isRunning() && dmrBeaconDurationTimer.hasExpired()) { dmrBeaconDurationTimer.stop(); - if (m_mode == STATE_DMR && !m_modeTimer.isRunning()) { + if (m_state == STATE_DMR && !m_modeTimer.isRunning()) { m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.start(); } @@ -1016,13 +1018,13 @@ int Host::run() p25CCIntervalTimer.start(); } else { - if ((m_mode == STATE_IDLE || m_mode == STATE_P25) && !m_modem->hasTX()) { + if ((m_state == STATE_IDLE || m_state == STATE_P25) && !m_modem->hasTX()) { if (m_modeTimer.isRunning()) { m_modeTimer.stop(); } - if (m_mode != STATE_P25) - setMode(STATE_P25); + if (m_state != STATE_P25) + setState(STATE_P25); if (g_interruptP25Control) { g_interruptP25Control = false; @@ -1060,7 +1062,7 @@ int Host::run() p25->writeControlEndRF(); p25->setCCRunning(false); - if (m_mode == STATE_P25 && !m_modeTimer.isRunning()) { + if (m_state == STATE_P25 && !m_modeTimer.isRunning()) { m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.start(); } @@ -1075,7 +1077,7 @@ int Host::run() // simply use the P25 CC interval timer in a non-broadcast state to transmit adjacent site data over // the network if (p25CCIntervalTimer.isRunning() && p25CCIntervalTimer.hasExpired()) { - if ((m_mode == STATE_IDLE || m_mode == STATE_P25) && !m_modem->hasTX()) { + if ((m_state == STATE_IDLE || m_state == STATE_P25) && !m_modem->hasTX()) { p25->writeAdjSSNetwork(); p25CCIntervalTimer.start(); } @@ -1110,7 +1112,7 @@ int Host::run() Thread::sleep(1U); } - setMode(HOST_STATE_QUIT); + setState(HOST_STATE_QUIT); if (dmr != NULL) { delete dmr; @@ -1428,11 +1430,10 @@ bool Host::createModem() return false; } - port::IModemPort* slavePort = NULL; if (portType == UDP_PORT) { std::transform(udpMode.begin(), udpMode.end(), udpMode.begin(), ::tolower); if (udpMode == UDP_MODE_MASTER) { - slavePort = new port::UDPPort(udpAddress, udpPort); + m_modemRemotePort = new port::UDPPort(udpAddress, udpPort); m_modemRemote = true; } else if (udpMode == UDP_MODE_PEER) { @@ -1480,7 +1481,9 @@ bool Host::createModem() m_modem->setP25NAC(m_p25NAC); if (m_modemRemote) { - m_modem->setSlavePort(slavePort); + m_modem->setOpenHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemOpen, this)); + m_modem->setCloseHandler(MODEM_OC_PORT_HANDLER_BIND(Host::rmtPortModemClose, this)); + m_modem->setResponseHandler(MODEM_RESP_HANDLER_BIND(Host::rmtPortModemHandler, this)); } bool ret = m_modem->open(); @@ -1586,21 +1589,111 @@ bool Host::createNetwork() return true; } +/// +/// +/// +/// +bool Host::rmtPortModemOpen(Modem* modem) +{ + assert(m_modemRemotePort != NULL); + + bool ret = m_modemRemotePort->open(); + if (!ret) + return false; + + LogMessage(LOG_MODEM, "Modem Ready [Remote Mode]"); + + // handled modem open + return true; +} + +/// +/// +/// +/// +bool Host::rmtPortModemClose(Modem* modem) +{ + assert(m_modemRemotePort != NULL); + + m_modemRemotePort->close(); + + // handled modem close + return true; +} + +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +bool Host::rmtPortModemHandler(Modem* modem, uint32_t ms, modem::RESP_TYPE_DVM rspType, bool rspDblLen, const uint8_t* buffer, uint16_t len) +{ + assert(m_modemRemotePort != NULL); + + if (rspType == RTM_OK && len > 0U) { + if (modem->getTrace()) + Utils::dump(1U, "TX Remote Data", buffer, len); + + // send entire modem packet over the remote port + m_modemRemotePort->write(buffer, len); + + // Only feed data to the modem if the playout timer has expired + modem->getPlayoutTimer().clock(ms); + if (!modem->getPlayoutTimer().hasExpired()) { + // handled modem response + return true; + } + } + + // read any data from the remote port for the air interface + uint8_t data[BUFFER_LENGTH]; + ::memset(data, 0x00U, BUFFER_LENGTH); + + uint32_t ret = m_modemRemotePort->read(data, BUFFER_LENGTH); + if (ret > 0) { + if (modem->getTrace()) + Utils::dump(1U, "RX Remote Data", (uint8_t*)data, ret); + + if (ret < 3U) { + LogError(LOG_MODEM, "Illegal length of remote data must be >3 bytes"); + Utils::dump("Buffer dump", data, ret); + + // handled modem response + return true; + } + + uint8_t len = data[1U]; + int ret = modem->write(data, len); + if (ret != int(len)) + LogError(LOG_MODEM, "Error writing remote data"); + } + + modem->getPlayoutTimer().start(); + + // handled modem response + return true; +} + /// /// Helper to set the host/modem running state. /// -/// Mode enumeration to switch the host/modem state to. -void Host::setMode(uint8_t mode) +/// Mode enumeration to switch the host/modem state to. +void Host::setState(uint8_t state) { assert(m_modem != NULL); - //if (m_mode != mode) { - // LogDebug(LOG_HOST, "setMode, m_mode = %u, mode = %u", m_mode, mode); + //if (m_state != state) { + // LogDebug(LOG_HOST, "setState, m_state = %u, state = %u", m_state, state); //} - switch (mode) { + switch (state) { case STATE_DMR: - m_modem->setMode(STATE_DMR); + m_modem->setState(STATE_DMR); // if the modem is in duplex -- write DMR start sync if (m_duplex) { @@ -1608,15 +1701,15 @@ void Host::setMode(uint8_t mode) m_dmrTXTimer.start(); } - m_mode = STATE_DMR; + m_state = STATE_DMR; m_modeTimer.start(); //m_cwIdTimer.stop(); createLockFile("DMR"); break; case STATE_P25: - m_modem->setMode(STATE_P25); - m_mode = STATE_P25; + m_modem->setState(STATE_P25); + m_state = STATE_P25; m_modeTimer.start(); //m_cwIdTimer.stop(); createLockFile("P25"); @@ -1627,13 +1720,13 @@ void Host::setMode(uint8_t mode) if (m_network != NULL) m_network->enable(false); - if (m_mode == STATE_DMR && m_duplex && m_modem->hasTX()) { + if (m_state == STATE_DMR && m_duplex && m_modem->hasTX()) { m_modem->writeDMRStart(false); m_dmrTXTimer.stop(); } - m_modem->setMode(STATE_IDLE); - m_mode = HOST_STATE_LOCKOUT; + m_modem->setState(STATE_IDLE); + m_state = HOST_STATE_LOCKOUT; m_modeTimer.stop(); //m_cwIdTimer.stop(); removeLockFile(); @@ -1644,12 +1737,12 @@ void Host::setMode(uint8_t mode) if (m_network != NULL) m_network->enable(false); - if (m_mode == STATE_DMR && m_duplex && m_modem->hasTX()) { + if (m_state == STATE_DMR && m_duplex && m_modem->hasTX()) { m_modem->writeDMRStart(false); m_dmrTXTimer.stop(); } - m_mode = HOST_STATE_ERROR; + m_state = HOST_STATE_ERROR; m_modeTimer.stop(); m_cwIdTimer.stop(); removeLockFile(); @@ -1659,14 +1752,14 @@ void Host::setMode(uint8_t mode) if (m_network != NULL) m_network->enable(true); - if (m_mode == STATE_DMR && m_duplex && m_modem->hasTX()) { + if (m_state == STATE_DMR && m_duplex && m_modem->hasTX()) { m_modem->writeDMRStart(false); m_dmrTXTimer.stop(); } - m_modem->setMode(STATE_IDLE); + m_modem->setState(STATE_IDLE); - if (m_mode == HOST_STATE_ERROR) { + if (m_state == HOST_STATE_ERROR) { m_modem->sendCWId(m_cwCallsign); m_cwIdTimer.setTimeout(m_cwIdTime); @@ -1676,7 +1769,7 @@ void Host::setMode(uint8_t mode) removeLockFile(); m_modeTimer.stop(); - if (m_mode == HOST_STATE_QUIT) { + if (m_state == HOST_STATE_QUIT) { if (m_modem != NULL) { m_modem->close(); delete m_modem; @@ -1702,7 +1795,7 @@ void Host::setMode(uint8_t mode) } } else { - m_mode = STATE_IDLE; + m_state = STATE_IDLE; } break; } @@ -1711,7 +1804,7 @@ void Host::setMode(uint8_t mode) /// /// /// -/// +/// void Host::createLockFile(const char* mode) const { FILE* fp = ::fopen(g_lockFile.c_str(), "wt"); diff --git a/host/Host.h b/host/Host.h index 2b86afa0..42c6b324 100644 --- a/host/Host.h +++ b/host/Host.h @@ -12,7 +12,7 @@ // /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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 @@ -71,7 +71,9 @@ private: bool m_modemRemote; network::Network* m_network; - uint8_t m_mode; + modem::port::IModemPort* m_modemRemotePort; + + uint8_t m_state; Timer m_modeTimer; Timer m_dmrTXTimer; @@ -133,8 +135,15 @@ private: /// Initializes network connectivity. bool createNetwork(); + /// + bool rmtPortModemOpen(modem::Modem* modem); + /// + bool rmtPortModemClose(modem::Modem* modem); + /// + bool rmtPortModemHandler(modem::Modem* modem, uint32_t ms, modem::RESP_TYPE_DVM rspType, bool rspDblLen, const uint8_t* buffer, uint16_t len); + /// Helper to set the host/modem running state. - void setMode(uint8_t mode); + void setState(uint8_t mode); /// void createLockFile(const char* mode) const; diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp index 33a0b092..aa478a16 100644 --- a/host/calibrate/HostCal.cpp +++ b/host/calibrate/HostCal.cpp @@ -13,7 +13,7 @@ /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2017,2018 by Andy Uribe CA6JAU -* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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,6 +31,7 @@ */ #include "host/calibrate/HostCal.h" #include "dmr/DMRDefines.h" +#include "modem/port/UARTPort.h" #include "p25/P25Defines.h" #include "p25/data/DataHeader.h" #include "p25/lc/LC.h" @@ -131,7 +132,7 @@ unsigned char LDU2_1K[] = { HostCal::HostCal(const std::string& confFile) : m_confFile(confFile), m_conf(), - m_serial(NULL), + m_modem(NULL), m_console(), m_fec(), m_transmit(false), @@ -174,7 +175,7 @@ HostCal::HostCal(const std::string& confFile) : /// HostCal::~HostCal() { - delete m_serial; + delete m_modem; } /// @@ -195,7 +196,16 @@ int HostCal::run() return 1; } - yaml::Node modemConf = m_conf["system"]["modem"]; + getHostVersion(); + ::LogInfo(">> Modem Calibration"); + + LogInfo("General Parameters"); + + yaml::Node systemConf = m_conf["system"]; + std::string identity = systemConf["identity"].as(); + ::LogInfo(" Identity: %s", identity.c_str()); + + yaml::Node modemConf = systemConf["modem"]; yaml::Node modemProtocol = modemConf["protocol"]; std::string portType = modemProtocol["type"].as("null"); @@ -204,6 +214,7 @@ int HostCal::run() std::string uartPort = uartProtocol["port"].as(); uint32_t uartSpeed = uartProtocol["speed"].as(115200); + port::IModemPort* modemPort = NULL; std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower); if (portType == NULL_PORT) { ::LogError(LOG_HOST, "Calibration mode is unsupported with the null modem!"); @@ -246,7 +257,8 @@ int HostCal::run() break; } - m_serial = new port::UARTPort(uartPort, serialSpeed, true); + modemPort = new port::UARTPort(uartPort, serialSpeed, true); + LogInfo("Modem Parameters"); LogInfo(" UART Port: %s", uartPort.c_str()); LogInfo(" UART Speed: %u", uartSpeed); } @@ -255,32 +267,27 @@ int HostCal::run() return 2; } - if (m_serial == NULL) { + if (modemPort == NULL) { ::LogError(LOG_HOST, "Invalid modem port type, %s!", portType.c_str()); return 2; } - getHostVersion(); - ::LogInfo(">> Modem Calibration"); + m_modem = new Modem(modemPort, false, false, false, false, true, false, 80, 7, 4, 10, false, false, false); - // open serial connection to modem DSP and initialize - ret = m_serial->open(); - if (!ret) { - ::LogError(LOG_CAL, "Failed to open serial device"); - return 1; - } + m_modem->setOpenHandler(MODEM_OC_PORT_HANDLER_BIND(HostCal::portModemOpen, this)); + m_modem->setCloseHandler(MODEM_OC_PORT_HANDLER_BIND(HostCal::portModemClose, this)); + m_modem->setResponseHandler(MODEM_RESP_HANDLER_BIND(HostCal::portModemHandler, this)); - ret = initModem(); + // open modem and initialize + ret = m_modem->open(); if (!ret) { - ::LogError(LOG_CAL, "Modem is unresponsive"); - m_serial->close(); + ::LogError(LOG_CAL, "Failed to open modem"); return 1; } // open terminal console ret = m_console.open(); if (!ret) { - m_serial->close(); return 1; } @@ -640,7 +647,7 @@ int HostCal::run() getHostVersion(); break; case 'v': - getFirmwareVersion(); + m_modem->getFirmwareVersion(); break; case 'H': case 'h': @@ -667,8 +674,7 @@ int HostCal::run() break; } - uint8_t buffer[200U]; - readModem(buffer, 200U); + m_modem->clock(0U); timerClock(); sleep(5U); @@ -677,7 +683,7 @@ int HostCal::run() if (m_transmit) setTransmit(); - m_serial->close(); + m_modem->close(); m_console.close(); return 0; } @@ -685,6 +691,155 @@ int HostCal::run() // --------------------------------------------------------------------------- // Private Class Members // --------------------------------------------------------------------------- + +/// +/// +/// +/// +bool HostCal::portModemOpen(Modem* modem) +{ + sleep(2000U); + + bool ret = writeConfig(); + if (!ret) { + ret = writeConfig(); + if (!ret) { + LogError(LOG_MODEM, "Modem unresponsive to configuration set after 2 attempts. Stopping."); + m_modem->close(); + return false; + } + } + + LogMessage(LOG_MODEM, "Modem Ready [Calibration Mode]"); + + // handled modem open + return true; +} + +/// +/// +/// +/// +bool HostCal::portModemClose(Modem* modem) +{ + // handled modem close + return true; +} + +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +bool HostCal::portModemHandler(Modem* modem, uint32_t ms, RESP_TYPE_DVM rspType, bool rspDblLen, const uint8_t* buffer, uint16_t len) +{ + if (rspType == RTM_OK && len > 0) { + switch (buffer[2U]) { + case CMD_CAL_DATA: + { + bool inverted = (buffer[3U] == 0x80U); + short high = buffer[4U] << 8 | buffer[5U]; + short low = buffer[6U] << 8 | buffer[7U]; + short diff = high - low; + short centre = (high + low) / 2; + LogMessage(LOG_CAL, "Levels: inverted: %s, max: %d, min: %d, diff: %d, centre: %d", inverted ? "yes" : "no", high, low, diff, centre); + } + break; + case CMD_RSSI_DATA: + { + unsigned short max = buffer[3U] << 8 | buffer[4U]; + unsigned short min = buffer[5U] << 8 | buffer[6U]; + unsigned short ave = buffer[7U] << 8 | buffer[8U]; + LogMessage(LOG_CAL, "RSSI: max: %u, min: %u, ave: %u", max, min, ave); + } + break; + + case CMD_DMR_DATA1: + case CMD_DMR_DATA2: + processDMRBER(buffer + 4U, buffer[3]); + break; + + case CMD_DMR_LOST1: + case CMD_DMR_LOST2: + { + LogMessage(LOG_CAL, "DMR Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); + + if (m_dmrEnabled) { + m_berBits = 0U; + m_berErrs = 0U; + m_berFrames = 0U; + m_berUndecodableLC = 0U; + m_berUncorrectable = 0U; + } + } + break; + + case CMD_P25_DATA: + processP25BER(buffer + 3U); + break; + + case CMD_P25_LOST: + { + LogMessage(LOG_CAL, "P25 Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); + + if (m_p25Enabled) { + m_berBits = 0U; + m_berErrs = 0U; + m_berFrames = 0U; + m_berUndecodableLC = 0U; + m_berUncorrectable = 0U; + } + } + break; + + case CMD_GET_STATUS: + { + uint8_t modemState = buffer[4U]; + bool tx = (buffer[5U] & 0x01U) == 0x01U; + + bool adcOverflow = (buffer[5U] & 0x02U) == 0x02U; + bool rxOverflow = (buffer[5U] & 0x04U) == 0x04U; + bool txOverflow = (buffer[5U] & 0x08U) == 0x08U; + bool dacOverflow = (buffer[5U] & 0x20U) == 0x20U; + + LogMessage(LOG_CAL, " - Diagnostic Values [Modem State: %u, Transmitting: %d, ADC Overflow: %d, Rx Overflow: %d, Tx Overflow: %d, DAC Overflow: %d]", + modemState, tx, adcOverflow, rxOverflow, txOverflow, dacOverflow); + } + break; + + case CMD_GET_VERSION: + case CMD_ACK: + break; + + case CMD_NAK: + LogWarning(LOG_MODEM, "NAK, command = 0x%02X, reason = %u", buffer[3U], buffer[4U]); + break; + + case CMD_DEBUG1: + case CMD_DEBUG2: + case CMD_DEBUG3: + case CMD_DEBUG4: + case CMD_DEBUG5: + case CMD_DEBUG_DUMP: + m_modem->printDebug(buffer, len); + break; + + default: + LogWarning(LOG_MODEM, "Unknown message, type = %02X", buffer[2U]); + Utils::dump("Buffer dump", buffer, len); + break; + } + } + + // handled modem response + return true; +} + /// /// Helper to print the calibration help to the console. /// @@ -946,7 +1101,7 @@ bool HostCal::setTransmit() buffer[2U] = CMD_CAL_DATA; buffer[3U] = m_transmit ? 0x01U : 0x00U; - int ret = m_serial->write(buffer, 4U); + int ret = m_modem->write(buffer, 4U); if (ret <= 0) return false; @@ -957,174 +1112,11 @@ bool HostCal::setTransmit() else LogMessage(LOG_CAL, " - Modem stop transmitting"); - ret = readModem(buffer, 50U); - if (ret <= 0) - return false; - - if (buffer[2U] == CMD_NAK) { - LogError(LOG_CAL, "Got a NAK from the modem"); - return false; - } - - if (buffer[2U] != CMD_ACK) { - Utils::dump("Invalid response", buffer, ret); - return false; - } + m_modem->clock(0U); return true; } -/// -/// Initializes the modem DSP. -/// -/// True, if modem DSP is initialized, otherwise false. -bool HostCal::initModem() -{ - LogMessage(LOG_CAL, " - Initializing modem"); - sleep(2000U); - - if (!getFirmwareVersion()) - return false; - - bool ret = writeConfig(); - if (!ret) { - ret = writeConfig(); - if (!ret) { - LogError(LOG_CAL, "Modem unresponsive to configuration set after 2 attempts, calibration may fail."); - } - } - - LogMessage(LOG_CAL, " - Modem Ready"); - return true; -} - -/// -/// Read data frames from the modem DSP. -/// -/// -/// -/// Zero if no data was read, otherwise returns length of data read. -int HostCal::readModem(uint8_t *buffer, uint32_t length) -{ - int n = m_serial->read(buffer + 0U, 1U); - if (n <= 0) - return n; - - if (buffer[0U] != DVM_FRAME_START) - return 0; - - n = 0; - for (uint32_t i = 0U; i < 20U && n == 0; i++) { - n = m_serial->read(buffer + 1U, 1U); - if (n < 0) - return n; - if (n == 0) - sleep(10U); - } - - if (n == 0) - return -1; - - uint32_t len = buffer[1U]; - - uint32_t offset = 2U; - for (uint32_t i = 0U; i < 20U && offset < len; i++) { - n = m_serial->read(buffer + offset, len - offset); - if (n < 0) - return n; - if (n == 0) - sleep(10U); - if (n > 0) - offset += n; - } - - if (len > 0) { - switch (buffer[2U]) { - case CMD_CAL_DATA: - { - bool inverted = (buffer[3U] == 0x80U); - short high = buffer[4U] << 8 | buffer[5U]; - short low = buffer[6U] << 8 | buffer[7U]; - short diff = high - low; - short centre = (high + low) / 2; - LogMessage(LOG_CAL, "Levels: inverted: %s, max: %d, min: %d, diff: %d, centre: %d", inverted ? "yes" : "no", high, low, diff, centre); - } - break; - case CMD_RSSI_DATA: - { - unsigned short max = buffer[3U] << 8 | buffer[4U]; - unsigned short min = buffer[5U] << 8 | buffer[6U]; - unsigned short ave = buffer[7U] << 8 | buffer[8U]; - LogMessage(LOG_CAL, "RSSI: max: %u, min: %u, ave: %u", max, min, ave); - } - break; - - case CMD_DMR_DATA1: - case CMD_DMR_DATA2: - processDMRBER(buffer + 4U, buffer[3]); - break; - - case CMD_DMR_LOST1: - case CMD_DMR_LOST2: - { - LogMessage(LOG_CAL, "DMR Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); - - if (m_dmrEnabled) { - m_berBits = 0U; - m_berErrs = 0U; - m_berFrames = 0U; - m_berUndecodableLC = 0U; - m_berUncorrectable = 0U; - } - } - break; - - case CMD_P25_DATA: - processP25BER(buffer + 3U); - break; - - case CMD_P25_LOST: - { - LogMessage(LOG_CAL, "P25 Transmission lost, total frames: %d, bits: %d, uncorrectable frames: %d, undecodable LC: %d, errors: %d, BER: %.4f%%", m_berFrames, m_berBits, m_berUncorrectable, m_berUndecodableLC, m_berErrs, float(m_berErrs * 100U) / float(m_berBits)); - - if (m_p25Enabled) { - m_berBits = 0U; - m_berErrs = 0U; - m_berFrames = 0U; - m_berUndecodableLC = 0U; - m_berUncorrectable = 0U; - } - } - break; - - // These should not be received, but don't complain if we do - case CMD_GET_STATUS: - case CMD_GET_VERSION: - case CMD_ACK: - break; - - case CMD_NAK: - LogWarning(LOG_MODEM, "NAK, command = 0x%02X, reason = %u", buffer[3U], buffer[4U]); - break; - - case CMD_DEBUG1: - case CMD_DEBUG2: - case CMD_DEBUG3: - case CMD_DEBUG4: - case CMD_DEBUG5: - printDebug(buffer, len); - break; - - default: - LogWarning(LOG_MODEM, "Unknown message, type = %02X", buffer[2U]); - Utils::dump("Buffer dump", buffer, len); - break; - } - } - - return len; -} - /// /// Process DMR Rx BER. /// @@ -1562,74 +1554,6 @@ void HostCal::processP251KBER(const uint8_t* buffer) } } -/// -/// Retrieve the modem DSP version. -/// -/// True, if firmware version was recieved, otherwise false. -bool HostCal::getFirmwareVersion() -{ - uint8_t buffer[150U]; - - int ret = 0; - for (uint32_t i = 0U; i < 5U && ret <= 0; i++) { - buffer[0U] = DVM_FRAME_START; - buffer[1U] = 3U; - buffer[2U] = CMD_GET_VERSION; - - ret = m_serial->write(buffer, 3U); - if (ret <= 0) - return false; - - sleep(100U); - - ret = readModem(buffer, 200U); - if (ret < 0) - return false; - if (ret == 0) - sleep(1000U); - } - - if (ret <= 0) { - LogError(LOG_CAL, "Unable to read the firmware version after 6 attempts"); - return false; - } - - int length = ret; - - if (buffer[2U] != CMD_GET_VERSION) { - Utils::dump("Invalid response", buffer, ret); - return false; - } - - uint8_t protoVer = buffer[3U]; - - switch (protoVer) { - case PROTOCOL_VERSION: - LogInfoEx(LOG_MODEM, MODEM_VERSION_STR, length - 21U, buffer + 21U, protoVer); - switch (buffer[4U]) { - case 0U: - LogMessage(LOG_MODEM, "Atmel ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", buffer[5U], buffer[6U], buffer[7U], buffer[8U], buffer[9U], buffer[10U], buffer[11U], buffer[12U], buffer[13U], buffer[14U], buffer[15U], buffer[16U], buffer[17U], buffer[18U], buffer[19U], buffer[20U]); - break; - case 1U: - LogMessage(LOG_MODEM, "NXP ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", buffer[5U], buffer[6U], buffer[7U], buffer[8U], buffer[9U], buffer[10U], buffer[11U], buffer[12U], buffer[13U], buffer[14U], buffer[15U], buffer[16U], buffer[17U], buffer[18U], buffer[19U], buffer[20U]); - break; - case 2U: - LogMessage(LOG_MODEM, "ST-Micro ARM, UDID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", buffer[5U], buffer[6U], buffer[7U], buffer[8U], buffer[9U], buffer[10U], buffer[11U], buffer[12U], buffer[13U], buffer[14U], buffer[15U], buffer[16U]); - break; - default: - LogMessage(LOG_MODEM, "Unknown CPU type: %u", buffer[4U]); - break; - } - return true; - - default: - LogError(LOG_MODEM, MODEM_UNSUPPORTED_STR, protoVer); - return false; - } - - return true; -} - /// /// Write configuration to the modem DSP. /// @@ -1710,26 +1634,13 @@ bool HostCal::writeConfig(uint8_t modeOverride) buffer[14U] = (uint8_t)m_p25CorrCount; - int ret = m_serial->write(buffer, 17U); + int ret = m_modem->write(buffer, 17U); if (ret <= 0) return false; sleep(10U); - ret = readModem(buffer, 50U); - if (ret <= 0) - return false; - - if (buffer[2U] == CMD_NAK) { - LogError(LOG_CAL, "Got a NAK from the modem"); - return false; - } - - if (buffer[2U] != CMD_ACK) { - Utils::dump("Invalid response", buffer, ret); - return false; - } - + m_modem->clock(0U); return true; } @@ -1755,26 +1666,13 @@ bool HostCal::writeSymbolAdjust() m_conf["system"]["modem"]["p25SymLvl1Adj"] = __INT_STR(m_p25SymLevel1Adj); buffer[6U] = (uint8_t)(m_p25SymLevel1Adj + 128); - int ret = m_serial->write(buffer, 7U); + int ret = m_modem->write(buffer, 7U); if (ret <= 0) return false; sleep(10U); - ret = readModem(buffer, 50U); - if (ret <= 0) - return false; - - if (buffer[2U] == CMD_NAK) { - LogError(LOG_CAL, "Got a NAK from the modem"); - return false; - } - - if (buffer[2U] != CMD_ACK) { - Utils::dump("Invalid response", buffer, ret); - return false; - } - + m_modem->clock(0U); return true; } @@ -1851,70 +1749,13 @@ void HostCal::printStatus() buffer[1U] = 4U; buffer[2U] = CMD_GET_STATUS; - int ret = m_serial->write(buffer, 4U); + int ret = m_modem->write(buffer, 4U); if (ret <= 0) return; sleep(25U); - ret = readModem(buffer, 50U); - if (ret <= 0) - return; - - if (buffer[2U] == CMD_NAK) { - LogError(LOG_CAL, "Got a NAK from the modem"); - return; - } - - if (buffer[2U] != CMD_GET_STATUS) { - Utils::dump("Invalid response", buffer, ret); - return; - } - - uint8_t modemState = buffer[4U]; - bool tx = (buffer[5U] & 0x01U) == 0x01U; - - bool adcOverflow = (buffer[5U] & 0x02U) == 0x02U; - bool rxOverflow = (buffer[5U] & 0x04U) == 0x04U; - bool txOverflow = (buffer[5U] & 0x08U) == 0x08U; - bool dacOverflow = (buffer[5U] & 0x20U) == 0x20U; - - LogMessage(LOG_CAL, " - Diagnostic Values [Modem State: %u, Transmitting: %d, ADC Overflow: %d, Rx Overflow: %d, Tx Overflow: %d, DAC Overflow: %d]", - modemState, tx, adcOverflow, rxOverflow, txOverflow, dacOverflow); -} - -/// -/// -/// -/// -/// -void HostCal::printDebug(const uint8_t* buffer, uint32_t length) -{ - if (buffer[2U] == CMD_DEBUG1) { - LogMessage(LOG_MODEM, "M: %.*s", length - 3U, buffer + 3U); - } - else if (buffer[2U] == CMD_DEBUG2) { - short val1 = (buffer[length - 2U] << 8) | buffer[length - 1U]; - LogMessage(LOG_MODEM, "M: %.*s %X", length - 5U, buffer + 3U, val1); - } - else if (buffer[2U] == CMD_DEBUG3) { - short val1 = (buffer[length - 4U] << 8) | buffer[length - 3U]; - short val2 = (buffer[length - 2U] << 8) | buffer[length - 1U]; - LogMessage(LOG_MODEM, "M: %.*s %X %X", length - 7U, buffer + 3U, val1, val2); - } - else if (buffer[2U] == CMD_DEBUG4) { - short val1 = (buffer[length - 6U] << 8) | buffer[length - 5U]; - short val2 = (buffer[length - 4U] << 8) | buffer[length - 3U]; - short val3 = (buffer[length - 2U] << 8) | buffer[length - 1U]; - LogMessage(LOG_MODEM, "M: %.*s %X %X %X", length - 9U, buffer + 3U, val1, val2, val3); - } - else if (buffer[2U] == CMD_DEBUG5) { - short val1 = (buffer[length - 8U] << 8) | buffer[length - 7U]; - short val2 = (buffer[length - 6U] << 8) | buffer[length - 5U]; - short val3 = (buffer[length - 4U] << 8) | buffer[length - 3U]; - short val4 = (buffer[length - 2U] << 8) | buffer[length - 1U]; - LogMessage(LOG_MODEM, "M: %.*s %X %X %X %X", length - 11U, buffer + 3U, val1, val2, val3, val4); - } + m_modem->clock(0U); } /// diff --git a/host/calibrate/HostCal.h b/host/calibrate/HostCal.h index 0b863a0e..d7f97135 100644 --- a/host/calibrate/HostCal.h +++ b/host/calibrate/HostCal.h @@ -13,7 +13,7 @@ /* * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX * Copyright (C) 2017,2018 by Andy Uribe CA6JAU -* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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 @@ -35,7 +35,6 @@ #include "Defines.h" #include "edac/AMBEFEC.h" #include "modem/Modem.h" -#include "modem/port/UARTPort.h" #include "host/calibrate/Console.h" #include "host/Host.h" #include "yaml/Yaml.h" @@ -61,7 +60,7 @@ private: const std::string& m_confFile; yaml::Node m_conf; - modem::port::UARTPort* m_serial; + modem::Modem* m_modem; Console m_console; edac::AMBEFEC m_fec; @@ -108,6 +107,13 @@ private: uint32_t m_timeout; uint32_t m_timer; + /// + bool portModemOpen(modem::Modem* modem); + /// + bool portModemClose(modem::Modem* modem); + /// + bool portModemHandler(modem::Modem* modem, uint32_t ms, modem::RESP_TYPE_DVM rspType, bool rspDblLen, const uint8_t* buffer, uint16_t len); + /// Helper to print the calibration help to the console. void displayHelp(); @@ -131,10 +137,6 @@ private: /// Helper to change the P25 Symbol Level 1 adjust. bool setP25SymLevel1Adj(int incr); - /// Initializes the modem DSP. - bool initModem(); - /// Read data frames from the modem DSP. - int readModem(uint8_t* buffer, uint32_t length); /// Process DMR Rx BER. void processDMRBER(const uint8_t* buffer, uint8_t seq); /// Process DMR Tx 1011hz BER. @@ -143,8 +145,7 @@ private: void processP25BER(const uint8_t* buffer); /// Process P25 Tx 1011hz BER. void processP251KBER(const uint8_t* buffer); - /// Retrieve the modem DSP version. - bool getFirmwareVersion(); + /// Write configuration to the modem DSP. bool writeConfig(); /// Write configuration to the modem DSP. @@ -163,8 +164,6 @@ private: /// Prints the current status of the calibration. void printStatus(); - /// - void printDebug(const uint8_t* buffer, uint32_t length); /// unsigned char countErrs(unsigned char a, unsigned char b); diff --git a/modem/Modem.cpp b/modem/Modem.cpp index 755da313..03f6012d 100644 --- a/modem/Modem.cpp +++ b/modem/Modem.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2011-2021 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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 @@ -51,6 +51,18 @@ using namespace modem; #include #endif +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +enum RESP_STATE { + RESP_START, + RESP_LENGTH1, + RESP_LENGTH2, + RESP_TYPE, + RESP_DATA +}; + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -74,7 +86,6 @@ using namespace modem; Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, bool dcBlocker, bool cosLockout, uint8_t fdmaPreamble, uint8_t dmrRxDelay, uint8_t p25CorrCount, uint8_t packetPlayoutTime, bool disableOFlowReset, bool trace, bool debug) : m_port(port), - m_remotePort(NULL), m_dmrColorCode(0U), m_p25NAC(0x293U), m_duplex(duplex), @@ -91,8 +102,6 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_dmrTXLevel(0U), m_p25TXLevel(0U), m_disableOFlowReset(disableOFlowReset), - m_trace(trace), - m_debug(debug), m_dmrEnabled(false), m_p25Enabled(false), m_rxDCOffset(0), @@ -106,7 +115,11 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_modemState(STATE_IDLE), m_buffer(NULL), m_length(0U), - m_offset(0U), + m_rspDoubleLength(false), + m_rspType(CMD_GET_STATUS), + m_openPortHandler(NULL), + m_closePortHandler(NULL), + m_rspHandler(NULL), m_rxDMRData1(1000U, "Modem RX DMR1"), m_rxDMRData2(1000U, "Modem RX DMR2"), m_txDMRData1(1000U, "Modem TX DMR1"), @@ -115,14 +128,16 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_txP25Data(1000U, "Modem TX P25"), m_statusTimer(1000U, 0U, 250U), m_inactivityTimer(1000U, 4U), - m_playoutTimer(1000U, 0U, packetPlayoutTime), m_dmrSpace1(0U), m_dmrSpace2(0U), m_p25Space(0U), m_tx(false), m_cd(false), m_lockout(false), - m_error(false) + m_error(false), + m_trace(trace), + m_debug(debug), + m_playoutTimer(1000U, 0U, packetPlayoutTime) { assert(port != NULL); @@ -135,11 +150,6 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, Modem::~Modem() { delete m_port; - - if (m_remotePort != NULL) { - delete m_remotePort; - } - delete[] m_buffer; } @@ -254,7 +264,7 @@ void Modem::setRXLevel(float rxLevel) // Utils::dump(1U, "Written", buffer, 16U); - int ret = m_port->write(buffer, 16U); + int ret = write(buffer, 16U); if (ret != 16) return; @@ -281,13 +291,43 @@ void Modem::setRXLevel(float rxLevel) } /// -/// Sets the slave port for remote operation. +/// Sets a custom modem response handler. +/// +/// +/// If the response handler returns true, processing will stop, otherwise it will continue. +/// +/// +void Modem::setResponseHandler(std::function handler) +{ + assert(handler != NULL); + + m_rspHandler = handler; +} + +/// +/// Sets a custom modem open port handler. /// -void Modem::setSlavePort(port::IModemPort* slavePort) +/// +/// If the open handler is set, it is the responsibility of the handler to complete air interface +/// initialization (i.e. write configuration, etc). +/// +/// +void Modem::setOpenHandler(std::function handler) { - assert(slavePort != NULL); + assert(handler != NULL); - m_remotePort = slavePort; + m_openPortHandler = handler; +} + +/// +/// Sets a custom modem close port handler. +/// +/// +void Modem::setCloseHandler(std::function handler) +{ + assert(handler != NULL); + + m_closePortHandler = handler; } /// @@ -313,18 +353,13 @@ bool Modem::open() m_inactivityTimer.stop(); } - if (m_remotePort != NULL) { - ret = m_remotePort->open(); + // do we have an open port handler? + if (m_openPortHandler) { + ret = m_openPortHandler(this); if (!ret) return false; - m_statusTimer.start(); - m_error = false; - m_offset = 0U; - - LogMessage(LOG_MODEM, "Modem Ready [Remote Mode]"); - m_playoutTimer.start(); return true; @@ -332,9 +367,12 @@ bool Modem::open() ret = writeConfig(); if (!ret) { - LogError(LOG_MODEM, "Modem is unresponsive"); - m_port->close(); - return false; + ret = writeConfig(); + if (!ret) { + LogError(LOG_MODEM, "Modem unresponsive to configuration set after 2 attempts. Stopping."); + m_port->close(); + return false; + } } writeSymbolAdjust(); @@ -342,7 +380,6 @@ bool Modem::open() m_statusTimer.start(); m_error = false; - m_offset = 0U; LogMessage(LOG_MODEM, "Modem Ready [Direct Mode]"); return true; @@ -379,6 +416,15 @@ void Modem::clock(uint32_t ms) bool forceModemReset = false; RESP_TYPE_DVM type = getResponse(); + // do we have a custom response handler? + if (m_rspHandler != NULL) { + // execute custom response handler + if (m_rspHandler(this, ms, type, m_rspDoubleLength, m_buffer, m_length)) { + // all logic handled by handler -- return + return; + } + } + if (type == RTM_TIMEOUT) { // Nothing to do } @@ -386,209 +432,225 @@ void Modem::clock(uint32_t ms) // Nothing to do } else { - if (m_remotePort != NULL) { + // type == RTM_OK + switch (m_buffer[2U]) { + /** Digital Mobile Radio */ + case CMD_DMR_DATA1: + { if (m_trace) - Utils::dump(1U, "TX Remote Data", m_buffer, m_length); + Utils::dump(1U, "RX DMR Data 1", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_DMR_DATA1 double length?; len = %u", m_length); + break; + } + + uint8_t data = m_length - 2U; + m_rxDMRData1.addData(&data, 1U); + + if (m_buffer[3U] == (dmr::DMR_SYNC_DATA | dmr::DT_TERMINATOR_WITH_LC)) + data = TAG_EOT; + else + data = TAG_DATA; + m_rxDMRData1.addData(&data, 1U); - // send entire modem packet over the slave port - m_remotePort->write(m_buffer, m_length); + m_rxDMRData1.addData(m_buffer + 3U, m_length - 3U); } - else { - // type == RTM_OK - switch (m_buffer[2U]) { - /** Digital Mobile Radio */ - case CMD_DMR_DATA1: - { - if (m_trace) - Utils::dump(1U, "RX DMR Data 1", m_buffer, m_length); - - uint8_t data = m_length - 2U; - m_rxDMRData1.addData(&data, 1U); - - if (m_buffer[3U] == (dmr::DMR_SYNC_DATA | dmr::DT_TERMINATOR_WITH_LC)) - data = TAG_EOT; - else - data = TAG_DATA; - m_rxDMRData1.addData(&data, 1U); - - m_rxDMRData1.addData(m_buffer + 3U, m_length - 3U); + break; + + case CMD_DMR_DATA2: + { + if (m_trace) + Utils::dump(1U, "RX DMR Data 2", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_DMR_DATA2 double length?; len = %u", m_length); + break; } - break; - case CMD_DMR_DATA2: - { - if (m_trace) - Utils::dump(1U, "RX DMR Data 2", m_buffer, m_length); + uint8_t data = m_length - 2U; + m_rxDMRData2.addData(&data, 1U); - uint8_t data = m_length - 2U; - m_rxDMRData2.addData(&data, 1U); + if (m_buffer[3U] == (dmr::DMR_SYNC_DATA | dmr::DT_TERMINATOR_WITH_LC)) + data = TAG_EOT; + else + data = TAG_DATA; + m_rxDMRData2.addData(&data, 1U); - if (m_buffer[3U] == (dmr::DMR_SYNC_DATA | dmr::DT_TERMINATOR_WITH_LC)) - data = TAG_EOT; - else - data = TAG_DATA; - m_rxDMRData2.addData(&data, 1U); + m_rxDMRData2.addData(m_buffer + 3U, m_length - 3U); + } + break; - m_rxDMRData2.addData(m_buffer + 3U, m_length - 3U); + case CMD_DMR_LOST1: + { + if (m_trace) + Utils::dump(1U, "RX DMR Lost 1", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_DMR_LOST1 double length?; len = %u", m_length); + break; } - break; - case CMD_DMR_LOST1: - { - if (m_trace) - Utils::dump(1U, "RX DMR Lost 1", m_buffer, m_length); + uint8_t data = 1U; + m_rxDMRData1.addData(&data, 1U); - uint8_t data = 1U; - m_rxDMRData1.addData(&data, 1U); + data = TAG_LOST; + m_rxDMRData1.addData(&data, 1U); + } + break; - data = TAG_LOST; - m_rxDMRData1.addData(&data, 1U); + case CMD_DMR_LOST2: + { + if (m_trace) + Utils::dump(1U, "RX DMR Lost 2", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_DMR_LOST2 double length?; len = %u", m_length); + break; } - break; - case CMD_DMR_LOST2: - { - if (m_trace) - Utils::dump(1U, "RX DMR Lost 2", m_buffer, m_length); + uint8_t data = 1U; + m_rxDMRData2.addData(&data, 1U); - uint8_t data = 1U; - m_rxDMRData2.addData(&data, 1U); + data = TAG_LOST; + m_rxDMRData2.addData(&data, 1U); + } + break; - data = TAG_LOST; - m_rxDMRData2.addData(&data, 1U); + /** Project 25 */ + case CMD_P25_DATA: + { + if (m_trace) + Utils::dump(1U, "RX P25 Data", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_P25_DATA double length?; len = %u", m_length); + break; } - break; - /** Project 25 */ - case CMD_P25_DATA: - { - if (m_trace) - Utils::dump(1U, "RX P25 Data", m_buffer, m_length); + uint8_t data = m_length - 2U; + m_rxP25Data.addData(&data, 1U); - uint8_t data = m_length - 2U; - m_rxP25Data.addData(&data, 1U); + data = TAG_DATA; + m_rxP25Data.addData(&data, 1U); - data = TAG_DATA; - m_rxP25Data.addData(&data, 1U); + m_rxP25Data.addData(m_buffer + 3U, m_length - 3U); + } + break; - m_rxP25Data.addData(m_buffer + 3U, m_length - 3U); + case CMD_P25_LOST: + { + if (m_trace) + Utils::dump(1U, "RX P25 Lost", m_buffer, m_length); + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "CMD_P25_LOST double length?; len = %u", m_length); + break; } - break; - case CMD_P25_LOST: - { - if (m_trace) - Utils::dump(1U, "RX P25 Lost", m_buffer, m_length); + uint8_t data = 1U; + m_rxP25Data.addData(&data, 1U); - uint8_t data = 1U; - m_rxP25Data.addData(&data, 1U); - - data = TAG_LOST; - m_rxP25Data.addData(&data, 1U); - } - break; + data = TAG_LOST; + m_rxP25Data.addData(&data, 1U); + } + break; - /** General */ - case CMD_GET_STATUS: - { - // if (m_trace) - // Utils::dump(1U, "Get Status", m_buffer, m_length); + /** General */ + case CMD_GET_STATUS: + { + // if (m_trace) + // Utils::dump(1U, "Get Status", m_buffer, m_length); - m_modemState = (DVM_STATE)m_buffer[4U]; + m_modemState = (DVM_STATE)m_buffer[4U]; - m_tx = (m_buffer[5U] & 0x01U) == 0x01U; + m_tx = (m_buffer[5U] & 0x01U) == 0x01U; - bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U; - if (adcOverflow) { - //LogError(LOG_MODEM, "ADC levels have overflowed"); - m_adcOverFlowCount++; + bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U; + if (adcOverflow) { + //LogError(LOG_MODEM, "ADC levels have overflowed"); + m_adcOverFlowCount++; - if (m_adcOverFlowCount >= MAX_ADC_OVERFLOW / 2U) { - LogWarning(LOG_MODEM, "ADC overflow count > %u!", MAX_ADC_OVERFLOW / 2U); - } + if (m_adcOverFlowCount >= MAX_ADC_OVERFLOW / 2U) { + LogWarning(LOG_MODEM, "ADC overflow count > %u!", MAX_ADC_OVERFLOW / 2U); + } - if (!m_disableOFlowReset) { - if (m_adcOverFlowCount > MAX_ADC_OVERFLOW) { - LogError(LOG_MODEM, "ADC overflow count > %u, resetting modem", MAX_ADC_OVERFLOW); - forceModemReset = true; - } - } - else { - m_adcOverFlowCount = 0U; + if (!m_disableOFlowReset) { + if (m_adcOverFlowCount > MAX_ADC_OVERFLOW) { + LogError(LOG_MODEM, "ADC overflow count > %u, resetting modem", MAX_ADC_OVERFLOW); + forceModemReset = true; } } else { - if (m_adcOverFlowCount != 0U) { - m_adcOverFlowCount--; - } + m_adcOverFlowCount = 0U; + } + } + else { + if (m_adcOverFlowCount != 0U) { + m_adcOverFlowCount--; } + } - bool rxOverflow = (m_buffer[5U] & 0x04U) == 0x04U; - if (rxOverflow) - LogError(LOG_MODEM, "RX buffer has overflowed"); + bool rxOverflow = (m_buffer[5U] & 0x04U) == 0x04U; + if (rxOverflow) + LogError(LOG_MODEM, "RX buffer has overflowed"); - bool txOverflow = (m_buffer[5U] & 0x08U) == 0x08U; - if (txOverflow) - LogError(LOG_MODEM, "TX buffer has overflowed"); + bool txOverflow = (m_buffer[5U] & 0x08U) == 0x08U; + if (txOverflow) + LogError(LOG_MODEM, "TX buffer has overflowed"); - m_lockout = (m_buffer[5U] & 0x10U) == 0x10U; + m_lockout = (m_buffer[5U] & 0x10U) == 0x10U; - bool dacOverflow = (m_buffer[5U] & 0x20U) == 0x20U; - if (dacOverflow) { - //LogError(LOG_MODEM, "DAC levels have overflowed"); - m_dacOverFlowCount++; + bool dacOverflow = (m_buffer[5U] & 0x20U) == 0x20U; + if (dacOverflow) { + //LogError(LOG_MODEM, "DAC levels have overflowed"); + m_dacOverFlowCount++; - if (m_dacOverFlowCount > MAX_DAC_OVERFLOW / 2U) { - LogWarning(LOG_MODEM, "DAC overflow count > %u!", MAX_DAC_OVERFLOW / 2U); - } + if (m_dacOverFlowCount > MAX_DAC_OVERFLOW / 2U) { + LogWarning(LOG_MODEM, "DAC overflow count > %u!", MAX_DAC_OVERFLOW / 2U); + } - if (!m_disableOFlowReset) { - if (m_dacOverFlowCount > MAX_DAC_OVERFLOW) { - LogError(LOG_MODEM, "DAC overflow count > %u, resetting modem", MAX_DAC_OVERFLOW); - forceModemReset = true; - } - } - else { - m_dacOverFlowCount = 0U; + if (!m_disableOFlowReset) { + if (m_dacOverFlowCount > MAX_DAC_OVERFLOW) { + LogError(LOG_MODEM, "DAC overflow count > %u, resetting modem", MAX_DAC_OVERFLOW); + forceModemReset = true; } } else { - if (m_dacOverFlowCount != 0U) { - m_dacOverFlowCount--; - } + m_dacOverFlowCount = 0U; + } + } + else { + if (m_dacOverFlowCount != 0U) { + m_dacOverFlowCount--; } + } - m_cd = (m_buffer[5U] & 0x40U) == 0x40U; + m_cd = (m_buffer[5U] & 0x40U) == 0x40U; - m_dmrSpace1 = m_buffer[7U]; - m_dmrSpace2 = m_buffer[8U]; - m_p25Space = m_buffer[10U]; + m_dmrSpace1 = m_buffer[7U]; + m_dmrSpace2 = m_buffer[8U]; + m_p25Space = m_buffer[10U]; - m_inactivityTimer.start(); - } - break; + m_inactivityTimer.start(); + } + break; - case CMD_GET_VERSION: - case CMD_ACK: - break; + case CMD_GET_VERSION: + case CMD_ACK: + break; - case CMD_NAK: - LogWarning(LOG_MODEM, "NAK, command = 0x%02X, reason = %u", m_buffer[3U], m_buffer[4U]); - break; + case CMD_NAK: + LogWarning(LOG_MODEM, "NAK, command = 0x%02X, reason = %u", m_buffer[3U], m_buffer[4U]); + break; - case CMD_DEBUG1: - case CMD_DEBUG2: - case CMD_DEBUG3: - case CMD_DEBUG4: - case CMD_DEBUG5: - printDebug(); - break; + case CMD_DEBUG1: + case CMD_DEBUG2: + case CMD_DEBUG3: + case CMD_DEBUG4: + case CMD_DEBUG5: + case CMD_DEBUG_DUMP: + printDebug(m_buffer, m_length); + break; - default: - LogWarning(LOG_MODEM, "Unknown message, type = %02X", m_buffer[2U]); - Utils::dump("Buffer dump", m_buffer, m_length); - break; - } + default: + LogWarning(LOG_MODEM, "Unknown message, type = %02X", m_buffer[2U]); + Utils::dump("Buffer dump", m_buffer, m_length); + break; } } @@ -611,33 +673,6 @@ void Modem::clock(uint32_t ms) if (!m_playoutTimer.hasExpired()) return; - // read any data from the slave port for the air interface - if (m_remotePort != NULL) { - uint8_t buffer[BUFFER_LENGTH]; - ::memset(buffer, 0x00U, BUFFER_LENGTH); - - uint32_t ret = m_remotePort->read(buffer, BUFFER_LENGTH); - if (ret > 0) { - if (m_trace) - Utils::dump(1U, "RX Remote Data", (uint8_t*)buffer, ret); - - if (ret < 3U) { - LogError(LOG_MODEM, "Illegal length of remote data must be >3 bytes"); - Utils::dump("Buffer dump", buffer, ret); - return; - } - - uint8_t len = buffer[1U]; - int ret = m_port->write(buffer, len); - if (ret != int(len)) - LogError(LOG_MODEM, "Error writing remote data data"); - } - - m_playoutTimer.start(); - - return; - } - // write DMR slot 1 data to air interface if (m_dmrSpace1 > 1U && !m_txDMRData1.isEmpty()) { uint8_t len = 0U; @@ -647,7 +682,7 @@ void Modem::clock(uint32_t ms) if (m_trace) Utils::dump(1U, "TX DMR Data 1", m_buffer, len); - int ret = m_port->write(m_buffer, len); + int ret = write(m_buffer, len); if (ret != int(len)) LogError(LOG_MODEM, "Error writing DMR slot 1 data"); @@ -665,7 +700,7 @@ void Modem::clock(uint32_t ms) if (m_trace) Utils::dump(1U, "TX DMR Data 2", m_buffer, len); - int ret = m_port->write(m_buffer, len); + int ret = write(m_buffer, len); if (ret != int(len)) LogError(LOG_MODEM, "Error writing DMR slot 2 data"); @@ -684,7 +719,7 @@ void Modem::clock(uint32_t ms) Utils::dump(1U, "TX P25 Data", m_buffer, len); } - int ret = m_port->write(m_buffer, len); + int ret = write(m_buffer, len); if (ret != int(len)) LogError(LOG_MODEM, "Error writing P25 data"); @@ -702,8 +737,9 @@ void Modem::close() LogDebug(LOG_MODEM, "Closing the modem"); m_port->close(); - if (m_remotePort != NULL) { - m_remotePort->close(); + // do we have a close port handler? + if (m_closePortHandler != NULL) { + m_closePortHandler(this); } } @@ -866,7 +902,7 @@ void Modem::clearP25Data() // Utils::dump(1U, "Written", buffer, 3U); - m_port->write(buffer, 3U); + write(buffer, 3U); } } @@ -1050,7 +1086,7 @@ bool Modem::writeDMRStart(bool tx) // Utils::dump(1U, "Written", buffer, 4U); - return m_port->write(buffer, 4U) == 4; + return write(buffer, 4U) == 4; } /// @@ -1079,7 +1115,7 @@ bool Modem::writeDMRShortLC(const uint8_t* lc) // Utils::dump(1U, "Written", buffer, 12U); - return m_port->write(buffer, 12U) == 12; + return write(buffer, 12U) == 12; } /// @@ -1103,15 +1139,35 @@ bool Modem::writeDMRAbort(uint32_t slotNo) // Utils::dump(1U, "Written", buffer, 4U); - return m_port->write(buffer, 4U) == 4; + return write(buffer, 4U) == 4; } /// -/// Sets the current operating mode for the air interface modem. +/// Writes raw data to the air interface modem. +/// +/// +/// +/// +int Modem::write(const uint8_t* data, uint32_t length) +{ + return m_port->write(data, length); +} + +/// +/// Gets the current operating state for the air interface modem. +/// +/// +DVM_STATE Modem::getState() const +{ + return m_modemState; +} + +/// +/// Sets the current operating state for the air interface modem. /// /// /// -bool Modem::setMode(DVM_STATE state) +bool Modem::setState(DVM_STATE state) { uint8_t buffer[4U]; @@ -1122,7 +1178,7 @@ bool Modem::setMode(DVM_STATE state) // Utils::dump(1U, "Written", buffer, 4U); - return m_port->write(buffer, 4U) == 4; + return write(buffer, 4U) == 4; } /// @@ -1151,7 +1207,7 @@ bool Modem::sendCWId(const std::string& callsign) Utils::dump(1U, "CW ID Data", buffer, length + 3U); } - return m_port->write(buffer, length + 3U) == int(length + 3U); + return write(buffer, length + 3U) == int(length + 3U); } // --------------------------------------------------------------------------- @@ -1174,7 +1230,7 @@ bool Modem::getFirmwareVersion() // Utils::dump(1U, "F/W Ver Written", buffer, 3U); - int ret = m_port->write(buffer, 3U); + int ret = write(buffer, 3U); if (ret != 3) return false; @@ -1235,7 +1291,7 @@ bool Modem::getStatus() // Utils::dump(1U, "Written", buffer, 3U); - return m_port->write(buffer, 3U) == 3; + return write(buffer, 3U) == 3; } /// @@ -1303,7 +1359,7 @@ bool Modem::writeConfig() // Utils::dump(1U, "Written", buffer, 17U); - int ret = m_port->write(buffer, 17U); + int ret = write(buffer, 17U); if (ret != 17) return false; @@ -1352,7 +1408,7 @@ bool Modem::writeSymbolAdjust() buffer[5U] = (uint8_t)(m_p25SymLevel3Adj + 128); buffer[6U] = (uint8_t)(m_p25SymLevel1Adj + 128); - int ret = m_port->write(buffer, 7U); + int ret = write(buffer, 7U); if (ret <= 0) return false; @@ -1386,32 +1442,56 @@ bool Modem::writeSymbolAdjust() /// /// /// -void Modem::printDebug() +/// +/// +void Modem::printDebug(const uint8_t* buffer, uint16_t len) { - if (m_buffer[2U] == CMD_DEBUG1) { - LogDebug(LOG_MODEM, "M: %.*s", m_length - 3U, m_buffer + 3U); + if (m_rspDoubleLength && buffer[3U] == CMD_DEBUG_DUMP) { + uint8_t data[512U]; + ::memset(data, 0x00U, 512U); + ::memcpy(data, buffer, len); + + Utils::dump(1U, "Modem Debug Dump", data, len); + return; + } + else { + if (m_rspDoubleLength) { + LogError(LOG_MODEM, "Invalid debug data received from the modem, len = %u", len); + return; + } + } + + if (buffer[2U] == CMD_DEBUG1) { + LogDebug(LOG_MODEM, "M: %.*s", len - 3U, buffer + 3U); } - else if (m_buffer[2U] == CMD_DEBUG2) { - short val1 = (m_buffer[m_length - 2U] << 8) | m_buffer[m_length - 1U]; - LogDebug(LOG_MODEM, "M: %.*s %X", m_length - 5U, m_buffer + 3U, val1); + else if (buffer[2U] == CMD_DEBUG2) { + short val1 = (buffer[len - 2U] << 8) | buffer[len - 1U]; + LogDebug(LOG_MODEM, "M: %.*s %X", len - 5U, buffer + 3U, val1); } - else if (m_buffer[2U] == CMD_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]; - LogDebug(LOG_MODEM, "M: %.*s %X %X", m_length - 7U, m_buffer + 3U, val1, val2); + else if (buffer[2U] == CMD_DEBUG3) { + short val1 = (buffer[len - 4U] << 8) | buffer[len - 3U]; + short val2 = (buffer[len - 2U] << 8) | buffer[len - 1U]; + LogDebug(LOG_MODEM, "M: %.*s %X %X", len - 7U, buffer + 3U, val1, val2); } - else if (m_buffer[2U] == CMD_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]; - LogDebug(LOG_MODEM, "M: %.*s %X %X %X", m_length - 9U, m_buffer + 3U, val1, val2, val3); + else if (buffer[2U] == CMD_DEBUG4) { + short val1 = (buffer[len - 6U] << 8) | buffer[len - 5U]; + short val2 = (buffer[len - 4U] << 8) | buffer[len - 3U]; + short val3 = (buffer[len - 2U] << 8) | buffer[len - 1U]; + LogDebug(LOG_MODEM, "M: %.*s %X %X %X", len - 9U, buffer + 3U, val1, val2, val3); } - else if (m_buffer[2U] == CMD_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]; - LogDebug(LOG_MODEM, "M: %.*s %X %X %X %X", m_length - 11U, m_buffer + 3U, val1, val2, val3, val4); + else if (buffer[2U] == CMD_DEBUG5) { + short val1 = (buffer[len - 8U] << 8) | buffer[len - 7U]; + short val2 = (buffer[len - 6U] << 8) | buffer[len - 5U]; + short val3 = (buffer[len - 4U] << 8) | buffer[len - 3U]; + short val4 = (buffer[len - 2U] << 8) | buffer[len - 1U]; + LogDebug(LOG_MODEM, "M: %.*s %X %X %X %X", len - 11U, buffer + 3U, val1, val2, val3, val4); + } + else if (buffer[2U] == CMD_DEBUG_DUMP) { + uint8_t data[255U]; + ::memset(data, 0x00U, 255U); + ::memcpy(data, buffer, len); + + Utils::dump(1U, "Modem Debug Dump", data, len); } } @@ -1421,111 +1501,118 @@ void Modem::printDebug() /// RESP_TYPE_DVM Modem::getResponse() { - if (m_offset == 0U) { - // Get the start of the frame or nothing at all + RESP_STATE state = RESP_START; + uint16_t offset = 0U; + + m_rspDoubleLength = false; + + // get the start of the frame or nothing at all + if (state == RESP_START) { int ret = m_port->read(m_buffer + 0U, 1U); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); return RTM_ERROR; } - // LogDebug(LOG_MODEM, "ret = %d", ret); - // Utils::dump(1U, "Response 0", m_buffer, 1U); - if (ret == 0) return RTM_TIMEOUT; if (m_buffer[0U] != DVM_FRAME_START) return RTM_TIMEOUT; - m_offset = 1U; + // LogDebug(LOG_MODEM, "getResponse(), RESP_START"); + + state = RESP_LENGTH1; } - if (m_offset == 1U) { - // Get the length of the frame + // get the length of the frame, 1/2 + if (state == RESP_LENGTH1) { int ret = m_port->read(m_buffer + 1U, 1U); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); - m_offset = 0U; return RTM_ERROR; } - // LogDebug(LOG_MODEM, "ret = %d", ret); - // Utils::dump(1U, "Response 1", m_buffer + 1U, 1U); - if (ret == 0) return RTM_TIMEOUT; if (m_buffer[1U] >= 250U) { LogError(LOG_MODEM, "Invalid length received from the modem, len = %u", m_buffer[1U]); - m_offset = 0U; return RTM_ERROR; } m_length = m_buffer[1U]; - m_offset = 2U; + + if (m_length == 0U) + state = RESP_LENGTH2; + else + state = RESP_TYPE; + + // LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH1, len = %u", m_length); + + m_rspDoubleLength = false; + offset = 2U; } - if (m_offset == 2U) { - // Get the frame type + // get the length of the frame, 2/2 + if (state == RESP_LENGTH2) { int ret = m_port->read(m_buffer + 2U, 1U); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); - m_offset = 0U; return RTM_ERROR; } - // LogDebug(LOG_MODEM, "ret = %d", ret); - // Utils::dump(1U, "Response 2", m_buffer + 2U, 1U); - if (ret == 0) return RTM_TIMEOUT; - m_offset = 3U; + m_length = m_buffer[2U] + 255U; + state = RESP_TYPE; + + // LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH2, len = %u", m_length); + + m_rspDoubleLength = true; + offset = 3U; } - if (m_offset >= 3U) { - // Use later two byte length field - if (m_length == 0U) { - int ret = m_port->read(m_buffer + 3U, 2U); - if (ret < 0) { - LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); - m_offset = 0U; - return RTM_ERROR; - } + // get the frame type + if (state == RESP_TYPE) { + int ret = m_port->read(m_buffer + offset, 1U); + if (ret < 0) { + LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); + return RTM_ERROR; + } - // LogDebug(LOG_MODEM, "ret = %d", ret); - // Utils::dump(1U, "Response 3", m_buffer + 3U, 2U); + if (ret == 0) + return RTM_TIMEOUT; - if (ret == 0) - return RTM_TIMEOUT; + m_rspType = (DVM_COMMANDS)m_buffer[offset]; - m_length = (m_buffer[3U] << 8) | m_buffer[4U]; - m_offset = 5U; - } + // LogDebug(LOG_MODEM, "getResponse(), RESP_TYPE, len = %u, type = %u", m_length, m_rspType); + + state = RESP_DATA; + offset++; + } + + // get the frame data + if (state == RESP_DATA) { + // LogDebug(LOG_MODEM, "getResponse(), RESP_DATA, len = %u, type = %u", m_length, m_rspType); - while (m_offset < m_length) { - int ret = m_port->read(m_buffer + m_offset, m_length - m_offset); + while (offset < m_length) { + int ret = m_port->read(m_buffer + offset, m_length - offset); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); - m_offset = 0U; return RTM_ERROR; } - // LogDebug(LOG_MODEM, "ret = %d", ret); - // Utils::dump(1U, "Response 4", m_buffer + m_offset, m_length - m_offset); - if (ret == 0) return RTM_TIMEOUT; if (ret > 0) - m_offset += ret; + offset += ret; } - } - m_offset = 0U; - - // Utils::dump(1U, "Received", m_buffer, m_length); + // Utils::dump(1U, "Modem getResponse()", m_buffer, m_length); + } return RTM_OK; } diff --git a/modem/Modem.h b/modem/Modem.h index 94046ffb..e28b36da 100644 --- a/modem/Modem.h +++ b/modem/Modem.h @@ -12,7 +12,7 @@ // /* * Copyright (C) 2011-2021 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2018 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL * * 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,13 +37,25 @@ #include "Timer.h" #include +#include #define MODEM_VERSION_STR "%.*s, Modem protocol: %u" #define MODEM_UNSUPPORTED_STR "Modem protocol: %u, unsupported! Stopping." #define NULL_MODEM "null" +#define MODEM_OC_PORT_HANDLER bool(modem::Modem* modem) +#define MODEM_OC_PORT_HANDLER_BIND(funcAddr, classInstance) std::bind(&funcAddr, classInstance, std::placeholders::_1) +#define MODEM_RESP_HANDLER bool(modem::Modem* modem, uint32_t ms, modem::RESP_TYPE_DVM rspType, bool rspDblLen, const uint8_t* buffer, uint16_t len) +#define MODEM_RESP_HANDLER_BIND(funcAddr, classInstance) std::bind(&funcAddr, classInstance, std::placeholders::_1, std::placeholders::_2, \ + std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6) + const uint8_t PROTOCOL_VERSION = 2U; +// --------------------------------------------------------------------------- +// Class Prototypes +// --------------------------------------------------------------------------- +class HOST_SW_API HostCal; + namespace modem { // --------------------------------------------------------------------------- @@ -124,6 +136,7 @@ namespace modem CMD_DEBUG3 = 0xF3U, CMD_DEBUG4 = 0xF4U, CMD_DEBUG5 = 0xF5U, + CMD_DEBUG_DUMP = 0xFAU, }; enum CMD_REASON_CODE { @@ -185,8 +198,16 @@ namespace modem void setP25NAC(uint32_t nac); /// Sets the RF receive deviation levels. void setRXLevel(float rxLevel); - /// Sets the slave port for remote operation. - void setSlavePort(port::IModemPort* slavePort); + + /// Sets a custom modem response handler. + /// If the response handler returns true, processing will stop, otherwise it will continue. + void setResponseHandler(std::function handler); + /// Sets a custom modem open port handler. + /// If the open handler is set, it is the responsibility of the handler to complete air interface + /// initialization (i.e. write configuration, etc). + void setOpenHandler(std::function handler); + /// Sets a custom modem close port handler. + void setCloseHandler(std::function handler); /// Opens connection to the air interface modem. bool open(); @@ -249,17 +270,21 @@ namespace modem /// Writes a DMR abort message for the given slot to the air interface modem. bool writeDMRAbort(uint32_t slotNo); - /// Gets the current operating mode for the air interface modem. - DVM_STATE getMode() const; - /// Sets the current operating mode for the air interface modem. - bool setMode(DVM_STATE state); + /// Writes raw data to the air interface modem. + int write(const uint8_t* data, uint32_t length); + + /// Gets the current operating state for the air interface modem. + DVM_STATE getState() const; + /// Sets the current operating state for the air interface modem. + bool setState(DVM_STATE state); /// Transmits the given string as CW morse. bool sendCWId(const std::string& callsign); private: + friend class ::HostCal; + port::IModemPort* m_port; - port::IModemPort* m_remotePort; uint32_t m_dmrColorCode; uint32_t m_p25NAC; @@ -283,8 +308,6 @@ namespace modem float m_p25TXLevel; bool m_disableOFlowReset; - bool m_trace; - bool m_debug; bool m_dmrEnabled; bool m_p25Enabled; @@ -302,8 +325,13 @@ namespace modem DVM_STATE m_modemState; uint8_t* m_buffer; - uint32_t m_length; - uint32_t m_offset; + uint16_t m_length; + bool m_rspDoubleLength; + DVM_COMMANDS m_rspType; + + std::function m_openPortHandler; + std::function m_closePortHandler; + std::function m_rspHandler; RingBuffer m_rxDMRData1; RingBuffer m_rxDMRData2; @@ -314,7 +342,6 @@ namespace modem Timer m_statusTimer; Timer m_inactivityTimer; - Timer m_playoutTimer; uint32_t m_dmrSpace1; uint32_t m_dmrSpace2; @@ -335,10 +362,19 @@ namespace modem bool writeSymbolAdjust(); /// - void printDebug(); + void printDebug(const uint8_t* buffer, uint16_t len); /// RESP_TYPE_DVM getResponse(); + + public: + /// Flag indicating if modem trace is enabled. + __READONLY_PROPERTY(bool, trace, Trace); + /// Flag indicating if modem debugging is enabled. + __READONLY_PROPERTY(bool, debug, Debug); + + /// + __READONLY_PROPERTY(Timer, playoutTimer, PlayoutTimer); }; } // namespace modem diff --git a/modem/port/UARTPort.cpp b/modem/port/UARTPort.cpp index 9233d03d..e62536e6 100644 --- a/modem/port/UARTPort.cpp +++ b/modem/port/UARTPort.cpp @@ -65,6 +65,7 @@ using namespace modem::port; /// Serial port speed. /// UARTPort::UARTPort(const std::string& device, SERIAL_SPEED speed, bool assertRTS) : + m_isOpen(false), m_device(device), m_speed(speed), m_assertRTS(assertRTS), @@ -87,6 +88,9 @@ UARTPort::~UARTPort() /// True, if connection is opened, otherwise false. bool UARTPort::open() { + if (m_isOpen) + return true; + assert(m_handle == INVALID_HANDLE_VALUE); DWORD errCode; @@ -163,6 +167,7 @@ bool UARTPort::open() ::ClearCommError(m_handle, &errCode, NULL); + m_isOpen = true; return true; } @@ -231,6 +236,9 @@ int UARTPort::write(const uint8_t* buffer, uint32_t length) /// void UARTPort::close() { + if (!m_isOpen) + return; + assert(m_handle != INVALID_HANDLE_VALUE); ::CloseHandle(m_handle); @@ -246,6 +254,7 @@ void UARTPort::close() /// Serial port speed. /// UARTPort::UARTPort(const std::string& device, SERIAL_SPEED speed, bool assertRTS) : + m_isOpen(false), m_device(device), m_speed(speed), m_assertRTS(assertRTS), @@ -267,6 +276,9 @@ UARTPort::~UARTPort() /// True, if connection is opened, otherwise false. bool UARTPort::open() { + if (m_isOpen) + return true; + assert(m_fd == -1); #if defined(__APPLE__) @@ -279,9 +291,106 @@ bool UARTPort::open() return false; } - if (::isatty(m_fd)) - return setRaw(); + if (::isatty(m_fd) == 0) { + LogError(LOG_HOST, "%s is not a TTY device", m_device.c_str()); + ::close(m_fd); + return false; + } + + termios termios; + if (::tcgetattr(m_fd, &termios) < 0) { + ::LogError(LOG_HOST, "Cannot get the attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + + termios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK); + termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL); + termios.c_iflag &= ~(IXON | IXOFF | IXANY); + termios.c_oflag &= ~(OPOST); + termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); + termios.c_cflag |= (CS8 | CLOCAL | CREAD); + termios.c_lflag &= ~(ISIG | ICANON | IEXTEN); + termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); +#if defined(__APPLE__) + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 1; +#else + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 10; +#endif + + switch (m_speed) { + case SERIAL_1200: + ::cfsetospeed(&termios, B1200); + ::cfsetispeed(&termios, B1200); + break; + case SERIAL_2400: + ::cfsetospeed(&termios, B2400); + ::cfsetispeed(&termios, B2400); + break; + case SERIAL_4800: + ::cfsetospeed(&termios, B4800); + ::cfsetispeed(&termios, B4800); + break; + case SERIAL_9600: + ::cfsetospeed(&termios, B9600); + ::cfsetispeed(&termios, B9600); + break; + case SERIAL_19200: + ::cfsetospeed(&termios, B19200); + ::cfsetispeed(&termios, B19200); + break; + case SERIAL_38400: + ::cfsetospeed(&termios, B38400); + ::cfsetispeed(&termios, B38400); + break; + case SERIAL_115200: + ::cfsetospeed(&termios, B115200); + ::cfsetispeed(&termios, B115200); + break; + case SERIAL_230400: + ::cfsetospeed(&termios, B230400); + ::cfsetispeed(&termios, B230400); + break; + case SERIAL_460800: + ::cfsetospeed(&termios, B460800); + ::cfsetispeed(&termios, B460800); + break; + default: + ::LogError(LOG_HOST, "Unsupported serial port speed - %u", m_speed); + ::close(m_fd); + return false; + } + + if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) { + ::LogError(LOG_HOST, "Cannot set the attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + if (m_assertRTS) { + uint32_t y; + if (::ioctl(m_fd, TIOCMGET, &y) < 0) { + ::LogError(LOG_HOST, "Cannot get the control attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + + y |= TIOCM_RTS; + + if (::ioctl(m_fd, TIOCMSET, &y) < 0) { + ::LogError(LOG_HOST, "Cannot set the control attributes for %s", m_device.c_str()); + ::close(m_fd); + return false; + } + } + +#if defined(__APPLE__) + setNonblock(false); +#endif + + m_isOpen = true; return true; } @@ -378,6 +487,9 @@ int UARTPort::write(const uint8_t* buffer, uint32_t length) /// void UARTPort::close() { + if (!m_isOpen) + return; + assert(m_fd != -1); ::close(m_fd); @@ -408,20 +520,6 @@ int UARTPort::setNonblock(bool nonblock) // --------------------------------------------------------------------------- #if defined(_WIN32) || defined(_WIN64) -/// -/// Initializes a new instance of the UARTPort class. -/// -/// Serial port speed. -/// -UARTPort::UARTPort(SERIAL_SPEED speed, bool assertRTS) : - m_device(), - m_speed(speed), - m_assertRTS(assertRTS), - m_handle(INVALID_HANDLE_VALUE) -{ - /* stub */ -} - /// /// /// @@ -462,20 +560,6 @@ int UARTPort::readNonblock(uint8_t* buffer, uint32_t length) #else -/// -/// Initializes a new instance of the UARTPort class. -/// -/// Serial port speed. -/// -UARTPort::UARTPort(SERIAL_SPEED speed, bool assertRTS) : - m_device(), - m_speed(speed), - m_assertRTS(assertRTS), - m_fd(-1) -{ - /* stub */ -} - /// /// /// @@ -500,106 +584,4 @@ bool UARTPort::canWrite() return true; #endif } - -/// -/// -/// -/// -bool UARTPort::setRaw() -{ - termios termios; - if (::tcgetattr(m_fd, &termios) < 0) { - ::LogError(LOG_HOST, "Cannot get the attributes for %s", m_device.c_str()); - ::close(m_fd); - return false; - } - - termios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK); - termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL); - termios.c_iflag &= ~(IXON | IXOFF | IXANY); - termios.c_oflag &= ~(OPOST); - termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); - termios.c_cflag |= (CS8 | CLOCAL | CREAD); - termios.c_lflag &= ~(ISIG | ICANON | IEXTEN); - termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); -#if defined(__APPLE__) - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 1; -#else - termios.c_cc[VMIN] = 0; - termios.c_cc[VTIME] = 10; -#endif - - switch (m_speed) { - case SERIAL_1200: - ::cfsetospeed(&termios, B1200); - ::cfsetispeed(&termios, B1200); - break; - case SERIAL_2400: - ::cfsetospeed(&termios, B2400); - ::cfsetispeed(&termios, B2400); - break; - case SERIAL_4800: - ::cfsetospeed(&termios, B4800); - ::cfsetispeed(&termios, B4800); - break; - case SERIAL_9600: - ::cfsetospeed(&termios, B9600); - ::cfsetispeed(&termios, B9600); - break; - case SERIAL_19200: - ::cfsetospeed(&termios, B19200); - ::cfsetispeed(&termios, B19200); - break; - case SERIAL_38400: - ::cfsetospeed(&termios, B38400); - ::cfsetispeed(&termios, B38400); - break; - case SERIAL_115200: - ::cfsetospeed(&termios, B115200); - ::cfsetispeed(&termios, B115200); - break; - case SERIAL_230400: - ::cfsetospeed(&termios, B230400); - ::cfsetispeed(&termios, B230400); - break; - case SERIAL_460800: - ::cfsetospeed(&termios, B460800); - ::cfsetispeed(&termios, B460800); - break; - default: - ::LogError(LOG_HOST, "Unsupported serial port speed - %u", m_speed); - ::close(m_fd); - return false; - } - - if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) { - ::LogError(LOG_HOST, "Cannot set the attributes for %s", m_device.c_str()); - ::close(m_fd); - return false; - } - - if (m_assertRTS) { - uint32_t y; - if (::ioctl(m_fd, TIOCMGET, &y) < 0) { - ::LogError(LOG_HOST, "Cannot get the control attributes for %s", m_device.c_str()); - ::close(m_fd); - return false; - } - - y |= TIOCM_RTS; - - if (::ioctl(m_fd, TIOCMSET, &y) < 0) { - ::LogError(LOG_HOST, "Cannot set the control attributes for %s", m_device.c_str()); - ::close(m_fd); - return false; - } - } - -#if defined(__APPLE__) - setNonblock(false); -#endif - - return true; -} #endif diff --git a/modem/port/UARTPort.h b/modem/port/UARTPort.h index 999ea2da..c8c4f266 100644 --- a/modem/port/UARTPort.h +++ b/modem/port/UARTPort.h @@ -94,8 +94,7 @@ namespace modem #endif protected: - /// Initializes a new instance of the UARTPort class. - UARTPort(SERIAL_SPEED speed, bool assertRTS = false); + bool m_isOpen; std::string m_device; SERIAL_SPEED m_speed; @@ -112,8 +111,6 @@ namespace modem #else /// bool canWrite(); - /// - bool setRaw(); #endif }; // class HOST_SW_API UARTPort : public ISerialPort, public IModemPort } // namespace port diff --git a/network/RemoteControl.cpp b/network/RemoteControl.cpp index d9bca173..8a6aea40 100644 --- a/network/RemoteControl.cpp +++ b/network/RemoteControl.cpp @@ -230,19 +230,19 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25) // Command is in the form of: "mode " if (mode == RCD_MODE_OPT_IDLE) { host->m_fixedMode = false; - host->setMode(STATE_IDLE); - LogInfoEx(LOG_RCON, "Dynamic mode, mode %u", host->m_mode); + host->setState(STATE_IDLE); + LogInfoEx(LOG_RCON, "Dynamic mode, mode %u", host->m_state); } else if (mode == RCD_MODE_OPT_LCKOUT) { host->m_fixedMode = false; - host->setMode(HOST_STATE_LOCKOUT); - LogInfoEx(LOG_RCON, "Lockout mode, mode %u", host->m_mode); + host->setState(HOST_STATE_LOCKOUT); + LogInfoEx(LOG_RCON, "Lockout mode, mode %u", host->m_state); } else if (mode == RCD_MODE_OPT_FDMR) { if (dmr != NULL) { host->m_fixedMode = true; - host->setMode(STATE_DMR); - LogInfoEx(LOG_RCON, "Fixed mode, mode %u", host->m_mode); + host->setState(STATE_DMR); + LogInfoEx(LOG_RCON, "Fixed mode, mode %u", host->m_state); } else { LogError(LOG_RCON, CMD_FAILED_STR "DMR mode is not enabled!"); @@ -251,8 +251,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25) else if (mode == RCD_MODE_OPT_FP25) { if (p25 != NULL) { host->m_fixedMode = true; - host->setMode(STATE_P25); - LogInfoEx(LOG_RCON, "Fixed mode, mode %u", host->m_mode); + host->setState(STATE_P25); + LogInfoEx(LOG_RCON, "Fixed mode, mode %u", host->m_state); } else { LogError(LOG_RCON, CMD_FAILED_STR "P25 mode is not enabled!"); @@ -262,7 +262,7 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25) else if (rcom == RCD_KILL_CMD) { // Command is in the form of: "kill" g_killed = true; - host->setMode(HOST_STATE_QUIT); + host->setState(HOST_STATE_QUIT); } else if (rcom == RCD_RID_WLIST_CMD && argCnt >= 1U) { // Command is in the form of: "rid-whitelist "