From 6f58e93018fec2757d683a7c3b45b97f465357c1 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Wed, 4 Jan 2023 15:37:23 +0100 Subject: [PATCH] added support for modes 0, 15 and 16 --- decode.cc | 57 ++++++++++++++++++++++++++++++------------- encode.cc | 72 ++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/decode.cc b/decode.cc index 36cf89d..a65d38b 100644 --- a/decode.cc +++ b/decode.cc @@ -173,8 +173,7 @@ struct Decoder static const int symbol_len = (1280 * rate) / 8000; static const int filter_len = (((21 * rate) / 8000) & ~3) | 1; static const int guard_len = symbol_len / 8; - static const int data_bits = 1360; - static const int crc_bits = data_bits + 32; + static const int max_bits = 1360 + 32; static const int cons_cols = 256; static const int cons_rows = 4; static const int cons_total = cons_rows * cons_cols; @@ -200,13 +199,16 @@ struct Decoder CODE::PolarEncoder polarenc; CODE::PolarListDecoder polardec; int8_t genmat[255*71]; - mesg_type mesg[crc_bits], mess[code_len]; + mesg_type mesg[max_bits], mess[code_len]; code_type code[code_len]; cmplx cons[cons_total], prev[cons_cols]; cmplx fdom[symbol_len], tdom[symbol_len]; value index[cons_cols], phase[cons_cols]; value cfo_rad, sfo_rad; + const uint32_t *frozen_bits; int symbol_pos; + int oper_mode; + int crc_bits; static int bin(int carrier) { @@ -236,10 +238,10 @@ struct Decoder } void systematic() { - polarenc(mess, mesg, frozen_2048_1392, code_order); + polarenc(mess, mesg, frozen_bits, code_order); int code_bits = 1 << code_order; for (int i = 0, j = 0; i < code_bits && j < crc_bits; ++i) - if (!((frozen_2048_1392[i/32] >> (i%32)) & 1)) + if (!((frozen_bits[i/32] >> (i%32)) & 1)) mesg[j++] = mess[i]; } cmplx mod_map(code_type *b) @@ -262,7 +264,7 @@ struct Decoder tmp = hilbert(blockdc(tmp.real())); return input_hist(tmp); } - Decoder(uint8_t *out, DSP::ReadPCM *pcm, int skip_count) : + Decoder(uint8_t *out, int *len, DSP::ReadPCM *pcm, int skip_count) : pcm(pcm), correlator(mls0_seq()), crc0(0xA8F4), crc1(0x8F6E37A0) { CODE::BoseChaudhuriHocquenghemGenerator<255, 71>::matrix(genmat, true, { @@ -320,8 +322,8 @@ struct Decoder std::cerr << "header CRC error." << std::endl; continue; } - int oper_mode = md & 255; - if (oper_mode != 14) { + oper_mode = md & 255; + if (oper_mode && (oper_mode < 14 || oper_mode > 16)) { std::cerr << "operation mode " << oper_mode << " unsupported." << std::endl; continue; } @@ -337,7 +339,8 @@ struct Decoder okay = true; } while (skip_count--); - if (!okay) + *len = 0; + if (!okay || !oper_mode) return; for (int i = 0; i < symbol_pos+(symbol_len+guard_len); ++i) @@ -415,8 +418,27 @@ struct Decoder for (int i = 0; i < cons_total; ++i) mod_soft(code+mod_bits*i, cons[i], precision); } + int data_bits = 0; + switch (oper_mode) { + case 14: + data_bits = 1360; + frozen_bits = frozen_2048_1392; + break; + case 15: + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; + case 16: + data_bits = 680; + frozen_bits = frozen_2048_712; + break; + default: + return; + } + *len = data_bits / 8; + crc_bits = data_bits + 32; CODE::PolarHelper::PATH metric[mesg_type::SIZE]; - polardec(metric, mesg, code, frozen_2048_1392, code_order); + polardec(metric, mesg, code, frozen_bits, code_order); systematic(); int order[mesg_type::SIZE]; for (int k = 0; k < mesg_type::SIZE; ++k) @@ -438,7 +460,7 @@ struct Decoder } int flips = 0; for (int i = 0, j = 0; i < data_bits; ++i, ++j) { - while ((frozen_2048_1392[j / 32] >> (j % 32)) & 1) + while ((frozen_bits[j / 32] >> (j % 32)) & 1) ++j; bool received = code[j] < 0; bool decoded = mesg[i].v[best] < 0; @@ -477,21 +499,22 @@ int main(int argc, char **argv) if (argc > 3) skip_count = std::atoi(argv[3]); - const int data_len = 1360 / 8; - uint8_t *output_data = new uint8_t[data_len]; + const int data_max = 1360 / 8; + uint8_t *output_data = new uint8_t[data_max]; + int data_len = 0; switch (input_file.rate()) { case 8000: - delete new Decoder(output_data, &input_file, skip_count); + delete new Decoder(output_data, &data_len, &input_file, skip_count); break; case 16000: - delete new Decoder(output_data, &input_file, skip_count); + delete new Decoder(output_data, &data_len, &input_file, skip_count); break; case 44100: - delete new Decoder(output_data, &input_file, skip_count); + delete new Decoder(output_data, &data_len, &input_file, skip_count); break; case 48000: - delete new Decoder(output_data, &input_file, skip_count); + delete new Decoder(output_data, &data_len, &input_file, skip_count); break; default: std::cerr << "Unsupported sample rate." << std::endl; diff --git a/encode.cc b/encode.cc index 76602cb..046be60 100644 --- a/encode.cc +++ b/encode.cc @@ -27,14 +27,12 @@ template struct Encoder { typedef int8_t code_type; - static const int oper_mode = 14; static const int mod_bits = 2; static const int code_order = 11; static const int code_len = 1 << code_order; static const int symbol_len = (1280 * rate) / 8000; static const int guard_len = symbol_len / 8; - static const int data_bits = 1360; - static const int crc_bits = data_bits + 32; + static const int max_bits = 1360 + 32; static const int cons_cols = 256; static const int cons_rows = 4; static const int mls0_len = 127; @@ -50,7 +48,7 @@ struct Encoder CODE::CRC crc1; CODE::BoseChaudhuriHocquenghemEncoder<255, 71> bchenc; CODE::PolarSysEnc polarenc; - code_type code[code_len], mesg[crc_bits]; + code_type code[code_len], mesg[max_bits]; cmplx fdom[symbol_len], fdom4[4*symbol_len]; cmplx tdom[symbol_len], tdom4[4*symbol_len]; cmplx temp[symbol_len]; @@ -178,7 +176,7 @@ struct Encoder { return PhaseShiftKeying<4, cmplx, code_type>::map(b); } - Encoder(DSP::WritePCM *pcm, const uint8_t *inp, int freq_off, uint64_t call_sign) : + Encoder(DSP::WritePCM *pcm, const uint8_t *inp, int freq_off, uint64_t call_sign, int oper_mode) : pcm(pcm), crc0(0xA8F4), crc1(0x8F6E37A0), bchenc({ 0b100011101, 0b101110111, 0b111110011, 0b101101001, 0b110111101, 0b111100111, 0b100101011, 0b111010111, @@ -195,19 +193,39 @@ struct Encoder pilot_block(); schmidl_cox(); meta_data((call_sign << 8) | oper_mode); - for (int i = 0; i < data_bits; ++i) - mesg[i] = nrz(CODE::get_le_bit(inp, i)); - crc1.reset(); - for (int i = 0; i < data_bits / 8; ++i) - crc1(inp[i]); - for (int i = 0; i < 32; ++i) - mesg[i+data_bits] = nrz((crc1()>>i)&1); - polarenc(code, mesg, frozen_2048_1392, code_order); - for (int j = 0; j < cons_rows; ++j) { - for (int i = 0; i < cons_cols; ++i) - fdom[bin(i+code_off)] *= - mod_map(code+mod_bits*(cons_cols*j+i)); - symbol(); + if (oper_mode > 0) { + const uint32_t *frozen_bits = nullptr; + int data_bits = 0; + switch (oper_mode) { + case 14: + data_bits = 1360; + frozen_bits = frozen_2048_1392; + break; + case 15: + data_bits = 1024; + frozen_bits = frozen_2048_1056; + break; + case 16: + data_bits = 680; + frozen_bits = frozen_2048_712; + break; + default: + return; + } + for (int i = 0; i < data_bits; ++i) + mesg[i] = nrz(CODE::get_le_bit(inp, i)); + crc1.reset(); + for (int i = 0; i < data_bits / 8; ++i) + crc1(inp[i]); + for (int i = 0; i < 32; ++i) + mesg[i+data_bits] = nrz((crc1()>>i)&1); + polarenc(code, mesg, frozen_bits, code_order); + for (int j = 0; j < cons_rows; ++j) { + for (int i = 0; i < cons_cols; ++i) + fdom[bin(i+code_off)] *= + mod_map(code+mod_bits*(cons_cols*j+i)); + symbol(); + } } for (int i = 0; i < symbol_len; ++i) fdom[i] = 0; @@ -289,6 +307,16 @@ int main(int argc, char **argv) uint8_t *input_data = new uint8_t[data_len]; for (int i = 0; i < data_len; ++i) input_data[i] = std::max(input_file.get(), 0); + int oper_mode = 0; + for (int i = 128; i < 170; ++i) + if (!oper_mode && input_data[i]) + oper_mode = 14; + for (int i = 85; i < 128; ++i) + if (!oper_mode && input_data[i]) + oper_mode = 15; + for (int i = 0; i < 85; ++i) + if (!oper_mode && input_data[i]) + oper_mode = 16; CODE::Xorshift32 scrambler; for (int i = 0; i < data_len; ++i) input_data[i] ^= scrambler(); @@ -297,16 +325,16 @@ int main(int argc, char **argv) output_file.silence(output_rate); switch (output_rate) { case 8000: - delete new Encoder(&output_file, input_data, freq_off, call_sign); + delete new Encoder(&output_file, input_data, freq_off, call_sign, oper_mode); break; case 16000: - delete new Encoder(&output_file, input_data, freq_off, call_sign); + delete new Encoder(&output_file, input_data, freq_off, call_sign, oper_mode); break; case 44100: - delete new Encoder(&output_file, input_data, freq_off, call_sign); + delete new Encoder(&output_file, input_data, freq_off, call_sign, oper_mode); break; case 48000: - delete new Encoder(&output_file, input_data, freq_off, call_sign); + delete new Encoder(&output_file, input_data, freq_off, call_sign, oper_mode); break; default: std::cerr << "Unsupported sample rate." << std::endl;