FastLED 3.9.15
Loading...
Searching...
No Matches

◆ validateParlioStreaming()

ValidateResult autoresearch::parlio_stream::validateParlioStreaming ( int base_tx_pin,
int num_lanes,
int num_leds,
int iterations,
uint32_t timeout_ms,
const int * tx_pins = nullptr )
inline

Run the PARLIO streaming functional test.

Parameters
base_tx_pinFirst PARLIO TX pin; lanes occupy [base_tx_pin .. base_tx_pin+num_lanes-1]
num_lanesNumber of PARLIO lanes (1-16). Use 16 to exercise BF1+pipe4.
num_ledsLEDs per lane.
iterationsNumber of back-to-back show()+wait() cycles (capped at kMaxIterations).
timeout_msPer-iteration timeout. Test fails if any iter exceeds this.
tx_pinsOptional explicit per-lane pins. If null, uses contiguous base_tx_pin+lane.

Definition at line 94 of file AutoResearchParlioStream.h.

99 {
100 ValidateResult r{};
101 r.channels_ok = false;
102 r.completed = false;
103 r.explicit_tx_pins = tx_pins != nullptr;
104 r.base_tx_pin = base_tx_pin;
105 r.lanes = num_lanes;
106 r.leds_per_lane = num_leds;
107 r.iterations = iterations;
108 r.timeout_ms = timeout_ms;
109 r.failed_iter = -1;
110 for (int lane = 0; lane < kMaxLanes; ++lane) {
111 r.tx_pins[lane] = -1;
112 }
113
114 if (iterations < 1) iterations = 1;
115 if (iterations > kMaxIterations) iterations = kMaxIterations;
116 r.iterations = iterations;
117 if (!tx_pins && base_tx_pin < 0) return r;
118 if (num_lanes < 1 || num_lanes > 16) return r;
119 if (num_leds < 1) return r;
120 if (tx_pins) {
121 base_tx_pin = tx_pins[0];
122 r.base_tx_pin = base_tx_pin;
123 for (int lane = 0; lane < num_lanes; ++lane) {
124 if (tx_pins[lane] < 0) return r;
125 }
126 }
127
128#if defined(ARDUINO_ARCH_ESP32) || defined(ESP_PLATFORM)
129 // Reuse a single static heap-resident LED buffer sized for the canonical
130 // worst case (16 lanes × 256 LEDs). Test callers must stay within these
131 // bounds. Static to avoid repeated allocation across RPC calls.
132 constexpr int kMaxLEDs = 256;
133 if (num_leds > kMaxLEDs) return r;
134 static CRGB leds[kMaxLanes][kMaxLEDs];
135 for (int lane = 0; lane < num_lanes; ++lane) {
136 for (int i = 0; i < num_leds; ++i) {
137 leds[lane][i] = CRGB(0xF0, 0x0F, 0xAA); // Pattern A (mixed bits)
138 }
139 }
140
141 fl::ChipsetTimingConfig timing =
143
144 fl::ChannelOptions parlio_opts;
145 parlio_opts.mBus = fl::Bus::PARLIO;
146
148
149 fl::vector<fl::shared_ptr<fl::Channel>> channels;
150 for (int lane = 0; lane < num_lanes; ++lane) {
151 const int tx_pin = tx_pins ? tx_pins[lane] : (base_tx_pin + lane);
152 r.tx_pins[lane] = tx_pin;
153 if (!isFastLedOutputPinValid(tx_pin)) {
155 return r;
156 }
157 fl::ChannelConfig cfg(
158 tx_pin,
159 timing,
160 fl::span<CRGB>(leds[lane], num_leds),
161 RGB,
162 parlio_opts);
163 auto ch = FastLED.add(cfg);
164 if (!ch) {
166 return r;
167 }
168 channels.push_back(ch);
169 }
170 r.channels_ok = true;
171
172 bool ok = true;
173 uint32_t steady_total = 0;
174 uint32_t steady_show_total = 0;
175 uint32_t steady_wait_total = 0;
176 for (int iter = 0; iter < iterations; ++iter) {
177 const uint32_t t0 = micros();
178 FastLED.show();
179 const uint32_t t_show = micros();
180 FastLED.wait(timeout_ms);
181 const uint32_t t1 = micros();
182 const uint32_t show_us = t_show - t0;
183 const uint32_t wait_us = t1 - t_show;
184 const uint32_t dt = t1 - t0;
185 r.per_iter_us[iter] = dt;
186 r.per_iter_show_us[iter] = show_us;
187 r.per_iter_wait_us[iter] = wait_us;
188 if (dt > timeout_ms * 1000u) {
189 r.failed_iter = iter;
190 ok = false;
191 break;
192 }
193 if (iter > 0) {
194 steady_total += dt;
195 steady_show_total += show_us;
196 steady_wait_total += wait_us;
197 }
198 }
199
201
202#if defined(ESP32) && FASTLED_ESP32_HAS_PARLIO
203 {
204 auto metrics = fl::detail::ParlioEngine::getInstance().getDebugMetrics();
205 r.tx_done_count = metrics.mTxDoneCount;
206 r.worker_isr_count = metrics.mWorkerIsrCount;
207 r.underrun_count = metrics.mUnderrunCount;
208 r.ring_count = metrics.mRingCount;
209 r.bytes_total = metrics.mBytesTotal;
210 r.bytes_transmitted = metrics.mBytesTransmitted;
211 r.ring_error = metrics.mRingError;
212 r.hardware_idle = metrics.mHardwareIdle;
213 }
214#endif
215
216 r.completed = ok;
217 if (ok && iterations > 1) {
218 r.steady_avg_us = steady_total / (iterations - 1);
219 r.steady_avg_show_us = steady_show_total / (iterations - 1);
220 r.steady_avg_wait_us = steady_wait_total / (iterations - 1);
221 } else if (ok) {
222 r.steady_avg_us = r.per_iter_us[0];
223 r.steady_avg_show_us = r.per_iter_show_us[0];
224 r.steady_avg_wait_us = r.per_iter_wait_us[0];
225 }
226#else
227 (void)base_tx_pin;
228 (void)timeout_ms;
229#endif
230 return r;
231}
fl::CRGB leds[NUM_LEDS]
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
@ CHANNELS
Remove all channels from controller list.
Definition FastLED.h:580
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 wait()
Wait for all channel bus transmissions to complete.
void clear(bool writeData=false)
Clear the leds, wiping the local array of data.
void push_back(const T &value) FL_NOEXCEPT
Definition vector.h:624
constexpr EOrder RGB
Definition eorder.h:17
fl::CRGB CRGB
Definition crgb.h:25
fl::u32 uint32_t
Definition s16x16x4.h:219
constexpr ChipsetTimingConfig makeTimingConfig() FL_NOEXCEPT
Convert compile-time CHIPSET type to runtime timing config.
@ PARLIO
ESP32-P4/C6/H2/C5 parallel I/O peripheral.
Definition bus.h:63
fl::u32 micros()
Universal microsecond timer - returns microseconds since system startup.

References CHANNELS, autoresearch::parlio_stream::ValidateResult::channels_ok, FastLED, isFastLedOutputPinValid(), kMaxIterations, kMaxLanes, leds, fl::makeTimingConfig(), fl::ChannelOptions::mBus, fl::PARLIO, fl::vector< T >::push_back(), and RGB.

Referenced by AutoResearchRemoteControl::registerFunctions().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: