16#include "platforms/is_platform.h"
48#define RO(X) RGB_BYTE(RGB_ORDER, X)
56#define RGB_BYTE(RO,X) ((static_cast<int>(RO)>>(3*(2-(X)))) & 0x3)
60#define RGB_BYTE0(RO) ((static_cast<int>(RO)>>6) & 0x3)
63#define RGB_BYTE1(RO) ((static_cast<int>(RO)>>3) & 0x3)
66#define RGB_BYTE2(RO) (static_cast<int>(RO) & 0x3)
78 #if FASTLED_HD_COLOR_MIXING
88 #if FASTLED_HD_COLOR_MIXING
89 adj.color =
CRGB(255, 255, 255);
103template<EOrder RGB_ORDER,
int LANES=1, fl::u32 MASK=0xFFFFFFFF>
128 #if FASTLED_HD_COLOR_MIXING
144 if (
this != &other) {
150 template<EOrder RGB_ORDER_OTHER>
155 template<
typename PixelControllerT>
156 void copy(
const PixelControllerT& other) {
157 FL_STATIC_ASSERT(
int(
kLanes) ==
int(PixelControllerT::kLanes),
"PixelController lanes must match or mOffsets will be wrong");
158 FL_STATIC_ASSERT(
int(
kMask) ==
int(PixelControllerT::kMask),
"PixelController mask must match or else one or the other controls different lanes");
169 for(
int i = 0; i < LANES; ++i) {
mOffsets[i] = other.mOffsets[i]; }
176 for(
int i = 0; i < LANES; ++i) {
178 if((1<<i) & MASK) { nOffset += (len *
mAdvance); }
226 #if FASTLED_HD_COLOR_MIXING
227 fl::u8 global_brightness()
const {
252#if FL_PLATFORM_HAS_TINY_MEMORY
462 #if FASTLED_HD_COLOR_MIXING
470 *c0 = getScaleFullBrightness<0>(*
this);
471 *c1 = getScaleFullBrightness<1>(*
this);
472 *c2 = getScaleFullBrightness<2>(*
this);
479 loadRGBScaleAndBrightness(c0, c1, c2,
brightness);
532 r_out, g_out, b_out, w_out);
542 FL_WARN_ONCE(
"RGBWW colorimetric is not supported on AVR -- the warm "
543 "and cool white channels will be black. Use an ESP32 / "
544 "Teensy / RP2040 target for full RGBWW support.");
559 r_out, g_out, b_out, ww_out, wc_out);
578 w_placement, out[0], out[1], out[2],
580 b0_out, b1_out, b2_out, b3_out);
596 b0_out, b1_out, b2_out, b3_out);
614 FL_WARN_ONCE(
"RGBWW colorimetric is not supported on AVR — the warm "
615 "and cool white channels will be black. Use an ESP32 / "
616 "Teensy / RP2040 target for full RGBWW support.");
624 b0_out, b1_out, b2_out, b3_out, b4_out);
639 b0_out, b1_out, b2_out, b3_out, b4_out);
fl::UISlider brightness("Brightness", BRIGHTNESS, 0, 255)
fl::UISlider scale("Scale", 4,.1, 4,.1)
Temporal binary dithering, as one self-contained, testable unit (#4672).
#define FL_DISABLE_WARNING_IMPLICIT_INT_CONVERSION
#define FASTLED_FORCE_INLINE
#define FL_DISABLE_WARNING_PUSH
#define FL_DEPRECATED(msg)
#define FL_DISABLE_WARNING_SIGN_CONVERSION
#define FL_DISABLE_WARNING_POP
#define FL_DISABLE_WARNING_FLOAT_CONVERSION
#define BINARY_DITHER
Enable dithering using binary dithering (only option)
fl::u8 EDitherMode
The dither setting, either DISABLE_DITHER or BINARY_DITHER.
Declares dithering options and types.
Defines color channel ordering enumerations.
Declares functions for five-bit gamma correction.
Integer mapping functions between different integer sizes.
Legacy compatibility header for 8-bit math functions.
Legacy compatibility header for 8-bit scaling functions.
#define FL_WARN_ONCE(...)
Centralized logging categories for FastLED hardware interfaces and subsystems.
u8 ditherFrame() FL_NO_EXCEPT
Return the temporal-dither phase shared by all controllers in this frame.
void rgbww_partial_reorder(EOrderWW ww_placement, u8 b0, u8 b1, u8 b2, u8 ww, u8 wc, u8 *out_b0, u8 *out_b1, u8 *out_b2, u8 *out_b3, u8 *out_b4) FL_NO_EXCEPT
Dispatch RGB->RGBWW for a given mode.
void rgbw_partial_reorder(EOrderW w_placement, u8 b0, u8 b1, u8 b2, u8 w, u8 *out_b0, u8 *out_b1, u8 *out_b2, u8 *out_b3)
FASTLED_FORCE_INLINE void rgb_2_rgbw(const Rgbw &cfg, u8 r, u8 g, u8 b, u8 r_scale, u8 g_scale, u8 b_scale, u8 *out_r, u8 *out_g, u8 *out_b, u8 *out_w) FL_NO_EXCEPT
Converts RGB to RGBW using one of the functions.
FASTLED_FORCE_INLINE void rgb_2_rgbww(const Rgbww &cfg, fl::u8 r, fl::u8 g, fl::u8 b, fl::u8 r_scale, fl::u8 g_scale, fl::u8 b_scale, fl::u8 *out_r, fl::u8 *out_g, fl::u8 *out_b, fl::u8 *out_ww, fl::u8 *out_wc) FL_NO_EXCEPT
Base definition for an LED controller.
#define RGB_BYTE2(RO)
Gets the color channel for byte 2.
#define RGB_BYTE1(RO)
Gets the color channel for byte 1.
#define RGB_BYTE0(RO)
Gets the color channel for byte 0.
#define RO(X)
Gets the assigned color channel for a byte's position in the output, using the color order (EOrder) t...
Functions for red, green, blue, white (RGBW) output.
5-channel RGB + warm-W + cool-W (RGBWW / RGBCCT) configuration types (issue #2558,...
#define FL_STATIC_ASSERT(...)
Portable compile-time assertion wrapper.
static ColorAdjustment noAdjustment()
the per-channel scale values premixed with brightness.
Color adjustment structure for pixel output.
static FASTLED_FORCE_INLINE fl::u8 loadAndScale(PixelController &pc, int lane, fl::u8 d, fl::u8 scale)
Complete pipeline: load → dither → scale (explicit dither/scale values)
static FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale(PixelController &pc, int lane)
A version of loadAndScale() that advances the output data pointer.
FASTLED_FORCE_INLINE fl::u8 loadAndScale1()
non-template alias of loadAndScale<1>()
FASTLED_FORCE_INLINE int size() const
Get the length of the LED strip.
PixelController(const fl::u8 *d, int len, ColorAdjustment color_adjustment, EDitherMode dither, bool advance, fl::u8 skip)
Constructor.
static FASTLED_FORCE_INLINE fl::u8 scale(PixelController &, fl::u8 b, fl::u8 scale)
Scale a value.
static FASTLED_FORCE_INLINE fl::u8 loadByte(PixelController &pc)
Read a byte of LED data.
void init_binary_dithering()
Set up the values for binary dithering from the shared frame phase.
static FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale(PixelController &pc, int lane, fl::u8 scale)
A version of loadAndScale() that advances the output data pointer without dithering.
int mLenRemaining
counter for the number of LEDs left to process
void initOffsets(int len)
Initialize the PixelController::mOffsets array based on the length of the strip.
FASTLED_FORCE_INLINE fl::u8 stepAdvanceAndLoadAndScale0(int lane, fl::u8 scale)
stepDithering() and advanceAndLoadAndScale0()
FASTLED_FORCE_INLINE void loadAndScaleRGBWWUnordered(fl::Rgbww rgbww, fl::u8 *r_out, fl::u8 *g_out, fl::u8 *b_out, fl::u8 *ww_out, fl::u8 *wc_out)
loadAndScaleRGBWW before its wire reorder. See loadAndScaleRGBWUnordered.
FASTLED_FORCE_INLINE fl::u8 getScale1()
non-template alias of getscale<1>()
FASTLED_FORCE_INLINE void preStepFirstByteDithering()
Some chipsets pre-cycle the first byte, which means we want to cycle byte 0's dithering separately.
fl::u8 e[3]
[DITHER] Max dither range per R,G,B channel (inversely proportional to brightness)
FASTLED_FORCE_INLINE void loadAndScaleRGBWW(fl::Rgbww rgbww, fl::u8 *b0_out, fl::u8 *b1_out, fl::u8 *b2_out, fl::u8 *b3_out, fl::u8 *b4_out)
Load + scale a single pixel to 5-channel RGBWW (issue #2558).
FASTLED_FORCE_INLINE fl::u8 loadAndScale0()
non-template alias of loadAndScale<0>()
FASTLED_FORCE_INLINE int advanceBy()
Get the amount to advance the pointer by.
static FASTLED_FORCE_INLINE fl::u8 loadAndScale(PixelController &pc, int lane)
Complete pipeline: load → dither → scale (parallel output version)
static FASTLED_FORCE_INLINE fl::u8 loadByte(PixelController &pc, int lane)
Read a byte of LED data for parallel output.
static FASTLED_FORCE_INLINE fl::u8 scale(PixelController &pc, fl::u8 b)
Scale a value using the per-channel scale data.
FASTLED_FORCE_INLINE int lanes()
Get the number of lanes of the Controller.
FASTLED_FORCE_INLINE void loadAndScaleRGBW(const Rgbw &rgbw, fl::u8 *b0_out, fl::u8 *b1_out, fl::u8 *b2_out, fl::u8 *b3_out)
fl::u8 d[3]
[DITHER] Current dither offset per R,G,B channel (toggles via stepDithering)
FASTLED_FORCE_INLINE fl::u8 stepAdvanceAndLoadAndScale0()
stepDithering() and advanceAndLoadAndScale0()
int mOffsets[LANES]
the number of bytes to offset each lane from the starting pointer
FASTLED_FORCE_INLINE fl::u8 loadAndScale2()
non-template alias of loadAndScale<2>()
static FASTLED_FORCE_INLINE fl::u8 getscale(PixelController &pc)
Gets the scale data for the provided output slot.
PixelController(const PixelController< RGB_ORDER_OTHER, LANES, MASK > &other)
PixelController(const CRGB &d, int len, ColorAdjustment color_adjustment, EDitherMode dither)
Constructor.
ColorAdjustment mColorAdjustment
const fl::u8 * mData
pointer to the underlying LED data
void reseed_binary_dithering(fl::u8 R)
Re-point binary dithering at phase R after construction, leaving the per-channel ranges e[] as init_b...
FASTLED_FORCE_INLINE void loadAndScaleRGB(fl::u8 *b0_out, fl::u8 *b1_out, fl::u8 *b2_out)
int mLen
number of LEDs in the data for one lane
FASTLED_FORCE_INLINE bool ditherActive() const
Is temporal dithering on for this frame? (any channel has a range)
static constexpr EOrder kColorOrder
The colour order this instantiation writes, as a value.
FASTLED_FORCE_INLINE fl::u8 loadAndScale0(int lane, fl::u8 scale)
non-template alias of loadAndScale<0>()
PixelController & operator=(const PixelController &other)
Copy assignment, through the same copy() as the copy constructor.
FASTLED_FORCE_INLINE fl::u8 loadAndScale2(int lane)
non-template alias of loadAndScale<2>()
FASTLED_FORCE_INLINE fl::u8 loadAndScaleChannel(fl::u8 c)
One source channel, loaded, dithered and scaled – loadAndScale<SLOT> with RO(SLOT) replaced by a runt...
void disableColorAdjustment()
const fl::u8 * getRawPixelData() const
Get read-only access to the current pixel data Used by encoders to access raw RGB values for HD proce...
static FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale(PixelController &pc)
A version of loadAndScale() that advances the output data pointer.
FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale0()
non-template alias of advanceAndLoadAndScale<0>()
void enable_dithering(EDitherMode dither)
Toggle dithering enable/disable.
FASTLED_FORCE_INLINE fl::u8 getScale0()
non-template alias of getscale<0>()
FASTLED_FORCE_INLINE void advanceData()
Advance the data pointer forward, adjust position counter.
static FASTLED_FORCE_INLINE fl::u8 dither(PixelController &, fl::u8 b, fl::u8 d)
Add explicit dither offset to pixel value (BEFORE scaling).
FASTLED_FORCE_INLINE fl::u8 loadAndScale1(int lane, fl::u8 scale)
non-template alias of loadAndScale<1>()
FASTLED_FORCE_INLINE fl::u8 stepAdvanceAndLoadAndScale0(int lane)
stepDithering() and advanceAndLoadAndScale0()
FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale0(int lane, fl::u8 scale)
non-template alias of advanceAndLoadAndScale<0>()
FASTLED_FORCE_INLINE bool has(int n)
Do we have n pixels left to process?
static FASTLED_FORCE_INLINE fl::u8 getd(PixelController &pc)
Gets the dithering data for the provided output slot.
PixelController(const CRGB *d, int len, ColorAdjustment color_adjustment, EDitherMode dither)
Constructor.
FASTLED_FORCE_INLINE void stepDithering()
Step the dithering forward - creates triangular wave that toggles between pixels.
FASTLED_FORCE_INLINE fl::u8 loadAndScale2(int lane, fl::u8 scale)
non-template alias of loadAndScale<2>()
FASTLED_FORCE_INLINE fl::PixelIterator as_iterator(const Rgbw &rgbw)
static FASTLED_FORCE_INLINE fl::u8 loadAndScale(PixelController &pc)
Complete pipeline: load → dither → scale (THE MAGIC HAPPENS HERE!) Order is critical: pixel + dit...
FASTLED_FORCE_INLINE fl::u8 loadAndScale1(int lane)
non-template alias of loadAndScale<1>()
PixelController(const PixelController &other)
Copy constructor.
FASTLED_FORCE_INLINE fl::u8 getScale2()
non-template alias of getscale<2>()
static FASTLED_FORCE_INLINE fl::u8 loadAndScale(PixelController &pc, int lane, fl::u8 scale)
Loads and scales a single byte for a given output slot and lane.
static FASTLED_FORCE_INLINE fl::u8 dither(PixelController &pc, fl::u8 b)
Add dither offset to pixel value (BEFORE scaling).
void copy(const PixelControllerT &other)
FASTLED_FORCE_INLINE fl::u8 advanceAndLoadAndScale0(int lane)
non-template alias of advanceAndLoadAndScale<0>()
FASTLED_FORCE_INLINE void loadAndScaleRGBWUnordered(const Rgbw &rgbw, fl::u8 *r_out, fl::u8 *g_out, fl::u8 *b_out, fl::u8 *w_out)
loadAndScaleRGBW before its wire reorder: RGB in source order plus W.
fl::i8 mAdvance
how many bytes to advance the pointer by each time. For CRGB this is 3.
FASTLED_FORCE_INLINE fl::u8 loadAndScale0(int lane)
non-template alias of loadAndScale<0>()
static FASTLED_FORCE_INLINE bool active(const u8(&e)[3]) FL_NO_EXCEPT
static FASTLED_FORCE_INLINE void stepChannel(u8(&d)[3], const u8(&e)[3], int c) FL_NO_EXCEPT
step for a single channel (drivers that pre-step their first byte).
static FASTLED_FORCE_INLINE void reseed(u8(&d)[3], const u8(&e)[3], u8 frame) FL_NO_EXCEPT
Re-point d at frame, keeping the ranges init left in e.
static FASTLED_FORCE_INLINE void clear(u8(&d)[3], u8(&e)[3]) FL_NO_EXCEPT
static FASTLED_FORCE_INLINE u8 apply(u8 b, u8 d) FL_NO_EXCEPT
Add the offset to a source byte, before scaling. Black is never lifted.
static FASTLED_FORCE_INLINE void init(u8(&d)[3], u8(&e)[3], const u8(&scale)[3], u8 frame) FL_NO_EXCEPT
Set up e from the per-channel brightness scale and d from frame.
static FASTLED_FORCE_INLINE void step(u8(&d)[3], const u8(&e)[3]) FL_NO_EXCEPT
Next pixel: toggle each offset to its complement in [0, e], so neighbours dither in opposite directio...
Per-strip RGBWW configuration.