From b9502ebe8649f2326362628c2db86683d8ad8244 Mon Sep 17 00:00:00 2001 From: RecklessAndFeckless Date: Thu, 10 Oct 2024 23:37:15 -0400 Subject: [PATCH] I am become lost, confuser of words --- include/encoder/Scrambler.h | 39 ++-- include/encoder/SymbolFormation.h | 283 +++++++++++++++--------------- 2 files changed, 166 insertions(+), 156 deletions(-) diff --git a/include/encoder/Scrambler.h b/include/encoder/Scrambler.h index 48ffa76..d73bb70 100644 --- a/include/encoder/Scrambler.h +++ b/include/encoder/Scrambler.h @@ -15,7 +15,7 @@ public: /** * @brief Constructor initializes the scrambler with a predefined register value. */ - Scrambler() : data_sequence_register(0x0BAD) {} + Scrambler() : data_sequence_register(0x0BAD), symbol_count(0) {} /** * @brief Scrambles a synchronization preamble using a fixed randomizer sequence. @@ -60,37 +60,44 @@ public: private: uint16_t data_sequence_register; + size_t symbol_count; /** * @brief Generates the next value from the data sequence randomizing generator. * @return A 3-bit random value (0-7) from the current state of the LFSR. */ uint8_t getNextRandomValue() { - uint8_t output = data_sequence_register & 0x07; + // Reset the LFSR state every 160 symbols, as per the specification + if (symbol_count >= 160) { + data_sequence_register = 0x0BAD; // Load initial value "BAD" (hex) + symbol_count = 0; + } + symbol_count++; + uint8_t output = data_sequence_register & 0x07; // Extract the lower 3 bits + + // Perform 8 shifts to generate the next 3-bit random value for (int i = 0; i < 8; ++i) { - // Get the most significant bit - uint16_t msb = (data_sequence_register >> 11) & 0x01; + // Extract the MSB (bit 11 in a 12-bit register) + uint16_t msb = (data_sequence_register & 0x0800) ? 1 : 0; // Bit 11 is 0x0800 - // XOR taps and shift into the LFSR - uint16_t bit1 = (data_sequence_register & 0x01) ^ msb; - uint16_t bit4 = ((data_sequence_register >> 3) & 0x01) ^ msb; - uint16_t bit6 = ((data_sequence_register >> 5) & 0x01) ^ msb; + // Shift the register left by 1 bit + data_sequence_register <<= 1; - // Update specific bits in the shift register - data_sequence_register = (data_sequence_register & ~(1 << 5)) | (bit6 << 5); - data_sequence_register = (data_sequence_register & ~(1 << 3)) | (bit4 << 3); - data_sequence_register = (data_sequence_register & ~0x01) | bit1; + // Apply feedback if MSB was set + if (msb) { + // XOR with the tapped bits (positions 1, 4, and 6) + // Tap mask is 0x052 (bits 1, 4, 6): taps at positions 1, 4, 6 affect the feedback + data_sequence_register ^= 0x052; + } - // Shift left and insert the MSB - data_sequence_register = (data_sequence_register << 1) | msb; - - // Keep the LFSR in 12 bits + // Ensure the LFSR stays within 12 bits data_sequence_register &= 0x0FFF; } return output; } + }; #endif diff --git a/include/encoder/SymbolFormation.h b/include/encoder/SymbolFormation.h index ba02bfb..72c177b 100644 --- a/include/encoder/SymbolFormation.h +++ b/include/encoder/SymbolFormation.h @@ -10,24 +10,6 @@ #include "Scrambler.h" -enum class SymbolType { SYNC_PREAMBLE, UNKNOWN_DATA, PROBE_DATA }; - -static constexpr size_t LONG_PROBE_DATA_BLOCK_SIZE = 20; -static constexpr size_t SHORT_PROBE_DATA_BLOCK_SIZE = 16; -static constexpr size_t LONG_UNKNOWN_DATA_BLOCK_SIZE = 32; -static constexpr size_t SHORT_UNKNOWN_DATA_BLOCK_SIZE = 20; -static constexpr size_t SET_SIZE_LONG = 360; -static constexpr size_t SET_SIZE_SHORT = 32; - -std::vector Sync_Preamble_0 = {0, 0, 0, 0, 0, 0, 0, 0}; -std::vector Sync_Preamble_1 = {0, 4, 0, 4, 0, 4, 0, 4}; -std::vector Sync_Preamble_2 = {0, 0, 4, 4, 0, 0, 4, 4}; -std::vector Sync_Preamble_3 = {0, 4, 4, 0, 0, 4, 4, 0}; -std::vector Sync_Preamble_4 = {0, 0, 0, 0, 4, 4, 4, 4}; -std::vector Sync_Preamble_5 = {0, 4, 0, 4, 4, 0, 4, 0}; -std::vector Sync_Preamble_6 = {0, 0, 4, 4, 4, 4, 0, 0}; -std::vector Sync_Preamble_7 = {0, 4, 4, 0, 4, 0, 0, 4}; - std::vector baud75_exceptional_0 = {0, 0, 0, 0, 4, 4, 4, 4}; std::vector baud75_exceptional_1 = {0, 4, 0, 4, 4, 0, 4, 0}; std::vector baud75_exceptional_2 = {0, 0, 4, 4, 4, 4, 0, 0}; @@ -46,8 +28,10 @@ class SymbolFormation { std::vector sync_preamble = generateSyncPreamble(); sync_preamble = scrambler.scrambleSyncPreamble(sync_preamble); - size_t unknown_data_block_size = (baud_rate >= 2400) ? LONG_UNKNOWN_DATA_BLOCK_SIZE : SHORT_UNKNOWN_DATA_BLOCK_SIZE; + // Determine the block sizes + size_t unknown_data_block_size = (baud_rate >= 2400) ? 32 : 20; size_t interleaver_block_size; + if (baud_rate == 2400) { interleaver_block_size = (interleave_setting == 2) ? (40 * 576) : (40 * 72); } else if (baud_rate == 1200) { @@ -64,13 +48,14 @@ class SymbolFormation { size_t current_index = 0; while (current_index < symbol_data.size()) { - // Process unknown data block + // Determine the size of the current unknown data block size_t block_size = std::min(unknown_data_block_size, symbol_data.size() - current_index); std::vector unknown_data_block(symbol_data.begin() + current_index, symbol_data.begin() + current_index + block_size); current_index += block_size; + // Map the unknown data based on baud rate if (baud_rate == 75) { - size_t set_size = (interleave_setting == 2) ? SET_SIZE_LONG : SET_SIZE_SHORT; + size_t set_size = (interleave_setting == 2) ? 360 : 32; for (size_t i = 0; i < unknown_data_block.size(); i += set_size) { bool is_exceptional_set = (set_count % ((interleave_setting == 1) ? 45 : 360)) == 0; std::vector mapped_set = map75bpsSet(unknown_data_block, i, set_size, is_exceptional_set); @@ -78,14 +63,16 @@ class SymbolFormation { set_count++; } } else { + // For baud rates greater than 75 bps std::vector mapped_unknown_data = mapUnknownData(unknown_data_block); symbol_count += mapped_unknown_data.size(); data_stream.insert(data_stream.end(), mapped_unknown_data.begin(), mapped_unknown_data.end()); } + // Insert probe data if we are at an interleaver block boundary if (baud_rate > 75) { - bool inside_block = (symbol_count % interleaver_block_size) != 0; - std::vector probe_data = generateProbeData(inside_block); + bool is_at_boundary = (symbol_count % interleaver_block_size) == 0; + std::vector probe_data = generateProbeData(!is_at_boundary); data_stream.insert(data_stream.end(), probe_data.begin(), probe_data.end()); } } @@ -108,113 +95,57 @@ class SymbolFormation { bool is_frequency_hopping; Scrambler scrambler = Scrambler(); - void appendProbeMapping(std::vector& symbol_stream, uint8_t symbol, size_t repeat_count) { + std::vector mapChannelSymbolToTribitPattern(uint8_t symbol, bool repeat_twice = false) { + std::vector tribit_pattern; + switch (symbol) { - case 0: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_0.begin(), Sync_Preamble_0.end()); - } + case 0b000: // 000 + tribit_pattern = {0, 0, 0, 0, 0, 0, 0, 0}; break; - case 1: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_1.begin(), Sync_Preamble_1.end()); - } + case 0b001: // 001 + tribit_pattern = {0, 4, 0, 4, 0, 4, 0, 4}; break; - case 2: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_2.begin(), Sync_Preamble_2.end()); - } + case 0b010: // 010 + tribit_pattern = {0, 0, 4, 4, 0, 0, 4, 4}; break; - case 3: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_3.begin(), Sync_Preamble_3.end()); - } + case 0b011: // 011 + tribit_pattern = {0, 4, 4, 0, 0, 4, 4, 0}; break; - case 4: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_4.begin(), Sync_Preamble_4.end()); - } + case 0b100: // 100 + tribit_pattern = {0, 0, 0, 0, 4, 4, 4, 4}; break; - case 5: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_5.begin(), Sync_Preamble_5.end()); - } + case 0b101: // 101 + tribit_pattern = {0, 4, 0, 4, 4, 0, 4, 0}; break; - case 6: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_6.begin(), Sync_Preamble_6.end()); - } + case 0b110: // 110 + tribit_pattern = {0, 0, 4, 4, 4, 4, 0, 0}; break; - case 7: - for (int i = 0; i < repeat_count; ++i) { - symbol_stream.insert(symbol_stream.end(), Sync_Preamble_7.begin(), Sync_Preamble_7.end()); - } + case 0b111: // 111 + tribit_pattern = {0, 4, 4, 0, 4, 0, 0, 4}; break; default: throw std::invalid_argument("Invalid channel symbol"); } - } - void append75bpsMapping(std::vector& symbol_stream, uint8_t symbol, bool is_exceptional_set) { - if (is_exceptional_set) { - switch (symbol) { - case 0: - for (int i = 0; i < 4; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_exceptional_0.begin(), baud75_exceptional_0.end()); - } - break; - case 1: - for (int i = 0; i < 4; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_exceptional_1.begin(), baud75_exceptional_1.end()); - } - break; - case 2: - for (int i = 0; i < 4; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_exceptional_2.begin(), baud75_exceptional_2.end()); - } - break; - case 3: - for (int i = 0; i < 4; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_exceptional_3.begin(), baud75_exceptional_3.end()); - } - break; - default: - throw std::invalid_argument("Invalid channel symbol"); - } + if (repeat_twice) { + // Repeat the pattern twice instead of four times for known symbols + tribit_pattern.insert(tribit_pattern.end(), tribit_pattern.begin(), tribit_pattern.end()); } else { - switch (symbol) { - case 0: - for (int i = 0; i < 8; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_normal_0.begin(), baud75_normal_0.end()); - } - break; - case 1: - for (int i = 0; i < 8; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_normal_1.begin(), baud75_normal_1.end()); - } - break; - case 2: - for (int i = 0; i < 8; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_normal_2.begin(), baud75_normal_2.end()); - } - break; - case 3: - for (int i = 0; i < 8; ++i) { - symbol_stream.insert(symbol_stream.end(), baud75_normal_3.begin(), baud75_normal_3.end()); - } - break; - default: - throw std::invalid_argument("Invalid channel symbol"); - } + // Repeat the pattern four times as per Table XIII + tribit_pattern.insert(tribit_pattern.end(), tribit_pattern.begin(), tribit_pattern.end()); + tribit_pattern.insert(tribit_pattern.end(), tribit_pattern.begin(), tribit_pattern.end()); + tribit_pattern.insert(tribit_pattern.end(), tribit_pattern.begin(), tribit_pattern.end()); } + + return tribit_pattern; } std::vector generateSyncPreamble() { std::vector preamble; - size_t num_segments = (interleave_setting == 0) ? 3 : 24; + size_t num_segments = (interleave_setting == 2) ? 24 : 3; - std::vector segment_sequence = {0,1,3,0,1,3,1,2,0}; + std::vector segment_sequence = {0, 1, 3, 0, 1, 3, 1, 2, 0}; uint8_t D1, D2; if (baud_rate == 4800) { @@ -245,7 +176,7 @@ class SymbolFormation { segment_sequence.push_back(D1); segment_sequence.push_back(D2); - + uint8_t C1, C2, C3; if (interleave_setting == 2) { C1 = 5; C2 = 5; C3 = 7; @@ -255,17 +186,16 @@ class SymbolFormation { for (size_t i = 0; i < num_segments; i++) { std::vector full_segment_sequence = segment_sequence; - - C1 = (1 << 2) | C1; - C2 = (1 << 2) | C2; - C3 = (1 << 2) | C3; - + full_segment_sequence.push_back(C1); full_segment_sequence.push_back(C2); full_segment_sequence.push_back(C3); full_segment_sequence.push_back(0); - preamble.insert(preamble.end(), full_segment_sequence.begin(), full_segment_sequence.end()); + for (uint8_t symbol : full_segment_sequence) { + std::vector mapped_tribit = mapChannelSymbolToTribitPattern(symbol); + preamble.insert(preamble.end(), mapped_tribit.begin(), mapped_tribit.end()); + } if (C3 > 0) { C3--; @@ -278,17 +208,14 @@ class SymbolFormation { C3 = 3; } } - - std::vector final_preamble; - for (auto& symbol : preamble) { - appendProbeMapping(final_preamble, symbol, 4); - } - return final_preamble; + return preamble; } std::vector generateProbeData(bool is_inside_block) { std::vector probe_data; + + // Determine interleaver block size based on baud rate and interleave setting size_t interleaver_block_size; if (baud_rate == 2400) { interleaver_block_size = (interleave_setting == 2) ? (40 * 576) : (40 * 72); @@ -300,10 +227,11 @@ class SymbolFormation { interleaver_block_size = (interleave_setting == 2) ? (20 * 36) : (10 * 9); } - probe_data.resize(interleaver_block_size, 0x00); - - if (!is_inside_block) { - // Set the known symbol patterns for D1 and D2 based on Table XI and Table XIII + // If we are inside an interleaver block, the probe data is filled with zeros + if (is_inside_block) { + probe_data.resize(interleaver_block_size, 0x00); + } else { + // Set the known symbol patterns for D1 and D2 based on Table XI uint8_t D1, D2; if (baud_rate == 4800) { D1 = 7; D2 = 6; @@ -324,24 +252,94 @@ class SymbolFormation { } else if (baud_rate == 150) { D1 = (interleave_setting <= 1) ? 7 : 5; D2 = 4; + } else if (baud_rate == 75) { + D1 = (interleave_setting <= 1) ? 7 : 5; + D2 = 5; } else { throw std::invalid_argument("Invalid baud rate for generateProbeData"); } - std::vector final_probe_data; - for (auto symbol : probe_data) { - appendProbeMapping(final_probe_data, symbol, 2); - } + // Generate the known symbol patterns D1 and D2, repeated twice + std::vector d1_pattern = mapChannelSymbolToTribitPattern(D1, true); + std::vector d2_pattern = mapChannelSymbolToTribitPattern(D2, true); + + probe_data.insert(probe_data.end(), d1_pattern.begin(), d1_pattern.end()); + probe_data.insert(probe_data.end(), d2_pattern.begin(), d2_pattern.end()); } return probe_data; } + void append75bpsMapping(std::vector& symbol_stream, uint8_t symbol, bool is_exceptional_set) { + if (is_exceptional_set) { + switch (symbol) { + case 0: + // Exceptional set mapping for symbol 00: (0000 4444) repeated 4 times + for (int i = 0; i < 4; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_exceptional_0.begin(), baud75_exceptional_0.end()); + } + break; + case 1: + // Exceptional set mapping for symbol 01: (0404 4040) repeated 4 times + for (int i = 0; i < 4; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_exceptional_1.begin(), baud75_exceptional_1.end()); + } + break; + case 2: + // Exceptional set mapping for symbol 10: (0044 4400) repeated 4 times + for (int i = 0; i < 4; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_exceptional_2.begin(), baud75_exceptional_2.end()); + } + break; + case 3: + // Exceptional set mapping for symbol 11: (0440 4004) repeated 4 times + for (int i = 0; i < 4; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_exceptional_3.begin(), baud75_exceptional_3.end()); + } + break; + default: + throw std::invalid_argument("Invalid channel symbol for exceptional set mapping"); + } + } else { + switch (symbol) { + case 0: + // Normal set mapping for symbol 00: (0000) repeated 8 times + for (int i = 0; i < 8; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_normal_0.begin(), baud75_normal_0.end()); + } + break; + case 1: + // Normal set mapping for symbol 01: (0404) repeated 8 times + for (int i = 0; i < 8; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_normal_1.begin(), baud75_normal_1.end()); + } + break; + case 2: + // Normal set mapping for symbol 10: (0044) repeated 8 times + for (int i = 0; i < 8; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_normal_2.begin(), baud75_normal_2.end()); + } + break; + case 3: + // Normal set mapping for symbol 11: (0440) repeated 8 times + for (int i = 0; i < 8; ++i) { + symbol_stream.insert(symbol_stream.end(), baud75_normal_3.begin(), baud75_normal_3.end()); + } + break; + default: + throw std::invalid_argument("Invalid channel symbol for normal set mapping"); + } + } + } + std::vector map75bpsSet(const std::vector& data, size_t start_index, size_t set_size, bool is_exceptional_set) { std::vector mapped_set; - - for (auto symbol : data) { - append75bpsMapping(mapped_set, symbol, is_exceptional_set); + + // Make sure we do not exceed the size of the data vector + size_t end_index = std::min(start_index + set_size, data.size()); + + for (size_t i = start_index; i < end_index; ++i) { + append75bpsMapping(mapped_set, data[i], is_exceptional_set); } return mapped_set; @@ -349,25 +347,24 @@ class SymbolFormation { std::vector mapUnknownData(const std::vector& data) { std::vector mapped_data; - - for (auto symbol : data) { + for (auto symbol : data) { if (baud_rate >= 2400) { // Pass tribit symbols as-is mapped_data.push_back(symbol); } else if (baud_rate == 1200) { // Map dibit symbols to tribit symbols 0, 2, 4, 6 switch (symbol) { - case 0: + case 0b00: mapped_data.push_back(0); break; - case 1: + case 0b01: mapped_data.push_back(2); break; - case 2: + case 0b10: mapped_data.push_back(4); break; - case 3: + case 0b11: mapped_data.push_back(6); break; default: @@ -375,7 +372,13 @@ class SymbolFormation { } } else if (baud_rate >= 150 && baud_rate <= 600) { // Map binary symbols to tribit symbols 0 and 4 - mapped_data.push_back(symbol == 0 ? 0 : 4); + if (symbol == 0) { + mapped_data.push_back(0); + } else if (symbol == 1) { + mapped_data.push_back(4); + } else { + throw std::invalid_argument("Invalid binary symbol for baud rates 150 to 600 bps"); + } } else { throw std::invalid_argument("Invalid baud rate for mapUnknownData"); }