FastLED 3.10.8
Loading...
Searching...
No Matches
validation.h
Go to the documentation of this file.
1// src/fl/channels/validation.h
2//
3// Validation test logic - stateless single-test execution
4// Extracted from examples/validation for unit testing
5
6#pragma once
7
8#include "fl/stl/vector.h"
9#include "fl/stl/string.h"
10#include "fl/stl/optional.h"
11#include "fl/stl/int.h"
12#include "fl/stl/noexcept.h"
14
15// Forward declarations for detail modules
16namespace fl {
17namespace validation {
18 class RxTest; // IWYU pragma: keep
19 class ResultFormatter; // IWYU pragma: keep
20 class Platform; // IWYU pragma: keep
21}
22}
23
24namespace fl {
25
26namespace validation {
27
33inline bool useRmtInternalLoopback(bool is_rmt_driver, int tx_pin,
34 int rx_pin) FL_NO_EXCEPT {
35 return is_rmt_driver && tx_pin == rx_pin;
36}
37
50inline RxBackend resolveCaptureBackend(RxBackend requested_backend,
51 bool has_explicit_override,
52 bool is_parlio_driver,
53 bool is_esp32_c6) FL_NO_EXCEPT {
54 if (!has_explicit_override && is_parlio_driver && is_esp32_c6) {
56 }
57 return requested_backend;
58}
59
65inline size_t captureEdgeCapacity(size_t shared_buffer_bytes,
66 size_t expected_data_bytes,
67 RxBackend backend) FL_NO_EXCEPT {
68 constexpr size_t kEdgesPerByte = 16;
69 constexpr size_t kFramingEdges = 2;
70 const size_t max_size = static_cast<size_t>(-1);
71
72 if (backend != RxBackend::ISR) {
73 if (shared_buffer_bytes > max_size / 8) {
74 return 0;
75 }
76 return shared_buffer_bytes * 8;
77 }
78
79 if (expected_data_bytes > (max_size - kFramingEdges) / kEdgesPerByte) {
80 return 0;
81 }
82 const size_t required =
83 expected_data_bytes * kEdgesPerByte + kFramingEdges;
84 size_t capacity = 1;
85 while (capacity < required) {
86 if (capacity > max_size / 2) {
87 return 0;
88 }
89 capacity *= 2;
90 }
91 return capacity;
92}
93
107inline bool isWholeCaptureFrame(size_t run_count, bool lead_run_is_low,
108 u32 lead_run_ns, u32 idle_threshold_ns,
109 size_t min_frame_runs) FL_NO_EXCEPT {
110 constexpr size_t kLeadPlusOneByteRuns = 1 + 8 + 7;
111 if (run_count >= min_frame_runs) {
112 return true;
113 }
114 return run_count >= kLeadPlusOneByteRuns && lead_run_is_low &&
115 lead_run_ns > idle_threshold_ns;
116}
117
156inline size_t rpPioMaxWireBytes(size_t edge_capacity,
157 size_t dma_tail_words,
158 u32 samples_per_dma_word,
159 u32 sample_period_ns,
160 u32 idle_tail_ns,
161 u32 arming_lead_in_ns,
162 u32 bit_period_ns) FL_NO_EXCEPT {
163 constexpr size_t kPhasesPerByte = 16; // 8 bits x (high + low)
164 constexpr u64 kBitsPerByte = 8;
165
166 if (bit_period_ns == 0 || edge_capacity == 0 || samples_per_dma_word == 0 ||
167 sample_period_ns == 0) {
168 return 0;
169 }
170
171 const size_t by_pool = edge_capacity / kPhasesPerByte;
172
173 const u64 dma_words =
174 static_cast<u64>((edge_capacity + 1u) / 2u) + dma_tail_words;
175 const u64 budget_ns =
176 dma_words * samples_per_dma_word * sample_period_ns;
177 const u64 reserved_ns =
178 static_cast<u64>(idle_tail_ns) + arming_lead_in_ns;
179 if (budget_ns <= reserved_ns) {
180 return 0;
181 }
182 const u64 by_clock =
183 (budget_ns - reserved_ns) / (kBitsPerByte * bit_period_ns);
184
185 if (static_cast<u64>(by_pool) < by_clock) {
186 return by_pool;
187 }
188 return static_cast<size_t>(by_clock);
189}
190
191} // namespace validation
192
195 string driver_name;
197 string pattern;
199 int pin_tx;
200 int pin_rx;
201
203 : pattern("MSB_LSB_A")
204 , iterations(1)
205 , pin_tx(1)
206 , pin_rx(0) {}
207};
208
234
240 bool skipped;
241
242 DriverTestResult(const char* name)
244 , total_tests(0)
245 , passed_tests(0)
246 , skipped(false) {}
247
249 : total_tests(0)
250 , passed_tests(0)
251 , skipped(false) {}
252
254 bool allPassed() const FL_NO_EXCEPT { return !skipped && total_tests > 0 && passed_tests == total_tests; }
255
257 bool anyFailed() const FL_NO_EXCEPT { return !skipped && total_tests > 0 && passed_tests < total_tests; }
258};
259
263SingleTestResult runSingleValidationTest(const SingleTestConfig& config) FL_NO_EXCEPT;
264
265} // namespace fl
bool useRmtInternalLoopback(bool is_rmt_driver, int tx_pin, int rx_pin) FL_NO_EXCEPT
Whether an RMT validation capture should use ESP-IDF loopback.
Definition validation.h:33
RxBackend resolveCaptureBackend(RxBackend requested_backend, bool has_explicit_override, bool is_parlio_driver, bool is_esp32_c6) FL_NO_EXCEPT
Select the independent capture backend used by AutoResearch.
Definition validation.h:50
bool isWholeCaptureFrame(size_t run_count, bool lead_run_is_low, u32 lead_run_ns, u32 idle_threshold_ns, size_t min_frame_runs) FL_NO_EXCEPT
Whether an oversampled capture holds a whole frame, not a fragment.
Definition validation.h:107
size_t captureEdgeCapacity(size_t shared_buffer_bytes, size_t expected_data_bytes, RxBackend backend) FL_NO_EXCEPT
Compute the RX edge-buffer capacity for a validation frame.
Definition validation.h:65
size_t rpPioMaxWireBytes(size_t edge_capacity, size_t dma_tail_words, u32 samples_per_dma_word, u32 sample_period_ns, u32 idle_tail_ns, u32 arming_lead_in_ns, u32 bit_period_ns) FL_NO_EXCEPT
Largest frame, in wire bytes, an RP PIO RX capture can hold.
Definition validation.h:156
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
Optional< T > optional
Definition optional.h:16
RxBackend
Definition types.h:8
@ ISR
Platform-neutral interrupt-driven edge capture backend when available.
Definition types.h:12
@ PARLIO_RX
PARLIO 1-bit oversampling backend (ESP32-C6 et al) — DMA sampling at 16 MHz with no per-edge interrup...
Definition types.h:16
SingleTestResult runSingleValidationTest(const SingleTestConfig &config) FL_NO_EXCEPT
Run a single stateless validation test.
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NO_EXCEPT
fl::u64 u64
Definition stdint.h:220
bool skipped
True if driver was skipped (e.g., failed to set exclusive)
Definition validation.h:240
int total_tests
Total test count across all chipset timings.
Definition validation.h:238
DriverTestResult(const char *name) FL_NO_EXCEPT
Definition validation.h:242
int passed_tests
Passed test count across all chipset timings.
Definition validation.h:239
DriverTestResult() FL_NO_EXCEPT
Definition validation.h:248
bool allPassed() const FL_NO_EXCEPT
Check if all tests passed.
Definition validation.h:254
fl::string driver_name
Driver name (e.g., "RMT", "SPI", "PARLIO")
Definition validation.h:237
bool anyFailed() const FL_NO_EXCEPT
Check if any tests failed.
Definition validation.h:257
int iterations
Number of test iterations (default: 1)
Definition validation.h:198
string driver_name
Driver to test (e.g., "PARLIO", "RMT")
Definition validation.h:195
SingleTestConfig() FL_NO_EXCEPT
Definition validation.h:202
vector< int > lane_sizes
LED count per lane [100, 100, 200].
Definition validation.h:196
string pattern
Test pattern name (default: "MSB_LSB_A")
Definition validation.h:197
int pin_tx
TX pin (base pin for multi-lane)
Definition validation.h:199
vector< int > lane_sizes
LED counts per lane.
Definition validation.h:218
bool passed
All validation tests passed.
Definition validation.h:212
int total_tests
Total validation tests run.
Definition validation.h:213
int lane_count
Number of lanes tested.
Definition validation.h:217
SingleTestResult() FL_NO_EXCEPT
Definition validation.h:226
optional< string > failure_details
Failure details.
Definition validation.h:224
optional< string > error_message
Error message if !success.
Definition validation.h:222
int passed_tests
Number of tests that passed.
Definition validation.h:214
bool success
RPC execution succeeded.
Definition validation.h:211
optional< string > failure_pattern
Pattern that failed if !passed.
Definition validation.h:223
string pattern
Pattern tested.
Definition validation.h:219
u32 duration_ms
Test execution time (milliseconds)
Definition validation.h:215
string driver
Driver tested.
Definition validation.h:216