19 if (edges.size() == 0 || bytes_out.size() == 0) {
24 u32 high_min = 0xFFFFFFFFu;
27 for (
size_t k = 0; k + 1 < edges.size(); k += 2) {
28 if (!edges[k].high)
continue;
29 const u32 h = edges[k].ns;
31 if (h < high_min) high_min = h;
32 if (h > high_max) high_max = h;
45 while (i < edges.size()) {
50 const u32 high_ns = edges[i].ns;
52 if (i + 1 == edges.size()) {
58 }
else if (!edges[i + 1].high) {
70 current_byte =
static_cast<u8>((current_byte << 1) | static_cast<u8>(bit));
71 if (++bit_count == 8) {
72 if (byte_index >= bytes_out.size()) {
76 bytes_out[byte_index++] = current_byte;
83 if (bit_count > 0 && byte_index < bytes_out.size()) {
84 bytes_out[byte_index++] = static_cast<u8>(current_byte << (8 - bit_count));
86 if (total_bits > 0 && (error_count * 10) > total_bits) {
133 ++
mStats.exceptionsDropped;
138 mCurByte =
static_cast<u8>((mCurByte << 1) | static_cast<u8>(b));
154 record(high_ns, mode, b >= 0);
164 record(high_ns, mode,
true);
219 const size_t pair_count = captures.size() / 2u;
220 for (
size_t p = 0; p < pair_count; ++p) {
221 const u16 rise = captures[2 * p];
222 const u16 fall = captures[2 * p + 1];
262 mStats.gapBitShift =
false;
268 const u32 frame_mid =
270 mStats.frameMidpointNs = frame_mid;
280 mStats.gapBitShift =
true;
289 const u32
byte = e.
bit_pos / 8u;
290 if (
byte >=
mOut.size()) {
293 const u8 mask =
static_cast<u8>(0x80u >> (e.
bit_pos % 8u));
310 if (
mStats.pairs == 0 || out.size() == 0) {
313 const u32 full =
mStats.fullBytes;
314 if (full > out.size() || full >
mOut.size()) {
321 for (u32 k = 0; k < n; ++k) {
void finish(const ChipsetTiming4Phase &timing) FL_NO_EXCEPT
Re-classify the recorded bits with the decode-time timing and write the partial final byte.
void classify(u32 high_ns, Mode mode) FL_NO_EXCEPT
ChipsetTiming4Phase mTiming
void flush() FL_NO_EXCEPT
End of capture: decode the final pair (HIGH only; its LOW is the reset) and fix the calibration.
void calibrate() FL_NO_EXCEPT
void pushBit(u32 high_ns, Mode mode) FL_NO_EXCEPT
void emitEdge(bool high, u32 ns) FL_NO_EXCEPT
void push(fl::span< const u16 > captures) FL_NO_EXCEPT
Consume capture pairs laid out as [rise0, fall0, rise1, fall1...].
void emitPair(u16 rise, u16 fall, bool has_low, u32 low_ns) FL_NO_EXCEPT
void record(u32 high_ns, Mode mode, bool stream_valid) FL_NO_EXCEPT
static constexpr u32 kMaxExceptions
Pending mPending[kCalibrationBits]
static constexpr u32 kExceptionBandNs
Bits within this distance of the calibrated threshold are recorded for re-classification against the ...
static constexpr u32 kCalibrationBits
Bits classified before the threshold is fixed. 64 bits = 8 bytes.
void reset(const ChipsetTiming4Phase &stream_timing, u32 ns_per_tick_q16, fl::span< u8 > out, fl::span< EdgeTime > diag_edges) FL_NO_EXCEPT
Start a frame.
void appendBit(int bit) FL_NO_EXCEPT
fl::span< EdgeTime > mDiag
Exception mExceptions[kMaxExceptions]
fl::result< u32, DecodeError > copyTo(fl::span< u8 > out) const FL_NO_EXCEPT
Copy the decoded frame into out with the batch decoder's result rules (overflow, >10% error rate,...
static expected failure(E err, const char *msg=nullptr) FL_NO_EXCEPT
Create error result.
static expected success(T value) FL_NO_EXCEPT
Create successful result.
#define FASTLED_FORCE_INLINE
#define FL_OPTIMIZE_FUNCTION
fl::result< u32, DecodeError > decodeFlexPwmEdges(const ChipsetTiming4Phase &timing, fl::span< const EdgeTime > edges, fl::span< u8 > bytes_out) FL_NO_EXCEPT
Batch decoder over an edge list (HIGH, LOW, HIGH, ... with a LOW left out after a gap).
constexpr u32 kFlexPwmGapNs
A LOW longer than this ends the bit without a LOW edge (gap or reset).
bool flexPwmIsMidpointSample(u32 high_ns) FL_NO_EXCEPT
Whether a HIGH width contributes to the adaptive-midpoint pre-pass (idle and glitch widths are exclud...
int flexPwmBitFromHigh(u32 high_ns, const ChipsetTiming4Phase &timing) FL_NO_EXCEPT
Bit from a HIGH whose LOW was a gap/reset or was not captured: range check against the T0H / T1H wind...
u32 flexPwmTickDeltaNs(u16 t0, u16 t1, u32 ns_per_tick_q16) FL_NO_EXCEPT
Convert a 16-bit capture-counter delta to ns.
int flexPwmBitFromMidpoint(u32 high_ns, u32 midpoint_ns) FL_NO_EXCEPT
Bit from a HIGH followed by a normal LOW: HIGH-only midpoint split.
u32 flexPwmAdaptiveMidpointNs(const ChipsetTiming4Phase &timing, u32 high_min, u32 high_max, u32 samples) FL_NO_EXCEPT
#3416 adaptive midpoint: (min + max) / 2 of the observed HIGH widths once there are enough samples sp...
u8 u8 fract8 blur_amount FL_NO_EXCEPT
bool flush(u32 timeoutMs) FL_NO_EXCEPT
expected< T, E > result
Alias for expected (Rust-style naming)
@ CAPTURE_OVERRUN
Streaming capture lost data (ring overwritten before decode)
@ HIGH_ERROR_RATE
Symbol decode error rate too high (>10%)
@ BUFFER_OVERFLOW
Output buffer overflow.
@ INVALID_ARGUMENT
Invalid input arguments.
Base definition for an LED controller.
4-phase RX timing thresholds for chipset detection
Universal edge timing representation (platform-agnostic)
WS2812 decoder for paired rise/fall capture timestamps, in batch and streaming form.