diff --git a/Makefile b/Makefile index 445364a..d44a968 100644 --- a/Makefile +++ b/Makefile @@ -17,10 +17,10 @@ test: encode decode $(QEMU) ./encode audio.wav 8000 8 1 1500 5 /dev/urandom $(QEMU) ./decode audio.wav /dev/null -encode: encode.cc +encode: encode.cc common.hh $(CXX) $(CXXFLAGS) $< -o $@ -decode: decode.cc schmidl_cox.hh +decode: decode.cc common.hh schmidl_cox.hh $(CXX) $(CXXFLAGS) $< -o $@ freezer: freezer.cc diff --git a/common.hh b/common.hh new file mode 100644 index 0000000..4a990b1 --- /dev/null +++ b/common.hh @@ -0,0 +1,159 @@ +/* +OFDM modem common bits + +Copyright 2025 Ahmet Inan +*/ + +#pragma once + +#include "polar_tables.hh" +#include "hadamard_encoder.hh" + +struct Common +{ + 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 = 4096; + static const int symbols_max = 44; + static const int mls0_poly = 0x331; + static const int mls0_seed = 214; + static const int mls1_poly = 0x25; + static const int data_tones = 256; + static const int pilot_tones = 32; + static const int reserved_tones = 32; + static const int tone_count = data_tones + pilot_tones + reserved_tones; + static const int block_length = 10; + static const int block_skew = 3; + static const int first_pilot = 4; + static const int first_reserved = 9; + CODE::HadamardEncoder<6> hadamard_encoder; + int8_t mode[32]; + const uint32_t *frozen_bits; + int mod_bits; + int data_bits; + int data_bytes; + int code_order; + int tone_off; + int pilot_off; + int reserved_off; + int symbol_count; + + void setup(int oper_mode) + { + switch (oper_mode) { + case 0: + 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 3: + mod_bits = 2; + symbol_count = 16; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + 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; + code_order = 12; + data_bits = 2048; + frozen_bits = frozen_4096_2080; + break; + case 6: + mod_bits = 4; + symbol_count = 8; + code_order = 13; + data_bits = 4096; + frozen_bits = frozen_8192_4128; + break; + case 7: + mod_bits = 4; + symbol_count = 16; + code_order = 14; + data_bits = 8192; + frozen_bits = frozen_16384_8224; + 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; + } + data_bytes = data_bits / 8; + } +}; + diff --git a/decode.cc b/decode.cc index 9d3bec9..d8e4333 100644 --- a/decode.cc +++ b/decode.cc @@ -8,6 +8,7 @@ Copyright 2021 Ahmet Inan #include #include namespace DSP { using std::abs; using std::min; using std::cos; using std::sin; } +#include "common.hh" #include "schmidl_cox.hh" #include "bip_buffer.hh" #include "theil_sen.hh" @@ -26,13 +27,11 @@ namespace DSP { using std::abs; using std::min; using std::cos; using std::sin; #include "crc.hh" #include "psk.hh" #include "qam.hh" -#include "polar_tables.hh" #include "polar_list_decoder.hh" -#include "hadamard_encoder.hh" #include "hadamard_decoder.hh" template -struct Decoder +struct Decoder : Common { typedef int16_t code_type; typedef SIMD mesg_type; @@ -41,26 +40,10 @@ 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 = 8; - static const int code_max = 16; - static const int bits_max = 1 << code_max; - static const int data_max = 4096; - static const int symbols_max = 44; - static const int mls0_poly = 0x331; - static const int mls0_seed = 214; - static const int mls1_poly = 0x25; static const int buffer_len = 5 * extended_len; static const int search_pos = extended_len; - static const int pilot_tones = 32; - static const int reserved_tones = 32; - static const int data_tones = 256; - static const int block_length = 10; - static const int block_skew = 3; - static const int first_pilot = 4; - static const int first_reserved = 9; - static const int tone_count = data_tones + pilot_tones + reserved_tones; - static const int tone_off = - tone_count / 2; static const int tones_max = tone_count * symbols_max; + static const int tone_off = - tone_count / 2; DSP::ReadPCM *pcm; DSP::FastFourierTransform fwd; DSP::BlockDC blockdc; @@ -69,27 +52,17 @@ struct Decoder DSP::TheilSenEstimator tse; SchmidlCox correlator; CODE::CRC crc0; - CODE::HadamardEncoder<6> hadamard_encoder; CODE::HadamardDecoder<6> hadamard_decoder; CODE::PolarListDecoder polar_decoder; uint8_t output_data[data_max]; mesg_type mesg[bits_max]; code_type code[bits_max], perm[bits_max]; - int8_t mode[32]; cmplx demod[tones_max], chan[tone_count], tone[tone_count]; cmplx fdom[symbol_len], tdom[symbol_len]; value index[tone_count], phase[tone_count]; value cfo_rad, sfo_rad; - const uint32_t *frozen_bits; - int mod_bits; - int code_order; int symbol_pos; int crc_bits; - int data_bits; - int data_bytes; - int pilot_off; - int reserved_off; - int symbol_count; static int bin(int carrier) { @@ -171,118 +144,6 @@ struct Decoder tmp = hilbert(blockdc(tmp.real())); return input_hist(tmp); } - 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 3: - mod_bits = 2; - symbol_count = 16; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - 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; - code_order = 12; - data_bits = 2048; - frozen_bits = frozen_4096_2080; - break; - case 6: - mod_bits = 4; - symbol_count = 8; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - break; - case 7: - mod_bits = 4; - symbol_count = 16; - code_order = 14; - data_bits = 8192; - frozen_bits = frozen_16384_8224; - 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; - } - data_bytes = data_bits / 8; - } Decoder(DSP::ReadPCM *pcm, const char *const *output_names, int output_count) : pcm(pcm), correlator(mls0_seq()), crc0(0x8F6E37A0) { diff --git a/encode.cc b/encode.cc index 1d33e24..580b21c 100644 --- a/encode.cc +++ b/encode.cc @@ -7,6 +7,7 @@ Copyright 2021 Ahmet Inan #include #include #include +#include "common.hh" #include "xorshift.hh" #include "complex.hh" #include "utils.hh" @@ -19,38 +20,21 @@ Copyright 2021 Ahmet Inan #include "crc.hh" #include "psk.hh" #include "qam.hh" -#include "polar_tables.hh" #include "polar_encoder.hh" -#include "hadamard_encoder.hh" template -struct Encoder +struct Encoder : public Common { typedef int8_t code_type; 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 = 4096; - static const int mls0_poly = 0x331; - static const int mls0_seed = 214; - static const int mls1_poly = 0x25; - static const int data_tones = 256; - static const int pilot_tones = 32; - static const int reserved_tones = 32; - static const int tone_count = data_tones + pilot_tones + reserved_tones; - static const int block_length = 10; - static const int block_skew = 3; - static const int first_pilot = 4; - static const int first_reserved = 9; DSP::WritePCM *pcm; DSP::FastFourierTransform fwd; DSP::FastFourierTransform bwd; CODE::CRC crc0; - CODE::HadamardEncoder<6> hadamard_encoder; CODE::PolarEncoder polar_encoder; uint8_t input_data[data_max]; code_type code[bits_max], perm[bits_max], mesg[bits_max]; - int8_t mode[32]; cmplx fdom[symbol_len]; cmplx tdom[symbol_len]; cmplx kern[symbol_len]; @@ -58,15 +42,6 @@ struct Encoder cmplx tone[tone_count]; value weight[guard_len]; value papr_min, papr_max; - const uint32_t *frozen_bits; - int mod_bits; - int data_bits; - int data_bytes; - int code_order; - int tone_off; - int pilot_off; - int reserved_off; - int symbol_count; static int bin(int carrier) { @@ -234,124 +209,6 @@ struct Encoder dest[i] = src[seq()]; } } - void setup(int oper_mode, int freq_off) - { - switch (oper_mode) { - case 0: - 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 3: - mod_bits = 2; - symbol_count = 16; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - 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; - code_order = 12; - data_bits = 2048; - frozen_bits = frozen_4096_2080; - break; - case 6: - mod_bits = 4; - symbol_count = 8; - code_order = 13; - data_bits = 4096; - frozen_bits = frozen_8192_4128; - break; - case 7: - mod_bits = 4; - symbol_count = 16; - code_order = 14; - data_bits = 8192; - frozen_bits = frozen_16384_8224; - 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; - } - data_bytes = data_bits / 8; - int offset = (freq_off * symbol_len) / rate; - tone_off = offset - tone_count / 2; - } void tone_reservation_kernel() { value mag = 1 / value(10 * reserved_tones); @@ -375,7 +232,9 @@ struct Encoder Encoder(DSP::WritePCM *pcm, const char *const *input_names, int input_count, int freq_off, int oper_mode) : pcm(pcm), crc0(0x8F6E37A0) { - setup(oper_mode, freq_off); + setup(oper_mode); + int offset = (freq_off * symbol_len) / rate; + tone_off = offset - tone_count / 2; guard_interval_weights(); papr_min = 1000, papr_max = -1000; leading_noise();