From de2860ca6ad2a362064c415417b576d0e257c486 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 24 Apr 2021 04:45:37 +0000 Subject: [PATCH] correct issue when trying to close and reopen modem; update copyright dates; fix issue in Modem where the getResponse may not continue properly after returning; reorder operations in Host to Write, Modem Clock, Read, Network, DMR, P25, Timers; --- host/Host.cpp | 333 +++++++++++++++++++------------------ host/calibrate/HostCal.cpp | 2 +- modem/Modem.cpp | 70 ++++---- modem/Modem.h | 10 ++ modem/port/UARTPort.cpp | 4 +- p25/DataPacket.cpp | 2 +- p25/data/DataBlock.cpp | 2 +- p25/data/DataBlock.h | 2 +- 8 files changed, 221 insertions(+), 204 deletions(-) diff --git a/host/Host.cpp b/host/Host.cpp index b8e2357e..29eae300 100644 --- a/host/Host.cpp +++ b/host/Host.cpp @@ -566,6 +566,168 @@ int Host::run() bool ret; bool hasCw = false; + if (m_modeTimer.isRunning() && m_modeTimer.hasExpired()) { + if (!m_fixedMode) { + setState(STATE_IDLE); + } + else { + if (dmr != NULL) + setState(STATE_DMR); + if (p25 != NULL) + setState(STATE_P25); + } + } + + // ------------------------------------------------------ + // -- Write to Modem Processing -- + // ------------------------------------------------------ + + /** DMR */ + if (dmr != NULL) { + // check if there is space on the modem for DMR slot 1 frames, + // if there is read frames from the DMR controller and write it + // to the modem + ret = m_modem->hasDMRSpace1(); + if (ret) { + len = dmr->getFrame1(data); + if (len > 0U) { + if (m_state == STATE_IDLE) { + m_modeTimer.setTimeout(m_netModeHang); + setState(STATE_DMR); + } + if (m_state == STATE_DMR) { + // if the modem is in duplex -- write DMR sync start + if (m_duplex) { + m_modem->writeDMRStart(true); + m_dmrTXTimer.start(); + } + + m_modem->writeDMRData1(data, len); + + dmrBeaconDurationTimer.stop(); + if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { + p25CCDurationTimer.pause(); + } + m_modeTimer.start(); + } + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); + } + } + } + + // check if there is space on the modem for DMR slot 2 frames, + // if there is read frames from the DMR controller and write it + // to the modem + ret = m_modem->hasDMRSpace2(); + if (ret) { + len = dmr->getFrame2(data); + if (len > 0U) { + if (m_state == STATE_IDLE) { + m_modeTimer.setTimeout(m_netModeHang); + setState(STATE_DMR); + } + if (m_state == STATE_DMR) { + // if the modem is in duplex -- write DMR sync start + if (m_duplex) { + m_modem->writeDMRStart(true); + m_dmrTXTimer.start(); + } + + m_modem->writeDMRData2(data, len); + + dmrBeaconDurationTimer.stop(); + if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { + p25CCDurationTimer.pause(); + } + m_modeTimer.start(); + } + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); + } + } + } + } + + /** P25 */ + // check if there is space on the modem for P25 frames, + // if there is read frames from the P25 controller and write it + // to the modem + if (p25 != NULL) { + ret = m_modem->hasP25Space(); + if (ret) { + len = p25->getFrame(data); + if (len > 0U) { + if (m_state == STATE_IDLE) { + m_modeTimer.setTimeout(m_netModeHang); + setState(STATE_P25); + } + + if (m_state == STATE_P25) { + m_modem->writeP25Data(data, len); + + dmrBeaconDurationTimer.stop(); + if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { + p25CCDurationTimer.pause(); + } + + m_modeTimer.start(); + } + else if (m_state != HOST_STATE_LOCKOUT) { + LogWarning(LOG_HOST, "P25 data received, state = %u", m_state); + } + } + else { + 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); + p25->writeControlRF(); + } + + // P25 status data, tail on idle + ret = p25->writeEndRF(); + if (ret) { + if (m_state == STATE_IDLE) { + m_modeTimer.setTimeout(m_netModeHang); + setState(STATE_P25); + } + + if (m_state == STATE_P25) { + m_modeTimer.start(); + } + } + } + } + + + // if the modem is in duplex -- handle P25 CC burst control + if (m_duplex) { + if (p25CCDurationTimer.isPaused() && !g_interruptP25Control) { + LogDebug(LOG_HOST, "traffic complete, resume P25 CC, g_interruptP25Control = %u", g_interruptP25Control); + p25CCDurationTimer.resume(); + } + + if (g_interruptP25Control) { + g_fireP25Control = true; + } + + if (g_fireP25Control) { + m_modeTimer.stop(); + } + } + } + } + + // ------------------------------------------------------ + // -- Modem Clocking -- + // ------------------------------------------------------ + + ms = stopWatch.elapsed(); + stopWatch.start(); + + m_modem->clock(ms); + // ------------------------------------------------------ // -- Read from Modem Processing -- // ------------------------------------------------------ @@ -759,156 +921,16 @@ int Host::run() } // ------------------------------------------------------ - // -- Write to Modem Processing -- + // -- Network, DMR, and P25 Clocking -- // ------------------------------------------------------ - if (m_modeTimer.isRunning() && m_modeTimer.hasExpired()) { - if (!m_fixedMode) { - setState(STATE_IDLE); - } else { - if (dmr != NULL) - setState(STATE_DMR); - if (p25 != NULL) - setState(STATE_P25); - } - } - - /** DMR */ - if (dmr != NULL) { - // check if there is space on the modem for DMR slot 1 frames, - // if there is read frames from the DMR controller and write it - // to the modem - ret = m_modem->hasDMRSpace1(); - if (ret) { - len = dmr->getFrame1(data); - if (len > 0U) { - if (m_state == STATE_IDLE) { - m_modeTimer.setTimeout(m_netModeHang); - setState(STATE_DMR); - } - if (m_state == STATE_DMR) { - // if the modem is in duplex -- write DMR sync start - if (m_duplex) { - m_modem->writeDMRStart(true); - m_dmrTXTimer.start(); - } - - m_modem->writeDMRData1(data, len); - - dmrBeaconDurationTimer.stop(); - if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { - p25CCDurationTimer.pause(); - } - m_modeTimer.start(); - } - else if (m_state != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); - } - } - } - - // check if there is space on the modem for DMR slot 2 frames, - // if there is read frames from the DMR controller and write it - // to the modem - ret = m_modem->hasDMRSpace2(); - if (ret) { - len = dmr->getFrame2(data); - if (len > 0U) { - if (m_state == STATE_IDLE) { - m_modeTimer.setTimeout(m_netModeHang); - setState(STATE_DMR); - } - if (m_state == STATE_DMR) { - // if the modem is in duplex -- write DMR sync start - if (m_duplex) { - m_modem->writeDMRStart(true); - m_dmrTXTimer.start(); - } - - m_modem->writeDMRData2(data, len); - - dmrBeaconDurationTimer.stop(); - if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { - p25CCDurationTimer.pause(); - } - m_modeTimer.start(); - } - else if (m_state != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "DMR data received, state = %u", m_state); - } - } - } - } - - /** P25 */ - // check if there is space on the modem for P25 frames, - // if there is read frames from the P25 controller and write it - // to the modem - if (p25 != NULL) { - ret = m_modem->hasP25Space(); - if (ret) { - len = p25->getFrame(data); - if (len > 0U) { - if (m_state == STATE_IDLE) { - m_modeTimer.setTimeout(m_netModeHang); - setState(STATE_P25); - } - - if (m_state == STATE_P25) { - m_modem->writeP25Data(data, len); - - dmrBeaconDurationTimer.stop(); - if (g_interruptP25Control && p25CCDurationTimer.isRunning()) { - p25CCDurationTimer.pause(); - } - - m_modeTimer.start(); - } - else if (m_state != HOST_STATE_LOCKOUT) { - LogWarning(LOG_HOST, "P25 data received, state = %u", m_state); - } - } - else { - 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); - p25->writeControlRF(); - } - - // P25 status data, tail on idle - ret = p25->writeEndRF(); - if (ret) { - if (m_state == STATE_IDLE) { - m_modeTimer.setTimeout(m_netModeHang); - setState(STATE_P25); - } - - if (m_state == STATE_P25) { - m_modeTimer.start(); - } - } - } - } - - - // if the modem is in duplex -- handle P25 CC burst control - if (m_duplex) { - if (p25CCDurationTimer.isPaused() && !g_interruptP25Control) { - LogDebug(LOG_HOST, "traffic complete, resume P25 CC, g_interruptP25Control = %u", g_interruptP25Control); - p25CCDurationTimer.resume(); - } - - if (g_interruptP25Control) { - g_fireP25Control = true; - } + if (m_network != NULL) + m_network->clock(ms); - if (g_fireP25Control) { - m_modeTimer.stop(); - } - } - } - } + if (dmr != NULL) + dmr->clock(); + if (p25 != NULL) + p25->clock(ms); // ------------------------------------------------------ // -- Remote Control Processing -- @@ -918,23 +940,6 @@ int Host::run() m_remoteControl->process(this, dmr, p25); } - // ------------------------------------------------------ - // -- Modem, DMR, P25 and Network Clocking -- - // ------------------------------------------------------ - - ms = stopWatch.elapsed(); - stopWatch.start(); - - m_modem->clock(ms); - - if (dmr != NULL) - dmr->clock(); - if (p25 != NULL) - p25->clock(ms); - - if (m_network != NULL) - m_network->clock(ms); - // ------------------------------------------------------ // -- Timer Clocking -- // ------------------------------------------------------ diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp index 5f206202..4992623c 100644 --- a/host/calibrate/HostCal.cpp +++ b/host/calibrate/HostCal.cpp @@ -182,7 +182,7 @@ int HostCal::run() } // initialize system logging - ret = ::LogInitialise("", "", 0U, 2U); + ret = ::LogInitialise("", "", 0U, 1U); if (!ret) { ::fprintf(stderr, "unable to open the log file\n"); return 1; diff --git a/modem/Modem.cpp b/modem/Modem.cpp index 6332295b..bb0f38cf 100644 --- a/modem/Modem.cpp +++ b/modem/Modem.cpp @@ -51,18 +51,6 @@ using namespace modem; #include #endif -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- - -enum RESP_STATE { - RESP_START, - RESP_LENGTH1, - RESP_LENGTH2, - RESP_TYPE, - RESP_DATA -}; - // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -115,6 +103,8 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert, m_modemState(STATE_IDLE), m_buffer(NULL), m_length(0U), + m_rspOffset(0U), + m_rspState(RESP_START), m_rspDoubleLength(false), m_rspType(CMD_GET_STATUS), m_openPortHandler(NULL), @@ -353,6 +343,9 @@ bool Modem::open() m_inactivityTimer.stop(); } + m_rspOffset = 0U; + m_rspState = RESP_START; + // do we have an open port handler? if (m_openPortHandler) { ret = m_openPortHandler(this); @@ -1503,16 +1496,14 @@ void Modem::printDebug(const uint8_t* buffer, uint16_t len) /// Response type from modem. RESP_TYPE_DVM Modem::getResponse() { - 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) { + if (m_rspState == 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); + m_rspState = RESP_START; return RTM_ERROR; } @@ -1524,14 +1515,15 @@ RESP_TYPE_DVM Modem::getResponse() // LogDebug(LOG_MODEM, "getResponse(), RESP_START"); - state = RESP_LENGTH1; + m_rspState = RESP_LENGTH1; } // get the length of the frame, 1/2 - if (state == RESP_LENGTH1) { + if (m_rspState == 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_rspState = RESP_START; return RTM_ERROR; } @@ -1546,21 +1538,22 @@ RESP_TYPE_DVM Modem::getResponse() m_length = m_buffer[1U]; if (m_length == 0U) - state = RESP_LENGTH2; + m_rspState = RESP_LENGTH2; else - state = RESP_TYPE; + m_rspState = RESP_TYPE; // LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH1, len = %u", m_length); m_rspDoubleLength = false; - offset = 2U; + m_rspOffset = 2U; } // get the length of the frame, 2/2 - if (state == RESP_LENGTH2) { + if (m_rspState == 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_rspState = RESP_START; return RTM_ERROR; } @@ -1568,41 +1561,44 @@ RESP_TYPE_DVM Modem::getResponse() return RTM_TIMEOUT; m_length = m_buffer[2U] + 255U; - state = RESP_TYPE; + m_rspState = RESP_TYPE; // LogDebug(LOG_MODEM, "getResponse(), RESP_LENGTH2, len = %u", m_length); m_rspDoubleLength = true; - offset = 3U; + m_rspOffset = 3U; } // get the frame type - if (state == RESP_TYPE) { - int ret = m_port->read(m_buffer + offset, 1U); + if (m_rspState == RESP_TYPE) { + int ret = m_port->read(m_buffer + m_rspOffset, 1U); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); + m_rspState = RESP_START; return RTM_ERROR; } if (ret == 0) return RTM_TIMEOUT; - m_rspType = (DVM_COMMANDS)m_buffer[offset]; + m_rspType = (DVM_COMMANDS)m_buffer[m_rspOffset]; // LogDebug(LOG_MODEM, "getResponse(), RESP_TYPE, len = %u, type = %u", m_length, m_rspType); - state = RESP_DATA; - offset++; + m_rspState = RESP_DATA; + m_rspOffset++; } // get the frame data - if (state == RESP_DATA) { - // LogDebug(LOG_MODEM, "getResponse(), RESP_DATA, len = %u, type = %u", m_length, m_rspType); + if (m_rspState == RESP_DATA) { + if (m_debug && m_trace) + LogDebug(LOG_MODEM, "getResponse(), RESP_DATA, len = %u, offset = %u, type = %02X", m_length, m_rspOffset, m_rspType); - while (offset < m_length) { - int ret = m_port->read(m_buffer + offset, m_length - offset); + while (m_rspOffset < m_length) { + int ret = m_port->read(m_buffer + m_rspOffset, m_length - m_rspOffset); if (ret < 0) { LogError(LOG_MODEM, "Error reading from the modem, ret = %d", ret); + m_rspState = RESP_START; return RTM_ERROR; } @@ -1610,11 +1606,15 @@ RESP_TYPE_DVM Modem::getResponse() return RTM_TIMEOUT; if (ret > 0) - offset += ret; + m_rspOffset += ret; } - // Utils::dump(1U, "Modem getResponse()", m_buffer, m_length); + if (m_debug && m_trace) + Utils::dump(1U, "Modem getResponse()", m_buffer, m_length); } + m_rspState = RESP_START; + m_rspOffset = 0U; + return RTM_OK; } diff --git a/modem/Modem.h b/modem/Modem.h index 9eca5b85..c6ac59b6 100644 --- a/modem/Modem.h +++ b/modem/Modem.h @@ -151,6 +151,14 @@ namespace modem RSN_P25_DISABLED = 64U, }; + enum RESP_STATE { + RESP_START, + RESP_LENGTH1, + RESP_LENGTH2, + RESP_TYPE, + RESP_DATA + }; + const uint8_t DVM_FRAME_START = 0xFEU; const uint8_t MAX_FDMA_PREAMBLE = 255U; @@ -316,6 +324,8 @@ namespace modem uint8_t* m_buffer; uint16_t m_length; + uint16_t m_rspOffset; + RESP_STATE m_rspState; bool m_rspDoubleLength; DVM_COMMANDS m_rspType; diff --git a/modem/port/UARTPort.cpp b/modem/port/UARTPort.cpp index e62536e6..9a20b98e 100644 --- a/modem/port/UARTPort.cpp +++ b/modem/port/UARTPort.cpp @@ -414,11 +414,13 @@ int UARTPort::read(uint8_t* buffer, uint32_t length) fd_set fds; FD_ZERO(&fds); FD_SET(m_fd, &fds); + int n; if (offset == 0U) { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; + n = ::select(m_fd + 1, &fds, NULL, NULL, &tv); if (n == 0) return 0; @@ -487,7 +489,7 @@ int UARTPort::write(const uint8_t* buffer, uint32_t length) /// void UARTPort::close() { - if (!m_isOpen) + if (!m_isOpen && m_fd == -1) return; assert(m_fd != -1); diff --git a/p25/DataPacket.cpp b/p25/DataPacket.cpp index 9d6036e4..9b753622 100644 --- a/p25/DataPacket.cpp +++ b/p25/DataPacket.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016,2017,2018 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 diff --git a/p25/data/DataBlock.cpp b/p25/data/DataBlock.cpp index 1713ff5f..cd538514 100644 --- a/p25/data/DataBlock.cpp +++ b/p25/data/DataBlock.cpp @@ -11,7 +11,7 @@ // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // /* -* Copyright (C) 2018-2019 by Bryan Biedenkapp N2PLL +* Copyright (C) 2018-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 diff --git a/p25/data/DataBlock.h b/p25/data/DataBlock.h index 4f0a052c..385ec779 100644 --- a/p25/data/DataBlock.h +++ b/p25/data/DataBlock.h @@ -11,7 +11,7 @@ // Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0) // /* -* Copyright (C) 2018-2019 by Bryan Biedenkapp N2PLL +* Copyright (C) 2018-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