From e6bec67c33645640802e7d806b7ddbbcf9fd6482 Mon Sep 17 00:00:00 2001 From: Aang23 Date: Tue, 1 Feb 2022 16:45:38 +0100 Subject: [PATCH] Use the generic decoder for xRIT signals --- pipelines/GEO.json | 83 ++-- src-core/module.cpp | 2 - src-core/modules/xrit/module_xrit_decoder.cpp | 373 ------------------ src-core/modules/xrit/module_xrit_decoder.h | 59 --- src-core/modules/xrit/stream_viterbi.cpp | 134 ------- src-core/modules/xrit/stream_viterbi.h | 63 --- 6 files changed, 58 insertions(+), 656 deletions(-) delete mode 100644 src-core/modules/xrit/module_xrit_decoder.cpp delete mode 100644 src-core/modules/xrit/module_xrit_decoder.h delete mode 100644 src-core/modules/xrit/stream_viterbi.cpp delete mode 100644 src-core/modules/xrit/stream_viterbi.h diff --git a/pipelines/GEO.json b/pipelines/GEO.json index f45142788..5b05526d1 100644 --- a/pipelines/GEO.json +++ b/pipelines/GEO.json @@ -121,9 +121,15 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": true, - "diff_decode": true + "ccsds_conv_r2_concat_decoder": { + "constellation": "bpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "nrzm": true, + "rs_i": 4, + "rs_type": "rs223" } }, "products": { @@ -172,9 +178,15 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": true, - "diff_decode": true + "ccsds_conv_r2_concat_decoder": { + "constellation": "bpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "nrzm": true, + "rs_i": 4, + "rs_type": "rs223" } }, "tcp": { @@ -220,9 +232,14 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": true, - "diff_decode": false + "ccsds_conv_r2_concat_decoder": { + "constellation": "bpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "rs_i": 4, + "rs_type": "rs223" } }, "products": { @@ -269,9 +286,14 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": true, - "diff_decode": false + "ccsds_conv_r2_concat_decoder": { + "constellation": "bpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "rs_i": 4, + "rs_type": "rs223" } }, "tcp": { @@ -313,11 +335,14 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": false, - "diff_decode": false, - "viterbi_outsync_after": 5, - "viterbi_ber_thresold": 0.170 + "ccsds_conv_r2_concat_decoder": { + "constellation": "qpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "rs_i": 4, + "rs_type": "rs223" } } } @@ -357,9 +382,14 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": true, - "diff_decode": false + "ccsds_conv_r2_concat_decoder": { + "constellation": "bpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "rs_i": 4, + "rs_type": "rs223" } }, "products": { @@ -408,11 +438,14 @@ } }, "cadu": { - "xrit_decoder": { - "is_bpsk": false, - "diff_decode": false, - "viterbi_outsync_after": 5, - "viterbi_ber_thresold": 0.170 + "ccsds_conv_r2_concat_decoder": { + "constellation": "qpsk", + "cadu_size": 8192, + "viterbi_ber_thresold": 0.300, + "viterbi_outsync_after": 20, + "derandomize": true, + "rs_i": 4, + "rs_type": "rs223" } }, "products": { diff --git a/src-core/module.cpp b/src-core/module.cpp index 1f384b6a4..41591e7a7 100644 --- a/src-core/module.cpp +++ b/src-core/module.cpp @@ -149,7 +149,6 @@ SATDUMP_DLL std::map()), - diff_decode(parameters["diff_decode"].get()), - viterbi(ENCODED_FRAME_SIZE / 2, viterbi::CCSDS_R2_K7_POLYS), - d_viterbi_outsync_after(parameters.count("viterbi_outsync_after") > 0 ? parameters["viterbi_outsync_after"].get() : 0), - d_viterbi_ber_threasold(parameters.count("viterbi_ber_thresold") > 0 ? parameters["viterbi_ber_thresold"].get() : 0), - stream_viterbi(d_viterbi_ber_threasold, d_viterbi_outsync_after, BUFFER_SIZE) - { - buffer = new uint8_t[ENCODED_FRAME_SIZE]; - viterbi_out = new uint8_t[BUFFER_SIZE * 2]; - } - - std::vector XRITDecoderModule::getInputTypes() - { - return {DATA_FILE, DATA_STREAM}; - } - - std::vector XRITDecoderModule::getOutputTypes() - { - return {DATA_FILE}; - } - - XRITDecoderModule::~XRITDecoderModule() - { - delete[] buffer; - delete[] viterbi_out; - } - - void XRITDecoderModule::process() - { - if (input_data_type == DATA_FILE) - filesize = getFilesize(d_input_file); - else - filesize = 0; - if (input_data_type == DATA_FILE) - data_in = std::ifstream(d_input_file, std::ios::binary); - if (output_data_type == DATA_FILE) - { - data_out = std::ofstream(d_output_file_hint + ".cadu", std::ios::binary); - d_output_files.push_back(d_output_file_hint + ".cadu"); - } - - logger->info("Using input symbols " + d_input_file); - logger->info("Decoding to " + d_output_file_hint + ".cadu"); - - time_t lastTime = 0; - - // Common objects - reedsolomon::ReedSolomon rs(reedsolomon::RS223); - diff::NRZMDiff diff; - - if (is_bpsk) // BPSK Variant using a correlator - { - // Correlator and shifter - Correlator correlator(BPSK, diff_decode ? 0xfc4ef4fd0cc2df89 : 0xfca2b63db00d9794); - - // Other buffers - uint8_t frameBuffer[FRAME_SIZE]; - - // Phase utils - phase_t phase; - bool swap; - - while (input_data_type == DATA_FILE ? !data_in.eof() : input_active.load()) - { - // Read a buffer - if (input_data_type == DATA_FILE) - data_in.read((char *)buffer, ENCODED_FRAME_SIZE); - else - input_fifo->read((uint8_t *)buffer, ENCODED_FRAME_SIZE); - - int pos = correlator.correlate((int8_t *)buffer, phase, swap, cor, ENCODED_FRAME_SIZE); - - locked = pos == 0; // Update locking state - - if (pos != 0 && pos < ENCODED_FRAME_SIZE) // Safety - { - std::memmove(buffer, &buffer[pos], pos); - - if (input_data_type == DATA_FILE) - data_in.read((char *)&buffer[ENCODED_FRAME_SIZE - pos], pos); - else - input_fifo->read((uint8_t *)&buffer[ENCODED_FRAME_SIZE - pos], pos); - } - - // Correct phase ambiguity - rotate_soft((int8_t *)buffer, ENCODED_FRAME_SIZE, (phase_t)(phase + 2), swap); - - // Viterbi - viterbi.work((int8_t *)buffer, frameBuffer); - - // NRZ-M Decoding - if (diff_decode) - diff.decode(frameBuffer, FRAME_SIZE); - - // Derandomize that frame - derand_ccsds(&frameBuffer[4], FRAME_SIZE - 4); - - // RS Correction - rs.decode_interlaved(&frameBuffer[4], true, 4, errors); - - // Write it out if it's not garbage - if (errors[0] >= 0 && errors[1] >= 0 && errors[2] >= 0 && errors[3] >= 0) - { - frameBuffer[0] = 0x1a; - frameBuffer[1] = 0xcf; - frameBuffer[2] = 0xfc; - frameBuffer[3] = 0x1d; - - if (output_data_type == DATA_FILE) - data_out.write((char *)frameBuffer, FRAME_SIZE); - else - output_fifo->write(frameBuffer, FRAME_SIZE); - } - - if (input_data_type == DATA_FILE) - progress = data_in.tellg(); - - // Update module stats - module_stats["lock_state"] = locked; - module_stats["viterbi_ber"] = viterbi.ber() * 100; - module_stats["rs_avg"] = (errors[0] + errors[1] + errors[2] + errors[3]) / 4; - - if (time(NULL) % 10 == 0 && lastTime != time(NULL)) - { - lastTime = time(NULL); - std::string lock_state = locked ? "SYNCED" : "NOSYNC"; - logger->info("Progress " + std::to_string(round(((float)progress / (float)filesize) * 1000.0f) / 10.0f) + "%, Viterbi BER : " + std::to_string(viterbi.ber() * 100) + "%, Lock : " + lock_state); - } - } - } - else - { - int vout; - - while (input_data_type == DATA_FILE ? !data_in.eof() : input_active.load()) - { - // Read a buffer - if (input_data_type == DATA_FILE) - data_in.read((char *)buffer, BUFFER_SIZE); - else - input_fifo->read((uint8_t *)buffer, BUFFER_SIZE); - - // Perform Viterbi decoding - vout = stream_viterbi.work((uint8_t *)buffer, BUFFER_SIZE, viterbi_out); - - // NRZ-M Decoding - if (diff_decode) - diff.decode(viterbi_out, vout); - - if (vout > 0) - { - // Deframe (and derand) - std::vector> frames = deframer.work(viterbi_out, vout); - - // if we found frame, write them - if (frames.size() > 0) - { - for (std::array cadu : frames) - { - // RS Correction - rs.decode_interlaved(&cadu[4], true, 4, errors); - - // Write it out - if (errors[0] >= 0 && errors[1] >= 0 && errors[2] >= 0 && errors[3] >= 0) - { - if (output_data_type == DATA_FILE) - data_out.write((char *)&cadu, FRAME_SIZE); - else - output_fifo->write((uint8_t *)&cadu, FRAME_SIZE); - } - } - } - } - - if (input_data_type == DATA_FILE) - progress = data_in.tellg(); - - // Update module stats - module_stats["viterbi_lock"] = stream_viterbi.getState(); - module_stats["viterbi_ber"] = stream_viterbi.ber() * 100; - module_stats["deframer_lock"] = deframer.getState(); - module_stats["rs_avg"] = (errors[0] + errors[1] + errors[2] + errors[3]) / 4; - - if (time(NULL) % 10 == 0 && lastTime != time(NULL)) - { - lastTime = time(NULL); - std::string viterbi_state = stream_viterbi.getState() == 0 ? "NOSYNC" : "SYNCED"; - std::string deframer_state = deframer.getState() == 0 ? "NOSYNC" : (deframer.getState() == 2 || deframer.getState() == 6 ? "SYNCING" : "SYNCED"); - logger->info("Progress " + std::to_string(round(((float)progress / (float)filesize) * 1000.0f) / 10.0f) + "%, Viterbi : " + viterbi_state + " BER : " + std::to_string(stream_viterbi.ber()) + ", Deframer : " + deframer_state); - } - } - } - - if (output_data_type == DATA_FILE) - data_out.close(); - if (input_data_type == DATA_FILE) - data_in.close(); - } - - void XRITDecoderModule::drawUI(bool window) - { - ImGui::Begin("xRIT Decoder", NULL, window ? NULL : NOWINDOW_FLAGS); - - float ber = is_bpsk ? viterbi.ber() : stream_viterbi.ber(); - - ImGui::BeginGroup(); - { - // Constellation - { - ImDrawList *draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(ImGui::GetCursorScreenPos(), - ImVec2(ImGui::GetCursorScreenPos().x + 200 * ui_scale, ImGui::GetCursorScreenPos().y + 200 * ui_scale), - ImColor::HSV(0, 0, 0)); - - if (is_bpsk) - { - for (int i = 0; i < 2048; i++) - { - draw_list->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + (int)(100 * ui_scale + (((int8_t *)buffer)[i] / 127.0) * 130 * ui_scale) % int(200 * ui_scale), - ImGui::GetCursorScreenPos().y + (int)(100 * ui_scale + rng.gasdev() * 14 * ui_scale) % int(200 * ui_scale)), - 2 * ui_scale, - ImColor::HSV(113.0 / 360.0, 1, 1, 1.0)); - } - } - else - { - for (int i = 0; i < 2048; i++) - { - draw_list->AddCircleFilled(ImVec2(ImGui::GetCursorScreenPos().x + (int)(100 * ui_scale + (((int8_t *)buffer)[i * 2 + 0] / 127.0) * 100 * ui_scale) % int(200 * ui_scale), - ImGui::GetCursorScreenPos().y + (int)(100 * ui_scale + (((int8_t *)buffer)[i * 2 + 1] / 127.0) * 100 * ui_scale) % int(200 * ui_scale)), - 2 * ui_scale, - ImColor::HSV(113.0 / 360.0, 1, 1, 1.0)); - } - } - - ImGui::Dummy(ImVec2(200 * ui_scale + 3, 200 * ui_scale + 3)); - } - } - ImGui::EndGroup(); - - ImGui::SameLine(); - - ImGui::BeginGroup(); - { - if (is_bpsk) - { - ImGui::Button("Correlator", {200 * ui_scale, 20 * ui_scale}); - { - ImGui::Text("Corr : "); - ImGui::SameLine(); - ImGui::TextColored(locked ? IMCOLOR_SYNCED : IMCOLOR_SYNCING, UITO_C_STR(cor)); - - std::memmove(&cor_history[0], &cor_history[1], (200 - 1) * sizeof(float)); - cor_history[200 - 1] = cor; - - ImGui::PlotLines("", cor_history, IM_ARRAYSIZE(cor_history), 0, "", 40.0f, 64.0f, ImVec2(200 * ui_scale, 50 * ui_scale)); - } - - ImGui::Spacing(); - - ImGui::Button("Viterbi", {200 * ui_scale, 20 * ui_scale}); - { - ImGui::Text("BER : "); - ImGui::SameLine(); - ImGui::TextColored(ber < 0.22 ? IMCOLOR_SYNCED : IMCOLOR_NOSYNC, UITO_C_STR(ber)); - - std::memmove(&ber_history[0], &ber_history[1], (200 - 1) * sizeof(float)); - ber_history[200 - 1] = ber; - - ImGui::PlotLines("", ber_history, IM_ARRAYSIZE(ber_history), 0, "", 0.0f, 1.0f, ImVec2(200 * ui_scale, 50 * ui_scale)); - } - } - else - { - ImGui::Button("Viterbi", {200 * ui_scale, 20 * ui_scale}); - { - ImGui::Text("State : "); - - ImGui::SameLine(); - - if (stream_viterbi.getState() == 0) - ImGui::TextColored(IMCOLOR_NOSYNC, "NOSYNC"); - else - ImGui::TextColored(IMCOLOR_SYNCED, "SYNCED"); - - ImGui::Text("BER : "); - ImGui::SameLine(); - ImGui::TextColored(stream_viterbi.getState() == 0 ? IMCOLOR_NOSYNC : IMCOLOR_SYNCED, UITO_C_STR(ber)); - - std::memmove(&ber_history[0], &ber_history[1], (200 - 1) * sizeof(float)); - ber_history[200 - 1] = ber; - - ImGui::PlotLines("", ber_history, IM_ARRAYSIZE(ber_history), 0, "", 0.0f, 1.0f, ImVec2(200 * ui_scale, 50 * ui_scale)); - } - - ImGui::Spacing(); - - ImGui::Button("Deframer", {200 * ui_scale, 20 * ui_scale}); - { - ImGui::Text("State : "); - - ImGui::SameLine(); - - if (deframer.getState() == 0) - ImGui::TextColored(IMCOLOR_NOSYNC, "NOSYNC"); - else if (deframer.getState() == 2 || deframer.getState() == 6) - ImGui::TextColored(IMCOLOR_SYNCING, "SYNCING"); - else - ImGui::TextColored(IMCOLOR_SYNCED, "SYNCED"); - } - } - - ImGui::Spacing(); - - ImGui::Button("Reed-Solomon", {200 * ui_scale, 20 * ui_scale}); - { - ImGui::Text("RS : "); - for (int i = 0; i < 4; i++) - { - ImGui::SameLine(); - - if (errors[i] == -1) - ImGui::TextColored(IMCOLOR_NOSYNC, "%i ", i); - else if (errors[i] > 0) - ImGui::TextColored(IMCOLOR_SYNCING, "%i ", i); - else - ImGui::TextColored(IMCOLOR_SYNCED, "%i ", i); - } - } - } - ImGui::EndGroup(); - - if (!streamingInput) - ImGui::ProgressBar((float)progress / (float)filesize, ImVec2(ImGui::GetWindowWidth() - 10, 20 * ui_scale)); - - ImGui::End(); - } - - std::string XRITDecoderModule::getID() - { - return "xrit_decoder"; - } - - std::vector XRITDecoderModule::getParameters() - { - return {"is_bpsk", "diff_decode", "viterbi_outsync_after", "viterbi_ber_thresold"}; - } - - std::shared_ptr XRITDecoderModule::getInstance(std::string input_file, std::string output_file_hint, nlohmann::json parameters) - { - return std::make_shared(input_file, output_file_hint, parameters); - } -} \ No newline at end of file diff --git a/src-core/modules/xrit/module_xrit_decoder.h b/src-core/modules/xrit/module_xrit_decoder.h deleted file mode 100644 index e830c6fae..000000000 --- a/src-core/modules/xrit/module_xrit_decoder.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include "module.h" -#include -#include "common/codings/viterbi/viterbi27.h" -#include -#include "common/dsp/random.h" - -#include "stream_viterbi.h" -#include "common/ccsds/ccsds_1_0_1024/deframer.h" - -namespace xrit -{ - class XRITDecoderModule : public ProcessingModule - { - protected: - uint8_t *buffer; - - std::ifstream data_in; - std::ofstream data_out; - std::atomic filesize; - std::atomic progress; - - bool is_bpsk; - bool diff_decode; - bool locked = false; - int errors[4]; - int cor; - - viterbi::Viterbi27 viterbi; - - // QPSK Variant - int d_viterbi_outsync_after; - float d_viterbi_ber_threasold; - xRITViterbi stream_viterbi; - uint8_t *viterbi_out; - ccsds::ccsds_1_0_1024::CADUDeframer deframer; - - // UI Stuff - float ber_history[200]; - float cor_history[200]; - - dsp::Random rng; - - public: - XRITDecoderModule(std::string input_file, std::string output_file_hint, nlohmann::json parameters); - ~XRITDecoderModule(); - void process(); - void drawUI(bool window); - std::vector getInputTypes(); - std::vector getOutputTypes(); - - public: - static std::string getID(); - virtual std::string getIDM() { return getID(); }; - static std::vector getParameters(); - static std::shared_ptr getInstance(std::string input_file, std::string output_file_hint, nlohmann::json parameters); - }; -} \ No newline at end of file diff --git a/src-core/modules/xrit/stream_viterbi.cpp b/src-core/modules/xrit/stream_viterbi.cpp deleted file mode 100644 index de09c73ad..000000000 --- a/src-core/modules/xrit/stream_viterbi.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "stream_viterbi.h" -#include -#include "common/utils.h" - -#define ST_IDLE 0 -#define ST_SYNCED 1 - -namespace xrit -{ - xRITViterbi::xRITViterbi(float ber_threshold, int outsync_after, int buffer_size) : d_buffer_size(buffer_size), - d_outsync_after(outsync_after), - d_ber_thresold(ber_threshold), - d_outsinc(0), - d_state(ST_IDLE), - d_first(true), - cc_decoder_in_ber(TEST_BITS_LENGTH / 2, 7, 2, {79, 109}, 0, -1, CC_STREAMING, false), - cc_encoder_in_ber(TEST_BITS_LENGTH / 2, 7, 2, {79, 109}, 0, CC_STREAMING, false), - cc_decoder_in(buffer_size / 2, 7, 2, {79, 109}, 0, -1, CC_STREAMING, false) - { - fixed_soft_packet = new uint8_t[buffer_size]; - viterbi_in = new uint8_t[buffer_size]; - output_buffer = new uint8_t[buffer_size * 2]; - d_ber = 0; - } - - xRITViterbi::~xRITViterbi() - { - delete[] fixed_soft_packet; - delete[] viterbi_in; - delete[] output_buffer; - } - - float xRITViterbi::getBER(uint8_t *input) - { - char_array_to_uchar((int8_t *)input, d_ber_input_buffer, TEST_BITS_LENGTH); - cc_decoder_in_ber.generic_work(d_ber_input_buffer, d_ber_decoded_buffer); - cc_encoder_in_ber.generic_work(d_ber_decoded_buffer, d_ber_encoded_buffer); - - float errors = 0; - for (int i = 0; i < TEST_BITS_LENGTH; i++) - errors += (d_ber_input_buffer[i] > 0) != (d_ber_encoded_buffer[i] > 0); - - return (errors / ((float)TEST_BITS_LENGTH * 2.0f)) * 4.0f; - } - - int xRITViterbi::work(uint8_t *input, size_t size, uint8_t *output) - { - int data_size_out = 0; - - if (d_state == ST_IDLE) - { - // Test 90 deg shifts with & without I/Q inversion - for (int sh = 0; sh < 2; sh++) - { - for (int ph = 0; ph < 2; ph++) - { - std::memcpy(d_ber_test_buffer, input, TEST_BITS_LENGTH); - rotate_soft((int8_t *)d_ber_test_buffer, TEST_BITS_LENGTH, (phase_t)ph, sh); - d_bers[sh][ph] = getBER(d_ber_test_buffer); - } - } - - for (int s = 0; s < 2; s++) - { - for (int p = 0; p < 2; p++) - { - if (d_ber_thresold > d_bers[s][p]) - { - d_ber = d_bers[s][p]; - d_iq_inv = s; - d_phase_shift = (phase_t)p; - d_state = ST_SYNCED; - } - } - } - } - - if (d_state == ST_SYNCED) - { - // Decode - std::memcpy(fixed_soft_packet, input, size); - rotate_soft((int8_t *)fixed_soft_packet, size, d_phase_shift, d_iq_inv); - - char_array_to_uchar((int8_t *)fixed_soft_packet, viterbi_in, size); - - int output_size = cc_decoder_in.continuous_work(viterbi_in, size, output_buffer); - - data_size_out = repacker.work(output_buffer, output_size, output); - - // Check BER - d_ber = getBER(fixed_soft_packet); - - // Check we're still in sync! - if (d_ber_thresold < d_ber) - { - d_outsinc++; - if (d_outsinc >= /*d_outsync_after*/ 10) - d_state = ST_IDLE; - } - else - { - d_outsinc = 0; - } - } - - return data_size_out; - } - - float xRITViterbi::ber() - { - if (d_state == ST_SYNCED) - return d_ber; - else - { - float ber = 10; - for (int s = 0; s < 2; s++) - { - for (int p = 0; p < 2; p++) - { - if (ber > d_bers[s][p]) - { - ber = d_bers[s][p]; - } - } - } - return ber; - } - } - - int xRITViterbi::getState() - { - return d_state; - } -} // namespace xrit \ No newline at end of file diff --git a/src-core/modules/xrit/stream_viterbi.h b/src-core/modules/xrit/stream_viterbi.h deleted file mode 100644 index e41cc09b2..000000000 --- a/src-core/modules/xrit/stream_viterbi.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#define TEST_BITS_LENGTH 1024 - -#include "common/codings/rotation.h" -#include "common/codings/viterbi/cc_decoder.h" -#include "common/codings/viterbi/cc_encoder.h" -#include "common/codings/viterbi/depuncture.h" -#include "common/repack_bits_byte.h" - -namespace xrit -{ - class xRITViterbi - { - private: - // Settings - const int d_buffer_size; - const int d_outsync_after; - const float d_ber_thresold; - - // Variables - int d_outsinc; - int d_state; - bool d_first; - float d_bers[2][2]; - float d_ber; - - // BER Decoders - fec::code::cc_decoder_impl cc_decoder_in_ber; - fec::code::cc_encoder_impl cc_encoder_in_ber; - - // BER Buffers - uint8_t d_ber_test_buffer[TEST_BITS_LENGTH]; - uint8_t d_ber_input_buffer[TEST_BITS_LENGTH]; - uint8_t d_ber_decoded_buffer[TEST_BITS_LENGTH / 2]; - uint8_t d_ber_encoded_buffer[TEST_BITS_LENGTH]; - - // Current phase status - phase_t d_phase_shift; - bool d_iq_inv; - - // Work buffers - uint8_t *fixed_soft_packet; - uint8_t *viterbi_in; - uint8_t *output_buffer; - - // Main decoder - fec::code::cc_decoder_impl cc_decoder_in; - - // Repacker - RepackBitsByte repacker; - - float getBER(uint8_t *input); - - public: - xRITViterbi(float ber_threshold, int outsync_after, int buffer_size); - ~xRITViterbi(); - - int work(uint8_t *input, size_t size, uint8_t *output); - float ber(); - int getState(); - }; -} // namespace npp \ No newline at end of file