MCPcopy Create free account
hub / github.com/FastLED/FastLED / capture

Function capture

examples/AutoResearch/AutoResearchTest.cpp:317–598  ·  view source on GitHub ↗

Capture transmitted LED data via RX loopback - rx_channel: Shared pointer to RX device (persistent across calls) - rx_buffer: Buffer to store received bytes - timing: Chipset timing configuration for RX decoder - driver_name: Name of the TX driver being tested (e.g., "RMT", "PARLIO") - enables io_loop_back only for RMT Returns number of bytes captured, or 0 on error

Source from the content-addressed store, hash-verified

315// - driver_name: Name of the TX driver being tested (e.g., "RMT", "PARLIO") - enables io_loop_back only for RMT
316// Returns number of bytes captured, or 0 on error
317size_t capture(fl::shared_ptr<fl::RxChannel> rx_channel, fl::span<uint8_t> rx_buffer, const fl::ChipsetTimingConfig& timing, const char* driver_name) {
318 if (!rx_channel) {
319 FL_ERROR("RX channel is null");
320 return 0;
321 }
322
323 // Clear RX buffer
324 fl::memset(rx_buffer.data(), 0, rx_buffer.size());
325
326 // Prepare RX config (but don't arm yet to avoid locking TX resources)
327 fl::RxChannelConfig rx_config(rx_channel->getPin());
328 rx_config.hz = 40000000; // 40MHz for high-precision LED timing capture
329
330 // Buffer size: 1 LED byte = 8 bits = 8 RMT symbols
331 // UART with TX inversion produces standard WS2812 waveform, same symbol count
332 bool is_uart_driver = (fl::strcmp(driver_name, "UART") == 0);
333 rx_config.edge_capacity = rx_buffer.size() * 8;
334
335 // Internal loopback configuration: Enable ONLY for RMT TX -> RMT RX scenarios
336 // When driver_name == "RMT", enable io_loop_back to route RMT TX output to RMT RX internally
337 // This is REQUIRED for ESP32-S3 because TX GPIO output stops when RX is active on different GPIO
338 // For other drivers (PARLIO, SPI, UART, I2S), disable io_loop_back (use external GPIO wire)
339 bool is_rmt_driver = (fl::strcmp(driver_name, "RMT") == 0);
340 rx_config.io_loop_back = is_rmt_driver;
341 // RX DMA streaming: extends capture past the non-DMA cap by sizing
342 // mem_block_symbols = 14336 so ESP-IDF allocates ~14 DMA descriptor
343 // nodes (each 4092 bytes), yielding a 57 KB user-buffer cap — enough to
344 // capture ~583 WS2812B LEDs in a single rmt_receive() call. Safe for
345 // non-RMT TX paths (SPI, PARLIO, I2S, UART, LCD_*) that don't contend
346 // for the shared ESP32-S3 DMA slot. RMT loopback stays non-DMA.
347 // See issue #2254.
348 rx_config.use_dma = !is_rmt_driver;
349 if (is_rmt_driver) {
350 FL_WARN("[CAPTURE] RMT TX -> RMT RX: Internal loopback enabled (io_loop_back=true)");
351 } else {
352 // The RX peripheral is platform-dependent (RMT on ESP32, FlexPWM on
353 // Teensy 4, LPC_SCT on LPC845, …). Don't claim "RMT RX" on platforms
354 // that have no RMT — that label burned an hour of Teensy-4 debug
355 // (FastLED#3059). Just say "external RX" so the label stays correct
356 // regardless of backend.
357 FL_WARN("[CAPTURE] " << driver_name << " TX -> external RX: External GPIO wire (io_loop_back=false, use_dma=true)");
358 }
359
360 // Driver-aware capture strategy:
361 // - RMT: Two-TX approach (ESP32-S3 workaround - TX GPIO blocked when RX active)
362 // - PARLIO/SPI/other: Single-TX approach (arm RX first, then TX)
363
364 // TX wait timeout: 1 second max per frame - prevents infinite hang if driver stalls
365 // Even a 10000-LED strip at 800kbps takes only ~300ms, so 1s is very safe
366 const uint32_t TX_WAIT_TIMEOUT_MS = 1000;
367
368 if (is_rmt_driver) {
369 // RMT: Two-TX approach for ESP32-S3 compatibility
370 // First TX without RX armed (diagnostics), then arm RX, then second TX
371 FL_WARN("[CAPTURE] RMT: Two-TX approach (ESP32-S3 workaround)");
372 FastLED.show();
373 if (!FastLED.wait(TX_WAIT_TIMEOUT_MS)) {
374 FL_ERROR("[CAPTURE] TX wait timeout (pre-arm) - driver may be stalled");

Callers 2

runTestFunction · 0.85
runMultiTestFunction · 0.85

Calls 15

memsetFunction · 0.85
strcmpFunction · 0.85
make4PhaseTimingFunction · 0.85
dumpRawEdgeTimingFunction · 0.85
EdgeRangeClass · 0.85
decodeSpiEdgesFunction · 0.85
canUseWave3Function · 0.85
dataMethod · 0.45
sizeMethod · 0.45
getPinMethod · 0.45
showMethod · 0.45
waitMethod · 0.45

Tested by

no test coverage detected