diff --git a/README.md b/README.md index 22a7768..336604c 100644 --- a/README.md +++ b/README.md @@ -43,21 +43,37 @@ diff -s uncoded.dat decoded.dat All modes need a bandwidth of 2000 Hz and use a 1/2-rate forward error correction code -* 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 +These use a differential modulation scheme: +* Mode 0: DBPSK, 1.70 seconds and 128 bytes +* Mode 1: DBPSK, 3.06 seconds and 256 bytes +* Mode 2: DBPSK, 5.78 seconds and 512 bytes +* Mode 3: DQPSK, 1.02 seconds and 128 bytes +* Mode 4: DQPSK, 1.70 seconds and 256 bytes +* Mode 5: DQPSK, 3.06 seconds and 512 bytes +* Mode 6: DQPSK, 5.78 seconds and 1024 bytes +* Mode 7: D8PSK, 2.21 seconds and 512 bytes +* Mode 8: D8PSK, 4.08 seconds and 1024 bytes +* Mode 9: D8PSK, 7.82 seconds and 2048 bytes + +And these a coherent modulation scheme: +* Mode 10: BPSK, 1.70 seconds and 128 bytes +* Mode 11: BPSK, 3.06 seconds and 256 bytes +* Mode 12: BPSK, 5.78 seconds and 512 bytes +* Mode 13: QPSK, 1.02 seconds and 128 bytes +* Mode 14: QPSK, 1.70 seconds and 256 bytes +* Mode 15: QPSK, 3.06 seconds and 512 bytes +* Mode 16: QPSK, 5.78 seconds and 1024 bytes +* Mode 17: QAM16, 1.02 seconds and 256 bytes +* Mode 18: QAM16, 1.70 seconds and 512 bytes +* Mode 19: QAM16, 3.06 seconds and 1024 bytes +* Mode 20: QAM16, 5.78 seconds and 2048 bytes +* Mode 21: QAM64, 2.21 seconds and 1024 bytes +* Mode 22: QAM64, 4.08 seconds and 2048 bytes +* Mode 23: QAM64, 7.82 seconds and 4096 bytes +* Mode 24: QAM256, 1.02 seconds and 512 bytes +* Mode 25: QAM256, 1.70 seconds and 1024 bytes +* Mode 26: QAM256, 3.06 seconds and 2048 bytes +* Mode 27: QAM256, 5.78 seconds and 4096 bytes ### Simulating diff --git a/common.hh b/common.hh index f521ccb..3e17b96 100644 --- a/common.hh +++ b/common.hh @@ -40,6 +40,7 @@ struct Common int pilot_off; int reserved_off; int symbol_count; + bool differential; Common() : crc0(0x8F6E37A0) {} @@ -47,109 +48,225 @@ struct Common { switch (oper_mode) { case 0: - symbol_count = 1; - break; - case 1: - mod_bits = 2; - symbol_count = 4; + mod_bits = 1; + symbol_count = 8; + differential = true; code_order = 11; data_bits = 1024; frozen_bits = frozen_2048_1056; break; - case 2: - mod_bits = 2; - symbol_count = 8; + case 1: + mod_bits = 1; + symbol_count = 16; + differential = true; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; + case 2: + mod_bits = 1; + symbol_count = 32; + differential = true; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; case 3: mod_bits = 2; - symbol_count = 16; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; + symbol_count = 4; + differential = true; + code_order = 11; + data_bits = 1024; + frozen_bits = frozen_2048_1056; break; case 4: mod_bits = 2; - symbol_count = 32; - code_order = 14; - data_bits = 8192; - frozen_bits = frozen_16384_8224; - break; - case 5: - mod_bits = 4; - symbol_count = 4; + symbol_count = 8; + differential = true; code_order = 12; data_bits = 2048; frozen_bits = frozen_4096_2080; break; - case 6: - mod_bits = 4; - symbol_count = 8; + case 5: + mod_bits = 2; + symbol_count = 16; + differential = true; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; - case 7: - mod_bits = 4; - symbol_count = 16; + case 6: + mod_bits = 2; + symbol_count = 32; + differential = true; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; + case 7: + mod_bits = 3; + symbol_count = 11; + differential = true; + 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; + mod_bits = 3; + symbol_count = 22; + differential = true; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 10: - mod_bits = 6; - symbol_count = 22; + case 9: + mod_bits = 3; + symbol_count = 44; + differential = true; code_order = 15; data_bits = 16384; frozen_bits = frozen_32768_16416; break; + case 10: + mod_bits = 1; + symbol_count = 8; + differential = true; + code_order = 11; + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; case 11: - mod_bits = 6; - symbol_count = 44; - code_order = 16; - data_bits = 32768; - frozen_bits = frozen_65536_32800; + mod_bits = 1; + symbol_count = 16; + differential = true; + code_order = 12; + data_bits = 2048; + frozen_bits = frozen_4096_2080; break; case 12: - mod_bits = 8; - symbol_count = 4; + mod_bits = 1; + symbol_count = 32; + differential = true; code_order = 13; data_bits = 4096; frozen_bits = frozen_8192_4128; break; case 13: - mod_bits = 8; + mod_bits = 2; + symbol_count = 4; + differential = false; + code_order = 11; + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; + case 14: + mod_bits = 2; symbol_count = 8; + differential = false; + code_order = 12; + data_bits = 2048; + frozen_bits = frozen_4096_2080; + break; + case 15: + mod_bits = 2; + symbol_count = 16; + differential = false; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 16: + mod_bits = 2; + symbol_count = 32; + differential = false; code_order = 14; data_bits = 8192; frozen_bits = frozen_16384_8224; break; - case 14: - mod_bits = 8; + case 17: + mod_bits = 4; + symbol_count = 4; + differential = false; + code_order = 12; + data_bits = 2048; + frozen_bits = frozen_4096_2080; + break; + case 18: + mod_bits = 4; + symbol_count = 8; + differential = false; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 19: + mod_bits = 4; symbol_count = 16; + differential = false; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + break; + case 20: + mod_bits = 4; + symbol_count = 32; + differential = false; code_order = 15; data_bits = 16384; frozen_bits = frozen_32768_16416; break; - case 15: + case 21: + mod_bits = 6; + symbol_count = 11; + differential = false; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + break; + case 22: + mod_bits = 6; + symbol_count = 22; + differential = false; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 23: + mod_bits = 6; + symbol_count = 44; + differential = false; + code_order = 16; + data_bits = 32768; + frozen_bits = frozen_65536_32800; + break; + case 24: + mod_bits = 8; + symbol_count = 4; + differential = false; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 25: + mod_bits = 8; + symbol_count = 8; + differential = false; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + break; + case 26: + mod_bits = 8; + symbol_count = 16; + differential = false; + code_order = 15; + data_bits = 16384; + frozen_bits = frozen_32768_16416; + break; + case 27: mod_bits = 8; symbol_count = 32; + differential = false; code_order = 16; data_bits = 32768; frozen_bits = frozen_65536_32800; diff --git a/decode.cc b/decode.cc index 2cb8ac3..c578ac8 100644 --- a/decode.cc +++ b/decode.cc @@ -88,8 +88,12 @@ struct Decoder : Common void demap_bits(code_type *b, cmplx c, value precision, int bits) { switch (bits) { + case 1: + return PhaseShiftKeying<2, cmplx, code_type>::soft(b, c, precision); case 2: return PhaseShiftKeying<4, cmplx, code_type>::soft(b, c, precision); + case 3: + return PhaseShiftKeying<8, cmplx, code_type>::soft(b, c, precision); case 4: return QuadratureAmplitudeModulation<16, cmplx, code_type>::soft(b, c, precision); case 6: @@ -181,13 +185,11 @@ struct Decoder : Common for (int i = 0; i < pilot_tones; ++i) mode[i] = clamp(std::nearbyint(127 * demod_or_erase(tone[i*block_length+first_pilot], chan[i*block_length+first_pilot]).real() * nrz(seq1()))); int oper_mode = hadamard_decoder(mode); - if (oper_mode < 0 || oper_mode > 15) { + if (oper_mode < 0 || oper_mode > 27) { std::cerr << "operation mode " << oper_mode << " unsupported." << std::endl; continue; } std::cerr << "oper mode: " << oper_mode << std::endl; - if (!oper_mode) - continue; setup(oper_mode); std::cerr << "Es/N0 (dB):"; for (int j = 0, k = 0; j < symbol_count; ++j) { @@ -242,7 +244,9 @@ struct Decoder : Common if (i % block_length == reserved_off) continue; int bits = mod_bits; - if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60) + if (oper_mode >= 7 && oper_mode <= 9 && k % 32 == 30) + bits = 2; + if (oper_mode >= 21 && oper_mode <= 23 && k % 64 == 60) bits = 4; demap_bits(perm+k, demod[i], precision, bits); k += bits; diff --git a/encode.cc b/encode.cc index 2f5fea7..85de1be 100644 --- a/encode.cc +++ b/encode.cc @@ -147,8 +147,12 @@ struct Encoder : public Common cmplx map_bits(code_type *b, int bits) { switch (bits) { + case 1: + return PhaseShiftKeying<2, cmplx, code_type>::map(b); case 2: return PhaseShiftKeying<4, cmplx, code_type>::map(b); + case 3: + return PhaseShiftKeying<8, cmplx, code_type>::map(b); case 4: return QuadratureAmplitudeModulation<16, cmplx, code_type>::map(b); case 6: @@ -161,8 +165,12 @@ struct Encoder : public Common value mod_distance() { switch (mod_bits) { + case 1: + return PhaseShiftKeying<2, cmplx, code_type>::DIST; case 2: return PhaseShiftKeying<4, cmplx, code_type>::DIST; + case 3: + return PhaseShiftKeying<8, cmplx, code_type>::DIST; case 4: return QuadratureAmplitudeModulation<16, cmplx, code_type>::DIST; case 6: @@ -234,20 +242,7 @@ struct Encoder : public Common guard_interval_weights(); papr_min = 1000, papr_max = -1000; leading_noise(); - if (oper_mode) { - hadamard_encoder(mode, oper_mode); - } else { - schmidl_cox(); - CODE::MLS seq1(mls1_poly); - for (int i = 0; i < tone_count; ++i) { - if (i % block_length == first_pilot) { - tone[i] = nrz(seq1()); - } else { - tone[i] = 0; - } - } - symbol(false); - } + hadamard_encoder(mode, oper_mode); for (int input_index = 0; input_index < input_count; ++input_index) { const char *input_name = input_names[input_index]; if (input_count == 1 && input_name[0] == '-' && input_name[1] == 0) @@ -283,7 +278,9 @@ struct Encoder : public Common tone[i] = 0; } else { int bits = mod_bits; - if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60) + if (oper_mode >= 7 && oper_mode <= 9 && k % 32 == 30) + bits = 2; + if (oper_mode >= 21 && oper_mode <= 23 && k % 64 == 60) bits = 4; tone[i] = map_bits(perm+k, bits); k += bits; @@ -302,7 +299,7 @@ struct Encoder : public Common int main(int argc, char **argv) { - if (argc < 7) { + if (argc < 8) { std::cerr << "usage: " << argv[0] << " OUTPUT RATE BITS CHANNELS OFFSET MODE INPUT.." << std::endl; return 1; } @@ -321,11 +318,7 @@ int main(int argc, char **argv) } int input_count = argc - 7; int oper_mode = std::atoi(argv[6]); - if (!oper_mode != !input_count) { - 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 > 15) { + if (oper_mode < 0 || oper_mode > 27) { std::cerr << "Unsupported operation mode." << std::endl; return 1; }