FastLED 3.10.8
Loading...
Searching...
No Matches
ws2812_stream_decoder.h File Reference

Detailed Description

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.

#include "fl/channels/rx.h"
#include "fl/stl/noexcept.h"
#include "fl/stl/result.h"
#include "fl/stl/span.h"
#include "fl/stl/stdint.h"
+ Include dependency graph for ws2812_stream_decoder.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  fl::channels::rx::Ws2812StreamDecoder
 Streaming decoder over (rise, fall) capture pairs. More...
 
struct  fl::channels::rx::Ws2812StreamDecoder::Exception
 
struct  fl::channels::rx::Ws2812StreamDecoder::Pending
 
struct  fl::channels::rx::Ws2812StreamDecoder::Stats
 

Namespaces

namespace  fl
 Base definition for an LED controller.
 
namespace  fl::channels
 
namespace  fl::channels::rx
 

Functions

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.
 

Variables

constexpr u32 fl::channels::rx::kFlexPwmGapNs = 5000
 A LOW longer than this ends the bit without a LOW edge (gap or reset).
 

Class Documentation

◆ fl::channels::rx::Ws2812StreamDecoder::Exception

struct fl::channels::rx::Ws2812StreamDecoder::Exception
Class Members
u32 bit_pos
u32 high_ns
Mode mode
bool stream_valid

◆ fl::channels::rx::Ws2812StreamDecoder::Pending

struct fl::channels::rx::Ws2812StreamDecoder::Pending
Class Members
u32 high_ns
Mode mode

◆ fl::channels::rx::Ws2812StreamDecoder::Stats

struct fl::channels::rx::Ws2812StreamDecoder::Stats
Class Members
u32 bits = 0 bits classified (batch total_bits)
u32 calibratedMidpointNs = 0
u32 errors = 0 out-of-window bits (batch error_count)
u32 exceptions = 0 near-threshold bits recorded
u32 exceptionsDropped = 0 near-threshold bits that did not fit
u32 frameMidpointNs = 0 whole-frame midpoint, set by finish()
u32 fullBytes = 0 complete bytes decoded (may exceed capacity)
bool gapBitShift = false a gap bit kept/dropped differs from decode timing
bool inexact = false finish() could not guarantee batch equality
bool overrun = false the owner reported lost captures
u32 pairs = 0 capture pairs consumed