mirror of
https://github.com/aicodix/modem.git
synced 2026-04-27 14:30:34 +00:00
moved common code to Common class
This commit is contained in:
parent
7c2b4d94a0
commit
8cab519b16
4 changed files with 169 additions and 290 deletions
4
Makefile
vendored
4
Makefile
vendored
|
|
@ -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
|
||||
|
|
|
|||
159
common.hh
Normal file
159
common.hh
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
OFDM modem common bits
|
||||
|
||||
Copyright 2025 Ahmet Inan <inan@aicodix.de>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
};
|
||||
|
||||
145
decode.cc
145
decode.cc
|
|
@ -8,6 +8,7 @@ Copyright 2021 Ahmet Inan <inan@aicodix.de>
|
|||
#include <cassert>
|
||||
#include <cmath>
|
||||
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 <typename value, typename cmplx, int rate>
|
||||
struct Decoder
|
||||
struct Decoder : Common
|
||||
{
|
||||
typedef int16_t code_type;
|
||||
typedef SIMD<code_type, 32> 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<value> *pcm;
|
||||
DSP::FastFourierTransform<symbol_len, cmplx, -1> fwd;
|
||||
DSP::BlockDC<value, value> blockdc;
|
||||
|
|
@ -69,27 +52,17 @@ struct Decoder
|
|||
DSP::TheilSenEstimator<value, tone_count> tse;
|
||||
SchmidlCox<value, cmplx, search_pos, symbol_len, guard_len> correlator;
|
||||
CODE::CRC<uint32_t> crc0;
|
||||
CODE::HadamardEncoder<6> hadamard_encoder;
|
||||
CODE::HadamardDecoder<6> hadamard_decoder;
|
||||
CODE::PolarListDecoder<mesg_type, code_max> 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<value> *pcm, const char *const *output_names, int output_count) :
|
||||
pcm(pcm), correlator(mls0_seq()), crc0(0x8F6E37A0)
|
||||
{
|
||||
|
|
|
|||
151
encode.cc
151
encode.cc
|
|
@ -7,6 +7,7 @@ Copyright 2021 Ahmet Inan <inan@aicodix.de>
|
|||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include "common.hh"
|
||||
#include "xorshift.hh"
|
||||
#include "complex.hh"
|
||||
#include "utils.hh"
|
||||
|
|
@ -19,38 +20,21 @@ Copyright 2021 Ahmet Inan <inan@aicodix.de>
|
|||
#include "crc.hh"
|
||||
#include "psk.hh"
|
||||
#include "qam.hh"
|
||||
#include "polar_tables.hh"
|
||||
#include "polar_encoder.hh"
|
||||
#include "hadamard_encoder.hh"
|
||||
|
||||
template <typename value, typename cmplx, int rate>
|
||||
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<value> *pcm;
|
||||
DSP::FastFourierTransform<symbol_len, cmplx, -1> fwd;
|
||||
DSP::FastFourierTransform<symbol_len, cmplx, 1> bwd;
|
||||
CODE::CRC<uint32_t> crc0;
|
||||
CODE::HadamardEncoder<6> hadamard_encoder;
|
||||
CODE::PolarEncoder<code_type> 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<value> *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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue