FastLED 3.10.6
Loading...
Searching...
No Matches
slim_bridge_controller.h
Go to the documentation of this file.
1
12
13#pragma once
14
16#include "fl/stl/noexcept.h"
17#include "fl/stl/vector.h"
18
20#include "fl/channels/data.h"
21#include "fl/channels/driver.h"
22#include "fl/channels/manager.h"
23#include "fl/channels/bus_traits.h" // IWYU pragma: keep (DriverTraits<Bus::X> satisfies the DriverTraits contract)
24#include "fl/channels/config.h"
26#include "fl/log/log.h"
28
33#ifndef FL_SLIM_BRIDGE_DIRECT_SHOW
34#define FL_SLIM_BRIDGE_DIRECT_SHOW (!FL_PLATFORM_HAS_LARGE_MEMORY)
35#endif
36
37namespace fl {
38
41template <bool DIRECT_SHOW>
43
46template <>
47struct SlimBridgeShowPolicy<false> {
48 template <typename DriverTraits>
49 static void attach() FL_NO_EXCEPT { DriverTraits::registerWithManager(); }
50 static bool enabled(IChannelDriver& driver) FL_NO_EXCEPT {
51 return ChannelManager::registry().isDriverEnabled(driver.getName().c_str());
52 }
54};
55
59template <>
61 template <typename DriverTraits>
62 static void attach() FL_NO_EXCEPT {}
63 static bool enabled(IChannelDriver&) FL_NO_EXCEPT { return true; }
64 static void afterEnqueue(IChannelDriver& driver) FL_NO_EXCEPT { driver.show(); }
65};
66
102template <int DATA_PIN, typename TIMING, EOrder RGB_ORDER, int WAIT_TIME, typename DriverTraits,
103 int XTRA0 = 0, bool DIRECT_SHOW = (FL_SLIM_BRIDGE_DIRECT_SHOW != 0)>
106
107public:
110 // (A?) Fold WAIT_TIME (microseconds) into reset_us, mirroring the
111 // historical ClocklessIdf4 behavior: the driver must honor whichever
112 // is longer -- the chipset's own latch/reset requirement, or the
113 // caller-requested minimum inter-frame wait.
114 if (WAIT_TIME > 0 && static_cast<u32>(WAIT_TIME) > timing.reset_us) {
115 timing.reset_us = static_cast<u32>(WAIT_TIME);
116 }
119 FL_STATIC_ASSERT(XTRA0 >= 0 && XTRA0 <= 32, "XTRA0 out of range");
120 mData->setExtraZeroBitsPerByte(static_cast<u8>(XTRA0));
121 // Idempotent by contract -- safe to call from every instantiation's
122 // constructor (mirrors ClocklessIdf5's registerWithManager() call).
123 // A no-op in direct-show mode.
124 Policy::template attach<DriverTraits>();
125 }
126
127 void init() FL_NO_EXCEPT override {}
128
130 const ChannelDataPtr& channelData() const FL_NO_EXCEPT { return mData; }
131
132protected:
134 IChannelDriver& driver = DriverTraits::instance();
135
136 // (A1) Respect runtime driver enable/disable: ChannelManager is the
137 // single source of truth. A disabled driver means "drop this frame",
138 // not "enqueue and hope" -- silently enqueuing to a disabled driver
139 // is the #2517 silent-drop failure mode.
140 if (!Policy::enabled(driver)) {
141 FL_WARN_ONCE("SlimBridgeController: driver '" << driver.getName().c_str() << "' is disabled - dropping frame");
142 return;
143 }
144
145 // (A8) If the previous frame's buffer is still in flight, block
146 // (bounded) until the driver reports it can accept more work rather
147 // than racing the driver's in-progress DMA/RMT transfer.
148 if (mData->isInUse()) {
149 if (!driver.waitForReady()) {
150 FL_WARN_ONCE("SlimBridgeController: driver '" << driver.getName().c_str() << "' did not become ready in time - dropping frame");
151 return;
152 }
153 }
154
155 // Give subclasses a chance to observe the accepted frame before it is
156 // encoded (e.g. feeding ActiveStripTracker for stub/WASM channels).
157 onBeforeEncode(pixels);
158
159 // (A5) Publish the pixel byte layout so the driver (and any
160 // downstream padding/diagnostic code) knows the encoded stride.
161 if (this->getRgbww().active()) {
162 mData->setPixelFormat(ChannelPixelFormat::RGBWW);
163 } else if (this->getRgbw().active()) {
164 mData->setPixelFormat(ChannelPixelFormat::RGBW);
165 } else {
166 mData->setPixelFormat(ChannelPixelFormat::RGB);
167 }
168
169 // (A3) Re-encode into the same buffer every frame -- clear() keeps
170 // capacity, so steady-state operation is allocation-free.
171 mData->getData().clear();
172 fl::PixelIterator iterator(&pixels, this->getRgbw(), this->getRgbww());
173 iterator.writeWS2812(&mData->getData());
174
175 driver.enqueue(mData);
176 Policy::afterEnqueue(driver);
177 }
178
181 virtual void onBeforeEncode(PixelController<RGB_ORDER>& pixels) FL_NO_EXCEPT { (void)pixels; }
182
183private:
184 ChannelDataPtr mData;
185};
186
187} // namespace fl
#define DATA_PIN
Definition ClientReal.h:82
#define RGB_ORDER
Per-driver traits keyed on fl::Bus.
CPixelLEDController(RegistrationMode mode)
Protected constructor with registration mode.
Rgbww getRgbww() const FL_NO_EXCEPT
Rgbw getRgbw() const FL_NO_EXCEPT
static ChannelDataPtr create(const ChipsetVariant &chipset, fl::vector_psram< u8 > &&encodedData=fl::vector_psram< u8 >(), ChannelPixelFormat pixelFormat=ChannelPixelFormat::RGB) FL_NO_EXCEPT
Create channel transmission data (modern variant-based API)
Definition data.cpp.hpp:12
static ChannelManager & registry() FL_NO_EXCEPT
Get the singleton WITHOUT registering platform default drivers.
bool isDriverEnabled(const char *name) const FL_NO_EXCEPT
Check if a driver is enabled by name.
virtual fl::string getName() const FL_NO_EXCEPT
Get the driver name for affinity binding.
Definition driver.h:217
virtual void enqueue(ChannelDataPtr channelData) FL_NO_EXCEPT=0
Enqueue channel data for transmission.
bool waitForReady(u32 timeoutMs=1000) FL_NO_EXCEPT
Wait for driver to become READY.
Minimal interface for LED channel transmission drivers.
Definition driver.h:52
const ChannelDataPtr & channelData() const FL_NO_EXCEPT
Expose the underlying ChannelDataPtr for conformance tests.
virtual void onBeforeEncode(PixelController< RGB_ORDER > &pixels) FL_NO_EXCEPT
Called once per accepted frame, after the enabled/ready gates pass and BEFORE the frame is encoded an...
void showPixels(PixelController< RGB_ORDER > &pixels) FL_NO_EXCEPT override
SlimBridgeShowPolicy< DIRECT_SHOW > Policy
void init() FL_NO_EXCEPT override
Initialize the LED controller.
const char * c_str() const FL_NO_EXCEPT
defines the templated version of the CLEDController class
Channel transmission data - lightweight DTO for driver transmission.
fl::EOrder EOrder
Definition eorder.h:12
Non-templated low level pixel data writing class.
#define FL_WARN_ONCE(...)
Definition log.h:442
Centralized logging categories for FastLED hardware interfaces and subsystems.
Unified manager for channel drivers with priority-based fallback.
unsigned char u8
Definition stdint.h:131
constexpr ChipsetTimingConfig makeTimingConfig() FL_NO_EXCEPT
Convert compile-time CHIPSET type to runtime timing config.
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
Base definition for an LED controller.
Definition crgb.hpp:179
How a SlimBridgeController reaches its driver.
#define FL_SLIM_BRIDGE_DIRECT_SHOW
Small-memory tier: the bridge drives its driver directly instead of through ChannelManager,...
#define FL_STATIC_ASSERT(...)
Portable compile-time assertion wrapper.
Pixel controller class.
u32 reset_us
Reset/latch time (microseconds)
Runtime bit-period timing for a clockless chipset.
static void afterEnqueue(IChannelDriver &) FL_NO_EXCEPT
static bool enabled(IChannelDriver &driver) FL_NO_EXCEPT
static void afterEnqueue(IChannelDriver &driver) FL_NO_EXCEPT
static bool enabled(IChannelDriver &) FL_NO_EXCEPT