mirror of
https://github.com/g4klx/MMDVMHost
synced 2025-12-21 06:55:52 +08:00
Restructure POCSAG code to allow for two input data streams.
This commit is contained in:
@@ -67,7 +67,7 @@ m_count(0U),
|
|||||||
m_output(),
|
m_output(),
|
||||||
m_buffer(),
|
m_buffer(),
|
||||||
m_ric(0U),
|
m_ric(0U),
|
||||||
m_text(),
|
m_data(),
|
||||||
m_state(PS_NONE),
|
m_state(PS_NONE),
|
||||||
m_enabled(true),
|
m_enabled(true),
|
||||||
m_fp(NULL)
|
m_fp(NULL)
|
||||||
@@ -79,6 +79,10 @@ CPOCSAGControl::~CPOCSAGControl()
|
|||||||
{
|
{
|
||||||
m_output.clear();
|
m_output.clear();
|
||||||
m_buffer.clear();
|
m_buffer.clear();
|
||||||
|
|
||||||
|
for (std::deque<POCSAGData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
|
||||||
|
delete it;
|
||||||
|
m_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CPOCSAGControl::readModem(unsigned char* data)
|
unsigned int CPOCSAGControl::readModem(unsigned char* data)
|
||||||
@@ -101,72 +105,94 @@ void CPOCSAGControl::sendPage(unsigned int ric, const std::string& text)
|
|||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_ric = ric;
|
POCSAGData* output = new POCSAGData;
|
||||||
m_text = text;
|
|
||||||
|
|
||||||
m_buffer.clear();
|
output->m_ric = ric;
|
||||||
|
output->m_text = text;
|
||||||
|
|
||||||
addAddress(FUNCTIONAL_ALPHANUMERIC);
|
addAddress(FUNCTIONAL_ALPHANUMERIC, ric, output->m_buffer);
|
||||||
|
|
||||||
LogDebug("Local message to %07u, func Alphanumeric: \"%s\"", m_ric, m_text.c_str());
|
LogDebug("Local message to %07u, func Alphanumeric: \"%s\"", ric, text.c_str());
|
||||||
|
|
||||||
packASCII();
|
packASCII(text, output->m_buffer);
|
||||||
|
|
||||||
// Ensure data is an even number of words
|
// Ensure data is an even number of words
|
||||||
if ((m_buffer.size() % 2U) == 1U)
|
if ((output->m_buffer.size() % 2U) == 1U)
|
||||||
m_buffer.push_back(POCSAG_IDLE_WORD);
|
output->m_buffer.push_back(POCSAG_IDLE_WORD);
|
||||||
|
|
||||||
|
m_data.push_back(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPOCSAGControl::processData()
|
bool CPOCSAGControl::readNetwork()
|
||||||
{
|
{
|
||||||
if (m_network == NULL)
|
if (m_network == NULL)
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
unsigned char data[300U];
|
unsigned char data[300U];
|
||||||
unsigned int length = m_network->read(data);
|
unsigned int length = m_network->read(data);
|
||||||
if (length == 0U)
|
if (length == 0U)
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_ric = 0U;
|
POCSAGData* output = new POCSAGData;
|
||||||
m_ric |= (data[0U] << 16) & 0x00FF0000U;
|
|
||||||
m_ric |= (data[1U] << 8) & 0x0000FF00U;
|
output->m_ric = 0U;
|
||||||
m_ric |= (data[2U] << 0) & 0x000000FFU;
|
output->m_ric |= (data[0U] << 16) & 0x00FF0000U;
|
||||||
|
output->m_ric |= (data[1U] << 8) & 0x0000FF00U;
|
||||||
|
output->m_ric |= (data[2U] << 0) & 0x000000FFU;
|
||||||
|
|
||||||
unsigned char functional = data[3U];
|
unsigned char functional = data[3U];
|
||||||
|
|
||||||
m_buffer.clear();
|
addAddress(functional, output->m_ric, output->m_buffer);
|
||||||
addAddress(functional);
|
|
||||||
|
|
||||||
switch (functional) {
|
switch (functional) {
|
||||||
case FUNCTIONAL_ALPHANUMERIC:
|
case FUNCTIONAL_ALPHANUMERIC:
|
||||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
output->m_text = std::string((char*)(data + 4U), length - 4U);
|
||||||
LogDebug("Message to %07u, func Alphanumeric: \"%s\"", m_ric, m_text.c_str());
|
LogDebug("Message to %07u, func Alphanumeric: \"%s\"", output->m_ric, output->m_text.c_str());
|
||||||
packASCII();
|
packASCII(output->m_text, output->m_buffer);
|
||||||
break;
|
break;
|
||||||
case FUNCTIONAL_NUMERIC:
|
case FUNCTIONAL_NUMERIC:
|
||||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
output->m_text = std::string((char*)(data + 4U), length - 4U);
|
||||||
LogDebug("Message to %07u, func Numeric: \"%s\"", m_ric, m_text.c_str());
|
LogDebug("Message to %07u, func Numeric: \"%s\"", output->m_ric, output->m_text.c_str());
|
||||||
packNumeric();
|
packNumeric(output->m_text, output->m_buffer);
|
||||||
break;
|
break;
|
||||||
case FUNCTIONAL_ALERT1:
|
case FUNCTIONAL_ALERT1:
|
||||||
m_text.clear();
|
LogDebug("Message to %07u, func Alert 1", output->m_ric);
|
||||||
LogDebug("Message to %07u, func Alert 1", m_ric);
|
|
||||||
break;
|
break;
|
||||||
case FUNCTIONAL_ALERT2:
|
case FUNCTIONAL_ALERT2:
|
||||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
output->m_text = std::string((char*)(data + 4U), length - 4U);
|
||||||
LogDebug("Message to %07u, func Alert 2: \"%s\"", m_ric, m_text.c_str());
|
LogDebug("Message to %07u, func Alert 2: \"%s\"", output->m_ric, output->m_text.c_str());
|
||||||
packASCII();
|
packASCII(output->m_text, output->m_buffer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure data is an even number of words
|
// Ensure data is an even number of words
|
||||||
if ((m_buffer.size() % 2U) == 1U)
|
if ((output->m_buffer.size() % 2U) == 1U)
|
||||||
m_buffer.push_back(POCSAG_IDLE_WORD);
|
output->m_buffer.push_back(POCSAG_IDLE_WORD);
|
||||||
|
|
||||||
|
m_data.push_back(output);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPOCSAGControl::processData()
|
||||||
|
{
|
||||||
|
if (m_data.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
POCSAGData* output = m_data.front();
|
||||||
|
m_data.pop_front();
|
||||||
|
|
||||||
|
m_display->writePOCSAG(output->m_ric, output->m_text);
|
||||||
|
|
||||||
|
m_buffer = output->m_buffer;
|
||||||
|
m_ric = output->m_ric;
|
||||||
|
|
||||||
|
delete output;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -174,11 +200,14 @@ bool CPOCSAGControl::processData()
|
|||||||
void CPOCSAGControl::clock(unsigned int ms)
|
void CPOCSAGControl::clock(unsigned int ms)
|
||||||
{
|
{
|
||||||
if (m_state == PS_NONE) {
|
if (m_state == PS_NONE) {
|
||||||
bool ret = processData();
|
bool ret = readNetwork();
|
||||||
|
if (!ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ret = processData();
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_display->writePOCSAG(m_ric, m_text);
|
|
||||||
m_state = PS_WAITING;
|
m_state = PS_WAITING;
|
||||||
m_frames = 0U;
|
m_frames = 0U;
|
||||||
m_count = 1U;
|
m_count = 1U;
|
||||||
@@ -214,7 +243,6 @@ void CPOCSAGControl::clock(unsigned int ms)
|
|||||||
|
|
||||||
bool ret = processData();
|
bool ret = processData();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
m_display->writePOCSAG(m_ric, m_text);
|
|
||||||
m_state = PS_WAITING;
|
m_state = PS_WAITING;
|
||||||
m_count++;
|
m_count++;
|
||||||
} else {
|
} else {
|
||||||
@@ -249,7 +277,7 @@ void CPOCSAGControl::clock(unsigned int ms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPOCSAGControl::addAddress(unsigned char functional)
|
void CPOCSAGControl::addAddress(unsigned char functional, unsigned int ric, std::deque<uint32_t>& buffer) const
|
||||||
{
|
{
|
||||||
uint32_t word = 0x00000000U;
|
uint32_t word = 0x00000000U;
|
||||||
|
|
||||||
@@ -268,21 +296,21 @@ void CPOCSAGControl::addAddress(unsigned char functional)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
word |= (m_ric / POCSAG_FRAME_ADDRESSES) << 13;
|
word |= (ric / POCSAG_FRAME_ADDRESSES) << 13;
|
||||||
|
|
||||||
addBCHAndParity(word);
|
addBCHAndParity(word);
|
||||||
|
|
||||||
m_buffer.push_back(word);
|
buffer.push_back(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPOCSAGControl::packASCII()
|
void CPOCSAGControl::packASCII(const std::string& text, std::deque<uint32_t>& buffer) const
|
||||||
{
|
{
|
||||||
const unsigned char MASK = 0x01U;
|
const unsigned char MASK = 0x01U;
|
||||||
|
|
||||||
uint32_t word = 0x80000000U;
|
uint32_t word = 0x80000000U;
|
||||||
unsigned int n = 0U;
|
unsigned int n = 0U;
|
||||||
|
|
||||||
for (std::string::const_iterator it = m_text.cbegin(); it != m_text.cend(); ++it) {
|
for (std::string::const_iterator it = text.cbegin(); it != text.cend(); ++it) {
|
||||||
unsigned char c = *it;
|
unsigned char c = *it;
|
||||||
for (unsigned int j = 0U; j < 7U; j++, c >>= 1) {
|
for (unsigned int j = 0U; j < 7U; j++, c >>= 1) {
|
||||||
bool b = (c & MASK) == MASK;
|
bool b = (c & MASK) == MASK;
|
||||||
@@ -292,7 +320,7 @@ void CPOCSAGControl::packASCII()
|
|||||||
|
|
||||||
if (n == 20U) {
|
if (n == 20U) {
|
||||||
addBCHAndParity(word);
|
addBCHAndParity(word);
|
||||||
m_buffer.push_back(word);
|
buffer.push_back(word);
|
||||||
word = 0x80000000U;
|
word = 0x80000000U;
|
||||||
n = 0U;
|
n = 0U;
|
||||||
}
|
}
|
||||||
@@ -301,16 +329,16 @@ void CPOCSAGControl::packASCII()
|
|||||||
|
|
||||||
if (n > 0U) {
|
if (n > 0U) {
|
||||||
addBCHAndParity(word);
|
addBCHAndParity(word);
|
||||||
m_buffer.push_back(word);
|
buffer.push_back(word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPOCSAGControl::packNumeric()
|
void CPOCSAGControl::packNumeric(const std::string& text, std::deque<uint32_t>& buffer) const
|
||||||
{
|
{
|
||||||
uint32_t word = 0x80000000U;
|
uint32_t word = 0x80000000U;
|
||||||
unsigned int n = 0U;
|
unsigned int n = 0U;
|
||||||
|
|
||||||
for (std::string::const_iterator it = m_text.cbegin(); it != m_text.cend(); ++it) {
|
for (std::string::const_iterator it = text.cbegin(); it != text.cend(); ++it) {
|
||||||
char c = *it;
|
char c = *it;
|
||||||
|
|
||||||
const BCD* bcd = NULL;
|
const BCD* bcd = NULL;
|
||||||
@@ -326,8 +354,8 @@ void CPOCSAGControl::packNumeric()
|
|||||||
n++;
|
n++;
|
||||||
|
|
||||||
if (n == 5U) {
|
if (n == 5U) {
|
||||||
addBCHAndParity(word);
|
addBCHAndParity(word);
|
||||||
m_buffer.push_back(word);
|
buffer.push_back(word);
|
||||||
word = 0x80000000U;
|
word = 0x80000000U;
|
||||||
n = 0U;
|
n = 0U;
|
||||||
}
|
}
|
||||||
@@ -339,7 +367,7 @@ void CPOCSAGControl::packNumeric()
|
|||||||
word |= BCD_SPACES[n];
|
word |= BCD_SPACES[n];
|
||||||
|
|
||||||
addBCHAndParity(word);
|
addBCHAndParity(word);
|
||||||
m_buffer.push_back(word);
|
buffer.push_back(word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +439,7 @@ bool CPOCSAGControl::openFile()
|
|||||||
struct tm* tm = ::localtime(&t);
|
struct tm* tm = ::localtime(&t);
|
||||||
|
|
||||||
char name[100U];
|
char name[100U];
|
||||||
::sprintf(name, "POCSAG_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
::sprintf(name, "POCSAG_%04d%02d%02d_%02d%02d%02d.dat", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
|
|
||||||
m_fp = ::fopen(name, "wb");
|
m_fp = ::fopen(name, "wb");
|
||||||
if (m_fp == NULL)
|
if (m_fp == NULL)
|
||||||
@@ -446,6 +474,10 @@ void CPOCSAGControl::enable(bool enabled)
|
|||||||
m_queue.clear();
|
m_queue.clear();
|
||||||
m_output.clear();
|
m_output.clear();
|
||||||
|
|
||||||
|
for (std::deque<POCSAGData*>::iterator it = m_data.begin(); it != m_data.end(); ++it)
|
||||||
|
delete it;
|
||||||
|
m_data.clear();
|
||||||
|
|
||||||
m_state = PS_NONE;
|
m_state = PS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,12 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
struct POCSAGData {
|
||||||
|
unsigned int m_ric;
|
||||||
|
std::string m_text;
|
||||||
|
std::deque<uint32_t> m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
class CPOCSAGControl {
|
class CPOCSAGControl {
|
||||||
public:
|
public:
|
||||||
CPOCSAGControl(CPOCSAGNetwork* network, CDisplay* display);
|
CPOCSAGControl(CPOCSAGNetwork* network, CDisplay* display);
|
||||||
@@ -59,17 +65,18 @@ private:
|
|||||||
|
|
||||||
std::deque<uint32_t> m_output;
|
std::deque<uint32_t> m_output;
|
||||||
std::deque<uint32_t> m_buffer;
|
std::deque<uint32_t> m_buffer;
|
||||||
uint32_t m_ric;
|
unsigned int m_ric;
|
||||||
std::string m_text;
|
std::deque<POCSAGData*> m_data;
|
||||||
POCSAG_STATE m_state;
|
POCSAG_STATE m_state;
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
FILE* m_fp;
|
FILE* m_fp;
|
||||||
|
|
||||||
bool processData();
|
bool readNetwork();
|
||||||
void writeQueue();
|
void writeQueue();
|
||||||
void addAddress(unsigned char functional);
|
bool processData();
|
||||||
void packASCII();
|
void addAddress(unsigned char functional, unsigned int ric, std::deque<uint32_t>& buffer) const;
|
||||||
void packNumeric();
|
void packASCII(const std::string& text, std::deque<uint32_t>& buffer) const;
|
||||||
|
void packNumeric(const std::string& text, std::deque<uint32_t>& buffer) const;
|
||||||
void addBCHAndParity(uint32_t& word) const;
|
void addBCHAndParity(uint32_t& word) const;
|
||||||
bool openFile();
|
bool openFile();
|
||||||
bool writeFile(const unsigned char* data);
|
bool writeFile(const unsigned char* data);
|
||||||
|
|||||||
Reference in New Issue
Block a user