152 {
154 out_passed = false;
155
156 metric.
set(
"requested",
true);
157 metric.
set(
"supported",
false);
158 metric.
set(
"driver", driver_name.
c_str());
159
160 if (iterations < 1) {
161 metric.
set(
"message",
"iterations must be >= 1");
162 return metric;
163 }
164 if (tx_configs.
empty()) {
165 metric.
set(
"message",
"no channel configs");
166 return metric;
167 }
168 for (fl::size i = 0; i < tx_configs.
size(); i++) {
169 if (tx_configs[i].isSpi()) {
170 metric.
set(
"message",
"clocked SPI timing metric is not supported");
171 return metric;
172 }
173 }
174
175 fl::vector<fl::ChannelConfig> sample_configs = tx_configs;
176 fl::vector<fl::shared_ptr<fl::Channel>> channels;
177 for (fl::size i = 0; i < sample_configs.
size(); i++) {
178 fl::ChannelConfig channel_config(
179 sample_configs[i].getDataPin(),
180 timing,
181 sample_configs[i].mLeds,
182 sample_configs[i].rgb_order);
183 fl::shared_ptr<fl::Channel> channel =
FastLED.
add(channel_config);
184 if (!channel) {
186 metric.
set(
"message",
"failed to create channel");
187 return metric;
188 }
190 }
191
193 for (fl::size lane = 0; lane < sample_configs.
size(); lane++) {
195 sample_configs[lane].mLeds.size(),
197 }
201 metric.
set(
"message",
"warmup wait timeout");
202 return metric;
203 }
205
212 uint32_t min_total_us = 0xFFFFFFFFu;
214 uint32_t min_overhead_us = 0xFFFFFFFFu;
216 uint64_t sum_show_us = 0;
217 uint64_t sum_wait_us = 0;
218 uint64_t sum_total_us = 0;
219 uint64_t sum_overhead_us = 0;
220 int samples = 0;
222
224 for (fl::size lane = 0; lane < sample_configs.
size(); lane++) {
229 sample_configs[lane].mLeds.size(),
231 }
232
238 if (!ok) {
240 break;
241 }
242
247 total_us > expected_wire_us ? total_us - expected_wire_us : 0;
248
249 if (show_us < min_show_us) min_show_us = show_us;
250 if (show_us > max_show_us) max_show_us = show_us;
251 if (wait_us < min_wait_us) min_wait_us = wait_us;
252 if (wait_us > max_wait_us) max_wait_us = wait_us;
253 if (total_us < min_total_us) min_total_us = total_us;
254 if (total_us > max_total_us) max_total_us = total_us;
255 if (overhead_us < min_overhead_us) min_overhead_us = overhead_us;
256 if (overhead_us > max_overhead_us) max_overhead_us = overhead_us;
257
258 sum_show_us += show_us;
259 sum_wait_us += wait_us;
260 sum_total_us += total_us;
261 sum_overhead_us += overhead_us;
262 samples++;
263 }
264
266
267 metric.
set(
"supported",
true);
268 metric.
set(
"samples",
static_cast<int64_t
>(samples));
269 metric.
set(
"iterations",
static_cast<int64_t
>(iterations));
270 metric.
set(
"expected_wire_us",
static_cast<int64_t
>(expected_wire_us));
271 metric.
set(
"max_allowed_overhead_us",
272 static_cast<int64_t>(max_allowed_overhead_us));
273
274 if (samples == 0) {
275 metric.
set(
"passed",
false);
276 metric.
set(
"message", timed_out ?
"timing wait timeout" :
"no samples");
277 return metric;
278 }
279
280 metric.
set(
"min_show_us",
static_cast<int64_t
>(min_show_us));
281 metric.
set(
"max_show_us",
static_cast<int64_t
>(max_show_us));
282 metric.
set(
"avg_show_us",
283 static_cast<int64_t>(sum_show_us / static_cast<uint64_t>(samples)));
284 metric.
set(
"min_wait_us",
static_cast<int64_t
>(min_wait_us));
285 metric.
set(
"max_wait_us",
static_cast<int64_t
>(max_wait_us));
286 metric.
set(
"avg_wait_us",
287 static_cast<int64_t>(sum_wait_us / static_cast<uint64_t>(samples)));
288 metric.
set(
"min_total_us",
static_cast<int64_t
>(min_total_us));
289 metric.
set(
"max_total_us",
static_cast<int64_t
>(max_total_us));
290 metric.
set(
"avg_total_us",
291 static_cast<int64_t>(sum_total_us / static_cast<uint64_t>(samples)));
292 metric.
set(
"min_overhead_us",
static_cast<int64_t
>(min_overhead_us));
293 metric.
set(
"max_overhead_us",
static_cast<int64_t
>(max_overhead_us));
294 metric.
set(
"avg_overhead_us",
295 static_cast<int64_t>(sum_overhead_us / static_cast<uint64_t>(samples)));
296
297 out_passed = !
timed_out && max_overhead_us <= max_allowed_overhead_us;
298 metric.
set(
"passed", out_passed);
299 if (timed_out) {
300 metric.
set(
"message",
"timing wait timeout");
301 } else {
302 metric.
set(
"message", out_passed ?
"tight timing within budget"
303 : "tight timing exceeded budget");
304 }
305 return metric;
306}
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
@ CHANNELS
Remove all channels from controller list.
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.
const char * c_str() const FL_NOEXCEPT
void set(const fl::string &key, const json &value) FL_NOEXCEPT
static json object() FL_NOEXCEPT
fl::size size() const FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void push_back(const T &value) FL_NOEXCEPT
void fill_solid(CRGB *targetArray, int numToFill, const CRGB &color) FL_NOEXCEPT
Fill a range of LEDs with a solid color.
uint32_t maxLaneLeds(const fl::vector< fl::ChannelConfig > &tx_configs)
uint32_t expectedClocklessWireUs(const fl::ChipsetTimingConfig &timing, uint32_t max_leds)
void delay(u32 ms, bool run_async=true) FL_NOEXCEPT
Public delay wrapper that keeps bare Arduino delay() preferred after using fl::delay; while still all...
CRGB sample(const CRGB *grid, const XYMap &xyMap, float x, float y, SampleMode mode)
Sample a pixel from a 2D CRGB grid at floating-point coordinates.
fl::u32 micros()
Universal microsecond timer - returns microseconds since system startup.
@ Black
<div style='background:#000000;width:4em;height:4em;'></div>