JS8Call-Improved master
Loading...
Searching...
No Matches
ldpc_feedback.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#include <QDebug>
16#include <QLoggingCategory>
17#include <QtGlobal>
18
19#include <algorithm>
20#include <array>
21#include <cmath>
22#include <cstdint>
23#include <cstdlib>
24#include <optional>
25
26Q_DECLARE_LOGGING_CATEGORY(decoder_js8);
27
28namespace js8 {
38constexpr float LLR_ERASURE_THRESHOLD_DEFAULT = 0.25f;
40constexpr float LLR_FEEDBACK_CONFIDENT_MIN = 3.0f;
42constexpr float LLR_FEEDBACK_UNCERTAIN_MAX = 1.0f;
44constexpr float LLR_FEEDBACK_CONFIDENT_BOOST = 1.2f;
46constexpr float LLR_FEEDBACK_UNCERTAIN_SHRINK = 0.5f;
48constexpr float LLR_FEEDBACK_MAX_MAG = 6.0f;
51
63inline float llrErasureThreshold() {
64 float threshold = LLR_ERASURE_THRESHOLD_DEFAULT;
65
66 if (auto const env = std::getenv("JS8_LLR_ERASURE_THRESH"); env) {
67 char *end = nullptr;
68 float val = std::strtof(env, &end);
69
70 if (end != env && std::isfinite(val)) {
71 threshold = val;
72 }
73 }
74
75 if (threshold <= 0.0f || !std::isfinite(threshold) ||
76 std::getenv("JS8_DISABLE_ERASURE_THRESHOLDING")) {
77 return 0.0f;
78 }
79
80 return threshold;
81}
82
92inline bool ldpcFeedbackEnabled() {
93 bool ok = false;
94 int value = qEnvironmentVariableIntValue("JS8_LDPC_FEEDBACK", &ok);
95 return ok ? value != 0 : true;
96}
97
108 bool ok = false;
109 int value = qEnvironmentVariableIntValue("JS8_LDPC_MAX_PASSES", &ok);
110
111 if (!ok)
113
114 return std::clamp(value, 1, LDPC_FEEDBACK_MAX_PASSES_DEFAULT);
115}
116
144template <std::size_t N>
145void refineLlrsWithLdpcFeedback(std::array<float, N> const &llrIn,
146 std::array<int8_t, N> const &cw,
147 float erasureThreshold,
148 std::array<float, N> &llrOut,
149 int &confidentCount, int &uncertainCount) {
150 llrOut = llrIn;
151 confidentCount = 0;
152 uncertainCount = 0;
153
154 for (std::size_t i = 0; i < llrOut.size(); ++i) {
155 float &value = llrOut[i];
156
157 if (!std::isfinite(value)) {
158 value = 0.0f;
159 ++uncertainCount;
160 continue;
161 }
162
163 bool const bitOne = cw[i] != 0;
164 float const mag = std::abs(value);
165 bool const signMatch = (value >= 0.0f) == bitOne;
166
167 if (signMatch && mag >= LLR_FEEDBACK_CONFIDENT_MIN) {
168 ++confidentCount;
169 float boosted = mag * LLR_FEEDBACK_CONFIDENT_BOOST;
170 boosted = std::clamp(boosted, 0.0f, LLR_FEEDBACK_MAX_MAG);
171 value = bitOne ? boosted : -boosted;
172 } else if (!signMatch || mag <= LLR_FEEDBACK_UNCERTAIN_MAX) {
173 ++uncertainCount;
174 float shrunk = mag * LLR_FEEDBACK_UNCERTAIN_SHRINK;
175
176 if (erasureThreshold > 0.0f && shrunk < erasureThreshold) {
177 value = 0.0f;
178 } else {
179 value = bitOne ? shrunk : -shrunk;
180 }
181 }
182 }
183}
184} // namespace js8
JS8 namespace for Kalman filter-based trackers.
Definition FrequencyTracker.cpp:14
constexpr float LLR_ERASURE_THRESHOLD_DEFAULT
LDPC erasure threshold config and feedback refinement helpers.
Definition ldpc_feedback.h:38
constexpr float LLR_FEEDBACK_MAX_MAG
Definition ldpc_feedback.h:48
constexpr float LLR_FEEDBACK_UNCERTAIN_MAX
Definition ldpc_feedback.h:42
constexpr int LDPC_FEEDBACK_MAX_PASSES_DEFAULT
Definition ldpc_feedback.h:50
constexpr float LLR_FEEDBACK_CONFIDENT_MIN
Definition ldpc_feedback.h:40
constexpr float LLR_FEEDBACK_UNCERTAIN_SHRINK
Definition ldpc_feedback.h:46
void refineLlrsWithLdpcFeedback(std::array< float, N > const &llrIn, std::array< int8_t, N > const &cw, float erasureThreshold, std::array< float, N > &llrOut, int &confidentCount, int &uncertainCount)
Refine LLRs using a decoded LDPC codeword as feedback.
Definition ldpc_feedback.h:145
int ldpcFeedbackMaxPasses()
Maximum LDPC feedback passes to attempt.
Definition ldpc_feedback.h:107
bool ldpcFeedbackEnabled()
Whether LDPC feedback is enabled.
Definition ldpc_feedback.h:92
float llrErasureThreshold()
Read configured LLR erasure threshold.
Definition ldpc_feedback.h:63
constexpr float LLR_FEEDBACK_CONFIDENT_BOOST
Definition ldpc_feedback.h:44