Improved free-text messages and bugfixes
This commit is contained in:
parent
c122a2b01d
commit
27c0f0c42d
2 changed files with 48 additions and 31 deletions
|
@ -15,14 +15,15 @@ So far only encoding is implemented. It should support the basic set of FT8 mess
|
||||||
* CQ {xy} {call} {grid}, e.g. CQ JA CA0LL GG77
|
* CQ {xy} {call} {grid}, e.g. CQ JA CA0LL GG77
|
||||||
* {call} {call} {report}, e.g. CA0LL OT7ER R-07
|
* {call} {call} {report}, e.g. CA0LL OT7ER R-07
|
||||||
* {call} {call} 73/RRR/RR73, e.g. OT7ER CA0LL 73
|
* {call} {call} 73/RRR/RR73, e.g. OT7ER CA0LL 73
|
||||||
|
* Free-text messages (up to 13 characters from a limited alphabet)
|
||||||
|
|
||||||
# What doesn't
|
# What doesn't
|
||||||
|
|
||||||
* Encoding free-text messages
|
* Encoding contest mode message
|
||||||
* Encoding contest mode messages
|
* Encoding extended range signal reports (<-30dB or >=0dB S/N)
|
||||||
* Encoding compound callsigns with country prefixes and mode suffixes
|
* Encoding compound callsigns with country prefixes and mode suffixes
|
||||||
* Decoding
|
* Decoding
|
||||||
* The revised FT8 protocol using 77-bit payload messages (since WSJT-X version 2.0)
|
* The revised FT8 protocol using 77-bit payload messages (introduced since WSJT-X version 2.0)
|
||||||
|
|
||||||
# What to do with it
|
# What to do with it
|
||||||
|
|
||||||
|
|
72
pack.cpp
72
pack.cpp
|
@ -170,9 +170,13 @@ void int_to_dd(char *str, int value, int width) {
|
||||||
|
|
||||||
|
|
||||||
// Pack a valid callsign into a 28-bit integer.
|
// Pack a valid callsign into a 28-bit integer.
|
||||||
int32_t packcall(const char *callsign) {
|
// Note that callsign points to a portion of text and may not be zero-terminated.
|
||||||
//LOG("Callsign = [%s]\n", callsign);
|
int32_t packcall(const char *callsign, int length) {
|
||||||
if (equals(callsign, "CQ")) {
|
if (length > 6) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (starts_with(callsign, "CQ ")) {
|
||||||
// TODO: support 'CQ nnn' frequency specification
|
// TODO: support 'CQ nnn' frequency specification
|
||||||
//if (callsign(4:4).ge.'0' .and. callsign(4:4).le.'9' .and. &
|
//if (callsign(4:4).ge.'0' .and. callsign(4:4).le.'9' .and. &
|
||||||
// callsign(5:5).ge.'0' .and. callsign(5:5).le.'9' .and. &
|
// callsign(5:5).ge.'0' .and. callsign(5:5).le.'9' .and. &
|
||||||
|
@ -182,44 +186,43 @@ int32_t packcall(const char *callsign) {
|
||||||
//endif
|
//endif
|
||||||
return NBASE + 1;
|
return NBASE + 1;
|
||||||
}
|
}
|
||||||
if (equals(callsign, "QRZ")) {
|
if (starts_with(callsign, "QRZ ")) {
|
||||||
return NBASE + 2;
|
return NBASE + 2;
|
||||||
}
|
}
|
||||||
if (equals(callsign, "DE")) {
|
if (starts_with(callsign, "DE ")) {
|
||||||
return 267796945;
|
return 267796945;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(callsign);
|
|
||||||
if (len > 6) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char callsign2[7] = {' ', ' ', ' ', ' ', ' ', ' ', 0}; // 6 spaces with zero terminator
|
char callsign2[7] = {' ', ' ', ' ', ' ', ' ', ' ', 0}; // 6 spaces with zero terminator
|
||||||
|
|
||||||
// Work-around for Swaziland prefix (see WSJT-X code):
|
// Work-around for Swaziland prefix (see WSJT-X code):
|
||||||
if (starts_with(callsign, "3DA0")) {
|
if (starts_with(callsign, "3DA0")) {
|
||||||
// callsign='3D0'//callsign(5:6)
|
// callsign='3D0'//callsign(5:6)
|
||||||
memcpy(callsign2, "3D0", 3);
|
memcpy(callsign2, "3D0", 3);
|
||||||
memcpy(callsign2 + 3, callsign + 4, 2);
|
if (length > 4) {
|
||||||
|
memcpy(callsign2 + 3, callsign + 4, length - 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Work-around for Guinea prefixes (see WSJT-X code):
|
// Work-around for Guinea prefixes (see WSJT-X code):
|
||||||
else if (starts_with(callsign, "3X") && is_letter(callsign[2])) {
|
else if (starts_with(callsign, "3X") && is_letter(callsign[2])) {
|
||||||
//callsign='Q'//callsign(3:6)
|
//callsign='Q'//callsign(3:6)
|
||||||
memcpy(callsign2, "Q", 1);
|
memcpy(callsign2, "Q", 1);
|
||||||
memcpy(callsign2 + 1, callsign + 2, 4);
|
if (length > 2) {
|
||||||
|
memcpy(callsign2 + 1, callsign + 2, length - 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Just copy, no modifications needed
|
// Just copy, no modifications needed
|
||||||
// Check for callsigns with 1 symbol prefix
|
// Check for callsigns with 1 symbol prefix
|
||||||
if (!is_digit(callsign[2]) && is_digit(callsign[1])) {
|
if (!is_digit(callsign[2]) && is_digit(callsign[1])) {
|
||||||
if (len > 5) {
|
if (length > 5) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Leave one space at the beginning as padding
|
// Leave one space at the beginning as padding
|
||||||
memcpy(callsign2 + 1, callsign, len);
|
memcpy(callsign2 + 1, callsign, length);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(callsign2, callsign, len);
|
memcpy(callsign2, callsign, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +254,7 @@ int32_t packcall(const char *callsign) {
|
||||||
|
|
||||||
// Pack a valid grid locator into an integer.
|
// Pack a valid grid locator into an integer.
|
||||||
int16_t packgrid(const char *grid) {
|
int16_t packgrid(const char *grid) {
|
||||||
//LOG("Grid = [%s]\n", grid);
|
printf("Grid = [%s]\n", grid);
|
||||||
int len = strlen(grid);
|
int len = strlen(grid);
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
|
@ -333,9 +336,11 @@ int16_t packgrid(const char *grid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack a free-text message into 3 integers (28+28+15 bits)
|
// Pack a free-text message into 3 integers (28+28+15 bits)
|
||||||
|
// NOTE: msg MUST contain at least 13 characters!
|
||||||
|
// No checking is done. Exactly 13 characters will be processed.
|
||||||
void packtext(const char *msg, int32_t &nc1, int32_t &nc2, int16_t &ng) {
|
void packtext(const char *msg, int32_t &nc1, int32_t &nc2, int16_t &ng) {
|
||||||
int32_t nc3;
|
int32_t nc3;
|
||||||
nc1 = nc2 = ng = 0;
|
nc1 = nc2 = nc3 = 0;
|
||||||
|
|
||||||
// Pack 5 characters (42^5) into 27 bits
|
// Pack 5 characters (42^5) into 27 bits
|
||||||
for (int i = 0; i < 5; ++i) { // First 5 characters in nc1
|
for (int i = 0; i < 5; ++i) { // First 5 characters in nc1
|
||||||
|
@ -373,7 +378,7 @@ int packmsg(const char *msg, uint8_t *dat) { // , itype, bcontest
|
||||||
char msg2[23]; // Including zero terminator!
|
char msg2[23]; // Including zero terminator!
|
||||||
|
|
||||||
fmtmsg(msg2, msg);
|
fmtmsg(msg2, msg);
|
||||||
|
|
||||||
//LOG("msg2 = [%s]\n", msg2);
|
//LOG("msg2 = [%s]\n", msg2);
|
||||||
|
|
||||||
// TODO: Change 'CQ n ' type messages to 'CQ 00n '
|
// TODO: Change 'CQ n ' type messages to 'CQ 00n '
|
||||||
|
@ -398,6 +403,7 @@ int packmsg(const char *msg, uint8_t *dat) { // , itype, bcontest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msg2len = strlen(msg2);
|
||||||
int32_t nc1 = -1;
|
int32_t nc1 = -1;
|
||||||
int32_t nc2 = -1;
|
int32_t nc2 = -1;
|
||||||
int16_t ng = -1;
|
int16_t ng = -1;
|
||||||
|
@ -406,34 +412,44 @@ int packmsg(const char *msg, uint8_t *dat) { // , itype, bcontest
|
||||||
// by locating spaces and changing them to zero terminators
|
// by locating spaces and changing them to zero terminators
|
||||||
|
|
||||||
// Locate the first delimiter in the message
|
// Locate the first delimiter in the message
|
||||||
char *s1 = (char *)strchr(msg2, ' ');
|
const char *s1 = strchr(msg2, ' ');
|
||||||
if (s1 != NULL) {
|
if (s1 != 0) {
|
||||||
*s1 = 0; // Separate fields by zero terminator
|
int s1len = s1 - msg2;
|
||||||
|
int s2len;
|
||||||
++s1; // s1 now points to the second field
|
++s1; // s1 now points to the second field
|
||||||
|
|
||||||
// Locate the second delimiter in the message
|
// Locate the second delimiter in the message
|
||||||
char *s2 = (char *)strchr(s1 + 1, ' ');
|
const char *s2 = strchr(s1 + 1, ' ');
|
||||||
if (s2 == NULL) {
|
if (s2 == 0) {
|
||||||
// If the second space is not found, point to the end of string
|
// If the second space is not found, point to the end of string
|
||||||
// to allow for blank grid (third field)
|
// to allow for blank grid (third field)
|
||||||
s2 = msg2 + strlen(msg2);
|
s2 = msg2 + msg2len;
|
||||||
|
s2len = s2 - s1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
*s2 = 0;// Separate fields by zero terminator
|
s2len = s2 - s1;
|
||||||
++s2; // s2 now points to the third field
|
++s2; // s2 now points to the third field
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: process callsign prefixes/suffixes
|
// TODO: process callsign prefixes/suffixes
|
||||||
|
|
||||||
// Pack message fields into integers
|
// Pack message fields into integers
|
||||||
nc1 = packcall(msg2);
|
nc1 = packcall(msg2, s1len);
|
||||||
nc2 = packcall(s1);
|
nc2 = packcall(s1, s2len);
|
||||||
ng = packgrid(s2);
|
ng = packgrid(s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for success in all three fields
|
// Check for success in all three fields
|
||||||
if (nc1 < 0 || nc2 < 0 || ng < 0) {
|
if (nc1 < 0 || nc2 < 0 || ng < 0) {
|
||||||
// Treat as plain text message
|
// Treat as plain text message
|
||||||
|
|
||||||
|
// Pad with spaces at the end if necessary
|
||||||
|
for (int i = msg2len; i < 13; ++i) {
|
||||||
|
msg2[i] = ' ';
|
||||||
|
}
|
||||||
|
msg2[13] = 0;
|
||||||
|
|
||||||
|
printf("Treating as free text\n");
|
||||||
packtext(msg2, nc1, nc2, ng);
|
packtext(msg2, nc1, nc2, ng);
|
||||||
ng += 0x8000; // Set bit 15 (we abuse signed int here)
|
ng += 0x8000; // Set bit 15 (we abuse signed int here)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue