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

◆ buildWave10LutForMaxBaud()

Wave10Lut fl::buildWave10LutForMaxBaud ( const ChipsetTimingConfig & timing,
u32 max_baud_rate )

Build a UART waveform LUT with a backend-specific baud ceiling.

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

222 {
223 Wave10Lut result = {};
224
225 // Evaluate both frame geometries (FastLED#3572 follow-up):
226 // P=5 -- wave10: 8 data bits, baud = 5/period (the classic shape)
227 // P=4 -- wave8-frame: 6 data bits, baud = 4/period (lower baud ->
228 // reaches faster chipsets under the 5 Mbps cap; different
229 // quantization grid -- e.g. SK6812 is exact at period/4)
230 // Pick the feasible geometry with the smaller total quantization
231 // error. P=5 wins ties and near-ties (50 ns hysteresis) so the
232 // long-proven wave10 shapes stay stable for existing chipsets.
233 const UartWaveFit fit5 = fitUartWave(timing, 5, max_baud_rate);
234 const UartWaveFit fit4 = fitUartWave(timing, 4, max_baud_rate);
235
236 u8 P = 0;
237 UartWaveFit fit = {};
238 constexpr u32 kHysteresisNs = 50;
239 // A symbol further than this from nominal is one a receiver may not
240 // classify at all. WS281x parts quote about +/-150 ns, and AutoResearch
241 // decodes at +/-170; `fitUartWave` on its own admits half a pulse width,
242 // which at a 2500 ns period is 250 ns -- wider than either, which is how a
243 // geometry emitting an unclassifiable symbol got selected. See #4379.
244 constexpr u32 kMaxSymbolErrorNs = 150;
245 if (fit5.ok && fit4.ok) {
246 const bool fit5_classifiable = fit5.max_err_ns <= kMaxSymbolErrorNs;
247 const bool fit4_classifiable = fit4.max_err_ns <= kMaxSymbolErrorNs;
248 if (fit5_classifiable != fit4_classifiable) {
249 // Exactly one geometry keeps every symbol inside a receiver's
250 // tolerance. Take it, whatever the totals say -- a smaller sum
251 // bought by putting one symbol out of range is not a better fit.
252 // WS2811 at 400 kHz is the case: P=5 nails T0H and misses T1H by
253 // 200 ns, P=4 spends 125 ns on T0H to bring T1H within 50 ns.
254 P = fit5_classifiable ? 5 : 4;
255 fit = fit5_classifiable ? fit5 : fit4;
256 } else if (fit4.total_err_ns + kHysteresisNs < fit5.total_err_ns) {
257 P = 4;
258 fit = fit4;
259 } else {
260 P = 5;
261 fit = fit5;
262 }
263 } else if (fit5.ok) {
264 P = 5;
265 fit = fit5;
266 } else if (fit4.ok) {
267 P = 4;
268 fit = fit4;
269 } else {
270 return result; // infeasible -- pulses_per_bit stays 0
271 }
272
273 result.pulses_per_bit = P;
274 result.lut[0] = buildUartByte(fit.pulses_0, fit.pulses_0, P); // "00"
275 result.lut[1] = buildUartByte(fit.pulses_0, fit.pulses_1, P); // "01"
276 result.lut[2] = buildUartByte(fit.pulses_1, fit.pulses_0, P); // "10"
277 result.lut[3] = buildUartByte(fit.pulses_1, fit.pulses_1, P); // "11"
278
279 return result;
280}
Definition Luminova.h:46
unsigned char u8
Definition stdint.h:131
u8 buildUartByte(u8 pulses_a, u8 pulses_b, u8 pulses_per_bit=5) FL_NO_EXCEPT
Build a UART data byte from two LED bit pulse counts.
FASTLED_FORCE_INLINE fl::u8 P(fl::u8 x)
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
Wave lookup table for UART LED encoding (waveN family)

References FL_NO_EXCEPT, and P().

Referenced by buildWave10Lut(), and uartWireTiming().

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