mirror of https://github.com/F5OEO/rpitx
Merge pull request #186 from cuddlycheetah/master
Added numeric pocsag mode
This commit is contained in:
commit
e8796bce41
|
|
@ -22,8 +22,9 @@ SOFTWARE.
|
|||
|
||||
Fork and modification for rpitx (c)(F5OEO 2018)
|
||||
|
||||
*/
|
||||
** 11.09.2019 : Added Numeric Pager support by cuddlycheetah (github.com/cuddlycheetah)
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -33,7 +34,7 @@ Fork and modification for rpitx (c)(F5OEO 2018)
|
|||
#include <unistd.h>
|
||||
#include "../librpitx/src/librpitx.h"
|
||||
|
||||
#define PROGRAM_VERSION "0.1"
|
||||
#define PROGRAM_VERSION "0.2"
|
||||
//Check out main() at the bottom of the file
|
||||
//You can modify MIN_DELAY and MAX_DELAY to fit your needs.
|
||||
|
||||
|
|
@ -84,6 +85,9 @@ Fork and modification for rpitx (c)(F5OEO 2018)
|
|||
//As mentioned above, characters are 7 bit ASCII encoded
|
||||
#define TEXT_BITS_PER_CHAR 7
|
||||
|
||||
#define NUMERIC_BITS_PER_WORD 20
|
||||
#define NUMERIC_BITS_PER_DIGIT 4
|
||||
|
||||
//Length of CRC codes in bits
|
||||
#define CRC_BITS 10
|
||||
|
||||
|
|
@ -225,6 +229,107 @@ 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 | FLAG_MESSAGE);
|
||||
out++;
|
||||
currentWord = 0;
|
||||
currentNumBits = 0;
|
||||
numWordsWritten++;
|
||||
|
||||
wordPosition++;
|
||||
if (wordPosition == BATCH_SIZE) {
|
||||
//We've filled a full batch, time to insert a SYNC word
|
||||
//and start a new one.
|
||||
*out = 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 | FLAG_MESSAGE);
|
||||
out++;
|
||||
numWordsWritten++;
|
||||
|
||||
wordPosition++;
|
||||
if (wordPosition == BATCH_SIZE) {
|
||||
//We've filled a full batch, time to insert a SYNC word
|
||||
//and start a new one.
|
||||
*out = 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
|
||||
|
|
@ -241,6 +346,7 @@ int addressOffset(int address) {
|
|||
* (*message) is a null terminated C string.
|
||||
* (*out) is the destination to which the transmission will be written.
|
||||
*/
|
||||
bool numeric = false;
|
||||
void encodeTransmission(int address, int fb, char* message, uint32_t* out) {
|
||||
|
||||
|
||||
|
|
@ -273,8 +379,12 @@ void encodeTransmission(int address, int fb, char* message, uint32_t* out) {
|
|||
out++;
|
||||
|
||||
//Encode the message itself
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//Finally, write an IDLE word indicating the end of the message
|
||||
*out = IDLE;
|
||||
|
|
@ -325,6 +435,41 @@ size_t textMessageLength(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 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 += BATCH_SIZE - (numWords % 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 / 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
|
||||
numWords += PREAMBLE_LENGTH / 32;
|
||||
|
||||
return numWords;
|
||||
}
|
||||
|
||||
void SendFsk(uint64_t Freq,bool Inverted,int SR,bool debug,uint32_t *Message,int Size)
|
||||
{
|
||||
|
||||
|
|
@ -375,6 +520,7 @@ Usage:\npocsag [-f Frequency] [-i] [-r Rate]\n\
|
|||
-f float central frequency Hz(50 kHz to 1500 MHz),\n\
|
||||
-r int baud rate (512, 1200 or 2400. Default 1200 bps),\n\
|
||||
-b int function bits (0-3. Default 3),\n\
|
||||
-n use numeric messages,\n\
|
||||
-i invert the modulation polarity,\n\
|
||||
-d debug,\n\
|
||||
-? help (this help).\n\
|
||||
|
|
@ -391,14 +537,14 @@ int main(int argc, char* argv[]) {
|
|||
//from 1-10 seconds in length, to act as a simulated "delay".
|
||||
int a;
|
||||
int anyargs = 1;
|
||||
uint64_t SetFrequency=439875000L;
|
||||
uint64_t SetFrequency=466230000L;
|
||||
int SetRate = 1200;
|
||||
int SetFunctionBits = 3;
|
||||
bool SetInverted = false;
|
||||
bool debug = false;
|
||||
while(1)
|
||||
{
|
||||
a = getopt(argc, argv, "b:df:ir:");
|
||||
a = getopt(argc, argv, "b:dnf:ir:");
|
||||
|
||||
if(a == -1)
|
||||
{
|
||||
|
|
@ -409,7 +555,10 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
switch(a)
|
||||
{
|
||||
|
||||
case 'n': // Numeric messages
|
||||
numeric = true;
|
||||
break;
|
||||
|
||||
case 'd': // Debug
|
||||
debug = true;
|
||||
break;
|
||||
|
|
@ -505,7 +654,9 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
}
|
||||
|
||||
size_t messageLength = textMessageLength(address, strlen(message));
|
||||
size_t messageLength = numeric
|
||||
? numericMessageLength(address, strlen(message))
|
||||
: textMessageLength(address, strlen(message));
|
||||
|
||||
uint32_t* transmission =
|
||||
(uint32_t*) malloc(sizeof(uint32_t) * messageLength+2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue