make sure the data length for P25 is twice the PDU length; add support to log if a dedicated CC stops transmitting from the host perspective (the logic for this is: is host in appropriate digital mode for CC, is the modem reporting no Tx, has the modem reported its status initially, and is the CC in a running state);

pull/55/head
Bryan Biedenkapp 2 years ago
parent a1a0065a74
commit 01af69a954

@ -139,6 +139,16 @@ void Host::writeFramesDMR1(dmr::Control* control, std::function<void()>&& afterW
// to the modem
bool ret = m_modem->hasDMRSpace1();
if (ret) {
uint32_t nextLen = control->peekFrameLength(1U);
if (m_dmrCtrlChannel) {
if (m_dmrDedicatedTxTestTimer.hasExpired()) {
m_dmrDedicatedTxTestTimer.pause();
if (!m_modem->hasTX() && m_modem->gotModemStatus() && m_state == STATE_DMR && (control->getTSCCSlotNo() == 1U) && control->getCCRunning()) {
LogError(LOG_HOST, "DMR dedicated control not transmitting, running = %u, halted = %u, frameLength1 = %u", control->getCCRunning(), control->getCCHalted(), nextLen);
}
}
}
uint32_t len = control->getFrame(1U, data);
if (len > 0U) {
// if the state is idle; set to DMR, start mode timer and start DMR idle frames
@ -261,6 +271,16 @@ void Host::writeFramesDMR2(dmr::Control* control, std::function<void()>&& afterW
// to the modem
bool ret = m_modem->hasDMRSpace2();
if (ret) {
uint32_t nextLen = control->peekFrameLength(1U);
if (m_dmrCtrlChannel) {
if (m_dmrDedicatedTxTestTimer.hasExpired()) {
m_dmrDedicatedTxTestTimer.pause();
if (!m_modem->hasTX() && m_modem->gotModemStatus() && m_state == STATE_DMR && (control->getTSCCSlotNo() == 2U) && control->getCCRunning()) {
LogError(LOG_HOST, "DMR dedicated control not transmitting, running = %u, halted = %u, frameLength2 = %u", control->getCCRunning(), control->getCCHalted(), nextLen);
}
}
}
uint32_t len = control->getFrame(2U, data);
if (len > 0U) {
// if the state is idle; set to DMR, start mode timer and start DMR idle frames

@ -88,6 +88,16 @@ void Host::writeFramesNXDN(nxdn::Control* control, std::function<void()>&& after
if (control != nullptr) {
bool ret = m_modem->hasNXDNSpace();
if (ret) {
uint32_t nextLen = control->peekFrameLength();
if (m_nxdnCtrlChannel) {
if (m_nxdnDedicatedTxTestTimer.hasExpired()) {
m_nxdnDedicatedTxTestTimer.pause();
if (!m_modem->hasTX() && m_modem->gotModemStatus() && m_state == STATE_NXDN && control->getCCRunning()) {
LogError(LOG_HOST, "NXDN dedicated control stopped transmitting, running = %u, halted = %u, frameLength = %u", control->getCCRunning(), control->getCCHalted(), nextLen);
}
}
}
uint32_t len = control->getFrame(data);
if (len > 0U) {
// if the state is idle; set to NXDN and start mode timer

@ -124,13 +124,22 @@ void Host::readFramesP25(p25::Control* control, std::function<void()>&& afterRea
/// <param name="afterWriteCallback"></param>
void Host::writeFramesP25(p25::Control* control, std::function<void()>&& afterWriteCallback)
{
uint8_t data[p25::P25_LDU_FRAME_LENGTH_BYTES * 2U];
uint8_t data[p25::P25_PDU_FRAME_LENGTH_BYTES * 2U];
// 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 (control != nullptr) {
uint8_t nextLen = control->peekFrameLength();
if (m_p25CtrlChannel) {
if (m_p25DedicatedTxTestTimer.hasExpired()) {
m_p25DedicatedTxTestTimer.pause();
if (!m_modem->hasTX() && m_modem->gotModemStatus() && m_state == STATE_P25 && control->getCCRunning()) {
LogError(LOG_HOST, "P25 dedicated control not transmitting, running = %u, halted = %u, frameLength = %u", control->getCCRunning(), control->getCCHalted(), nextLen);
}
}
}
if (nextLen > 0U) {
bool ret = m_modem->hasP25Space(nextLen);
if (ret) {

@ -117,8 +117,11 @@ Host::Host(const std::string& confFile) :
m_authoritative(true),
m_supervisor(false),
m_dmrBeaconDurationTimer(1000U),
m_dmrDedicatedTxTestTimer(1000U, 0U, 125U),
m_p25BcastDurationTimer(1000U),
m_p25DedicatedTxTestTimer(1000U, 0U, 125U),
m_nxdnBcastDurationTimer(1000U),
m_nxdnDedicatedTxTestTimer(1000U, 0U, 125U),
m_activeTickDelay(5U),
m_idleTickDelay(5U),
m_restAddress("0.0.0.0"),
@ -1127,13 +1130,42 @@ int Host::run()
if (m_network != nullptr)
m_network->clock(ms);
if (dmr != nullptr)
if (dmr != nullptr) {
dmr->clock(ms);
if (p25 != nullptr)
if (m_dmrCtrlChannel) {
if (!m_dmrDedicatedTxTestTimer.isRunning()) {
m_dmrDedicatedTxTestTimer.start();
} else {
m_dmrDedicatedTxTestTimer.clock(ms);
}
}
}
if (p25 != nullptr) {
p25->clock(ms);
if (nxdn != nullptr)
if (m_p25CtrlChannel) {
if (!m_p25DedicatedTxTestTimer.isRunning()) {
m_p25DedicatedTxTestTimer.start();
} else {
m_p25DedicatedTxTestTimer.clock(ms);
}
}
}
if (nxdn != nullptr) {
nxdn->clock(ms);
if (m_nxdnCtrlChannel) {
if (!m_nxdnDedicatedTxTestTimer.isRunning()) {
m_nxdnDedicatedTxTestTimer.start();
} else {
m_nxdnDedicatedTxTestTimer.clock(ms);
}
}
}
// ------------------------------------------------------
// -- Timer Clocking --
// ------------------------------------------------------

@ -143,8 +143,11 @@ private:
bool m_supervisor;
Timer m_dmrBeaconDurationTimer;
Timer m_dmrDedicatedTxTestTimer;
Timer m_p25BcastDurationTimer;
Timer m_p25DedicatedTxTestTimer;
Timer m_nxdnBcastDurationTimer;
Timer m_nxdnDedicatedTxTestTimer;
uint8_t m_activeTickDelay;
uint8_t m_idleTickDelay;

@ -331,9 +331,28 @@ bool Control::processFrame(uint32_t slotNo, uint8_t *data, uint32_t len)
}
}
/// <summary>
/// Get the frame data length for the next frame in the data ring buffer.
/// </summary>
/// <param name="slotNo"></param>
/// <returns>Length of frame data retrieved.</returns>
uint32_t Control::peekFrameLength(uint32_t slotNo)
{
switch (slotNo) {
case 1U:
return m_slot1->peekFrameLength();
case 2U:
return m_slot2->peekFrameLength();
default:
LogError(LOG_DMR, "DMR, invalid slot, slotNo = %u", slotNo);
return 0U;
}
}
/// <summary>
/// Get a data frame for slot, from data ring buffer.
/// </summary>
/// <param name="slotNo"></param>
/// <param name="data">Buffer to put retrieved DMR data frame data.</param>
/// <returns>Length of data retrieved from DMR ring buffer.</returns>
uint32_t Control::getFrame(uint32_t slotNo, uint8_t* data)

@ -69,6 +69,8 @@ namespace dmr
/// <summary>Process a data frame for slot, from the RF interface.</summary>
bool processFrame(uint32_t slotNo, uint8_t* data, uint32_t len);
/// <summary>Get the frame data length for the next frame in the data ring buffer.</summary>
uint32_t peekFrameLength(uint32_t slotNo);
/// <summary>Get a data frame for slot, from data ring buffer.</summary>
uint32_t getFrame(uint32_t slotNo, uint8_t* data);
@ -91,6 +93,8 @@ namespace dmr
/// <summary>Helper to return the slot carrying the TSCC.</summary>
Slot* getTSCCSlot() const;
/// <summary>Helper to return the slot number carrying the TSCC.</summary>
uint8_t getTSCCSlotNo() const { return m_tsccSlotNo; }
/// <summary>Helper to payload activate the slot carrying granted payload traffic.</summary>
void tsccActivateSlot(uint32_t slotNo, uint32_t dstId, uint32_t srcId, bool group, bool voice);
/// <summary>Helper to clear an activated payload slot.</summary>

@ -327,6 +327,28 @@ bool Slot::processFrame(uint8_t *data, uint32_t len)
return m_voice->process(data, len);
}
/// <summary>
/// Get the frame data length for the next frame in the data ring buffer.
/// </summary>
/// <returns>Length of frame data retrieved.</returns>
uint32_t Slot::peekFrameLength()
{
if (m_txQueue.isEmpty() && m_txImmQueue.isEmpty())
return 0U;
uint8_t len = 0U;
// tx immediate queue takes priority
if (!m_txImmQueue.isEmpty()) {
m_txImmQueue.peek(&len, 1U);
}
else {
m_txQueue.peek(&len, 1U);
}
return len;
}
/// <summary>
/// Get frame data from data ring buffer.
/// </summary>

@ -85,6 +85,8 @@ namespace dmr
/// <summary>Process a data frame from the RF interface.</summary>
bool processFrame(uint8_t* data, uint32_t len);
/// <summary>Get the frame data length for the next frame in the data ring buffer.</summary>
uint32_t peekFrameLength();
/// <summary>Get data frame from data ring buffer.</summary>
uint32_t getFrame(uint8_t* data);

@ -174,6 +174,7 @@ Modem::Modem(port::IModemPort* port, bool duplex, bool rxInvert, bool txInvert,
m_error(false),
m_ignoreModemConfigArea(ignoreModemConfigArea),
m_flashDisabled(false),
m_gotModemStatus(false),
m_dumpModemStatus(dumpModemStatus),
m_trace(trace),
m_debug(debug)
@ -524,6 +525,7 @@ void Modem::setCloseHandler(std::function<MODEM_OC_PORT_HANDLER> handler)
bool Modem::open()
{
LogMessage(LOG_MODEM, "Initializing modem");
m_gotModemStatus = false;
bool ret = m_port->open();
if (!ret)
@ -905,6 +907,7 @@ void Modem::clock(uint32_t ms)
m_rxP25Queue.length(), m_rxP25Queue.dataSize(), m_rxP25Queue.freeSpace(), m_rxNXDNQueue.length(), m_rxNXDNQueue.dataSize(), m_rxNXDNQueue.freeSpace());
}
m_gotModemStatus = true;
m_inactivityTimer.start();
}
break;
@ -972,6 +975,8 @@ void Modem::close()
LogDebug(LOG_MODEM, "Closing the modem");
m_port->close();
m_gotModemStatus = false;
// do we have a close port handler?
if (m_closePortHandler != nullptr) {
m_closePortHandler(this);
@ -1167,6 +1172,15 @@ bool Modem::hasError() const
return m_error;
}
/// <summary>
/// Flag indicating whether or not the air interface modem has sent the initial modem status.
/// </summary>
/// <returns>True, if the air interface modem has sent the initial status, otherwise false.</returns>
bool Modem::gotModemStatus() const
{
return m_gotModemStatus;
}
/// <summary>
/// Clears any buffered DMR Slot 1 frame data to be sent to the air interface modem.
/// </summary>
@ -1467,7 +1481,10 @@ bool Modem::writeP25Frame(const uint8_t* data, uint32_t length)
assert(length > 0U);
if (m_p25Enabled) {
const uint16_t MAX_LENGTH = 520U;
uint16_t MAX_LENGTH = 520U;
if (m_protoVer <= 3U) {
MAX_LENGTH = 251U; // for older firmware always ensure frames are shorter then 252 bytes
}
if (data[0U] != TAG_DATA && data[0U] != TAG_EOT)
return false;

@ -311,6 +311,9 @@ namespace modem
/// <summary>Flag indicating whether or not the air interface modem is currently in an error condition.</summary>
bool hasError() const;
/// <summary>Flag indicating whether or not the air interface modem has sent the initial modem status.</summary>
bool gotModemStatus() const;
/// <summary>Clears any buffered DMR Slot 1 frame data to be sent to the air interface modem.</summary>
void clearDMRFrame1();
/// <summary>Clears any buffered DMR Slot 2 frame data to be sent to the air interface modem.</summary>
@ -489,6 +492,8 @@ namespace modem
bool m_ignoreModemConfigArea;
bool m_flashDisabled;
bool m_gotModemStatus;
bool m_dumpModemStatus;
/// <summary>Internal helper to warm reset the connection to the modem.</summary>

@ -480,6 +480,28 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
return ret;
}
/// <summary>
/// Get the frame data length for the next frame in the data ring buffer.
/// </summary>
/// <returns>Length of frame data retrieved.</returns>
uint32_t Control::peekFrameLength()
{
if (m_txQueue.isEmpty() && m_txImmQueue.isEmpty())
return 0U;
uint8_t len = 0U;
// tx immediate queue takes priority
if (!m_txImmQueue.isEmpty()) {
m_txImmQueue.peek(&len, 1U);
}
else {
m_txQueue.peek(&len, 1U);
}
return len;
}
/// <summary>
/// Get frame data from data ring buffer.
/// </summary>

@ -80,6 +80,8 @@ namespace nxdn
/// <summary>Process a data frame from the RF interface.</summary>
bool processFrame(uint8_t* data, uint32_t len);
/// <summary>Get the frame data length for the next frame in the data ring buffer.</summary>
uint32_t peekFrameLength();
/// <summary>Get frame data from data ring buffer.</summary>
uint32_t getFrame(uint8_t* data);

Loading…
Cancel
Save

Powered by TurnKey Linux.