WS2812 decoder for paired rise/fall capture timestamps, in batch and streaming form.
Used by the Teensy 4.x FlexPWM input-capture RX (platforms/arm/teensy/teensy4_common/rx_flexpwm_channel.cpp.hpp). The capture hardware delivers one (rise, fall) pair of 16-bit counter timestamps per WS2812 bit. The streaming decoder consumes those pairs in chunks (one DMA ring half at a time, from the DMA ISR) and writes decoded bytes straight into the final output buffer, so a frame of any length needs only the output bytes plus a small fixed ring.
Both forms share one set of threshold rules (the functions below), and the streaming decoder produces the same bytes as running decodeFlexPwmEdges() over the full edge list built from the same captures. The batch decoder picks its bit threshold from a pre-pass over the whole frame (the adaptive midpoint). A stream cannot look ahead, so it calibrates the threshold on the first kCalibrationBits bits, and records every bit whose HIGH lies within kExceptionBandNs of that threshold. Bits that end at a gap (range-checked against the T0H/T1H windows) are recorded too. finish() recomputes the whole-frame midpoint with the decode-time timing and re-classifies the recorded bits. That is exact whenever the two midpoints are within the band, the exception list did not overflow, and no gap bit changes between valid and invalid under the decode-time timing; otherwise stats().inexact is set.
The stream needs a timing while it runs (for the static-midpoint fallback and the gap-bit windows) before the caller's decode(timing) is known: the capture config supplies it (RxConfig::stream_timing).
Definition in file ws2812_stream_decoder.h.
|
| fl::result< u32, DecodeError > | fl::channels::rx::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).
|
| |
| u32 | fl::channels::rx::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 spread wide enough to trust; else the static one.
|
| |
| int | fl::channels::rx::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 windows.
|
| |
| int | fl::channels::rx::flexPwmBitFromMidpoint (u32 high_ns, u32 midpoint_ns) FL_NO_EXCEPT |
| | Bit from a HIGH followed by a normal LOW: HIGH-only midpoint split.
|
| |
| bool | fl::channels::rx::flexPwmIsMidpointSample (u32 high_ns) FL_NO_EXCEPT |
| | Whether a HIGH width contributes to the adaptive-midpoint pre-pass (idle and glitch widths are excluded).
|
| |
| u32 | fl::channels::rx::flexPwmNsPerTickQ16 (u32 counter_hz) FL_NO_EXCEPT |
| | Q16.16 ns-per-tick for a counter clock.
|
| |
| u32 | fl::channels::rx::flexPwmStaticMidpointNs (const ChipsetTiming4Phase &timing) FL_NO_EXCEPT |
| | Static threshold between a 0 and a 1 HIGH: midpoint of T0H max / T1H min.
|
| |
| u32 | fl::channels::rx::flexPwmTickDeltaNs (u16 t0, u16 t1, u32 ns_per_tick_q16) FL_NO_EXCEPT |
| | Convert a 16-bit capture-counter delta to ns.
|
| |