132 lines
4.6 KiB
C++
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 |