FastLED 3.10.6
Loading...
Searching...
No Matches

◆ fitUartWave()

UartWaveFit fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::fitUartWave ( const ChipsetTimingConfig & timing,
u8 pulses_per_bit,
u32 max_baud_rate )

Evaluate whether P pulses/LED-bit can represent the timing.

Shared by buildWave10Lut() and canRepresentTiming() so the LUT that gets built is always judged by the same rules that admitted it.

Definition at line 126 of file uart_wave_encoder.cpp.hpp.

128 {
129 UartWaveFit fit = {};
130 const u32 period_ns = timing.total_period_ns();
131 if (period_ns == 0) return fit;
132
133 // Baud = one UART bit per pulse = P / period. Must fit the ESP32
134 // UART ceiling.
135 const u64 baud =
136 static_cast<u64>(pulses_per_bit) * 1000000000ULL / period_ns;
137 if (baud == 0 || baud > max_baud_rate) return fit;
138
139 const u32 pulse_width_ns = period_ns / pulses_per_bit;
140 if (pulse_width_ns == 0) return fit;
141
142 const u32 t0h_ns = timing.t1_ns;
143 const u32 t1h_ns = timing.t1_ns + timing.t2_ns;
144 const u8 max_pulses = static_cast<u8>(pulses_per_bit - 1);
145
146 u8 pulses_0 = computePulseCount(t0h_ns, pulse_width_ns);
147 u8 pulses_1 = computePulseCount(t1h_ns, pulse_width_ns);
148 if (pulses_0 < 1 || pulses_0 > max_pulses) return fit;
149 if (pulses_1 < 1 || pulses_1 > max_pulses) return fit;
150 if (pulses_0 == pulses_1) return fit;
151
152 // FastLED#3569/#3572 -- enforce a minimum ABSOLUTE wire separation
153 // between the 0 and 1 symbols, widening T1H upward (a longer HIGH
154 // still reads as 1). Best-fit rounding alone can land them one
155 // pulse apart, and at high baud one pulse is too little: WS2812B-V5
156 // at P=5 rounds to 245 vs 490 ns -- inside real WS281x parts'
157 // sampling-threshold band (~550-625 ns); it flapped the WROOM bench
158 // decoder. Slow chipsets (WS2811-400: 500+ ns pulses) already
159 // exceed the floor with single-pulse separation.
160 constexpr u32 kMinSymbolSeparationNs = 400;
161 const u8 pulses_1_raw = pulses_1;
162 while (pulses_1 < max_pulses &&
163 static_cast<u32>(pulses_1 - pulses_0) * pulse_width_ns <
164 kMinSymbolSeparationNs) {
165 ++pulses_1;
166 }
167
168 // Quantized timing must be within half a pulse of nominal -- the
169 // natural error bound for best-fit rounding. When the separation
170 // bump deliberately widened T1H, allow exactly the pulses it added
171 // on top of that bound.
172 const u32 tolerance_ns = pulse_width_ns / 2;
173 const u32 actual_t0h = static_cast<u32>(pulses_0) * pulse_width_ns;
174 const u32 actual_t1h = static_cast<u32>(pulses_1) * pulse_width_ns;
175 const u32 t1h_tolerance_ns =
176 tolerance_ns +
177 static_cast<u32>(pulses_1 - pulses_1_raw) * pulse_width_ns;
178 const u32 err_t0h = absDiff(actual_t0h, t0h_ns);
179 const u32 err_t1h = absDiff(actual_t1h, t1h_ns);
180 if (err_t0h > tolerance_ns) return fit;
181 if (err_t1h > t1h_tolerance_ns) return fit;
182
183 const u32 raw_t1h = static_cast<u32>(pulses_1_raw) * pulse_width_ns;
184 const u32 err_t1h_raw = absDiff(raw_t1h, t1h_ns);
185
186 fit.ok = true;
187 fit.pulses_0 = pulses_0;
188 fit.pulses_1 = pulses_1;
189 fit.total_err_ns = err_t0h + err_t1h;
190 fit.max_err_ns = err_t0h > err_t1h_raw ? err_t0h : err_t1h_raw;
191 return fit;
192}
u8 computePulseCount(u32 timing_ns, u32 pulse_width_ns) FL_NO_EXCEPT
Compute HIGH pulse count for a given timing value.
u32 absDiff(u32 a, u32 b) FL_NO_EXCEPT
Absolute value of difference (unsigned-safe)
u32 max_err_ns
Worst single-symbol error, measured pre-bump.
Fit result for one UART wave geometry (P pulses per LED bit)
unsigned char u8
Definition stdint.h:131
fl::u64 u64
Definition stdint.h:220
u32 t1_ns
T0H: High time for bit 0 (nanoseconds)
u32 t2_ns
T1H-T0H: Additional high time for bit 1 (nanoseconds)
constexpr u32 total_period_ns() const FL_NO_EXCEPT
Get total bit period (T1 + T2 + T3)

References absDiff(), computePulseCount(), fitUartWave(), fl::FL_NO_EXCEPT, fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::UartWaveFit::max_err_ns, fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::UartWaveFit::ok, fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::UartWaveFit::pulses_0, fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::UartWaveFit::pulses_1, and fl::anonymous_namespace{uart_wave_encoder.cpp.hpp}::UartWaveFit::total_err_ns.

Referenced by fitUartWave().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: