diff --git a/README.md b/README.md index 3db1a69..e0aa7be 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ Quick start: -Create file ```uncoded.dat``` with ```64768``` bits of random data: +Create file ```uncoded.dat``` with ```64576``` bits of random data: ``` -dd if=/dev/urandom of=uncoded.dat bs=1 count=8096 +dd if=/dev/urandom of=uncoded.dat bs=1 count=8072 ``` 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: diff --git a/decode.cc b/decode.cc index 989b252..cb7626a 100644 --- a/decode.cc +++ b/decode.cc @@ -25,6 +25,8 @@ namespace DSP { using std::abs; using std::min; using std::cos; using std::sin; #include "crc.hh" #include "osd.hh" #include "psk.hh" +#include "galois_field.hh" +#include "bose_chaudhuri_hocquenghem_decoder.hh" template struct SchmidlCox @@ -155,7 +157,7 @@ struct Decoder static const int filter_len = (((21 * rate) / 8000) & ~3) | 1; static const int guard_len = symbol_len / 8; static const int code_bits = 64800; - static const int data_bits = code_bits - 32; + static const int data_bits = code_bits - 32 - 12 * 16; static const int code_cols = 432; static const int code_rows = code_bits / code_cols / Mod::BITS; static const int code_off = -216; @@ -177,6 +179,9 @@ struct Decoder SchmidlCox correlator; CODE::CRC crc0; CODE::CRC crc1; + typedef CODE::GaloisField<16, 0b10000000000101101, uint16_t> GF; + GF gf; + CODE::BoseChaudhuriHocquenghemDecoder<24, 1, 65343, GF> bchdec1; CODE::OrderedStatisticsDecoder<255, 71, 4> osddec; int8_t genmat[255*71]; cmplx head[symbol_len], tail[symbol_len]; @@ -341,8 +346,15 @@ struct Decoder } } } + int ret = bchdec1(out, out+(data_bits+32)/8, 0, 0, data_bits+32); + if (ret < 0) { + std::cerr << "payload BCH error." << std::endl; + return; + } + if (ret) + std::cerr << "payload BCH corrected " << ret << " errors." << std::endl; crc1.reset(); - for (int i = 0; i < code_bits / 8; ++i) + for (int i = 0; i < (data_bits+32)/8; ++i) crc1(out[i]); if (crc1()) std::cerr << "payload CRC error." << std::endl; @@ -399,7 +411,7 @@ int main(int argc, char **argv) std::cerr << "Couldn't open file \"" << output_name << "\" for writing." << std::endl; return 1; } - const int data_len = code_len - 32 / 8; + const int data_len = code_len - (32 + 12 * 16) / 8; for (int i = 0; i < data_len; ++i) output_file.put(output_data[i]); delete []output_data; diff --git a/encode.cc b/encode.cc index f986660..c564469 100644 --- a/encode.cc +++ b/encode.cc @@ -27,7 +27,7 @@ struct Encoder static const int symbol_len = (1280 * rate) / 8000; static const int guard_len = symbol_len / 8; static const int code_bits = 64800; - static const int data_bits = code_bits - 32; + static const int data_bits = code_bits - 32 - 12 * 16; static const int code_cols = 432; static const int code_rows = code_bits / code_cols / Mod::BITS; static const int mls0_len = 127; @@ -39,7 +39,8 @@ struct Encoder DSP::FastFourierTransform bwd; CODE::CRC crc0; CODE::CRC crc1; - CODE::BoseChaudhuriHocquenghemEncoder<255, 71> bchenc; + CODE::BoseChaudhuriHocquenghemEncoder<255, 71> bchenc0; + CODE::BoseChaudhuriHocquenghemEncoder<65535, 65343> bchenc1; cmplx fdom[symbol_len]; cmplx tdom[symbol_len]; cmplx guard[guard_len]; @@ -115,7 +116,7 @@ struct Encoder uint16_t cs = crc0(md << 9); for (int i = 0; i < 16; ++i) CODE::set_be_bit(data, i+55, (cs>>i)&1); - bchenc(data, parity); + bchenc0(data, parity); CODE::MLS seq4(mls1_poly); value mls1_fac = sqrt(value(symbol_len) / value(mls1_len)); for (int i = 0; i < symbol_len; ++i) @@ -132,13 +133,17 @@ struct Encoder symbol(); } Encoder(DSP::WritePCM *pcm, uint8_t *inp, int freq_off, uint64_t call_sign) : - pcm(pcm), crc0(0xA8F4), crc1(0xD419CC15), bchenc({ + pcm(pcm), crc0(0xA8F4), crc1(0xD419CC15), bchenc0({ 0b100011101, 0b101110111, 0b111110011, 0b101101001, 0b110111101, 0b111100111, 0b100101011, 0b111010111, 0b000010011, 0b101100101, 0b110001011, 0b101100011, 0b100011011, 0b100111111, 0b110001101, 0b100101101, 0b101011111, 0b111111001, 0b111000011, 0b100111001, - 0b110101001, 0b000011111, 0b110000111, 0b110110001}) + 0b110101001, 0b000011111, 0b110000111, 0b110110001}), bchenc1({ + 0b10000000000101101, 0b10000000101110011, 0b10000111110111101, + 0b10101101001010101, 0b10001111100101111, 0b11111011110110101, + 0b11010111101100101, 0b10111001101100111, 0b10000111010100001, + 0b10111010110100111, 0b10011101000101101, 0b10001101011100011}) { code_off = (freq_off * symbol_len) / rate - code_cols / 2; mls0_off = code_off + 90; @@ -153,6 +158,7 @@ struct Encoder crc1(inp[i]); for (int i = 0; i < 4; ++i) inp[data_bits/8+i] = (crc1() >> (8*i)) & 255; + bchenc1(inp, inp+(data_bits+32)/8, data_bits+32); for (int j = 0; j < code_rows; ++j) { for (int i = 0; i < code_cols; ++i) { value tmp[Mod::BITS]; @@ -233,7 +239,7 @@ int main(int argc, char **argv) return 1; } const int code_len = 64800 / 8; - const int data_len = code_len - 32 / 8; + const int data_len = code_len - (32 + 12 * 16) / 8; uint8_t *input_data = new uint8_t[code_len]; for (int i = 0; i < data_len; ++i) input_data[i] = input_file.get();