9#if FL_PLATFORM_HAS_LARGE_MEMORY
12#define DEBUG_PRINT(x) do {} while(0)
13#define DEBUG_PRINTLN(x) do {} while(0)
49#include "platforms/arm/teensy/teensy4_common/drivers/flexio/flexio_spi_mode.h"
53#include "platforms/arm/teensy/teensy4_common/drivers/objectfled/objectfled_spi_mode.h"
64#if defined(FL_IS_TEENSY_4X)
65struct FlexIoObjectFledState {
69FlexIoObjectFledState& flexIoObjectFledState() {
96 remote.bind(
"flexioRxBenchmark", [](
const fl::json&
args) -> fl::json {
98#if !defined(FL_IS_TEENSY_4X)
101 response.set(
"error",
"PlatformNotSupported");
103 "flexioRxBenchmark is Teensy 4.x-only (FLEXIO1 capture).");
107 int frequency_hz = 1000;
108 int duration_ms = 100;
111 if (
args.is_array() &&
args.size() >= 1 &&
args[0].is_object()) {
112 fl::json cfg =
args[0];
113 if (cfg.
contains(
"frequency_hz") && cfg[
"frequency_hz"].is_int()) {
114 frequency_hz =
static_cast<int>(cfg[
"frequency_hz"].
as_int().value());
116 if (cfg.
contains(
"duration_ms") && cfg[
"duration_ms"].is_int()) {
117 duration_ms =
static_cast<int>(cfg[
"duration_ms"].
as_int().value());
119 if (cfg.
contains(
"tx_pin") && cfg[
"tx_pin"].is_int()) {
120 tx_pin =
static_cast<int>(cfg[
"tx_pin"].
as_int().value());
122 if (cfg.
contains(
"rx_pin") && cfg[
"rx_pin"].is_int()) {
123 rx_pin =
static_cast<int>(cfg[
"rx_pin"].
as_int().value());
126 if (frequency_hz < 1 || frequency_hz > 5000000 ||
127 duration_ms < 1 || duration_ms > 5000) {
129 response.set(
"error",
"InvalidArgs");
131 "frequency_hz in [1, 5_000_000]; duration_ms in [1, 5000].");
136 analogWriteFrequency(tx_pin, (
float)frequency_hz);
146 const fl::u64 expected_edges =
147 (fl::u64)2 * (fl::u64)frequency_hz * (fl::u64)duration_ms / 1000ULL;
148 fl::u64 target = expected_edges + expected_edges / 2;
149 if (target < 1024ULL) target = 1024ULL;
150 if (target > 16384ULL) target = 16384ULL;
151 rx_cfg.edge_capacity = (
size_t)target;
152 rx_cfg.start_low =
false;
157 response.set(
"error",
"RxCreateFailed");
159 "Failed to create FlexIO RX channel on pin (no FLEXIO1 mapping).");
162 if (!rx_channel->begin(rx_cfg)) {
165 response.set(
"error",
"RxBeginFailed");
167 "RxChannel::begin() returned false (see device WARN log).");
172 rx_channel->wait((u32)duration_ms);
178 fl::vector<fl::EdgeTime> edges;
179 edges.
assign(rx_cfg.edge_capacity, fl::EdgeTime());
180 size_t edges_captured =
181 rx_channel->getRawEdgeTimes(fl::span<fl::EdgeTime>(edges), 0);
182 edges.
resize(edges_captured);
187 fl::u64 sum_sq_ns = 0;
188 fl::u32 min_ns = 0xFFFFFFFFu;
191 for (
size_t i = 0; i + 1 < edges_captured; i += 2) {
192 const fl::u32 period_ns =
193 (fl::u32)edges[i].ns + (fl::u32)edges[i + 1].ns;
194 if (period_ns == 0)
continue;
196 sum_sq_ns += (fl::u64)period_ns * (fl::u64)period_ns;
197 if (period_ns < min_ns) min_ns = period_ns;
198 if (period_ns > max_ns) max_ns = period_ns;
202 fl::u32 sigma_ns = 0;
204 mean_ns = (fl::u32)(sum_ns / (fl::u64)periods);
205 const fl::u64 mean64 = (fl::u64)mean_ns;
207 periods > 0 ? (sum_sq_ns / (fl::u64)periods) - (mean64 * mean64)
212 while ((fl::u64)(s + 1) * (fl::u64)(s + 1) <= var) ++s;
215 if (min_ns == 0xFFFFFFFFu) min_ns = 0;
218 response.set(
"frequency_hz",
static_cast<int64_t
>(frequency_hz));
219 response.set(
"duration_ms",
static_cast<int64_t
>(duration_ms));
220 response.set(
"tx_pin",
static_cast<int64_t
>(tx_pin));
221 response.set(
"rx_pin",
static_cast<int64_t
>(rx_pin));
222 response.set(
"edges_captured",
static_cast<int64_t
>(edges_captured));
223 response.set(
"periods",
static_cast<int64_t
>(periods));
224 response.set(
"period_mean_ns",
static_cast<int64_t
>(mean_ns));
225 response.set(
"period_sigma_ns",
static_cast<int64_t
>(sigma_ns));
226 response.set(
"period_min_ns",
static_cast<int64_t
>(min_ns));
227 response.set(
"period_max_ns",
static_cast<int64_t
>(max_ns));
259 remote.bind(
"flexioObjectFledTest", [](
const fl::json&
args) -> fl::json {
261#if !defined(FL_IS_TEENSY_4X)
264 response.set(
"error",
"PlatformNotSupported");
266 "flexioObjectFledTest is Teensy 4.x-only (FLEXIO1 RX + "
267 "Teensy-core ObjectFLED driver).");
275 if (
args.is_array() &&
args.size() >= 1 &&
args[0].is_object()) {
276 fl::json cfg =
args[0];
277 if (cfg.
contains(
"test_case") && cfg[
"test_case"].is_int()) {
278 test_case =
static_cast<int>(cfg[
"test_case"].
as_int().value());
280 if (cfg.
contains(
"tx_pin") && cfg[
"tx_pin"].is_int()) {
281 tx_pin =
static_cast<int>(cfg[
"tx_pin"].
as_int().value());
283 if (cfg.
contains(
"rx_pin") && cfg[
"rx_pin"].is_int()) {
284 rx_pin =
static_cast<int>(cfg[
"rx_pin"].
as_int().value());
286 if (cfg.
contains(
"capture_ms") && cfg[
"capture_ms"].is_int()) {
287 capture_ms =
static_cast<int>(cfg[
"capture_ms"].
as_int().value());
290 if (test_case < 0 || test_case > 4 ||
291 capture_ms < 1 || capture_ms > 5000) {
293 response.set(
"error",
"InvalidArgs");
295 "test_case in [0,4]; capture_ms in [1, 5000].");
301 CRGB* leds_buf = flexIoObjectFledState().leds;
320 leds_buf[0] =
CRGB(0xFF, 0xFF, 0xFF);
324 for (
int i = 0; i < 100; ++i) {
326 : (i % 3 == 1) ?
CRGB::Green
333 fl::vector<u8> expected;
334 expected.
reserve((
size_t)num_leds * 3);
335 for (
int i = 0; i < num_leds; ++i) {
343 const size_t expected_edges = (
size_t)num_leds * 24u * 2u;
344 size_t edge_capacity = expected_edges + expected_edges / 4u + 64u;
345 if (edge_capacity > 16384u) edge_capacity = 16384u;
348 rx_cfg.edge_capacity = edge_capacity;
349 rx_cfg.start_low =
true;
351 if (!rx_channel || !rx_channel->begin(rx_cfg)) {
353 response.set(
"error",
"RxBeginFailed");
355 "Failed to bring up FlexIO RX on the requested pin "
356 "(check kFlexIo1Pins[] mapping).");
361 fl::ChannelOptions opts;
366 fl::NamedTimingConfig timing_cfg(resolved_timing,
"WS2812B-V5",
368 fl::ChannelConfig tx_cfg(
371 fl::span<CRGB>(leds_buf, (
size_t)num_leds),
377 response.set(
"error",
"TxAddFailed");
379 "FastLED.add() rejected the ObjectFLED ChannelConfig.");
392 const u32 ws2812_tx_us =
393 (u32)num_leds * 24u * 13u / 10u + 100u;
394 const u32 min_capture_ms = (ws2812_tx_us + 999u) / 1000u + 10u;
395 const u32 effective_capture_ms = ((u32)capture_ms > min_capture_ms)
398 rx_channel->wait(effective_capture_ms);
401 const fl::ChipsetTiming ws2812_timing =
403 fl::ChipsetTiming4Phase rx_timing =
405 fl::vector<u8> decoded;
408 rx_channel->decode(rx_timing, fl::span<u8>(decoded));
411 u32 decoded_bytes = 0u;
413 decoded_bytes = decode_result.value();
415 const size_t cmp_n = (decoded_bytes < expected.
size())
419 size_t mismatched = 0;
420 for (
size_t i = 0; i < cmp_n; ++i) {
421 if (decoded[i] == expected[i]) ++matched;
else ++mismatched;
423 if (decoded_bytes < expected.
size()) {
424 mismatched += expected.size() - decoded_bytes;
428 fl::vector<fl::EdgeTime> edges;
429 edges.
assign(edge_capacity, fl::EdgeTime());
430 const size_t edges_captured =
431 rx_channel->getRawEdgeTimes(fl::span<fl::EdgeTime>(edges), 0);
438 response.set(
"success", mismatched == 0 && decoded_bytes == expected.
size());
439 response.set(
"test_case",
static_cast<int64_t
>(test_case));
440 response.set(
"tx_pin",
static_cast<int64_t
>(tx_pin));
441 response.set(
"rx_pin",
static_cast<int64_t
>(rx_pin));
442 response.set(
"num_leds",
static_cast<int64_t
>(num_leds));
443 response.set(
"expected_bytes",
static_cast<int64_t
>(expected.
size()));
444 response.set(
"decoded_bytes",
static_cast<int64_t
>(decoded_bytes));
445 response.set(
"matched",
static_cast<int64_t
>(matched));
446 response.set(
"mismatched",
static_cast<int64_t
>(mismatched));
447 response.set(
"edges_captured",
static_cast<int64_t
>(edges_captured));
476 remote.bind(
"flexioRxLoopbackPing", [](
const fl::json&
args) -> fl::json {
478#if !defined(FL_IS_TEENSY_4X)
481 response.set(
"error",
"PlatformNotSupported");
483 "flexioRxLoopbackPing is Teensy 4.x-only (FLEXIO1 RX).");
490 if (
args.is_array() &&
args.size() >= 1 &&
args[0].is_object()) {
491 const fl::json &cfg =
args[0];
492 if (cfg.
contains(
"tx_pin") && cfg[
"tx_pin"].is_int()) {
493 tx_pin =
static_cast<int>(cfg[
"tx_pin"].
as_int().value());
495 if (cfg.
contains(
"rx_pin") && cfg[
"rx_pin"].is_int()) {
496 rx_pin =
static_cast<int>(cfg[
"rx_pin"].
as_int().value());
498 if (cfg.
contains(
"toggle_us") && cfg[
"toggle_us"].is_int()) {
499 toggle_us =
static_cast<int>(cfg[
"toggle_us"].
as_int().value());
501 if (cfg.
contains(
"edges") && cfg[
"edges"].is_int()) {
502 edges =
static_cast<int>(cfg[
"edges"].
as_int().value());
505 if (edges < 2 || edges > 64) {
507 response.set(
"error",
"InvalidEdges");
508 response.set(
"message",
"edges must be in [2, 64]");
514 rx_cfg.edge_capacity = 1024;
515 rx_cfg.start_low =
true;
517 if (!rx_channel || !rx_channel->begin(rx_cfg)) {
519 response.set(
"error",
"RxBeginFailed");
521 "FlexIO RX begin() failed (kFlexIo1Pins[] mapping?).");
533 for (
int i = 0; i < edges; ++i) {
544 constexpr uintptr_t kFLEXIO1_BASE_DIAG = 0x401AC000u;
546 volatile uint32_t *shftstat = (
volatile uint32_t *)(kFLEXIO1_BASE_DIAG + 0x010);
547 volatile uint32_t *timstat = (
volatile uint32_t *)(kFLEXIO1_BASE_DIAG + 0x018);
548 volatile uint32_t *shftbuf = (
volatile uint32_t *)(kFLEXIO1_BASE_DIAG + 0x200);
549 volatile uint32_t *shftbufbis = (
volatile uint32_t *)(kFLEXIO1_BASE_DIAG + 0x280);
550 volatile uint32_t *shftbufbys = (
volatile uint32_t *)(kFLEXIO1_BASE_DIAG + 0x300);
552 flexio_diag.
set(
"pin",
static_cast<int64_t
>(*pin));
553 flexio_diag.
set(
"shiftstat",
static_cast<int64_t
>(*shftstat));
554 flexio_diag.
set(
"timstat",
static_cast<int64_t
>(*timstat));
555 flexio_diag.
set(
"shiftbuf0",
static_cast<int64_t
>(*shftbuf));
556 flexio_diag.
set(
"shiftbufbis0",
static_cast<int64_t
>(*shftbufbis));
557 flexio_diag.
set(
"shiftbufbys0",
static_cast<int64_t
>(*shftbufbys));
558 response.set(
"flexio1", flexio_diag);
565 rx_channel->wait(50);
568 fl::vector<fl::EdgeTime> captured_edges;
569 captured_edges.
assign(64, fl::EdgeTime());
571 rx_channel->getRawEdgeTimes(fl::span<fl::EdgeTime>(captured_edges), 0);
577 response.set(
"tx_pin",
static_cast<int64_t
>(tx_pin));
578 response.set(
"rx_pin",
static_cast<int64_t
>(rx_pin));
579 response.set(
"toggle_us",
static_cast<int64_t
>(toggle_us));
580 response.set(
"edges",
static_cast<int64_t
>(edges));
581 response.set(
"edges_captured",
static_cast<int64_t
>(edge_count));
587 const size_t to_dump = (edge_count < 8u) ? edge_count : 8u;
588 for (
size_t i = 0; i < to_dump; ++i) {
590 e.
set(
"high", captured_edges[i].high);
591 e.
set(
"ns",
static_cast<int64_t
>(captured_edges[i].ns));
594 response.set(
"first_edges", edges_arr);
607 remote.bind(
"timingDriftTest", [](
const fl::json&
args) -> fl::json {
615 if (
args.is_object()) {
617 }
else if (
args.is_array() &&
args.size() >= 1 &&
args[0].is_object()) {
621 if (config.
contains(
"pin") && config[
"pin"].is_int()) {
622 pin =
static_cast<int>(config[
"pin"].
as_int().value());
624 if (config.
contains(
"numLeds") && config[
"numLeds"].is_int()) {
625 num_leds =
static_cast<int>(config[
"numLeds"].
as_int().value());
627 if (config.
contains(
"iterations") && config[
"iterations"].is_int()) {
628 iterations =
static_cast<int>(config[
"iterations"].
as_int().value());
634 response.set(
"success", r.valid_pin);
636 response.set(
"error",
"InvalidPin");
638 "pin is outside LegacyClocklessProxy range");
643 response.set(
"num_leds", r.num_leds);
644 response.set(
"iterations", r.iterations);
645 response.set(
"cpu_mhz",
static_cast<int64_t
>(r.cpu_mhz));
646 response.set(
"show_count",
static_cast<int64_t
>(r.show_count));
647 response.set(
"show_min_us",
static_cast<int64_t
>(r.show_min_us));
648 response.set(
"show_max_us",
static_cast<int64_t
>(r.show_max_us));
649 response.set(
"show_total_us",
static_cast<int64_t
>(r.show_total_us));
652 for (
int i = 0; i < r.iterations; ++i) {
653 iter_ms_arr.
push_back(
static_cast<int64_t
>(r.iter_ms[i]));
655 response.set(
"iter_ms", iter_ms_arr);
684 remote.bind(
"flexioSpiSelfTest", [](
const fl::json&
args) -> fl::json {
686#if !defined(FL_IS_TEENSY_4X)
689 response.set(
"error",
"PlatformNotSupported");
691 "flexioSpiSelfTest is Teensy 4.x-only (FlexIO2 SPI master mode).");
703 int clock_hz = 1000000;
705 if (
args.is_object()) {
706 const fl::json& cfg =
args;
707 if (cfg.
contains(
"mosi_pin") && cfg[
"mosi_pin"].is_int()) {
708 mosi_pin =
static_cast<int>(cfg[
"mosi_pin"].
as_int().value());
710 if (cfg.
contains(
"sclk_pin") && cfg[
"sclk_pin"].is_int()) {
711 sclk_pin =
static_cast<int>(cfg[
"sclk_pin"].
as_int().value());
713 if (cfg.
contains(
"clock_hz") && cfg[
"clock_hz"].is_int()) {
714 clock_hz =
static_cast<int>(cfg[
"clock_hz"].
as_int().value());
716 if (cfg.
contains(
"num_bytes") && cfg[
"num_bytes"].is_int()) {
717 num_bytes =
static_cast<int>(cfg[
"num_bytes"].
as_int().value());
723 response.set(
"clock_hz",
static_cast<int64_t
>(clock_hz));
724 response.set(
"num_bytes", num_bytes);
731 if (num_bytes <= 0 || num_bytes > 64) {
733 response.set(
"error",
"InvalidArgs");
734 response.set(
"message",
"num_bytes must be in [1, 64].");
737 if (mosi_pin < 0 || mosi_pin > 255 ||
738 sclk_pin < 0 || sclk_pin > 255) {
740 response.set(
"error",
"InvalidArgs");
741 response.set(
"message",
"mosi_pin / sclk_pin must be in [0, 255].");
746 response.set(
"error",
"InvalidArgs");
747 response.set(
"message",
"clock_hz must be > 0.");
752 fl::FlexIOSPIPinInfo pin_info{};
753 bool lookup_ok = fl::flexio_spi_lookup_pins(
754 static_cast<fl::u8>(mosi_pin),
755 static_cast<fl::u8>(sclk_pin),
757 response.set(
"lookup_ok", lookup_ok);
760 response.set(
"error",
"PinNotRoutable");
762 "(MOSI, SCLK) pair is not FlexIO2-routable; both pins "
763 "must be in {6, 7, 8, 9, 10, 11, 12, 13, 32}.");
767 static_cast<int64_t
>(pin_info.mosi_flexio_pin));
769 static_cast<int64_t
>(pin_info.sclk_flexio_pin));
772 bool init_ok = fl::flexio_spi_init(pin_info,
773 static_cast<fl::u32
>(clock_hz));
777 response.set(
"error",
"InitFailed");
778 response.set(
"message",
"flexio_spi_init returned false.");
786 for (
int i = 0; i < num_bytes; ++i) {
788 case 0: buffer[i] = 0xA5;
break;
789 case 1: buffer[i] = 0x5A;
break;
790 case 2: buffer[i] = 0xFF;
break;
791 case 3: buffer[i] = 0x00;
break;
795 const fl::u32 show_start_ms =
millis();
796 bool show_ok = fl::flexio_spi_show(buffer,
797 static_cast<fl::u32
>(num_bytes));
800 fl::flexio_spi_deinit();
802 response.set(
"error",
"ShowFailed");
803 response.set(
"message",
"flexio_spi_show returned false.");
808 fl::flexio_spi_wait();
809 const fl::u32 wait_ms =
millis() - show_start_ms;
810 response.set(
"wait_ms",
static_cast<int64_t
>(wait_ms));
813 fl::flexio_spi_deinit();
838 remote.bind(
"objectfledSpiSelfTest", [](
const fl::json&
args) -> fl::json {
840#if !defined(FL_IS_TEENSY_4X)
843 response.set(
"error",
"PlatformNotSupported");
845 "objectfledSpiSelfTest is Teensy 4.x-only (FlexPWM2 + eDMA + GPIO6).");
853 int clock_hz = 1000000;
855 if (
args.is_object()) {
856 const fl::json& cfg =
args;
857 if (cfg.
contains(
"mosi_pin") && cfg[
"mosi_pin"].is_int()) {
858 mosi_pin =
static_cast<int>(cfg[
"mosi_pin"].
as_int().value());
860 if (cfg.
contains(
"sclk_pin") && cfg[
"sclk_pin"].is_int()) {
861 sclk_pin =
static_cast<int>(cfg[
"sclk_pin"].
as_int().value());
863 if (cfg.
contains(
"clock_hz") && cfg[
"clock_hz"].is_int()) {
864 clock_hz =
static_cast<int>(cfg[
"clock_hz"].
as_int().value());
866 if (cfg.
contains(
"num_bytes") && cfg[
"num_bytes"].is_int()) {
867 num_bytes =
static_cast<int>(cfg[
"num_bytes"].
as_int().value());
873 response.set(
"clock_hz",
static_cast<int64_t
>(clock_hz));
874 response.set(
"num_bytes", num_bytes);
877 if (num_bytes <= 0 || num_bytes > 64) {
879 response.set(
"error",
"InvalidArgs");
880 response.set(
"message",
"num_bytes must be in [1, 64].");
883 if (mosi_pin < 0 || mosi_pin > 255 ||
884 sclk_pin < 0 || sclk_pin > 255) {
886 response.set(
"error",
"InvalidArgs");
887 response.set(
"message",
"mosi_pin / sclk_pin must be in [0, 255].");
892 response.set(
"error",
"InvalidArgs");
893 response.set(
"message",
"clock_hz must be > 0.");
898 fl::ObjectFLEDSPIPinInfo pin_info{};
899 bool lookup_ok = fl::objectfled_spi_lookup_pins(
900 static_cast<fl::u8>(mosi_pin),
901 static_cast<fl::u8>(sclk_pin),
903 response.set(
"lookup_ok", lookup_ok);
906 response.set(
"error",
"PinNotRoutable");
908 "(MOSI, SCLK) pair is not on GPIO6 or otherwise invalid; "
909 "both pins must be GPIO6-resident (T4.x: 0, 1, 14-27, "
910 "T4.1 adds 38-41).");
913 response.set(
"mosi_bit",
static_cast<int64_t
>(pin_info.mosi_bit));
914 response.set(
"sclk_bit",
static_cast<int64_t
>(pin_info.sclk_bit));
917 bool init_ok = fl::objectfled_spi_init(pin_info,
918 static_cast<fl::u32
>(clock_hz));
922 response.set(
"error",
"InitFailed");
923 response.set(
"message",
"objectfled_spi_init returned false.");
929 for (
int i = 0; i < num_bytes; ++i) {
931 case 0: buffer[i] = 0xA5;
break;
932 case 1: buffer[i] = 0x5A;
break;
933 case 2: buffer[i] = 0xFF;
break;
934 case 3: buffer[i] = 0x00;
break;
938 const fl::u32 show_start_ms =
millis();
939 bool show_ok = fl::objectfled_spi_show(
940 fl::span<const fl::u8>(buffer,
941 static_cast<fl::size
>(num_bytes)));
944 fl::objectfled_spi_deinit();
946 response.set(
"error",
"ShowFailed");
947 response.set(
"message",
"objectfled_spi_show returned false.");
952 fl::objectfled_spi_wait();
953 const fl::u32 wait_ms =
millis() - show_start_ms;
954 response.set(
"wait_ms",
static_cast<int64_t
>(wait_ms));
957 fl::ObjectFLEDSPIDiagnostics diag{};
958 fl::objectfled_spi_read_diagnostics(&diag);
959 response.set(
"dma_channel",
static_cast<int64_t
>(diag.dma_channel));
960 response.set(
"dma_erq",
static_cast<int64_t
>(diag.dma_erq));
961 response.set(
"dma_int",
static_cast<int64_t
>(diag.dma_int));
962 response.set(
"dma_err",
static_cast<int64_t
>(diag.dma_err));
963 response.set(
"dma_es",
static_cast<int64_t
>(diag.dma_es));
964 response.set(
"dma_citer",
static_cast<int64_t
>(diag.dma_citer));
965 response.set(
"dma_biter",
static_cast<int64_t
>(diag.dma_biter));
966 response.set(
"tmr3_cntr0",
static_cast<int64_t
>(diag.tmr3_cntr0));
967 response.set(
"tmr3_csctrl0",
static_cast<int64_t
>(diag.tmr3_csctrl0));
968 response.set(
"tmr3_sctrl0",
static_cast<int64_t
>(diag.tmr3_sctrl0));
969 response.set(
"tmr3_ctrl0",
static_cast<int64_t
>(diag.tmr3_ctrl0));
970 response.set(
"tmr3_enbl",
static_cast<int64_t
>(diag.tmr3_enbl));
971 response.set(
"xbar1_ctrl1",
static_cast<int64_t
>(diag.xbar1_ctrl1));
974 fl::objectfled_spi_deinit();
Full PARLIO encode bench for ESP32-P4 (post-byte-LUT, #2526 landed).
PARLIO ISR-streaming functional validation (#2548 deep-dive follow-up).
Issue #2994 repro: compounded per-sequence timing drift vs 3.10.3.
Wave8 expansion micro-benchmark for #2526.
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
fl::unique_ptr< fl::Remote > remote
fl::net::ble — BLE GATT transport layer for JSON-RPC
SPI encoder configuration for clocked LED chipsets.
void bindDriverMethods(fl::Remote &remote)
void show(fl::u8 scale)
Update all our controllers with the current led colors, using the passed in brightness.
static void add(fl::ChannelPtr channel)
Add a Channel-based LED controller (from ChannelPtr)
void clear(bool writeData=false)
Clear the leds, wiping the local array of data.
JSON-RPC server with scheduling support.
static RxChannelPtr create(const RxChannelConfig &config) FL_NO_EXCEPT
static T & instance() FL_NO_EXCEPT
fl::optional< i64 > as_int() const FL_NO_EXCEPT
void set(const fl::string &key, const json &value) FL_NO_EXCEPT
bool is_null() const FL_NO_EXCEPT
void push_back(const json &value) FL_NO_EXCEPT
bool contains(size_t idx) const FL_NO_EXCEPT
static json object() FL_NO_EXCEPT
static json array() FL_NO_EXCEPT
fl::size size() const FL_NO_EXCEPT
void reserve(fl::size n) FL_NO_EXCEPT
void resize(fl::size n) FL_NO_EXCEPT
void push_back(const T &value) FL_NO_EXCEPT
void assign(InputIt first, InputIt last) FL_NO_EXCEPT
Task executor — runs registered task runners and manages the run loop.
@ CHANNELS
Remove all channels from controller list.
Platform-abstracted heap memory query functions.
FastLED's Elegant JSON Library: fl::json
DriftResult run(int pin, int num_leds, int iterations)
constexpr ChipsetTiming to_runtime_timing() FL_NO_EXCEPT
Convert enum-based timing type to runtime ChipsetTiming struct.
constexpr ChipsetTimingConfig makeTimingConfig() FL_NO_EXCEPT
Convert compile-time CHIPSET type to runtime timing config.
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
ChipsetTiming4Phase make4PhaseTiming(const ChipsetTiming &timing_3phase, u32 tolerance_ns) FL_NO_EXCEPT
Create 4-phase RX timing from 3-phase chipset timing with tolerance.
@ FLEXIO
Teensy 4.x-only FlexIO capture backend (FLEXIO1 — FLEXIO2 is owned by the WS2812 TX driver)....
void pinMode(int pin, PinMode mode)
Set pin mode (input, output, pull-up, pull-down)
void analogWrite(int pin, u16 val)
Write analog value to pin (PWM)
void digitalWrite(int pin, PinValue val)
Write digital value to pin.
constexpr ClocklessEncoder encoder_for() FL_NO_EXCEPT
Extract the encoder selector from a compile-time TIMING type.
void delayMicroseconds(u32 us)
Delay for a given number of microseconds.
Promise-based fluent API for FastLED - standalone async primitives.
Umbrella header for SIMD subsystem.
@ Green
<div style='background:#008000;width:4em;height:4em;'></div>
@ Red
<div style='background:#FF0000;width:4em;height:4em;'></div>
@ Blue
<div style='background:#0000FF;width:4em;height:4em;'></div>
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>