diff --git a/firmware/scripts/wspr_coding b/firmware/scripts/wspr_coding new file mode 100755 index 0000000..ed8466e Binary files /dev/null and b/firmware/scripts/wspr_coding differ diff --git a/firmware/scripts/wspr_coding.c b/firmware/scripts/wspr_coding.c index 193d2dd..4317e95 100644 --- a/firmware/scripts/wspr_coding.c +++ b/firmware/scripts/wspr_coding.c @@ -1,6 +1,7 @@ #include #include #include +#include uint8_t wspr_call_char(char c) { c = toupper(c); @@ -37,7 +38,7 @@ uint8_t wspr_power(uint8_t power) { return power; } -uint64_t wspr_message(char *call, char* loc, uint8_t power) { +uint64_t wspr_message(char *call, char *loc, uint8_t power) { uint32_t m, n; n = wspr_loc_char(call[0]); @@ -54,13 +55,92 @@ uint64_t wspr_message(char *call, char* loc, uint8_t power) { return n << 21 | m; } +const uint32_t WSPR_FEC_TAPS1 = 0xF2D05351; +const uint32_t WSPR_FEC_TAPS2 = 0xE4613C47; +uint8_t wspr_parity32(uint32_t x) { + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + x ^= x >> 2; + x ^= x >> 1; + return x & 1; +} + +void wspr_fec(uint64_t msg, uint8_t *output) { + memset(output, 0, 162); + + uint32_t reg = 0; + for(uint8_t i = 0; i < 81; i++) { + uint8_t bit = 0; + if(i < 50) { + bit = (msg & (1 << (50 - i))) != 0; + } + + reg = (reg << 1) | bit; + + uint32_t tabs1 = reg & WSPR_FEC_TAPS1; + uint32_t tabs2 = reg & WSPR_FEC_TAPS2; + + output[i * 2] = wspr_parity32(tabs1); + output[i * 2 + 1] = wspr_parity32(tabs2); + } +} + +uint8_t wspr_reverse_bits(uint8_t bits) { + //https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html + //return __builtin_avr_insert_bits (0x01234567, bits, 0); + return (bits & 0x80 ? 0x01 : 0) | + (bits & 0x40 ? 0x02 : 0) | + (bits & 0x20 ? 0x04 : 0) | + (bits & 0x10 ? 0x08 : 0) | + (bits & 0x08 ? 0x10 : 0) | + (bits & 0x04 ? 0x20 : 0) | + (bits & 0x02 ? 0x40 : 0) | + (bits & 0x01 ? 0x80 : 0); +} + + +void wspr_interleave(uint8_t *input, uint8_t *output) { + uint8_t p = 0; + uint8_t i = 0; + while(p < 162) { + uint8_t rev_i = wspr_reverse_bits(i); + if(rev_i < 162) { + output[rev_i] = input[p]; + p++; + } + i++; + } +} + +const uint8_t WSPR_SYNC[162] = { + 1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0, + 0,0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0, + 1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1,0,1,0,0,0,1, + 1,1,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0.0,0 +}; + +void wspr_add_sync(uint8_t *symbols) { + for(uint8_t i = 0; i < 161; i++) { + symbols[i] = WSPR_SYNC[i] + 2 * symbols[i]; + } +} int main(int argc, char const *argv[]) { + uint8_t test[161]; + uint8_t test1[161]; + uint64_t msg = wspr_message("DL1SSK", "JN39WE", 27); + wspr_fec(msg, test); + wspr_interleave(test, test1); + wspr_add_sync(test1); - + for(uint8_t i = 0; i < 161; i++) { + printf("%d,", test1[i]); + } + printf("\n"); return 0; }