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;

pull/1/head
Bryan Biedenkapp 5 years ago
parent d672f8827f
commit de2860ca6a

@ -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 --
// ------------------------------------------------------

@ -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;

@ -51,18 +51,6 @@ using namespace modem;
#include <unistd.h>
#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)
/// <returns>Response type from modem.</returns>
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;
}

@ -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;

@ -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)
/// </summary>
void UARTPort::close()
{
if (!m_isOpen)
if (!m_isOpen && m_fd == -1)
return;
assert(m_fd != -1);

@ -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

@ -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

@ -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

Loading…
Cancel
Save

Powered by TurnKey Linux.