FastLED 3.10.8
Loading...
Searching...
No Matches
slim_spi_bridge_controller.h
Go to the documentation of this file.
1
40
41#pragma once
42
43#include "fl/stl/noexcept.h"
45
47#include "fl/channels/data.h"
48#include "fl/channels/driver.h"
49#include "fl/channels/manager.h"
50#include "fl/channels/bus.h"
51#include "fl/channels/bus_traits.h" // IWYU pragma: keep (DriverTraits<Bus::X> satisfies the DriverTraits contract)
52#include "fl/channels/channel_typed.h" // IWYU pragma: keep (detail::resolve_bus, BusSupports)
53#include "fl/channels/config.h"
55#include "fl/log/log.h"
56
57namespace fl {
58
73template <fl::SpiChipset CHIPSET, EOrder RGB_ORDER, fl::Bus B, fl::u8 B_WHICH>
75public:
79
80 // Compile-time contract, mirrors TypedChannel<B, SpiChipsetConfig, Which>.
83 "SlimSpiBridgeController: Bus does not support SpiChipsetConfig");
84
87 // Idempotent by contract -- safe to call from every instantiation's
88 // constructor (mirrors TypedChannel::create()'s registerWithManager() call).
90 }
91
92 void init() FL_NO_EXCEPT override {}
93
95 const ChannelDataPtr& channelData() const FL_NO_EXCEPT { return mData; }
96
97protected:
100 if (!driver) {
101 return;
102 }
103
104 // (A1) Respect runtime driver enable/disable: ChannelManager is the
105 // single source of truth. A disabled driver means "drop this frame",
106 // not "enqueue and hope" -- silently enqueuing to a disabled driver
107 // is the #2517 silent-drop failure mode.
108 if (!ChannelManager::registry().isDriverEnabled(*driver)) {
109 FL_WARN_ONCE("SlimSpiBridgeController: driver '" << driver->getName() << "' is disabled - dropping frame");
110 return;
111 }
112
113 // (A8) If the previous frame's buffer is still in flight, block
114 // (bounded) until the driver reports it can accept more work rather
115 // than racing the driver's in-progress transfer.
116 if (mData->isInUse()) {
117 if (!driver->waitForReady()) {
118 FL_WARN_ONCE("SlimSpiBridgeController: driver '" << driver->getName() << "' did not become ready in time - dropping frame");
119 return;
120 }
121 }
122
123 // (A5) Publish the pixel byte layout so the driver (and any
124 // downstream padding/diagnostic code) knows the encoded stride.
125 if (this->getRgbww().active()) {
126 mData->setPixelFormat(ChannelPixelFormat::RGBWW);
127 } else if (this->getRgbw().active()) {
128 mData->setPixelFormat(ChannelPixelFormat::RGBW);
129 } else {
130 mData->setPixelFormat(ChannelPixelFormat::RGB);
131 }
132
133 // Dither reseed mirrors Channel::encodeFrame(): only reseed when a
134 // non-zero dither mode is set.
135 if (pixels.ditherActive()) {
136 pixels.reseed_binary_dithering(mDitherPhase);
137 }
138
139 // (A3) Re-encode into the same buffer every frame -- clear() keeps
140 // capacity, so steady-state operation is allocation-free.
141 mData->getData().clear();
142 fl::PixelIterator it(&pixels, this->getRgbw(), this->getRgbww());
143 encode(it, mData->getData());
144
145 driver->enqueue(mData);
146 // Presented, per the driver contract: an accepted enqueue is the
147 // frame -- mirrors Channel::submitFrame()'s ++mDitherPhase placement
148 // (dither only advances when a frame is actually handed to the
149 // driver, not on every showPixels() attempt).
150 ++mDitherPhase;
151 }
152
153private:
161#if defined(FASTLED_DISABLE_DYNAMIC_DRIVER) && FASTLED_DISABLE_DYNAMIC_DRIVER
162 return {};
163#else
164 // Build busKey only when we actually need it (kBus != AUTO).
165 fl::string busKey;
166 if (kBus != Bus::AUTO) {
167 busKey = fl::string::from_literal(busDriverName(kBus, B_WHICH, /*spi=*/true));
168 }
169
172
173#if FASTLED_LOG_RUNTIME_ENABLED
174 if (!driver && !mBusWarned) {
175 FL_ERROR("SlimSpiBridgeController: no compatible driver found for bus '" << busKey << "' - cannot transmit");
176 mBusWarned = true;
177 }
178#endif // FASTLED_LOG_RUNTIME_ENABLED
179 return driver;
180#endif // !FASTLED_DISABLE_DYNAMIC_DRIVER
181 }
182
188 switch (CHIPSET) {
192 it.writeAPA102(&out, false);
193 break;
197 it.writeAPA102(&out, true);
198 break;
200 it.writeSK9822(&out, false);
201 break;
203 it.writeSK9822(&out, true);
204 break;
206 it.writeWS2801(&out);
207 break;
209 it.writeWS2803(&out);
210 break;
212 it.writeP9813(&out);
213 break;
215 it.writeLPD8806(&out);
216 break;
218 it.writeLPD6803(&out);
219 break;
221 it.writeSM16716(&out);
222 break;
224 it.writeHD108(&out, false);
225 break;
227 // Never routed here -- FastLED.h sends MY9221 to the bit-bang
228 // MY9221Controller (see file header comment). Defensive
229 // no-op if this controller is ever instantiated directly
230 // with CHIPSET == MY9221.
231 break;
232 }
233 }
234
235 ChannelDataPtr mData;
237#if FASTLED_LOG_RUNTIME_ENABLED
238 bool mBusWarned = false;
239#endif
240};
241
242} // namespace fl
#define CHIPSET
Portable compile-time identifiers for LED channel buses.
Per-driver traits keyed on fl::Bus.
Phase 3b templated channel facade – Channel<Bus, Chipset> with compile-time bus/chipset enforcement.
CPixelLEDController(RegistrationMode mode) FL_NO_EXCEPT
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.
fl::shared_ptr< IChannelDriver > selectDriverForChannel(const ChannelDataPtr &data, const fl::string &affinity) FL_NO_EXCEPT
Select best driver for channel data (used by Channel::showPixels)
SlimSpiBridgeController(const SpiChipsetConfig &cfg) FL_NO_EXCEPT
static void encode(fl::PixelIterator &it, fl::vector_psram< u8 > &out) FL_NO_EXCEPT
Encode it into out using the writer selected by CHIPSET.
void init() FL_NO_EXCEPT override
Initialize the LED controller.
static constexpr Bus kBus
The bus actually used after resolving Bus::AUTO – mirrors TypedChannel<B, SpiChipsetConfig,...
const ChannelDataPtr & channelData() const FL_NO_EXCEPT
Expose the underlying ChannelDataPtr for conformance tests.
FL_STATIC_ASSERT(BusSupports< kBus, SpiChipsetConfig, B_WHICH >::value, "SlimSpiBridgeController: Bus does not support SpiChipsetConfig")
void showPixels(PixelController< RGB_ORDER > &pixels) FL_NO_EXCEPT override
fl::shared_ptr< IChannelDriver > resolveDriver() FL_NO_EXCEPT
Resolve the driver for this frame.
static string from_literal(const char *literal) FL_NO_EXCEPT
defines the templated version of the CLEDController class
Channel transmission data - lightweight DTO for driver transmission.
Non-templated low level pixel data writing class.
#define FL_WARN_ONCE(...)
Definition log.h:439
#define FL_ERROR(...)
Definition log.h:373
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
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
const char * busDriverName(Bus b, fl::u8 which=0, bool spi=false) FL_NO_EXCEPT
Concrete ChannelManager driver name for a portable bus.
Definition bus.h:170
fl::variant< ClocklessChipset, SpiChipsetConfig > ChipsetVariant
Definition config.h:157
Bus
Portable public bus selector.
Definition bus.h:27
@ AUTO
Definition bus.h:28
@ SM16716
SM16716 LED chipset.
@ LPD6803
LPD6803 LED chipset.
@ APA102HD
APA102 LED chipset with 5-bit gamma correction.
@ HD107
Same as APA102, but in turbo 40-mhz mode.
@ DOTSTARHD
APA102HD LED chipset alias.
@ SK9822HD
SK9822 LED chipset with 5-bit gamma correction.
@ SK9822
SK9822 LED chipset.
@ DOTSTAR
APA102 LED chipset alias.
@ P9813
P9813 LED chipset.
@ APA102
APA102 LED chipset.
@ HD108
16-bit variant of HD107, always gamma corrected. No SD (standard definition) option available - all H...
@ LPD8806
LPD8806 LED chipset.
@ WS2803
WS2803 LED chipset.
@ MY9221
MY9221 12-channel LED driver (dual-edge clocked; 4 RGB LEDs per chip)
@ WS2801
WS2801 LED chipset.
@ HD107HD
Same as APA102HD, but in turbo 40-mhz mode.
Base definition for an LED controller.
Primary template — intentionally undefined.
Definition bus_traits.h:31
Portable compile-time assertion wrapper.
Pixel controller class.
SPI chipset configuration (data + clock pins)
Definition config.h:103
static constexpr Bus value