MIL-STD-188-110C/include/encoder/FECEncoder.h

132 lines
4.6 KiB
C++

#ifndef FEC_ENCODER_H
#define FEC_ENCODER_H
#include <cstdint>
#include <stdexcept>
#include <vector>
#include "bitstream/bitstream.h"
/**
* @class FECEncoder
* @brief A class to perform Forward Error Correction (FEC) encoding on input data.
*
* The FECEncoder class implements convolutional coding with different rates based on the
* baud rate and whether frequency hopping is used. It uses a constraint length 7 convolutional
* code with repeat coding or puncturing as required.
*/
class FECEncoder {
public:
/**
* @brief Constructs an FECEncoder.
* @param baud_rate The baud rate for the encoding process.
* @param is_frequency_hopping True if frequency hopping is used, otherwise false.
*/
FECEncoder(size_t baud_rate, bool is_frequency_hopping)
: baud_rate(baud_rate), is_frequency_hopping(is_frequency_hopping), shift_register(0) {}
/**
* @brief Encodes the input data using convolutional coding.
* @param data The input BitStream to be encoded.
* @return The encoded BitStream.
*/
void encode(bitstream::growing_bit_writer<std::vector<uint8_t>>& output_data, bitstream::fixed_bit_reader& input_data) {
std::vector<uint8_t> intermediate_buffer;
bitstream::growing_bit_writer<std::vector<uint8_t>> intermediate_data(intermediate_buffer);
while (input_data.get_remaining_bits() > 0) {
uint32_t bit;
input_data.serialize_bits(bit, 1);
// Shift the input bit into the shift register
shift_register = ((shift_register << 1) | bit) & 0x7F;
// Calculate T1 and T2 using the generator polynomials
uint32_t t1 = calculateT1();
uint32_t t2 = calculateT2();
// Append T1 and T2 to the encoded data
intermediate_data.serialize_bits(t1, 1);
intermediate_data.serialize_bits(t2, 1);
}
bitstream::fixed_bit_reader intermediate_reader(intermediate_buffer.data(), intermediate_data.get_num_bits_serialized());
// Apply repetition or puncturing based on baud rate and operation mode
return adjustRate(output_data, intermediate_reader);
}
private:
size_t baud_rate; ///< The baud rate used for encoding.
bool is_frequency_hopping; ///< Indicates if frequency hopping is being used.
uint8_t shift_register; ///< The shift register used for convolutional coding.
/**
* @brief Calculates the T1 output bit using the generator polynomial T1(x) = x^6 + x^4 + x^3 + x + 1.
* @return The calculated T1 bit.
*/
uint8_t calculateT1() {
return (shift_register >> 6) ^ ((shift_register >> 4) & 0x01) ^
((shift_register >> 3) & 0x01) ^ ((shift_register >> 1) & 0x01) ^
(shift_register & 0x01);
}
/**
* @brief Calculates the T2 output bit using the generator polynomial T2(x) = x^6 + x^5 + x^4 + x + 1.
* @return The calculated T2 bit.
*/
uint8_t calculateT2() {
return (shift_register >> 6) ^ ((shift_register >> 5) & 0x01) ^
((shift_register >> 4) & 0x01) ^ ((shift_register >> 1) & 0x01) ^
(shift_register & 0x01);
}
/**
* @brief Adjusts the rate of the encoded data by applying repetition or puncturing.
* @param encoded_data The encoded BitStream to be adjusted.
* @return The adjusted BitStream.
*/
void adjustRate(bitstream::growing_bit_writer<std::vector<uint8_t>>& adjusted_data, bitstream::fixed_bit_reader& encoded_data) {
size_t repetition_factor = getRepetitionFactor();
if (repetition_factor == 1) {
while (encoded_data.get_remaining_bits() > 0) {
uint32_t bit;
encoded_data.serialize_bits(bit, 1);
adjusted_data.serialize_bits(bit, 1);
}
return;
}
while (encoded_data.get_remaining_bits() >= 2) {
uint32_t t1, t2;
encoded_data.serialize_bits(t1, 1);
encoded_data.serialize_bits(t2, 1);
for (size_t j = 0; j < repetition_factor; j++) {
adjusted_data.serialize_bits(t1, 1);
adjusted_data.serialize_bits(t2, 1);
}
}
}
size_t getRepetitionFactor() const {
if (is_frequency_hopping) {
switch (baud_rate) {
case 300: return 2;
case 150: return 4;
case 75: return 8;
default: return 1;
}
} else {
switch (baud_rate) {
case 300: return 2;
case 150: return 4;
default: return 1;
}
}
}
};
#endif