diff --git a/README.md b/README.md index 3cff464..22a7768 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ dd if=/dev/urandom of=uncoded.dat bs=1 count=256 Encode file ```uncoded.dat``` to ```encoded.wav``` [WAV](https://en.wikipedia.org/wiki/WAV) audio file with 8000 Hz sample rate, 16 bits and only 1 (real) channel: ``` -./encode encoded.wav 8000 16 1 1500 23 CALLSIGN uncoded.dat +./encode encoded.wav 8000 16 1 1500 5 uncoded.dat ``` Start recording to ```recorded.wav``` audio file and stop after 5 seconds: @@ -41,18 +41,23 @@ diff -s uncoded.dat decoded.dat ### Supported Modes -Ping: -* Mode 0: DBPSK, 2/7-rate code, 1600 Hz bandwidth, 0.36 seconds and no payload +All modes need a bandwidth of 2000 Hz and use a 1/2-rate forward error correction code -Next: -* Mode 23: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 1.80 seconds and 256 bytes -* Mode 24: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 3.24 seconds and 512 bytes -* Mode 25: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 6.12 seconds and 1024 bytes -* Mode 26: QAM16, 1/2-rate code, 1700 Hz bandwidth, 1.08 seconds and 256 bytes -* Mode 27: QAM16, 1/2-rate code, 1700 Hz bandwidth, 1.80 seconds and 512 bytes -* Mode 28: QAM16, 1/2-rate code, 1700 Hz bandwidth, 3.24 seconds and 1024 bytes -* Mode 29: QAM64, 1/2-rate code, 1900 Hz bandwidth, 1.26 seconds and 512 bytes -* Mode 30: QAM64, 1/2-rate code, 1900 Hz bandwidth, 2.16 seconds and 1024 bytes +* Mode 1: QPSK, 1.02 seconds and 128 bytes +* Mode 2: QPSK, 1.70 seconds and 256 bytes +* Mode 3: QPSK, 3.06 seconds and 512 bytes +* Mode 4: QPSK, 5.78 seconds and 1024 bytes +* Mode 5: QAM16, 1.02 seconds and 256 bytes +* Mode 6: QAM16, 1.70 seconds and 512 bytes +* Mode 7: QAM16, 3.06 seconds and 1024 bytes +* Mode 8: QAM16, 5.78 seconds and 2048 bytes +* Mode 9: QAM64, 2.21 seconds and 1024 bytes +* Mode 10: QAM64, 4.08 seconds and 2048 bytes +* Mode 11: QAM64, 7.82 seconds and 4096 bytes +* Mode 12: QAM256, 1.02 seconds and 512 bytes +* Mode 13: QAM256, 1.70 seconds and 1024 bytes +* Mode 14: QAM256, 3.06 seconds and 2048 bytes +* Mode 15: QAM256, 5.78 seconds and 4096 bytes ### Simulating @@ -61,7 +66,7 @@ Prerequisite: [disorders](https://github.com/aicodix/disorders) Encode ```uncoded.dat``` to [analytic](https://en.wikipedia.org/wiki/Analytic_signal) audio signal, add [multipath](https://en.wikipedia.org/wiki/Multipath_propagation), [CFO, SFO](https://en.wikipedia.org/wiki/Carrier_frequency_offset), [AWGN](https://en.wikipedia.org/wiki/Additive_white_Gaussian_noise), decode and compare: ``` -./encode - 8000 16 2 1500 23 CALLSIGN uncoded.dat | ../disorders/multipath - - ../disorders/multipath.txt 10 | ../disorders/cfo - - 234.567 | ../disorders/sfo - - 147 | ../disorders/awgn - - -30 | ./decode - - | diff -q -s uncoded.dat - +./encode - 8000 16 2 1500 5 uncoded.dat | ../disorders/multipath - - ../disorders/multipath.txt 10 | ../disorders/cfo - - 234.567 | ../disorders/sfo - - 147 | ../disorders/awgn - - -30 | ./decode - - | diff -q -s uncoded.dat - ``` ### Reading diff --git a/decode.cc b/decode.cc index 3d7824f..6dbcd7f 100644 --- a/decode.cc +++ b/decode.cc @@ -45,11 +45,11 @@ struct Decoder static const int symbol_len = guard_len * 16; static const int filter_len = (((21 * rate) / 8000) & ~3) | 1; static const int extended_len = symbol_len + guard_len; - static const int mod_max = 6; + static const int mod_max = 8; static const int code_max = 16; static const int bits_max = 1 << code_max; - static const int data_max = 1024; - static const int symbols_max = 32; + static const int data_max = 4096; + static const int symbols_max = 44; static const int mls0_poly = 0b1100110001; static const int mls0_seed = 214; static const int mls1_poly = 0b100101011; @@ -127,6 +127,8 @@ struct Decoder return QuadratureAmplitudeModulation<16, cmplx, code_type>::soft(b, c, precision); case 6: return QuadratureAmplitudeModulation<64, cmplx, code_type>::soft(b, c, precision); + case 8: + return QuadratureAmplitudeModulation<256, cmplx, code_type>::soft(b, c, precision); } } void shuffle(code_type *dest, const code_type *src) @@ -174,61 +176,110 @@ struct Decoder void setup(int oper_mode) { switch (oper_mode) { case 1: + mod_bits = 2; + symbol_count = 4; + code_order = 11; + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; + case 2: mod_bits = 2; symbol_count = 8; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; - case 2: + case 3: mod_bits = 2; symbol_count = 16; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; - case 3: + case 4: mod_bits = 2; symbol_count = 32; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 4: + case 5: mod_bits = 4; symbol_count = 4; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; - case 5: + case 6: mod_bits = 4; symbol_count = 8; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; - case 6: + case 7: mod_bits = 4; symbol_count = 16; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 7: - mod_bits = 6; - symbol_count = 6; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - break; case 8: + mod_bits = 4; + symbol_count = 32; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 9: mod_bits = 6; symbol_count = 11; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; + case 10: + mod_bits = 6; + symbol_count = 22; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 11: + mod_bits = 6; + symbol_count = 44; + code_order = 16; + data_bits = 32768; + frozen_bits = frozen_65536_32800; + break; + case 12: + mod_bits = 8; + symbol_count = 4; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 13: + mod_bits = 8; + symbol_count = 8; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + break; + case 14: + mod_bits = 8; + symbol_count = 16; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 15: + mod_bits = 8; + symbol_count = 32; + code_order = 16; + data_bits = 32768; + frozen_bits = frozen_65536_32800; + break; default: return; } @@ -276,7 +327,7 @@ struct Decoder for (int i = 0; i < pilot_tones; ++i) mode[i] = clamp(std::nearbyint(127 * demod_or_erase(tone[i*block_length+pilot_offset], chan[i*block_length+pilot_offset]).real() * nrz(seq1()))); int oper_mode = hadamarddec(mode); - if (oper_mode < 0 || oper_mode > 8) { + if (oper_mode < 0 || oper_mode > 15) { std::cerr << "operation mode " << oper_mode << " unsupported." << std::endl; continue; } @@ -347,9 +398,7 @@ struct Decoder if (i % block_length == roff) continue; int bits = mod_bits; - if (oper_mode == 7 && k % 32 == 30) - bits = 2; - else if (oper_mode == 8 && k % 64 == 60) + if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60) bits = 4; demap_bits(perm+k, demod[tone_count*j+i], precision, bits); k += bits; diff --git a/encode.cc b/encode.cc index a0fc0cb..e317b03 100644 --- a/encode.cc +++ b/encode.cc @@ -30,7 +30,7 @@ struct Encoder static const int guard_len = rate / 100; static const int symbol_len = guard_len * 16; static const int bits_max = 65536; - static const int data_max = 1024; + static const int data_max = 4096; static const int mls0_poly = 0b1100110001; static const int mls0_seed = 214; static const int mls1_poly = 0b100101011; @@ -172,6 +172,8 @@ struct Encoder return QuadratureAmplitudeModulation<16, cmplx, code_type>::map(b); case 6: return QuadratureAmplitudeModulation<64, cmplx, code_type>::map(b); + case 8: + return QuadratureAmplitudeModulation<256, cmplx, code_type>::map(b); } return 0; } @@ -184,6 +186,8 @@ struct Encoder return QuadratureAmplitudeModulation<16, cmplx, code_type>::DIST; case 6: return QuadratureAmplitudeModulation<64, cmplx, code_type>::DIST; + case 8: + return QuadratureAmplitudeModulation<256, cmplx, code_type>::DIST; } return 2; } @@ -228,61 +232,110 @@ struct Encoder symbol_count = 1; break; case 1: + mod_bits = 2; + symbol_count = 4; + code_order = 11; + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; + case 2: mod_bits = 2; symbol_count = 8; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; - case 2: + case 3: mod_bits = 2; symbol_count = 16; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; - case 3: + case 4: mod_bits = 2; symbol_count = 32; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 4: + case 5: mod_bits = 4; symbol_count = 4; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; - case 5: + case 6: mod_bits = 4; symbol_count = 8; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; - case 6: + case 7: mod_bits = 4; symbol_count = 16; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 7: - mod_bits = 6; - symbol_count = 6; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - break; case 8: + mod_bits = 4; + symbol_count = 32; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 9: mod_bits = 6; symbol_count = 11; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; + case 10: + mod_bits = 6; + symbol_count = 22; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 11: + mod_bits = 6; + symbol_count = 44; + code_order = 16; + data_bits = 32768; + frozen_bits = frozen_65536_32800; + break; + case 12: + mod_bits = 8; + symbol_count = 4; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 13: + mod_bits = 8; + symbol_count = 8; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + break; + case 14: + mod_bits = 8; + symbol_count = 16; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 15: + mod_bits = 8; + symbol_count = 32; + code_order = 16; + data_bits = 32768; + frozen_bits = frozen_65536_32800; + break; default: return; } @@ -365,9 +418,7 @@ struct Encoder tone[i] = 0; } else { int bits = mod_bits; - if (oper_mode == 7 && k % 32 == 30) - bits = 2; - else if (oper_mode == 8 && k % 64 == 60) + if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60) bits = 4; tone[i] = map_bits(perm+k, bits); k += bits; @@ -409,7 +460,7 @@ int main(int argc, char **argv) std::cerr << "Using operation mode " << oper_mode << " but " << input_count << " input file" << (input_count == 1 ? "" : "s") << " provided." << std::endl; return 1; } - if (oper_mode < 0 || oper_mode > 8) { + if (oper_mode < 0 || oper_mode > 15) { std::cerr << "Unsupported operation mode." << std::endl; return 1; }