Improved free-text messages and bugfixes

This commit is contained in:
Karlis Goba 2018-10-18 19:22:01 +03:00
parent c122a2b01d
commit 27c0f0c42d
2 changed files with 48 additions and 31 deletions

View file

@ -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

View file

@ -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
@ -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)
} }