262 {
264
265
267
268
269
271
272
273
274
275
276
278 remote.bind(
"echo", [](
int v) ->
int {
280 return v;
281 });
282
283#if defined(FL_IS_ARM_LPC_845) && defined(FASTLED_AUTORESEARCH_FAULT_TEST)
284 remote.bind(
"trigger_oom", []() ->
bool {
285
286
287
288 volatile char* const p = new char[16UL * 1024UL * 1024UL];
289 if (p == nullptr) {
290 triggerLowMemoryNullFault();
291 }
292 p[0] = 0x33;
293 triggerLowMemoryNullFault();
294 return false;
295 });
296 remote.bind(
"trigger_stackblow", []() ->
bool {
297 (void)recurseLowMemoryStackBlow(0);
298 triggerLowMemoryNullFault();
299 return false;
300 });
301#endif
302
303#if defined(FASTLED_AUTORESEARCH_IEEE754_MODE)
309 response.set(
"tests_run",
static_cast<int64_t
>(r.tests_run));
310 response.set(
"tests_failed",
static_cast<int64_t
>(r.tests_failed));
311 response.set(
"first_failure", r.first_failure ? r.first_failure :
"");
312 response.set(
"expected_bits",
static_cast<int64_t
>(r.expected_bits));
313 response.set(
"actual_bits",
static_cast<int64_t
>(r.actual_bits));
315 });
316#endif
317
318#if defined(FL_IS_ARM_LPC) && !defined(FASTLED_AUTORESEARCH_IEEE754_MODE) && \
319 !defined(FASTLED_AUTORESEARCH_FAULT_TEST)
320
321
322#if !defined(FASTLED_AUTORESEARCH_LPC_DMA_LOOPBACK)
323
324
325
326 remote.bind(
"pinToggleRx",
327 [](
int tx_pin,
int rx_pin,
int freq_hz,
int duration_ms) ->
fl::string {
328 if (tx_pin < 0 || rx_pin < 0 || freq_hz <= 0 || duration_ms <= 0) {
330 }
331 const fl::u32 expected_edges =
332 2u * static_cast<fl::u32>(freq_hz) *
333 static_cast<fl::u32>(duration_ms) / 1000u;
334
335
336
337
338
339 constexpr fl::u32 kLowMemEdgeBufSize = 64u;
340 fl::u32 cap = expected_edges + (expected_edges / 2u);
341 if (cap < 2u) cap = 2u;
342 if (cap > kLowMemEdgeBufSize) cap = kLowMemEdgeBufSize;
343
344 auto rx = fl::LpcSctRxChannel::create(rx_pin);
346
350 if (!rx->begin(cfg))
return fl::string(
"0,0,0,0,0,0,0");
351
354
355 const fl::u32 half_us = 500000u / static_cast<fl::u32>(freq_hz);
356 const fl::u32 cycles = static_cast<fl::u32>(freq_hz) *
357 static_cast<fl::u32>(duration_ms) / 1000u;
358
359 for (fl::u32 i = 0; i < cycles; ++i) {
362 rx->pollOnce();
365 rx->pollOnce();
366 if ((i & 0x7Fu) == 0u) {
368 }
369 }
370 rx->wait(1);
371
372
373
374 fl::EdgeTime* edges_buf = autoresearch::low_memory::pinToggleState().edges;
375 const fl::size n_read = rx->getRawEdgeTimes(
377
378 LowMemPinTogglePeriodStats stats = computeLowMemPeriodStats(edges_buf, n_read);
379
381 const bool success = (stats.periods > 0);
382 s << (success ? 1 : 0) << ',' << static_cast<fl::u32>(n_read) << ','
383 << stats.periods << ',' << stats.mean_ns << ',' << stats.sigma_ns << ','
384 << stats.min_ns << ',' << stats.max_ns;
386 });
387#endif
388
389#if defined(FASTLED_AUTORESEARCH_LPC_WS2812)
390
391 remote.bind(
"ws2812SctTest",
392 [](
int test_case,
int tx_pin,
int rx_pin,
int capture_ms) ->
fl::string {
393 if (test_case < 0 || test_case > 4 ||
394 tx_pin < 0 || rx_pin < 0 || capture_ms <= 0) {
396 }
397 int num_leds = 1;
398 switch (test_case) {
399 case 1: num_leds = 3; break;
400 case 4: num_leds = 100; break;
401 default: num_leds = 1; break;
402 }
403 autoresearch::low_memory::Ws2812State& ws_state =
404 autoresearch::low_memory::ws2812State();
405 CRGB* leds_buf = ws_state.leds;
406 for (int i = 0; i < num_leds; ++i) {
407 switch (test_case) {
408 case 0: leds_buf[i] =
CRGB(0xFF, 0x00, 0x00);
break;
409 case 1: {
410 if (i == 0) leds_buf[i] =
CRGB(0xFF, 0x00, 0x00);
411 else if (i == 1) leds_buf[i] =
CRGB(0x00, 0xFF, 0x00);
412 else leds_buf[i] =
CRGB(0x00, 0x00, 0xFF);
413 break;
414 }
415 case 2: leds_buf[i] =
CRGB(0x00, 0x00, 0x00);
break;
416 case 3: leds_buf[i] =
CRGB(0xFF, 0xFF, 0xFF);
break;
417 case 4: {
418 const uint8_t r = (i % 3 == 0) ? 0xFFu : 0u;
419 const uint8_t g = (i % 3 == 1) ? 0xFFu : 0u;
420 const uint8_t b = (i % 3 == 2) ? 0xFFu : 0u;
421 leds_buf[i] =
CRGB(r, g, b);
422 break;
423 }
424 }
425 }
426 const int expected_bytes = num_leds * 3;
427 uint8_t* expected_buf = ws_state.expected;
428 for (int i = 0; i < num_leds; ++i) {
429 expected_buf[i * 3 + 0] = leds_buf[i].g;
430 expected_buf[i * 3 + 1] = leds_buf[i].r;
431 expected_buf[i * 3 + 2] = leds_buf[i].b;
432 }
433 auto rx = fl::LpcSctRxChannel::create(rx_pin);
434 if (!rx)
return fl::string(
"0,0,0,0,0,0,0,0");
436 const fl::u32 expected_edges = (fl::u32)num_leds * 24u * 2u;
437 fl::u32 cap = expected_edges + (expected_edges / 2u);
438
439
440
441
442 constexpr fl::u32 kLowMemWs2812EdgeCapacity = 192u;
443 if (cap < 48u) cap = 48u;
444 if (cap > kLowMemWs2812EdgeCapacity) cap = kLowMemWs2812EdgeCapacity;
447 if (!rx->begin(cfg))
return fl::string(
"0,0,0,0,0,0,0,0");
448
449 constexpr int kFixedTxPin = 10;
450 if (tx_pin != kFixedTxPin) {
452 }
453 if (!ws_state.fastled_initialized) {
454 FastLED.addLeds<WS2812, kFixedTxPin,
GRB>(leds_buf, 100);
455 ws_state.fastled_initialized = true;
456 }
458 rx->wait(capture_ms);
459
460 uint8_t* decoded_buf = ws_state.decoded;
461 for (int i = 0; i < expected_bytes; ++i) decoded_buf[i] = 0;
462
466 0u);
467
468 auto dec = rx->decode(timing,
fl::span<u8>(decoded_buf, expected_bytes));
469 const fl::u32 decoded_bytes =
dec.ok() ?
dec.value() : 0u;
470
471 fl::u32 matched = 0;
472 fl::u32 mismatched = 0;
473 for (fl::u32 i = 0; i < decoded_bytes && i < (fl::u32)expected_bytes; ++i) {
474 if (decoded_buf[i] == expected_buf[i]) ++matched;
475 else ++mismatched;
476 }
477 const fl::u32 missing = (fl::u32)expected_bytes - decoded_bytes;
478 mismatched += missing;
479
480
481
482 constexpr fl::size kLowMemWs2812ProbeSize = 64u;
484 const fl::size edges_captured = rx->getRawEdgeTimes(
486
487 const bool success = (mismatched == 0 && decoded_bytes == (fl::u32)expected_bytes);
488
490 s << (
success ? 1 : 0) <<
',' << test_case <<
',' << num_leds <<
','
491 << expected_bytes << ',' << decoded_bytes << ','
492 << matched << ',' << mismatched << ','
493 << static_cast<fl::u32>(edges_captured);
495 });
496#endif
497
498
499
500
501
502#if defined(FL_IS_ARM_LPC_845) && defined(FASTLED_LPC_PWM_DMA)
503 autoresearch::pwm_dma_cl::bind(
remote);
504#endif
505
506
507
508
509#if defined(FL_IS_ARM_LPC_845) && defined(FASTLED_LPC_SPI_DMA)
510 autoresearch::dma_spi::bind(
remote);
511#endif
512
513
514
515
516#if defined(FL_IS_ARM_LPC_845) && FASTLED_AUTORESEARCH_LPC_UART_DMA
517 autoresearch::uart_dma::bind(
remote);
518#endif
519
520#endif
521}
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
fl::unique_ptr< fl::Remote > remote
JSON-RPC server with scheduling support.
static Watchdog & instance() FL_NO_EXCEPT
void begin(fl::u32 timeout_ms) FL_NO_EXCEPT
static json object() FL_NO_EXCEPT
string str() const FL_NO_EXCEPT
#define FL_WARN_LIT(LITERAL)
RemoteState & remoteState()
constexpr ChipsetTiming to_runtime_timing() FL_NO_EXCEPT
Convert enum-based timing type to runtime ChipsetTiming struct.
ChipsetTiming4Phase make4PhaseTiming(const ChipsetTiming &timing_3phase, u32 tolerance_ns) FL_NO_EXCEPT
Create 4-phase RX timing from 3-phase chipset timing with tolerance.
void serial_begin(u32 baudRate) FL_NO_EXCEPT
void digitalWrite(int pin, PinValue val) FL_NO_EXCEPT
Write digital value to pin.
void pinMode(int pin, PinMode mode) FL_NO_EXCEPT
Set pin mode (input, output, pull-up, pull-down)
void delayMicroseconds(u32 us) FL_NO_EXCEPT
Delay for a given number of microseconds.
4-phase RX timing thresholds for chipset detection
Universal edge timing representation (platform-agnostic)
size_t buffer_size
Buffer size in symbols/edges (default: 512)
bool start_low
Pin idle state: true=LOW (WS2812B), false=HIGH (inverted)
Configuration for RX device initialization.