mirror of
https://github.com/g4klx/DAPNETGateway.git
synced 2026-08-26 12:32:45 -04:00
Hopefully fix queue stalls.
This commit is contained in:
parent
7b9f7ce2c1
commit
7b50c495bc
4 changed files with 55 additions and 30 deletions
|
|
@ -66,6 +66,8 @@ const unsigned int BATCHES_PER_SLOT = SLOT_TIME_US / BATCH_TIME_US; // 14
|
|||
const unsigned char FUNCTIONAL_NUMERIC = 0U;
|
||||
const unsigned char FUNCTIONAL_ALPHANUMERIC = 3U;
|
||||
|
||||
const unsigned int MAX_TIME_TO_HOLD_TIME_MESSAGES = 2000U; // 2s
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* iniFile = DEFAULT_INI_FILE;
|
||||
|
|
@ -100,6 +102,7 @@ m_pocsagNetwork(NULL),
|
|||
m_queue(),
|
||||
m_slotTimer(),
|
||||
m_schedule(NULL),
|
||||
m_allSlots(false),
|
||||
m_currentSlot(0U),
|
||||
m_sentCodewords(0U),
|
||||
m_mmdvmFree(false)
|
||||
|
|
@ -248,12 +251,14 @@ int CDAPNETGateway::run()
|
|||
case 0x00U:
|
||||
// The MMDVM is idle
|
||||
if (!m_mmdvmFree) {
|
||||
// LogDebug("*** MMDVM is free");
|
||||
m_mmdvmFree = true;
|
||||
m_sentCodewords = (m_slotTimer.elapsed() * 1000U) / CODEWORD_TIME_US;
|
||||
}
|
||||
break;
|
||||
case 0xFFU:
|
||||
// The MMDVM is busy
|
||||
// LogDebug("*** MMDVM is busy");
|
||||
m_mmdvmFree = false;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -276,6 +281,7 @@ int CDAPNETGateway::run()
|
|||
unsigned int t = (m_slotTimer.time() / 100ULL) % 1024ULL;
|
||||
unsigned int slot = t / 64U;
|
||||
if (slot != m_currentSlot) {
|
||||
// LogDebug("Start of slot %u", slot);
|
||||
m_currentSlot = slot;
|
||||
if (m_schedule == NULL || m_currentSlot == 0U)
|
||||
loadSchedule();
|
||||
|
|
@ -302,22 +308,16 @@ int CDAPNETGateway::run()
|
|||
void CDAPNETGateway::sendMessages()
|
||||
{
|
||||
// If the MMDVM is busy, we can't send anything.
|
||||
if (!m_mmdvmFree) {
|
||||
removeTimeMessages();
|
||||
if (!m_mmdvmFree)
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we have a schedule?
|
||||
if (m_schedule == NULL) {
|
||||
removeTimeMessages();
|
||||
if (m_schedule == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to see if we're allowed to send within a slot.
|
||||
if (!m_schedule[m_currentSlot]) {
|
||||
removeTimeMessages();
|
||||
if (!m_schedule[m_currentSlot])
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have data to send, see if we have time to do so in the current schedule.
|
||||
if (m_queue.empty())
|
||||
|
|
@ -326,24 +326,36 @@ void CDAPNETGateway::sendMessages()
|
|||
CPOCSAGMessage* message = m_queue.back();
|
||||
assert(message != NULL);
|
||||
|
||||
// Special case, only test if slots are being used.
|
||||
if (m_allSlots) {
|
||||
sendMessage(message);
|
||||
m_queue.pop_back();
|
||||
delete message;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int codewords = calculateCodewords(message);
|
||||
|
||||
// Do we have too much data already sent in this slot?
|
||||
unsigned int totalCodewords = m_sentCodewords + PREAMBLE_LENGTH_CODEWORDS + codewords;
|
||||
if (totalCodewords >= CODEWORDS_PER_SLOT)
|
||||
if (totalCodewords >= CODEWORDS_PER_SLOT) {
|
||||
// LogDebug("Too many codewords sent in slot %u already %u + %u + %u = %u >= %u", m_currentSlot, m_sentCodewords, PREAMBLE_LENGTH_CODEWORDS, codewords, totalCodewords, CODEWORDS_PER_SLOT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is there enough time to send it in this slot before it ends?
|
||||
unsigned int sendTime = (PREAMBLE_TIME_US + codewords * CODEWORD_TIME_US) / 1000U;
|
||||
unsigned int timeLeft = SLOT_TIME_MS - m_slotTimer.elapsed();
|
||||
if (sendTime >= timeLeft)
|
||||
if (sendTime >= timeLeft) {
|
||||
// LogDebug("Too little time to send the message in slot %u, %u + %u + %u = %u >= %u = %u - %u", m_currentSlot, PREAMBLE_TIME_US, codewords, CODEWORD_TIME_US, sendTime, timeLeft, SLOT_TIME_MS, m_slotTimer.elapsed());
|
||||
return;
|
||||
}
|
||||
|
||||
m_sentCodewords = totalCodewords;
|
||||
LogMessage("Sending message in slot %u to %07u, type %u, func %s: \"%.*s\"", m_currentSlot, message->m_ric, message->m_type, message->m_functional == FUNCTIONAL_NUMERIC ? "Numeric" : "Alphanumeric", message->m_length, message->m_message);
|
||||
bool ret = sendMessage(message);
|
||||
if (ret)
|
||||
m_sentCodewords = totalCodewords;
|
||||
|
||||
m_queue.pop_back();
|
||||
m_pocsagNetwork->write(message);
|
||||
delete message;
|
||||
}
|
||||
|
||||
|
|
@ -381,15 +393,14 @@ unsigned int CDAPNETGateway::calculateCodewords(const CPOCSAGMessage* message) c
|
|||
if (message->m_functional == FUNCTIONAL_NUMERIC)
|
||||
len = message->m_length / 5U; // For the number packing, five to a word
|
||||
else
|
||||
len = (message->m_length * 20U) / 7U; // For the ASCII packing, 20/7 to a word
|
||||
len = (message->m_length * 7U) / 20U; // For the ASCII packing, 7/20 to a word
|
||||
|
||||
len++; // For the address word
|
||||
|
||||
if ((len % 2U) == 1U) // Always an even number of words
|
||||
len++;
|
||||
|
||||
if (len > 16U) // A very long message will include a sync word
|
||||
len++;
|
||||
len += len % 16U; // A very long message will include sync words
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
@ -403,28 +414,35 @@ void CDAPNETGateway::loadSchedule()
|
|||
delete[] m_schedule;
|
||||
m_schedule = schedule;
|
||||
|
||||
m_allSlots = true;
|
||||
|
||||
std::string text;
|
||||
for (unsigned int i = 0U; i < 16U; i++) {
|
||||
if (m_schedule[i])
|
||||
if (m_schedule[i]) {
|
||||
text += "*";
|
||||
else
|
||||
} else {
|
||||
text += "-";
|
||||
m_allSlots = false;
|
||||
}
|
||||
}
|
||||
|
||||
LogMessage("Loaded new schedule: %s", text.c_str());
|
||||
if (m_allSlots)
|
||||
LogMessage("All slots are available for transmission");
|
||||
else
|
||||
LogMessage("Loaded new schedule: %s", text.c_str());
|
||||
}
|
||||
|
||||
void CDAPNETGateway::removeTimeMessages()
|
||||
bool CDAPNETGateway::sendMessage(CPOCSAGMessage* message) const
|
||||
{
|
||||
if (m_queue.empty())
|
||||
return;
|
||||
|
||||
CPOCSAGMessage* message = m_queue.back();
|
||||
assert(message != NULL);
|
||||
|
||||
if (isTimeMessage(message)) {
|
||||
bool ret = isTimeMessage(message);
|
||||
if (ret && message->m_timeQueued.elapsed() >= MAX_TIME_TO_HOLD_TIME_MESSAGES) {
|
||||
LogDebug("Rejecting message to %07u, type %u, func %s: \"%.*s\"", message->m_ric, message->m_type, message->m_functional == FUNCTIONAL_NUMERIC ? "Numeric" : "Alphanumeric", message->m_length, message->m_message);
|
||||
m_queue.pop_back();
|
||||
delete message;
|
||||
return false;
|
||||
} else {
|
||||
LogMessage("Sending message in slot %u to %07u, type %u, func %s: \"%.*s\"", m_currentSlot, message->m_ric, message->m_type, message->m_functional == FUNCTIONAL_NUMERIC ? "Numeric" : "Alphanumeric", message->m_length, message->m_message);
|
||||
m_pocsagNetwork->write(message);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ private:
|
|||
std::deque<CPOCSAGMessage*> m_queue;
|
||||
CStopWatch m_slotTimer;
|
||||
bool* m_schedule;
|
||||
bool m_allSlots;
|
||||
unsigned int m_currentSlot;
|
||||
unsigned int m_sentCodewords;
|
||||
bool m_mmdvmFree;
|
||||
|
|
@ -54,7 +55,7 @@ private:
|
|||
bool isTimeMessage(const CPOCSAGMessage* message) const;
|
||||
unsigned int calculateCodewords(const CPOCSAGMessage* message) const;
|
||||
void loadSchedule();
|
||||
void removeTimeMessages();
|
||||
bool sendMessage(CPOCSAGMessage* message) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ m_type(type),
|
|||
m_ric(ric),
|
||||
m_functional(functional),
|
||||
m_message(NULL),
|
||||
m_length(length)
|
||||
m_length(length),
|
||||
m_timeQueued()
|
||||
{
|
||||
assert(ric > 0U);
|
||||
assert(functional < 4U);
|
||||
|
|
@ -36,6 +37,8 @@ m_length(length)
|
|||
|
||||
m_message = new unsigned char[length];
|
||||
::memcpy(m_message, message, length);
|
||||
|
||||
m_timeQueued.start();
|
||||
}
|
||||
|
||||
CPOCSAGMessage::~CPOCSAGMessage()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef POCSAGMessage_H
|
||||
#define POCSAGMessage_H
|
||||
|
||||
#include "StopWatch.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -32,6 +34,7 @@ public:
|
|||
unsigned char m_functional;
|
||||
unsigned char* m_message;
|
||||
unsigned int m_length;
|
||||
CStopWatch m_timeQueued;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue