120 {
122
123
125
126
127
129
130
131
132
133
134
139 remote.bind(
"echo", [](
int v) ->
int {
141 return v;
142 });
143
144#if defined(FL_IS_ARM_LPC)
145
146
147 remote.bind(
"pinToggleRx",
148 [](
int tx_pin,
int rx_pin,
int freq_hz,
int duration_ms) ->
fl::string {
149 if (tx_pin < 0 || rx_pin < 0 || freq_hz <= 0 || duration_ms <= 0) {
151 }
152 const fl::u32 expected_edges =
153 2u * static_cast<fl::u32>(freq_hz) *
154 static_cast<fl::u32>(duration_ms) / 1000u;
155 fl::u32 cap = expected_edges + (expected_edges / 2u);
156 if (cap < 256u) cap = 256u;
157 if (cap > 2048u) cap = 2048u;
158
159 auto rx = fl::LpcSctRxChannel::create(rx_pin);
161
165 if (!rx->begin(cfg))
return fl::string(
"0,0,0,0,0,0,0");
166
169
170 const fl::u32 half_us = 500000u / static_cast<fl::u32>(freq_hz);
171 const fl::u32 cycles = static_cast<fl::u32>(freq_hz) *
172 static_cast<fl::u32>(duration_ms) / 1000u;
173
174 for (fl::u32 i = 0; i < cycles; ++i) {
177 rx->pollOnce();
180 rx->pollOnce();
181 if ((i & 0x7Fu) == 0u) {
183 }
184 }
185 rx->wait(1);
186
188 const fl::size n_read = rx->getRawEdgeTimes(
190
191 LowMemPinTogglePeriodStats stats = computeLowMemPeriodStats(edges_buf, n_read);
192
194 const bool success = (stats.periods > 0);
195 s << (success ? 1 : 0) << ',' << static_cast<fl::u32>(n_read) << ','
196 << stats.periods << ',' << stats.mean_ns << ',' << stats.sigma_ns << ','
197 << stats.min_ns << ',' << stats.max_ns;
199 });
200
201#if defined(FASTLED_LPC_RX_SCT_WS2812)
202
203 remote.bind(
"ws2812SctTest",
204 [](
int test_case,
int tx_pin,
int rx_pin,
int capture_ms) ->
fl::string {
205 if (test_case < 0 || test_case > 4 ||
206 tx_pin < 0 || rx_pin < 0 || capture_ms <= 0) {
208 }
209 int num_leds = 1;
210 switch (test_case) {
211 case 1: num_leds = 3; break;
212 case 4: num_leds = 100; break;
213 default: num_leds = 1; break;
214 }
215 static CRGB leds_buf[100];
216 for (int i = 0; i < num_leds; ++i) {
217 switch (test_case) {
218 case 0: leds_buf[i] =
CRGB(0xFF, 0x00, 0x00);
break;
219 case 1: {
220 if (i == 0) leds_buf[i] =
CRGB(0xFF, 0x00, 0x00);
221 else if (i == 1) leds_buf[i] =
CRGB(0x00, 0xFF, 0x00);
222 else leds_buf[i] =
CRGB(0x00, 0x00, 0xFF);
223 break;
224 }
225 case 2: leds_buf[i] =
CRGB(0x00, 0x00, 0x00);
break;
226 case 3: leds_buf[i] =
CRGB(0xFF, 0xFF, 0xFF);
break;
227 case 4: {
228 const uint8_t r = (i % 3 == 0) ? 0xFFu : 0u;
229 const uint8_t g = (i % 3 == 1) ? 0xFFu : 0u;
230 const uint8_t b = (i % 3 == 2) ? 0xFFu : 0u;
231 leds_buf[i] =
CRGB(r, g, b);
232 break;
233 }
234 }
235 }
236 const int expected_bytes = num_leds * 3;
237 static uint8_t expected_buf[300];
238 for (int i = 0; i < num_leds; ++i) {
239 expected_buf[i * 3 + 0] = leds_buf[i].g;
240 expected_buf[i * 3 + 1] = leds_buf[i].r;
241 expected_buf[i * 3 + 2] = leds_buf[i].b;
242 }
243 auto rx = fl::LpcSctRxChannel::create(rx_pin);
244 if (!rx)
return fl::string(
"0,0,0,0,0,0,0,0");
246 const fl::u32 expected_edges = (fl::u32)num_leds * 24u * 2u;
247 fl::u32 cap = expected_edges + (expected_edges / 2u);
248 if (cap < 256u) cap = 256u;
249 if (cap > 2048u) cap = 2048u;
252 if (!rx->begin(cfg))
return fl::string(
"0,0,0,0,0,0,0,0");
253
254 constexpr int kFixedTxPin = 10;
255 if (tx_pin != kFixedTxPin) {
257 }
258 static bool fastled_inited = false;
259 if (!fastled_inited) {
260 FastLED.addLeds<WS2812, kFixedTxPin,
GRB>(leds_buf, 100);
261 fastled_inited = true;
262 }
264 rx->wait(capture_ms);
265
266 static uint8_t decoded_buf[300];
267 for (int i = 0; i < expected_bytes; ++i) decoded_buf[i] = 0;
268
272 0u);
273
274 auto dec = rx->decode(timing,
fl::span<u8>(decoded_buf, expected_bytes));
275 const fl::u32 decoded_bytes =
dec.ok() ?
dec.value() : 0u;
276
277 fl::u32 matched = 0;
278 fl::u32 mismatched = 0;
279 for (fl::u32 i = 0; i < decoded_bytes && i < (fl::u32)expected_bytes; ++i) {
280 if (decoded_buf[i] == expected_buf[i]) ++matched;
281 else ++mismatched;
282 }
283 const fl::u32 missing = (fl::u32)expected_bytes - decoded_bytes;
284 mismatched += missing;
285
287 const fl::size edges_captured = rx->getRawEdgeTimes(
289
290 const bool success = (mismatched == 0 && decoded_bytes == (fl::u32)expected_bytes);
291
293 s << (
success ? 1 : 0) <<
',' << test_case <<
',' << num_leds <<
','
294 << expected_bytes << ',' << decoded_bytes << ','
295 << matched << ',' << mismatched << ','
296 << static_cast<fl::u32>(edges_captured);
298 });
299#endif
300#endif
301}
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_NOEXCEPT
void begin(fl::u32 timeout_ms) FL_NOEXCEPT
string str() const FL_NOEXCEPT
#define FL_WARN_LIT(LITERAL)
fl::Remote * g_low_memory_remote
constexpr ChipsetTiming to_runtime_timing() FL_NOEXCEPT
Convert enum-based timing type to runtime ChipsetTiming struct.
void serial_begin(u32 baudRate)
fl::function< fl::optional< fl::json >()> createSerialRequestSource(const char *prefix="")
Create a JSON-RPC RequestSource that reads from fl:: serial input.
ChipsetTiming4Phase make4PhaseTiming(const ChipsetTiming &timing_3phase, u32 tolerance_ns) FL_NOEXCEPT
Create 4-phase RX timing from 3-phase chipset timing with tolerance.
void pinMode(int pin, PinMode mode)
Set pin mode (input, output, pull-up, pull-down)
fl::function< void(const fl::json &)> createSerialResponseSink(const char *prefix="REMOTE: ")
Create a JSON-RPC ResponseSink that writes to fl:: serial output.
void digitalWrite(int pin, PinValue val)
Write digital value to pin.
void delayMicroseconds(u32 us)
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.