FastLED 3.9.15
Loading...
Searching...
No Matches
log.h
Go to the documentation of this file.
1#pragma once
2
4#include "fl/stl/strstream.h" // IWYU pragma: keep - Required by FL_WARN/FL_ERROR/FL_DBG macros
5#include "fl/stl/chrono.h" // IWYU pragma: keep - Required by FL_WARN_EVERY/FL_DBG_EVERY/FL_PRINT_EVERY macros
6#include "fl/stl/compiler_control.h" // IWYU pragma: keep - FL_NO_INLINE for log_emit
7
8// =============================================================================
9// FL_LOG_*_ENABLED → FASTLED_LOG_*_ENABLED backward compatibility
10// =============================================================================
11// Users can now use the shorter FL_LOG_*_ENABLED defines. The old
12// FASTLED_LOG_*_ENABLED names still work for backward compatibility.
13#if defined(FL_LOG_SPI_ENABLED) && !defined(FASTLED_LOG_SPI_ENABLED)
14 #define FASTLED_LOG_SPI_ENABLED
15#endif
16#if defined(FL_LOG_RMT_ENABLED) && !defined(FASTLED_LOG_RMT_ENABLED)
17 #define FASTLED_LOG_RMT_ENABLED
18#endif
19#if defined(FL_LOG_PARLIO_ENABLED) && !defined(FASTLED_LOG_PARLIO_ENABLED)
20 #define FASTLED_LOG_PARLIO_ENABLED
21#endif
22#if defined(FL_LOG_AUDIO_ENABLED) && !defined(FASTLED_LOG_AUDIO_ENABLED)
23 #define FASTLED_LOG_AUDIO_ENABLED
24#endif
25#if defined(FL_LOG_INTERRUPT_ENABLED) && !defined(FASTLED_LOG_INTERRUPT_ENABLED)
26 #define FASTLED_LOG_INTERRUPT_ENABLED
27#endif
28#if defined(FL_LOG_FLEXIO_ENABLED) && !defined(FASTLED_LOG_FLEXIO_ENABLED)
29 #define FASTLED_LOG_FLEXIO_ENABLED
30#endif
31#if defined(FL_LOG_OBJECTFLED_ENABLED) && !defined(FASTLED_LOG_OBJECTFLED_ENABLED)
32 #define FASTLED_LOG_OBJECTFLED_ENABLED
33#endif
34
35// Conditional include for async logger functions (only when logging features are enabled)
36#if defined(FASTLED_LOG_SPI_ENABLED) || defined(FASTLED_LOG_RMT_ENABLED) || defined(FASTLED_LOG_PARLIO_ENABLED) || defined(FASTLED_LOG_AUDIO_ENABLED) || defined(FASTLED_LOG_INTERRUPT_ENABLED)
37 #include "fl/log/async_logger.h" // IWYU pragma: keep - Required by FL_LOG_*_ASYNC_* macros
38#include "fl/stl/noexcept.h"
39#endif
40
41// =============================================================================
42// FASTLED_LOG_VERBOSITY — release-mode knob to no-op FL_WARN/FL_INFO/
43// FL_ERROR/FL_PRINT and free ~20-40 KB of
44// `.flash.rodata` string-pool bloat on embedded
45// builds. See FastLED #2773 item 2.3.
46// =============================================================================
47//
48// Each `FL_WARN(...)` / `FL_INFO(...)` / `FL_ERROR(...)` / `FL_PRINT(...)`
49// call site bakes a `__FILE__ + __LINE__ + user-supplied message` literal
50// into `.flash.rodata`. On the ESP32-S3 NEOPIXEL Blink build that pool is
51// ~57 KB — the single biggest `.rodata` contributor (see the audit on
52// #2473). The strings are live only because their call sites are live.
53//
54// Levels (mirror standard log-verbosity conventions; higher = more output):
55//
56// * `FASTLED_LOG_VERBOSITY == 0` → ALL of FL_WARN/FL_INFO/FL_ERROR/
57// FL_PRINT/FL_DBG expand to `do {} while(0)`. Strings, `fl::sstream`
58// uses, and any transitive `fl::println` references vanish; the
59// downstream printf chain may shrink further as a result.
60// * `FASTLED_LOG_VERBOSITY == 1` → current behavior; FL_WARN /
61// FL_INFO / FL_ERROR / FL_PRINT fire on platforms where
62// `SKETCH_HAS_LARGE_MEMORY` is set. FL_DBG follows its existing
63// `FASTLED_HAS_DBG` gate.
64// * `FASTLED_LOG_VERBOSITY >= 2` → reserved for future "even noisier
65// than debug" output; currently equivalent to level 1.
66//
67// Default selection (in resolution order):
68//
69// * `FASTLED_TESTING` is set → 1 (host unit tests need full diagnostics)
70// * `NDEBUG` is set (release) → 0 (drop ~55 KB of FL_WARN/FL_LOG strings
71// on ESP32-S3 NEOPIXEL Blink; see #2886)
72// * otherwise (debug builds) → 1 (preserve current behavior)
73//
74// Users who want logs back on a release build define
75// `-DFASTLED_LOG_VERBOSITY=1` in their build flags or
76// `#define FASTLED_LOG_VERBOSITY 1` before `#include <FastLED.h>`. The
77// per-channel logging defines (`FASTLED_LOG_RMT_ENABLED`, `FASTLED_LOG_SPI_ENABLED`,
78// etc.) are still gated by their own `#define`s — only the verbosity floor
79// changes here.
80#ifdef FASTLED_TESTING
81 // Host unit tests always want the full diagnostic stream so assertion
82 // and warning messages can be checked in CI.
83 #if !defined(FASTLED_LOG_VERBOSITY) || FASTLED_LOG_VERBOSITY < 1
84 #undef FASTLED_LOG_VERBOSITY
85 #define FASTLED_LOG_VERBOSITY 1
86 #endif
87#else
88 #ifndef FASTLED_LOG_VERBOSITY
89 #ifdef NDEBUG
90 #define FASTLED_LOG_VERBOSITY 0
91 #else
92 #define FASTLED_LOG_VERBOSITY 1
93 #endif
94 #endif
95#endif
96
97// Resolved compile-time gate. Logging fires only when BOTH the platform
98// has a sufficient memory budget AND the user hasn't opted out via
99// `FASTLED_LOG_VERBOSITY=0`. The two gates are independent — embedded
100// targets without `SKETCH_HAS_LARGE_MEMORY` are no-op regardless of the
101// verbosity knob (matching the pre-#2773 behavior on AVR/ATtiny).
102#if SKETCH_HAS_LARGE_MEMORY && (FASTLED_LOG_VERBOSITY >= 1)
103 #define FASTLED_LOG_RUNTIME_ENABLED 1
104#else
105 #define FASTLED_LOG_RUNTIME_ENABLED 0
106#endif
107
108// Lite gate for FL_WARN_LIT / FL_LOG_LIT — string-literal-only macros that
109// route through fl::println without the sstream / operator<< / log_emit
110// chain. These are intentionally usable on Low-memory targets (LPC845,
111// AVR, ATtiny) where the full FL_WARN pipeline is too expensive — the
112// caller pays for one `fl::println(const char*)` symbol and the literal
113// bytes, nothing more. See FastLED #3002 (LPC845 bring-up).
114#if FASTLED_LOG_VERBOSITY >= 1
115 #define FASTLED_LOG_LITE_ENABLED 1
116#else
117 #define FASTLED_LOG_LITE_ENABLED 0
118#endif
119
120// =============================================================================
121// Forward Declarations
122// =============================================================================
123
124// Forward declare println to avoid pulling in full fl/stl/cstdio.h machinery
125// This prevents ~5KB memory bloat for simple applications
126#ifndef FL_PRINTLN_DECLARED
127#define FL_PRINTLN_DECLARED
128namespace fl {
129 void println(const char* str) FL_NOEXCEPT;
130}
131#endif
132
133// =============================================================================
134// Debug Output Helpers
135// =============================================================================
136
137namespace fl {
138// ".build/src/fl/dbg.h" -> "src/fl/dbg.h"
139// "blah/blah/blah.h" -> "blah.h"
140const char *fastled_file_offset(const char *file) FL_NOEXCEPT;
141} // namespace fl
142
143// =============================================================================
144// Centralised log emit (#2963 Proposal B, Option 3)
145// =============================================================================
146//
147// `fl::detail::log_emit(kind, file, line, body)` consumes the
148// user-supplied sstream (passed by rvalue reference) and **rewrites
149// it in place** to hold the full prefixed message:
150//
151// "<file>(<line>): <KIND>: <user payload>"
152//
153// then emits via `fl::println(body.c_str())`.
154//
155// Lifetime-safe variant of Path C's "Option 1" attempt. The body
156// sstream temporary lives in the **caller's** frame — its
157// lifetime extends to the end of the FL_WARN/FL_ERROR/FL_INFO
158// full expression, exactly as the OLD inline macro's temporary
159// did. So `body.c_str()` passed to `println` has the same
160// async-handler-safe lifetime as before: whatever the test
161// harness or platform println did synchronously continues to
162// work, and async deferred-flush handlers still see a live
163// pointer until the semicolon.
164//
165// The legacy macro inlined the entire
166// `<< file << "(" << line << "): KIND: " << X`
167// chain at every FL_WARN site (1,372 sites × ~30-50 B of inlined
168// prefix-format code). With this helper, the prefix-format chain
169// is compiled ONCE into libFastLED — each call site only emits
170// the `fl::sstream() << X` ctor + the user's payload chain + a
171// single `log_emit` call.
172namespace fl { namespace detail {
173enum class log_kind : fl::u8 {
174 WARN = 0,
175 ERROR = 1,
176 INFO = 2,
177};
178// Takes `body` by non-const lvalue reference (not `&&`) because the
179// macro's `fl::sstream() << X` expression has type `sstream&` (the
180// returned lvalue ref from chained operator<<). The underlying
181// temporary's lifetime is the FL_WARN full-expression's, so mutating
182// it through this lvalue ref is well-defined and the c_str() handed
183// to println outlives the call exactly as the OLD inline macro's
184// `(fl::sstream() << ...).c_str()` did.
185//
186// `FL_NO_INLINE` enforces the centralisation. Without it, at -O2
187// with LTO the compiler often inlines `log_emit` at every FL_WARN
188// site — defeating the whole point of moving the prefix chain
189// out-of-line. The noinline attribute is what makes this proposal
190// actually win bytes; bare centralisation alone isn't enough.
191void log_emit(log_kind kind, const char* file, int line, fl::sstream& body) FL_NO_INLINE FL_NOEXCEPT;
192} } // namespace fl::detail
193
194// =============================================================================
195// Error Macros (FL_ERROR)
196// =============================================================================
197
198#ifndef FASTLED_ERROR
199// FASTLED_ERROR: Supports stream-style formatting with << operator.
200// Routes through fl::detail::log_emit so the prefix-format chain
201// is single-copy in libFastLED instead of inlined at every site.
202#define FASTLED_ERROR(MSG) fl::detail::log_emit( \
203 fl::detail::log_kind::ERROR, \
204 fl::fastled_file_offset(__FILE__), int(__LINE__), \
205 fl::sstream() << MSG)
206#define FASTLED_ERROR_IF(COND, MSG) do { if (COND) FASTLED_ERROR(MSG); } while(0)
207#endif
208
209#ifndef FL_ERROR
210#if FASTLED_LOG_RUNTIME_ENABLED
211// FL_ERROR: routes through fl::detail::log_emit (see header banner above).
212#define FL_ERROR(X) fl::detail::log_emit( \
213 fl::detail::log_kind::ERROR, \
214 fl::fastled_file_offset(__FILE__), int(__LINE__), \
215 fl::sstream() << X)
216#define FL_ERROR_IF(COND, MSG) do { if (COND) FL_ERROR(MSG); } while(0)
217#else
218// No-op macros — either memory-constrained platform or FASTLED_LOG_VERBOSITY=0.
219#define FL_ERROR(X) do { } while(0)
220#define FL_ERROR_IF(COND, MSG) do { } while(0)
221#endif
222#endif
223
224// =============================================================================
225// Warning Macros (FL_WARN)
226// =============================================================================
227
228#ifndef FASTLED_WARN
229// FASTLED_WARN: Supports stream-style formatting with << operator.
230#define FASTLED_WARN(MSG) fl::detail::log_emit( \
231 fl::detail::log_kind::WARN, \
232 fl::fastled_file_offset(__FILE__), int(__LINE__), \
233 fl::sstream() << MSG)
234#define FASTLED_WARN_IF(COND, MSG) do { if (COND) FASTLED_WARN(MSG); } while(0)
235#endif
236
237#ifndef FL_WARN
238#if FASTLED_LOG_RUNTIME_ENABLED
239// FL_WARN: routes through fl::detail::log_emit (see header banner above).
240#define FL_WARN(X) fl::detail::log_emit( \
241 fl::detail::log_kind::WARN, \
242 fl::fastled_file_offset(__FILE__), int(__LINE__), \
243 fl::sstream() << X)
244#define FL_WARN_IF(COND, MSG) do { if (COND) FL_WARN(MSG); } while(0)
245
246// FL_WARN_ONCE: Emits warning only once per unique location (static flag per call site)
247// Uses static bool flag initialized to false - first call prints, subsequent calls no-op
248#define FL_WARN_ONCE(X) do { \
249 static bool _warned = false; \
250 if (!_warned) { \
251 _warned = true; \
252 FL_WARN(X); \
253 } \
254} while(0)
255
256// FL_WARN_FMT: Alias for FL_WARN (kept for backwards compatibility)
257#define FL_WARN_FMT(X) FL_WARN(X)
258#define FL_WARN_FMT_IF(COND, MSG) FL_WARN_IF(COND, MSG)
259
260// FL_WARN_LIT: defined below outside the FASTLED_LOG_RUNTIME_ENABLED block —
261// gated on FASTLED_LOG_LITE_ENABLED so it stays available on Low-memory
262// targets. See "Lite-variant literal macros" section below.
263
264// FL_WARN_EVERY: Rate-limited warning that prints at most once per interval
265// Uses static timestamp to track last print time - throttles output in tight loops
266#define FL_WARN_EVERY(MILLIS, X) do { \
267 static fl::u32 _last_warn_time = 0; \
268 fl::u32 _now = fl::millis(); \
269 if (_now - _last_warn_time >= (MILLIS)) { \
270 _last_warn_time = _now; \
271 FL_WARN(X); \
272 } \
273} while(0)
274#else
275// No-op macros — either memory-constrained platform or FASTLED_LOG_VERBOSITY=0.
276#define FL_WARN(X) do { } while(0)
277#define FL_WARN_IF(COND, MSG) if(false) { void(fl::sstream_noop() << MSG); }
278#define FL_WARN_ONCE(X) do { } while(0)
279#define FL_WARN_FMT(X) do { } while(0)
280#define FL_WARN_FMT_IF(COND, MSG) do { } while(0)
281#define FL_WARN_EVERY(MILLIS, X) do { } while(0)
282#endif
283#endif
284
285// Lite-variant literal macros: gated on FASTLED_LOG_LITE_ENABLED so they
286// remain usable on Low-memory targets where the full FL_WARN chain is a
287// no-op. Use these at well-known WARN sites where the message is a fixed
288// string and the byte budget matters (FastLED #2856 item 3.2, #3002).
289#ifndef FL_WARN_LIT
290#if FASTLED_LOG_LITE_ENABLED
291#define FL_WARN_LIT(LITERAL) fl::println(LITERAL)
292#define FL_LOG_LIT(LITERAL) fl::println(LITERAL)
293#else
294#define FL_WARN_LIT(LITERAL) do { } while(0)
295#define FL_LOG_LIT(LITERAL) do { } while(0)
296#endif
297#endif
298
299// =============================================================================
300// Info Macros (FL_INFO)
301// =============================================================================
302
303#ifndef FASTLED_INFO
304// FASTLED_INFO: Supports stream-style formatting with << operator.
305#define FASTLED_INFO(MSG) fl::detail::log_emit( \
306 fl::detail::log_kind::INFO, \
307 fl::fastled_file_offset(__FILE__), int(__LINE__), \
308 fl::sstream() << MSG)
309#define FASTLED_INFO_IF(COND, MSG) do { if (COND) FASTLED_INFO(MSG); } while(0)
310#endif
311
312#ifndef FL_INFO
313#if FASTLED_LOG_RUNTIME_ENABLED
314// FL_INFO: routes through fl::detail::log_emit (see header banner above).
315#define FL_INFO(X) fl::detail::log_emit( \
316 fl::detail::log_kind::INFO, \
317 fl::fastled_file_offset(__FILE__), int(__LINE__), \
318 fl::sstream() << X)
319#define FL_INFO_IF(COND, MSG) do { if (COND) FL_INFO(MSG); } while(0)
320
321// FL_INFO_ONCE: Emits info only once per unique location (static flag per call site)
322// Uses static bool flag initialized to false - first call prints, subsequent calls no-op
323#define FL_INFO_ONCE(X) do { \
324 static bool _infoed = false; \
325 if (!_infoed) { \
326 _infoed = true; \
327 FL_INFO(X); \
328 } \
329} while(0)
330#else
331// No-op macros — either memory-constrained platform or FASTLED_LOG_VERBOSITY=0.
332#define FL_INFO(X) do { } while(0)
333#define FL_INFO_IF(COND, MSG) do { } while(0)
334#define FL_INFO_ONCE(X) do { } while(0)
335#endif
336#endif
337
338// =============================================================================
339// Debug Macros (FL_DBG)
340// =============================================================================
341
342#if defined(FL_IS_WASM) || !defined(RELEASE) || defined(FASTLED_TESTING)
343#define FASTLED_FORCE_DBG 1
344#endif
345
346// Reusable no-op macro for disabled debug output - avoids linker symbol pollution
347#define FL_DBG_NO_OP(X) do { if (false) { fl::sstream_noop() << X; } } while(0)
348
349// Debug printing control:
350// - FASTLED_DISABLE_DBG=1: Explicitly disable FL_DBG output (highest priority)
351// - FASTLED_LOG_VERBOSITY=0: Disable FL_DBG along with all other macros
352// - FASTLED_FORCE_DBG: Force enable FL_DBG (auto-set for debug builds)
353// - SKETCH_HAS_LARGE_MEMORY: Enable FL_DBG when platform has enough memory
354//
355// Priority: FASTLED_DISABLE_DBG > FASTLED_LOG_VERBOSITY > FASTLED_FORCE_DBG > SKETCH_HAS_LARGE_MEMORY
356#if defined(FASTLED_DISABLE_DBG) && FASTLED_DISABLE_DBG
357// Explicit disable takes highest priority - useful for reducing serial spam
358#define FASTLED_HAS_DBG 0
359#define _FASTLED_DGB(X) FL_DBG_NO_OP(X)
360#elif FASTLED_LOG_VERBOSITY < 1
361// FASTLED_LOG_VERBOSITY=0 disables FL_DBG too. See #2773 item 2.3.
362#define FASTLED_HAS_DBG 0
363#define _FASTLED_DGB(X) FL_DBG_NO_OP(X)
364#elif !defined(FASTLED_FORCE_DBG) && !SKETCH_HAS_LARGE_MEMORY
365// By default, debug printing is disabled to prevent memory bloat in simple applications
366#define FASTLED_HAS_DBG 0
367#define _FASTLED_DGB(X) FL_DBG_NO_OP(X)
368#else
369// Explicit debug mode enabled - uses fl::println()
370#define FASTLED_HAS_DBG 1
371#define _FASTLED_DGB(X) \
372 fl::println( \
373 (fl::sstream() << (fl::fastled_file_offset(__FILE__)) \
374 << "(" << int(__LINE__) << "): " << X) \
375 .c_str())
376#endif
377
378#define FASTLED_DBG(X) _FASTLED_DGB(X)
379
380#ifndef FASTLED_DBG_IF
381#define FASTLED_DBG_IF(COND, MSG) \
382 if (COND) \
383 FASTLED_DBG(MSG)
384#endif // FASTLED_DBG_IF
385
386// Short-form aliases for convenience (following pattern from warn.h)
387#ifndef FL_DBG
388#define FL_DBG FASTLED_DBG
389#define FL_DBG_IF FASTLED_DBG_IF
390
391// FL_DBG_EVERY: Rate-limited debug output that prints at most once per interval
392// Uses static timestamp to track last print time - throttles output in tight loops
393#if FASTLED_HAS_DBG
394#define FL_DBG_EVERY(MILLIS, X) do { \
395 static fl::u32 _last_dbg_time = 0; \
396 fl::u32 _now = fl::millis(); \
397 if (_now - _last_dbg_time >= (MILLIS)) { \
398 _last_dbg_time = _now; \
399 FL_DBG(X); \
400 } \
401} while(0)
402#else
403#define FL_DBG_EVERY(MILLIS, X) FL_DBG_NO_OP(X)
404#endif
405#endif
406
407// =============================================================================
408// AsyncLogger Class (in fl/log/async_logger.h)
409// =============================================================================
410// AsyncLogger, LogCategory enum, and accessor functions are now in fl/log/async_logger.h
411// This provides template-based lazy instantiation with linker-friendly auto-registration
412
429
430// =============================================================================
431// General Logging Macros
432// =============================================================================
433
441#ifndef FL_PRINT
442#if FASTLED_LOG_RUNTIME_ENABLED
443#define FL_PRINT(X) fl::println((fl::sstream() << X).c_str())
444
445// FL_PRINT_EVERY: Rate-limited print that outputs at most once per interval
446// Uses static timestamp to track last print time - throttles output in tight loops
447#define FL_PRINT_EVERY(MILLIS, X) do { \
448 static fl::u32 _last_print_time = 0; \
449 fl::u32 _now = fl::millis(); \
450 if (_now - _last_print_time >= (MILLIS)) { \
451 _last_print_time = _now; \
452 FL_PRINT(X); \
453 } \
454} while(0)
455#else
456// No-op macro for memory-constrained platforms
457#define FL_PRINT(X) do { } while(0)
458#define FL_PRINT_EVERY(MILLIS, X) do { } while(0)
459#endif
460#endif
461
462// =============================================================================
463// Hardware Interface Logging Categories
464// =============================================================================
465
468
471#ifdef FASTLED_LOG_SPI_ENABLED
472 #define FL_LOG_SPI(X) FL_WARN(X)
473#else
474 #define FL_LOG_SPI(X) FL_DBG_NO_OP(X)
475#endif
476
479#ifdef FASTLED_LOG_RMT_ENABLED
480 #define FL_LOG_RMT(X) FL_WARN(X)
481#else
482 #define FL_LOG_RMT(X) FL_DBG_NO_OP(X)
483#endif
484
487#ifdef FASTLED_LOG_PARLIO_ENABLED
488 #define FL_LOG_PARLIO(X) FL_WARN(X)
489#else
490 #define FL_LOG_PARLIO(X) FL_DBG_NO_OP(X)
491#endif
492
495#ifdef FASTLED_LOG_AUDIO_ENABLED
496 #define FL_LOG_AUDIO(X) FL_WARN(X)
497#else
498 #define FL_LOG_AUDIO(X) FL_DBG_NO_OP(X)
499#endif
500
503#ifdef FASTLED_LOG_INTERRUPT_ENABLED
504 #define FL_LOG_INTERRUPT(X) FL_WARN(X)
505#else
506 #define FL_LOG_INTERRUPT(X) FL_DBG_NO_OP(X)
507#endif
508
511#ifdef FASTLED_LOG_FLEXIO_ENABLED
512 #define FL_LOG_FLEXIO(X) FL_WARN(X)
513#else
514 #define FL_LOG_FLEXIO(X) FL_DBG_NO_OP(X)
515#endif
516
519#ifdef FASTLED_LOG_OBJECTFLED_ENABLED
520 #define FL_LOG_OBJECTFLED(X) FL_WARN(X)
521#else
522 #define FL_LOG_OBJECTFLED(X) FL_DBG_NO_OP(X)
523#endif
524
526
527// =============================================================================
528// Async Logging Infrastructure (ISR-Safe)
529// =============================================================================
530
583
589#define FL_LOG_ASYNC(logger, X) \
590 do { \
591 (logger).push((fl::sstream() << X).str()); \
592 } while(0)
593
600#define FL_LOG_ASYNC_ISR(logger, msg) \
601 do { \
602 (logger).push(msg); \
603 } while(0)
604
605// -----------------------------------------------------------------------------
606// SPI Async Logging
607// -----------------------------------------------------------------------------
608
609#ifdef FASTLED_LOG_SPI_ENABLED
610 #define FL_LOG_SPI_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_spi_async_logger_isr(), X)
611 #define FL_LOG_SPI_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_spi_async_logger_main(), X)
612 #define FL_LOG_SPI_ASYNC_FLUSH() do { \
613 fl::get_spi_async_logger_isr().flush(); \
614 fl::get_spi_async_logger_main().flush(); \
615 } while(0)
616#else
617 #define FL_LOG_SPI_ASYNC_ISR(X) FL_DBG_NO_OP(X)
618 #define FL_LOG_SPI_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
619 #define FL_LOG_SPI_ASYNC_FLUSH() do {} while(0)
620#endif
621
622// -----------------------------------------------------------------------------
623// RMT Async Logging
624// -----------------------------------------------------------------------------
625
626#ifdef FASTLED_LOG_RMT_ENABLED
627 #define FL_LOG_RMT_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_rmt_async_logger_isr(), X)
628 #define FL_LOG_RMT_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_rmt_async_logger_main(), X)
629 #define FL_LOG_RMT_ASYNC_FLUSH() do { \
630 fl::get_rmt_async_logger_isr().flush(); \
631 fl::get_rmt_async_logger_main().flush(); \
632 } while(0)
633#else
634 #define FL_LOG_RMT_ASYNC_ISR(X) FL_DBG_NO_OP(X)
635 #define FL_LOG_RMT_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
636 #define FL_LOG_RMT_ASYNC_FLUSH() do {} while(0)
637#endif
638
639// -----------------------------------------------------------------------------
640// PARLIO Async Logging
641// -----------------------------------------------------------------------------
642
643#ifdef FASTLED_LOG_PARLIO_ENABLED
644 #define FL_LOG_PARLIO_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_parlio_async_logger_isr(), X)
645 #define FL_LOG_PARLIO_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_parlio_async_logger_main(), X)
646 #define FL_LOG_PARLIO_ASYNC_FLUSH() do { \
647 fl::get_parlio_async_logger_isr().flush(); \
648 fl::get_parlio_async_logger_main().flush(); \
649 } while(0)
650#else
651 #define FL_LOG_PARLIO_ASYNC_ISR(X) FL_DBG_NO_OP(X)
652 #define FL_LOG_PARLIO_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
653 #define FL_LOG_PARLIO_ASYNC_FLUSH() do {} while(0)
654#endif
655
656// -----------------------------------------------------------------------------
657// AUDIO Async Logging
658// -----------------------------------------------------------------------------
659
660#ifdef FASTLED_LOG_AUDIO_ENABLED
661 #define FL_LOG_AUDIO_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_audio_async_logger_isr(), X)
662 #define FL_LOG_AUDIO_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_audio_async_logger_main(), X)
663 #define FL_LOG_AUDIO_ASYNC_FLUSH() do { \
664 fl::get_audio_async_logger_isr().flush(); \
665 fl::get_audio_async_logger_main().flush(); \
666 } while(0)
667#else
668 #define FL_LOG_AUDIO_ASYNC_ISR(X) FL_DBG_NO_OP(X)
669 #define FL_LOG_AUDIO_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
670 #define FL_LOG_AUDIO_ASYNC_FLUSH() do {} while(0)
671#endif
672
673// -----------------------------------------------------------------------------
674// INTERRUPT Async Logging
675// -----------------------------------------------------------------------------
676
677#ifdef FASTLED_LOG_INTERRUPT_ENABLED
678 #define FL_LOG_INTERRUPT_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_interrupt_async_logger_isr(), X)
679 #define FL_LOG_INTERRUPT_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_interrupt_async_logger_main(), X)
680 #define FL_LOG_INTERRUPT_ASYNC_FLUSH() do { \
681 fl::get_interrupt_async_logger_isr().flush(); \
682 fl::get_interrupt_async_logger_main().flush(); \
683 } while(0)
684#else
685 #define FL_LOG_INTERRUPT_ASYNC_ISR(X) FL_DBG_NO_OP(X)
686 #define FL_LOG_INTERRUPT_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
687 #define FL_LOG_INTERRUPT_ASYNC_FLUSH() do {} while(0)
688#endif
689
690// -----------------------------------------------------------------------------
691// FLEXIO Async Logging
692// -----------------------------------------------------------------------------
693
694#ifdef FASTLED_LOG_FLEXIO_ENABLED
695 #define FL_LOG_FLEXIO_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_flexio_async_logger_isr(), X)
696 #define FL_LOG_FLEXIO_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_flexio_async_logger_main(), X)
697 #define FL_LOG_FLEXIO_ASYNC_FLUSH() do { \
698 fl::get_flexio_async_logger_isr().flush(); \
699 fl::get_flexio_async_logger_main().flush(); \
700 } while(0)
701#else
702 #define FL_LOG_FLEXIO_ASYNC_ISR(X) FL_DBG_NO_OP(X)
703 #define FL_LOG_FLEXIO_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
704 #define FL_LOG_FLEXIO_ASYNC_FLUSH() do {} while(0)
705#endif
706
707// -----------------------------------------------------------------------------
708// OBJECTFLED Async Logging
709// -----------------------------------------------------------------------------
710
711#ifdef FASTLED_LOG_OBJECTFLED_ENABLED
712 #define FL_LOG_OBJECTFLED_ASYNC_ISR(X) FL_LOG_ASYNC_ISR(fl::get_objectfled_async_logger_isr(), X)
713 #define FL_LOG_OBJECTFLED_ASYNC_MAIN(X) FL_LOG_ASYNC(fl::get_objectfled_async_logger_main(), X)
714 #define FL_LOG_OBJECTFLED_ASYNC_FLUSH() do { \
715 fl::get_objectfled_async_logger_isr().flush(); \
716 fl::get_objectfled_async_logger_main().flush(); \
717 } while(0)
718#else
719 #define FL_LOG_OBJECTFLED_ASYNC_ISR(X) FL_DBG_NO_OP(X)
720 #define FL_LOG_OBJECTFLED_ASYNC_MAIN(X) FL_DBG_NO_OP(X)
721 #define FL_LOG_OBJECTFLED_ASYNC_FLUSH() do {} while(0)
722#endif
723
724// -----------------------------------------------------------------------------
725// Background Flush Service
726// -----------------------------------------------------------------------------
727
733namespace fl {
735
755 void configureAsyncLogService(u32 interval_ms = 16, fl::size messages_per_tick = 5) FL_NOEXCEPT;
756}
757
ISR-safe async logger using SPSC queue backend (zero heap allocation)
FastLED chrono implementation - duration types for time measurements.
FL_NO_INLINE void log_emit(log_kind kind, const char *file, int line, fl::sstream &body) FL_NOEXCEPT
Definition log.cpp.hpp:31
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
unsigned char u8
Definition s16x16x4.h:132
void configureAsyncLogService(u32 interval_ms, fl::size messages_per_tick)
Configure async logger automatic servicing task.
void async_log_service()
void println(const char *str) FL_NOEXCEPT
const char * fastled_file_offset(const char *file)
Definition log.cpp.hpp:56
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NO_INLINE
#define FL_NOEXCEPT