#include "unpack.h" #include "text.h" #include constexpr uint32_t NBASE = 37L*36L*10L*27L*27L*27L; // convert packed character to ASCII character // 0..9 a..z space +-./? char charn(uint8_t c) { if (c >= 0 && c <= 9) return '0' + c; if (c >= 10 && c < 36) return 'A' + c - 10; if (c < 42) return " +-./?" [c - 36]; return ' '; } // nc is a 28-bit integer, e.g. nc1 or nc2, containing all the // call sign bits from a packed message. void unpackcall(uint32_t nc, char *callsign) { callsign[5] = charn((nc % 27) + 10); // + 10 b/c only alpha+space nc /= 27; callsign[4] = charn((nc % 27) + 10); nc /= 27; callsign[3] = charn((nc % 27) + 10); nc /= 27; callsign[2] = charn(nc % 10); // digit only nc /= 10; callsign[1] = charn(nc % 36); // letter or digit nc /= 36; callsign[0] = charn(nc); callsign[6] = 0; } // extract maidenhead locator void unpackgrid(uint16_t ng, char *grid) { // start of special grid locators for sig strength &c. constexpr uint16_t NGBASE = 180*180; if (ng == NGBASE + 1) { grid[0] = 0; return; } // if ng >= NGBASE+1 and ng < NGBASE+31: // return " -%02d" % (ng - (NGBASE+1)) // sig str, -01 to -30 DB // if ng >= NGBASE+31 and ng < NGBASE+62: // return "R-%02d" % (ng - (NGBASE+31)) if (ng == NGBASE + 62) { strcpy(grid, "RO"); return; } if (ng == NGBASE + 63) { strcpy(grid, "RRR"); return; } if (ng == NGBASE + 64) { strcpy(grid, "73"); return; } int16_t lat = (int16_t)(ng % 180) - 90; int16_t lng = ((int16_t)(ng / 180) * 2) - 180; grid[0] = 'A' + ((179 - lng) / 20); grid[1] = 'A' + ((90 + lat) / 10); grid[2] = '0' + (((179 - lng) % 20) / 2); grid[3] = '0' + ((90 + lat) % 10); grid[4] = 0; if ((grid[0] == 'K') && (grid[1] == 'A')) { // really + signal strength // sig = int(g[2:4]) - 50 // return "+%02d" % (sig) return; } else if ((grid[0] == 'L') && (grid[1] == 'A')) { // really R+ signal strength // sig = int(g[2:4]) - 50 // return "R+%02d" % (sig) return; } } void unpacktext(uint32_t nc1, uint32_t nc2, uint16_t ng, char *text) { uint32_t nc3 = (ng & 0x7FFF); // Check for bit 0 and copy it to nc3 if ((nc1 & 1) != 0) nc3 |= 0x08000; if ((nc2 & 1) != 0) nc3 |= 0x10000; nc1 >>= 1; nc2 >>= 1; for (int i = 4; i >= 0; --i) { text[i] = charn(nc1 % 42); nc1 /= 42; } for (int i = 9; i >= 5; --i) { text[i] = charn(nc2 % 42); nc2 /= 42; } for (int i = 12; i >= 10; --i) { text[i] = charn(nc3 % 42); nc3 /= 42; } text[13] = 0; } int unpack(const uint8_t *a72, char *message) { uint32_t nc1, nc2; uint16_t ng; nc1 = (a72[0] << 20); nc1 |= (a72[1] << 12); nc1 |= (a72[2] << 4); nc1 |= (a72[3] >> 4); nc2 = ((a72[3] & 0x0F) << 24); nc2 |= (a72[4] << 16); nc2 |= (a72[5] << 8); nc2 |= (a72[6]); ng = (a72[7] >> 8); ng |= (a72[8]); if (ng & 0x8000) { unpacktext(nc1, nc2, ng, message); return 0; } char c2[7]; char grid[5]; if (nc1 == NBASE+1) { // CQ with standard callsign unpackcall(nc2, c2); unpackgrid(ng, grid); strcpy(message, "CQ "); strcat(message, c2); strcat(message, " "); strcat(message, grid); return 0; } if (nc1 >= 267649090L && nc1 <= 267698374L) { // CQ with suffix (e.g. /QRP) uint32_t n = nc1 - 267649090L; char sf[4]; sf[0] = charn(n % 37); n /= 37; sf[1] = charn(n % 37); n /= 37; sf[2] = charn(n % 37); unpackcall(nc2, c2); unpackgrid(ng, grid); strcpy(message, "CQ "); strcat(message, c2); strcat(message, "/"); strcat(message, sf); strcat(message, " "); strcat(message, grid); return 0; } // Standard two-call exchange char c1[7]; unpackcall(nc1, c1); if (equals(c1, "CQ9DX ")) { strcpy(c1, "CQ DX"); } else if (starts_with(c1, " E9") && is_letter(c1[3]) && is_letter(c1[4]) && is_space(c1[5])) { strcpy(c1, "CQ "); c1[5] = 0; } unpackcall(nc2, c2); unpackgrid(ng, grid); strcpy(message, c1); strcat(message, " "); strcat(message, c2); strcat(message, " "); strcat(message, grid); //if "000AAA" in msg: // return None return 0; }