FastLED 3.10.6
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->getName().c_str())) {
109 FL_WARN_ONCE("SlimSpiBridgeController: driver '%s' is disabled - dropping frame",
110 driver->getName().c_str());
111 return;
112 }
113
114 // (A8) If the previous frame's buffer is still in flight, block
115 // (bounded) until the driver reports it can accept more work rather
116 // than racing the driver's in-progress transfer.
117 if (mData->isInUse()) {
118 if (!driver->waitForReady()) {
119 FL_WARN_ONCE("SlimSpiBridgeController: driver '%s' did not become ready in "
120 "time - dropping frame", driver->getName().c_str());
121 return;
122 }
123 }
124
125 // (A5) Publish the pixel byte layout so the driver (and any
126 // downstream padding/diagnostic code) knows the encoded stride.
127 if (this->getRgbww().active()) {
128 mData->setPixelFormat(ChannelPixelFormat::RGBWW);
129 } else if (this->getRgbw().active()) {
130 mData->setPixelFormat(ChannelPixelFormat::RGBW);
131 } else {
132 mData->setPixelFormat(ChannelPixelFormat::RGB);
133 }
134
135 // Dither reseed mirrors Channel::encodeFrame(): only reseed when a
136 // non-zero dither mode is set.
137 if (pixels.ditherActive()) {
138 pixels.reseed_binary_dithering(mDitherPhase);
139 }
140
141 // (A3) Re-encode into the same buffer every frame -- clear() keeps
142 // capacity, so steady-state operation is allocation-free.
143 mData->getData().clear();
144 fl::PixelIterator it(&pixels, this->getRgbw(), this->getRgbww());
145 encode(it, mData->getData());
146
147 driver->enqueue(mData);
148 // Presented, per the driver contract: an accepted enqueue is the
149 // frame -- mirrors Channel::submitFrame()'s ++mDitherPhase placement
150 // (dither only advances when a frame is actually handed to the
151 // driver, not on every showPixels() attempt).
152 ++mDitherPhase;
153 }
154
155private:
163#if defined(FASTLED_DISABLE_DYNAMIC_DRIVER) && FASTLED_DISABLE_DYNAMIC_DRIVER
164 return {};
165#else
166 // Build busKey only when we actually need it (kBus != AUTO).
167 fl::string busKey;
168 if (kBus != Bus::AUTO) {
169 busKey = fl::string::from_literal(busDriverName(kBus, B_WHICH, /*spi=*/true));
170 }
171
174
175#if FASTLED_LOG_RUNTIME_ENABLED
176 if (!driver && !mBusWarned) {
177 FL_ERROR("SlimSpiBridgeController: no compatible driver found for bus '%s' - "
178 "cannot transmit", busKey.c_str());
179 mBusWarned = true;
180 }
181#endif // FASTLED_LOG_RUNTIME_ENABLED
182 return driver;
183#endif // !FASTLED_DISABLE_DYNAMIC_DRIVER
184 }
185
191 switch (CHIPSET) {
195 it.writeAPA102(&out, false);
196 break;
200 it.writeAPA102(&out, true);
201 break;
203 it.writeSK9822(&out, false);
204 break;
206 it.writeSK9822(&out, true);
207 break;
209 it.writeWS2801(&out);
210 break;
212 it.writeWS2803(&out);
213 break;
215 it.writeP9813(&out);
216 break;
218 it.writeLPD8806(&out);
219 break;
221 it.writeLPD6803(&out);
222 break;
224 it.writeSM16716(&out);
225 break;
227 it.writeHD108(&out, false);
228 break;
230 // Never routed here -- FastLED.h sends MY9221 to the bit-bang
231 // MY9221Controller (see file header comment). Defensive
232 // no-op if this controller is ever instantiated directly
233 // with CHIPSET == MY9221.
234 break;
235 }
236 }
237
238 ChannelDataPtr mData;
240#if FASTLED_LOG_RUNTIME_ENABLED
241 bool mBusWarned = false;
242#endif
243};
244
245} // 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)
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.
const char * c_str() const FL_NO_EXCEPT
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:442
#define FL_ERROR(...)
Definition log.h:372
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
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
InputGamut g FL_NO_EXCEPT
Definition rgbw.h:121
@ 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.
Definition crgb.hpp:179
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