added numeric paging
This commit is contained in:
parent
fde63704eb
commit
4f4bc0129a
8 changed files with 179 additions and 6 deletions
|
@ -42,6 +42,9 @@
|
|||
<label for="text">Text</label>
|
||||
<input type="text" id="text" name="text" placeholder="Enter text..." />
|
||||
|
||||
<label for="numeric">Numeric 4-bit BCD</label>
|
||||
<input type="checkbox" name="numeric"/>
|
||||
|
||||
<div class="button-group">
|
||||
<button type="submit" name="add">Queue</button>
|
||||
<button type="submit" name="addtx">Direct Transmit</button>
|
||||
|
|
|
@ -68,6 +68,7 @@ void txControllerBatchStart();
|
|||
int txControllerBatchQueueCount();
|
||||
String txHandleUmlauts(String message);
|
||||
void txControllerInsert(uint32_t ric, uint8_t functionBit, char *text);
|
||||
void txControllerInsert(uint32_t ric, uint8_t functionBit, bool numeric, char *text);
|
||||
void setup_radio();
|
||||
void setup_network();
|
||||
void setup_mqtt();
|
||||
|
|
|
@ -20,10 +20,16 @@
|
|||
#define CRC_BITS 10
|
||||
#define CRC_GENERATOR 0b11101101001
|
||||
|
||||
#define NUMERIC_BITS_PER_WORD 20
|
||||
#define NUMERIC_BITS_PER_DIGIT 4
|
||||
|
||||
uint32_t crc(uint32_t inputMsg);
|
||||
uint32_t parity(uint32_t x);
|
||||
uint32_t encodeCodeword(uint32_t msg);
|
||||
uint32_t encodeASCII(uint32_t initial_offset, char *str, uint32_t *out);
|
||||
char encodeDigit(char ch);
|
||||
uint32_t encodeNumeric(uint32_t initial_offset, char *str, uint32_t *out);
|
||||
int addressOffset(int address);
|
||||
void encodeTransmission(int repeatIndex, int address, int fb, char *message, uint32_t *out);
|
||||
size_t textMessageLength(int repeatIndex, int address, int numChars);
|
||||
void encodeTransmission(int repeatIndex, int address, int fb, bool numeric, char *message, uint32_t *out);
|
||||
size_t textMessageLength(int repeatIndex, int address, int numChars);
|
||||
size_t numericMessageLength(int repeatIndex, int address, int numChars);
|
|
@ -53,6 +53,7 @@ public:
|
|||
int8_t getQueueCount();
|
||||
bool isActive();
|
||||
void queuePage(uint32_t ric, uint8_t functionBit, char *text);
|
||||
void queuePage(uint32_t ric, uint8_t functionBit, bool numeric, char *text);
|
||||
bool transmitBatch();
|
||||
void test();
|
||||
|
||||
|
|
|
@ -341,6 +341,10 @@ void txControllerInsert(uint32_t ric, uint8_t functionBit, char *text)
|
|||
{
|
||||
transmitter.queuePage(ric, functionBit, text);
|
||||
}
|
||||
void txControllerInsert(uint32_t ric, uint8_t functionBit, bool numeric, char *text)
|
||||
{
|
||||
transmitter.queuePage(ric, functionBit, numeric, text);
|
||||
}
|
||||
void txControllerBatchStart()
|
||||
{
|
||||
transmitter.transmitBatch();
|
||||
|
|
|
@ -142,6 +142,115 @@ uint32_t encodeASCII(uint32_t initial_offset, char *str, uint32_t *out)
|
|||
return numWordsWritten;
|
||||
}
|
||||
|
||||
// Char Translationtable
|
||||
char *mirrorTab = new char[10]{0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09};
|
||||
char encodeDigit(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return mirrorTab[ch - '0'];
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
return 0x03;
|
||||
|
||||
case 'u':
|
||||
case 'U':
|
||||
return 0x0d;
|
||||
|
||||
case '-':
|
||||
case '_':
|
||||
return 0x0b;
|
||||
|
||||
case '(':
|
||||
case '[':
|
||||
return 0x0f;
|
||||
|
||||
case ')':
|
||||
case ']':
|
||||
return 0x07;
|
||||
}
|
||||
|
||||
return 0x05;
|
||||
}
|
||||
|
||||
uint32_t encodeNumeric(uint32_t initial_offset, char *str, uint32_t *out)
|
||||
{
|
||||
//Number of words written to *out
|
||||
uint32_t numWordsWritten = 0;
|
||||
|
||||
//Data for the current word we're writing
|
||||
uint32_t currentWord = 0;
|
||||
|
||||
//Nnumber of bits we've written so far to the current word
|
||||
uint32_t currentNumBits = 0;
|
||||
|
||||
//Position of current word in the current batch
|
||||
uint32_t wordPosition = initial_offset;
|
||||
|
||||
while (*str != 0)
|
||||
{
|
||||
unsigned char c = *str;
|
||||
str++;
|
||||
//Encode the digit bits backwards
|
||||
for (int i = 0; i < NUMERIC_BITS_PER_DIGIT; i++)
|
||||
{
|
||||
currentWord <<= 1;
|
||||
char digit = encodeDigit(c);
|
||||
digit = ((digit & 1) << 3) |
|
||||
((digit & 2) << 1) |
|
||||
((digit & 4) >> 1) |
|
||||
((digit & 8) >> 3);
|
||||
|
||||
currentWord |= (digit >> i) & 1;
|
||||
currentNumBits++;
|
||||
if (currentNumBits == NUMERIC_BITS_PER_WORD)
|
||||
{
|
||||
//Add the MESSAGE flag to our current word and encode it.
|
||||
*out = encodeCodeword(currentWord | POCSAG_FLAG_MESSAGE);
|
||||
out++;
|
||||
currentWord = 0;
|
||||
currentNumBits = 0;
|
||||
numWordsWritten++;
|
||||
|
||||
wordPosition++;
|
||||
if (wordPosition == POCSAG_BATCH_SIZE)
|
||||
{
|
||||
//We've filled a full batch, time to insert a SYNC word
|
||||
//and start a new one.
|
||||
*out = POCSAG_SYNC;
|
||||
out++;
|
||||
numWordsWritten++;
|
||||
wordPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Write remainder of message
|
||||
if (currentNumBits > 0)
|
||||
{
|
||||
//Pad out the word to 20 bits with zeroes
|
||||
currentWord <<= 20 - currentNumBits;
|
||||
*out = encodeCodeword(currentWord | POCSAG_FLAG_MESSAGE);
|
||||
out++;
|
||||
numWordsWritten++;
|
||||
|
||||
wordPosition++;
|
||||
if (wordPosition == POCSAG_BATCH_SIZE)
|
||||
{
|
||||
//We've filled a full batch, time to insert a SYNC word
|
||||
//and start a new one.
|
||||
*out = POCSAG_SYNC;
|
||||
out++;
|
||||
numWordsWritten++;
|
||||
wordPosition = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return numWordsWritten;
|
||||
}
|
||||
|
||||
/**
|
||||
* An address of 21 bits, but only 18 of those bits are encoded in the address
|
||||
* word itself. The remaining 3 bits are derived from which frame in the batch
|
||||
|
@ -159,7 +268,7 @@ int addressOffset(int address)
|
|||
* (*message) is a null terminated C string.
|
||||
* (*out) is the destination to which the transmission will be written.
|
||||
*/
|
||||
void encodeTransmission(int repeatIndex, int address, int fb, char *message, uint32_t *out)
|
||||
void encodeTransmission(int repeatIndex, int address, int fb, bool numeric, char *message, uint32_t *out)
|
||||
{
|
||||
// Encode preamble
|
||||
// Alternating 1,0,1,0 bits for 576 bits, used for receiver to synchronize
|
||||
|
@ -192,7 +301,11 @@ void encodeTransmission(int repeatIndex, int address, int fb, char *message, uin
|
|||
*out = encodeCodeword(((address >> 3) << 2) | fb);
|
||||
out++;
|
||||
|
||||
out += encodeASCII(addressOffset(address) + 1, message, out);
|
||||
if (numeric == true)
|
||||
out += encodeNumeric(addressOffset(address) + 1, message, out);
|
||||
else
|
||||
out += encodeASCII(addressOffset(address) + 1, message, out);
|
||||
// out += encodeASCII(addressOffset(address) + 1, message, out);
|
||||
|
||||
// Finally, write an IDLE word indicating the end of the message
|
||||
*out = POCSAG_IDLE;
|
||||
|
@ -244,3 +357,40 @@ size_t textMessageLength(int repeatIndex, int address, int numChars)
|
|||
|
||||
return numWords;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the length in words of a numeric POCSAG message, given the address
|
||||
* and the number of characters to be transmitted.
|
||||
*/
|
||||
size_t numericMessageLength(int repeatIndex, int address, int numChars)
|
||||
{
|
||||
size_t numWords = 0;
|
||||
|
||||
//Padding before address word.
|
||||
numWords += addressOffset(address);
|
||||
|
||||
//Address word itself
|
||||
numWords++;
|
||||
|
||||
//numChars * 7 bits per character / 20 bits per word, rounding up
|
||||
numWords += (numChars * NUMERIC_BITS_PER_DIGIT + (NUMERIC_BITS_PER_WORD - 1)) / NUMERIC_BITS_PER_WORD;
|
||||
|
||||
//Idle word representing end of message
|
||||
numWords++;
|
||||
|
||||
//Pad out last batch with idles
|
||||
numWords += POCSAG_BATCH_SIZE - (numWords % POCSAG_BATCH_SIZE);
|
||||
|
||||
//Batches consist of 16 words each and are preceded by a sync word.
|
||||
//So we add one word for every 16 message words
|
||||
numWords += numWords / POCSAG_BATCH_SIZE;
|
||||
|
||||
//Preamble of 576 alternating 1,0,1,0 bits before the message
|
||||
//Even though this comes first, we add it to the length last so it
|
||||
//doesn't affect the other word-based calculations
|
||||
if (repeatIndex == 0)
|
||||
numWords += POCSAG_PREAMBLE_LENGTH / 32;
|
||||
|
||||
return numWords;
|
||||
}
|
|
@ -63,12 +63,16 @@ uint32_t POCSAGTransmitter::getTransmitWord()
|
|||
return transmitterData[ transmitterOffset ];
|
||||
}
|
||||
void POCSAGTransmitter::queuePage(uint32_t ric, uint8_t functionBit, char *text)
|
||||
{
|
||||
this->queuePage(ric, functionBit, false, text);
|
||||
}
|
||||
void POCSAGTransmitter::queuePage(uint32_t ric, uint8_t functionBit, bool numeric, char *text)
|
||||
{
|
||||
size_t beforeLength = transmitterLength + 0;
|
||||
size_t messageLength = textMessageLength(queueCount, ric, strlen(text));
|
||||
// uint32_t *transmission = (uint32_t *)malloc(sizeof(uint32_t) * messageLength);
|
||||
uint32_t *encodingBufferPointer = encodingBuffer;
|
||||
encodeTransmission(queueCount, ric, functionBit, text, encodingBufferPointer);
|
||||
encodeTransmission(queueCount, ric, functionBit, numeric, text, encodingBufferPointer);
|
||||
transmitterLength += messageLength;
|
||||
|
||||
#ifdef POCSAG_DEBUG
|
||||
|
|
|
@ -69,6 +69,7 @@ static void redirectHomeResponse(AsyncWebServerRequest *request, String location
|
|||
uint32_t address = 0;
|
||||
int ric = -1;
|
||||
int fun = 0;
|
||||
bool numeric;
|
||||
String message;
|
||||
//
|
||||
if (request->hasArg("text")) {
|
||||
|
@ -82,13 +83,16 @@ static void redirectHomeResponse(AsyncWebServerRequest *request, String location
|
|||
if (request->hasArg("fun")) {
|
||||
fun = request->arg("fun").toInt();
|
||||
}
|
||||
if (request->hasArg("numeric")) {
|
||||
numeric = true;
|
||||
}
|
||||
Serial.printf("RIC: %d -> %d MSG: %s\n\n", ric, address, message);
|
||||
|
||||
if (ric > 0) {
|
||||
char *messageText = new char[message.length() + 1]{};
|
||||
message.toCharArray(messageText, message.length() + 1);
|
||||
// messageText[ message.length() ] = 0x20;
|
||||
txControllerInsert(address, fun + 0, messageText);
|
||||
txControllerInsert(address, fun + 0, numeric, messageText);
|
||||
delete []messageText;
|
||||
|
||||
if (request->hasArg("addtx")) {
|
||||
|
|
Loading…
Add table
Reference in a new issue