19 if (profile ==
nullptr) {
25 out, binding.mHasTargetWhite
26 ? &binding.mTargetWhite :
nullptr);
38 if (profile !=
nullptr) {
41 const Rgbww* rgbww = options.mWhiteCfg.ptr<
Rgbww>();
42 const bool is_rgbw =
rgbw !=
nullptr &&
rgbw->active();
43 const bool is_rgbww = rgbww !=
nullptr && rgbww->active();
46 (is_rgbw || is_rgbww)) ||
63 const bool supports_rgbw =
66 const bool supports_rgbww =
70 ? !supports_rgbw : !supports_rgbww) {
87 void* source_storage,
void* iterator_storage,
93#if FL_COLOR_PIPELINE_SHARED
94 const PowerFrameHooks& hooks = powerFrameHooks();
95 if (hooks.frameFluxActive) {
97 static_cast<i32
>(hooks.frameFluxQ16)));
113#if FL_COLOR_PIPELINE_SHARED
114void colorPipelineBuildPowerHistogram(
117 if (out ==
nullptr)
return;
118 *out = ManagedPowerHistogram();
119 out->pixels =
static_cast<u32
>(
leds.size());
120 out->emitters = emitter_count;
121 for (fl::size i = 0; i <
leds.size(); ++i) {
129 leds[i].b, rgb_light);
130 for (
int c = 0; c < 3; ++c) light[c] = rgb_light[c];
132 for (
u8 c = 0; c < emitter_count; ++c) {
134 const u32 bounded = light[c] > 65536 ? 65536u :
135 static_cast<u32
>(light[c]);
136 const u8 bin =
static_cast<u8>((bounded - 1u) >> 10);
137 ++out->counts[c][bin];
143u64 colorPipelineHistogramPowerNumerator(
145 const ManagedPowerHistogram& histogram,
FluxScalar flux,
149 for (
u8 c = 0; c < histogram.emitters; ++c) {
150 for (
u8 bin = 0; bin < ManagedPowerHistogram::kBins; ++bin) {
151 const u32 count = histogram.counts[c][bin];
152 if (count == 0)
continue;
153 const i32 upper_light =
static_cast<i32
>((bin + 1u) << 10);
156 if (drive <= 0)
continue;
157 u8 mapped_upper = 255;
159 const u32 code = (
static_cast<u32
>(drive) * 255u + 65535u) >> 16;
160 mapped_upper = electrical_map(
static_cast<u8>(code > 255 ? 255 : code));
164 const u32 native = (
static_cast<u32
>(drive) * max_code + 65535u) >> 16;
165 const u32 equivalent = (native * 255u + max_code - 1u) / max_code;
166 mapped_upper = electrical_map(
static_cast<u8>(equivalent > 255 ? 255 : equivalent));
169 const u32 min_field = codec.min_field < 1 ? 1 : codec.min_field;
170 for (u32 field = min_field; field <= 31; ++field) {
171 const u64 numerator_code =
static_cast<u64>(drive) * 255u * 31u;
172 const u64 denominator =
static_cast<u64>(65536) * field;
173 const u32 code =
static_cast<u32
>((numerator_code + denominator - 1) / denominator);
174 const u8 bounded_code =
static_cast<u8>(code > 255 ? 255 : code);
175 const u32 weighted = (
static_cast<u32
>(electrical_map(bounded_code)) *
177 if (weighted > mapped_upper) mapped_upper =
static_cast<u8>(weighted);
180 numerator +=
static_cast<u64>(count) * mapped_upper * weights[c];
186u32 colorPipelineUnscaledPowerMilliwatts(
188 u8 emitter_count, ColorPipelineHooks::PowerEstimator estimate)
FL_NO_EXCEPT {
200 enum { kChunk = 32 };
201 u8 chunk[kChunk * 5];
204 for (fl::size i = 0; i <
leds.size(); ++i) {
213 for (
int c = 0; c < 3; ++c) drives[c] = rgb_drives[c];
215 for (
int c = 0; c < emitter_count; ++c) {
223 chunk[filled * emitter_count + c] =
224 static_cast<u8>((d * 255 + 32768) >> 16);
226 if (++filled == kChunk) {
243#if !FL_PLATFORM_HAS_TINY_MEMORY
255#if FASTLED_HD_COLOR_MIXING && !FL_PLATFORM_HAS_TINY_MEMORY
282 if (min_field >= 31) {
312#if FL_COLOR_PIPELINE_SHARED
314 static PowerFrameHooks hooks = {};
321 hooks.
build = &buildPipelineForChannelBinding;
326#if FL_COLOR_PIPELINE_SHARED
327 hooks.unscaledPowerMilliwatts = &colorPipelineUnscaledPowerMilliwatts;
328 PowerFrameHooks& power_hooks = powerFrameHooks();
329 power_hooks.buildPowerHistogram = &colorPipelineBuildPowerHistogram;
330 power_hooks.histogramPowerNumerator = &colorPipelineHistogramPowerNumerator;
338 if (notify !=
nullptr) {
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
CLEDController * controller
void setFlux(u8 brightness) FL_NO_EXCEPT
Frame-local brightness is applied to the source's owned pipeline on shared tiers; only managed iterat...
Runs processPixelQ16 over a PixelController's pixels as they are read.
static FluxScalar fromRawQ16(i32 raw) FL_NO_EXCEPT
A limiter fraction already in s16.16, clamped to [0, 1].
static FluxScalar unity() FL_NO_EXCEPT
Identity. Drives pass through unchanged.
A linear flux scalar in s16.16.
base definitions used by led controllers for writing out led data
bool buildPipelineForChannelBinding(const ColorProfileBinding &binding, const ChannelOptions &options, const ChipsetVariant &chipset, StreamingPipelineQ16 *out) FL_NO_EXCEPT
bool encodeColorPipelineManagedSpi(PixelIterator &pixels, vector_psram< u8 > *out, SpiChipset chip, const CLEDController &controller) FL_NO_EXCEPT
PixelIterator * makeColorPipelineIterator(void *source_storage, void *iterator_storage, PixelController< RGB, 1, 0xFFFFFFFF > &controller, EOrder order, ColorPipelineFrameRef pipeline, const Rgbw &rgbw, Rgbww rgbww, u8 dither_phase, u8 brightness) FL_NO_EXCEPT
Builds the managed iterator in the caller's storage.
void destroyColorPipelineIterator(void *source_storage, void *iterator_storage) FL_NO_EXCEPT
void notifyColorPipelineProfileClearedByLegacy() FL_NO_EXCEPT
u8 & hdFieldFloor() FL_NO_EXCEPT
Backing store for CFastLED::setHdFieldFloor().
back_insert_iterator< Container > back_inserter(Container &c) FL_NO_EXCEPT
Helper function to create a back_insert_iterator.
ClocklessEncoder
Identifies which encoder to use for clockless chipsets in the Channel API.
@ CLOCKLESS_ENCODER_UCS7604_8BIT
UCS7604 8-bit 800KHz.
@ CLOCKLESS_ENCODER_TM1812_RGBWW
TM1812: two 5-byte RGBWW pixels in each 12-byte IC frame.
@ CLOCKLESS_ENCODER_WS2812
Default, no preamble (WS2812 and compatible)
void installColorPipelineHooks() FL_NO_EXCEPT
Point the hooks at the real implementations.
void notifyColorProfileClearedByLegacy() FL_NO_EXCEPT
void setPipelineFluxQ16(StreamingPipelineQ16 *pipeline, FluxScalar flux) FL_NO_EXCEPT
Set the composed brightness-and-power scalar for the frames that follow.
u8 hdMinimumField(FiveBitSemantics semantics, u8 floor_setting) FL_NO_EXCEPT
The lowest field the managed HD path may choose: the configured flicker floor for a secondary slow-PW...
fl::variant< ClocklessChipset, SpiChipsetConfig > ChipsetVariant
ColorPipelineHooks & colorPipelineHooks() FL_NO_EXCEPT
The installed hooks.
void processPixelLinearQ16(const StreamingPipelineQ16 &pipeline, u8 r, u8 g, u8 b, i32(&drives)[3]) FL_NO_EXCEPT
Pre-response linear emitter light for a power prepass.
void processPixelWideLinearQ16(const StreamingPipelineQ16 &pipeline, u8 r, u8 g, u8 b, i32(&drives)[5]) FL_NO_EXCEPT
InputGamut g FL_NO_EXCEPT
bool buildPipelineForBinding(const ColorProfileBinding &binding, StreamingPipelineQ16 *out) FL_NO_EXCEPT
Build the streaming pipeline a binding describes.
EOrder
RGB color channel orderings, used when instantiating controllers to determine what order the controll...
bool buildStreamingPipelineQ16(const SourceProfile &source, const colorimetric_response::EmitterProfile &device, GamutPolicy policy, StreamingPipelineQ16 *out, const Chromaticity *target_white) FL_NO_EXCEPT
Bind a source declaration and a device profile into a pipeline.
void processPixelWideQ16(const StreamingPipelineQ16 &pipeline, u8 r, u8 g, u8 b, i32(&drives)[5]) FL_NO_EXCEPT
Like processPixelQ16, but solves the physical 4/5-emitter hull.
StreamingPipelineQ16 & ColorPipelineFrameRef
i32 encodeLinearEmitterQ16(const StreamingPipelineQ16 &pipeline, u8 emitter, i32 light, FluxScalar flux) FL_NO_EXCEPT
Scale one linear emitter and invert its physical response, using the identical final stage as process...
SpiChipset
LED chipsets with SPI interface (clocked protocols) Modern type-safe enum class - prefer this for new...
@ LPD6803
LPD6803 LED chipset.
@ HD107
Same as APA102, but in turbo 40-mhz mode.
@ SK9822
SK9822 LED chipset.
@ DOTSTAR
APA102 LED chipset alias.
@ APA102
APA102 LED chipset.
@ LPD8806
LPD8806 LED chipset.
FiveBitSemantics fiveBitSemanticsFor(SpiChipset chip, FiveBitSemantics profile) FL_NO_EXCEPT
The 5-bit semantics for chip, with profile overriding the chip's default when it is not NotApplicable...
void processPixelQ16(const StreamingPipelineQ16 &pipeline, u8 r, u8 g, u8 b, i32(&drives)[3]) FL_NO_EXCEPT
One pixel: an RGB8 code triple to three physical emitter drives in s16.16.
Base definition for an LED controller.
bool(* build)(const ColorProfileBinding &, const ChannelOptions &, const ChipsetVariant &, StreamingPipelineQ16 *)
Derives a pipeline from a binding. Null until installed.
void(* destroyIterator)(void *source_storage, void *iterator_storage)
Destroys what makeIterator built. Null until installed.
void(* notifyProfileClearedByLegacy)()
Fires ChannelEvents::onColorProfileWarning(ProfileClearedByLegacy).
PixelIterator *(* makeIterator)(void *source_storage, void *iterator_storage, PixelController< RGB, 1, 0xFFFFFFFF > &controller, EOrder order, ColorPipelineFrameRef pipeline, const Rgbw &rgbw, Rgbww rgbww, u8 dither_phase, u8 brightness)
Constructs a colour-managed PixelIterator in caller-provided storage.
bool(* encodeManagedSpi)(PixelIterator &pixels, vector_psram< u8 > *out, SpiChipset chip, const CLEDController &controller)
Unscaled (full-brightness) power demand of leds as the pipeline will drive them, in mW,...
Payload shared by every color-profile notification.
Everything the per-pixel path needs, derived once when a profile binds.
fl::PixelIterator PixelIterator
fl::function_list< void(const ColorProfileEvent &)> onColorProfileWarning
static ChannelEvents & instance()
Optional channel configuration parameters All fields have sensible defaults and can be overridden as ...
Clockless chipset configuration (single data pin)
Immutable profile binding carried by a channel.
Per-strip RGBWW configuration.
FiveBitSemantics five_bit_semantics