16#include "five_bit_hd_gamma.h"
17#include "force_inline.h"
20#include "dither_mode.h"
21#include "pixel_iterator.h"
24FASTLED_NAMESPACE_BEGIN
33#define RO(X) RGB_BYTE(RGB_ORDER, X)
41#define RGB_BYTE(RO,X) (((RO)>>(3*(2-(X)))) & 0x3)
45#define RGB_BYTE0(RO) ((RO>>6) & 0x3)
48#define RGB_BYTE1(RO) ((RO>>3) & 0x3)
51#define RGB_BYTE2(RO) ((RO) & 0x3)
57 #if FASTLED_HD_COLOR_MIXING
70template<EOrder RGB_ORDER,
int LANES=1, u
int32_t MASK=0xFFFFFFFF>
90 void disableColorAdjustment() {
91 #if FASTLED_HD_COLOR_MIXING
92 mColorAdjustment.premixed =
CRGB(mColorAdjustment.brightness, mColorAdjustment.brightness, mColorAdjustment.brightness);
93 mColorAdjustment.color =
CRGB(0xff, 0xff, 0xff);
103 template<EOrder RGB_ORDER_OTHER>
108 template<
typename PixelControllerT>
109 void copy(
const PixelControllerT& other) {
110 static_assert(int(kLanes) == int(PixelControllerT::kLanes),
"PixelController lanes must match or mOffsets will be wrong");
111 static_assert(int(kMask) == int(PixelControllerT::kMask),
"PixelController mask must match or else one or the other controls different lanes");
119 mColorAdjustment = other.mColorAdjustment;
122 for(
int i = 0; i < LANES; ++i) {
mOffsets[i] = other.mOffsets[i]; }
129 for(
int i = 0; i < LANES; ++i) {
131 if((1<<i) & MASK) { nOffset += (len *
mAdvance); }
144 EDitherMode
dither,
bool advance, uint8_t skip)
179 #if FASTLED_HD_COLOR_MIXING
180 uint8_t global_brightness()
const {
181 return mColorAdjustment.brightness;
186#if !defined(NO_DITHERING) || (NO_DITHERING != 1)
189#define MAX_LIKELY_UPDATE_RATE_HZ 400
192#define MIN_ACCEPTABLE_DITHER_RATE_HZ 50
195#define UPDATES_PER_FULL_DITHER_CYCLE (MAX_LIKELY_UPDATE_RATE_HZ / MIN_ACCEPTABLE_DITHER_RATE_HZ)
210#define RECOMMENDED_VIRTUAL_BITS ((UPDATES_PER_FULL_DITHER_CYCLE>1) + \
211 (UPDATES_PER_FULL_DITHER_CYCLE>2) + \
212 (UPDATES_PER_FULL_DITHER_CYCLE>4) + \
213 (UPDATES_PER_FULL_DITHER_CYCLE>8) + \
214 (UPDATES_PER_FULL_DITHER_CYCLE>16) + \
215 (UPDATES_PER_FULL_DITHER_CYCLE>32) + \
216 (UPDATES_PER_FULL_DITHER_CYCLE>64) + \
217 (UPDATES_PER_FULL_DITHER_CYCLE>128) )
220#define VIRTUAL_BITS RECOMMENDED_VIRTUAL_BITS
227#if !defined(NO_DITHERING) || (NO_DITHERING != 1)
229 static uint8_t R = 0;
234 uint8_t ditherBits = VIRTUAL_BITS;
235 R &= (0x01 << ditherBits) - 1;
244 if(R & 0x01) { Q |= 0x80; }
245 if(R & 0x02) { Q |= 0x40; }
246 if(R & 0x04) { Q |= 0x20; }
247 if(R & 0x08) { Q |= 0x10; }
248 if(R & 0x10) { Q |= 0x08; }
249 if(R & 0x20) { Q |= 0x04; }
250 if(R & 0x40) { Q |= 0x02; }
251 if(R & 0x80) { Q |= 0x01; }
258 if( ditherBits < 8) {
259 Q += 0x01 << (7 - ditherBits);
267 for(
int i = 0; i < 3; ++i) {
268 uint8_t s = mColorAdjustment.premixed.
raw[i];
269 e[i] = s ? (256/s) + 1 : 0;
271#if (FASTLED_SCALE8_FIXED == 1)
282 FASTLED_FORCE_INLINE
bool has(
int n) {
294 default:
d[0]=
d[1]=
d[2]=
e[0]=
e[1]=
e[2]=0;
break;
304 FASTLED_FORCE_INLINE
int lanes() {
return LANES; }
325 d[RO(0)] =
e[RO(0)] -
d[RO(0)];
361 template<
int SLOT> FASTLED_FORCE_INLINE
static uint8_t
scale(
PixelController & pc, uint8_t b) {
return scale8(b, pc.mColorAdjustment.premixed.
raw[RO(SLOT)]); }
470 #if FASTLED_HD_COLOR_MIXING
471 template<
int SLOT> FASTLED_FORCE_INLINE
static uint8_t getScaleFullBrightness(
PixelController & pc) {
return pc.mColorAdjustment.color.raw[RO(SLOT)]; }
474 FASTLED_FORCE_INLINE
void getHdScale(uint8_t* c0, uint8_t* c1, uint8_t* c2, uint8_t* brightness) {
475 *c0 = getScaleFullBrightness<0>(*
this);
476 *c1 = getScaleFullBrightness<1>(*
this);
477 *c2 = getScaleFullBrightness<2>(*
this);
478 *brightness = mColorAdjustment.brightness;
483 FASTLED_FORCE_INLINE
void loadAndScale_APA102_HD(uint8_t *b0_out, uint8_t *b1_out,
485 uint8_t *brightness_out) {
487 uint8_t brightness = 0;
489 #if FASTLED_HD_COLOR_MIXING
490 brightness = mColorAdjustment.brightness;
494 CRGB scale = mColorAdjustment.premixed;
496 five_bit_hd_gamma_bitshift(
503 const uint8_t b0_index = RGB_BYTE0(RGB_ORDER);
504 const uint8_t b1_index = RGB_BYTE1(RGB_ORDER);
505 const uint8_t b2_index = RGB_BYTE2(RGB_ORDER);
506 *b0_out = rgb.
raw[b0_index];
507 *b1_out = rgb.
raw[b1_index];
508 *b2_out = rgb.
raw[b2_index];
509 *brightness_out = brightness;
512 FASTLED_FORCE_INLINE
void loadAndScaleRGB(uint8_t *b0_out, uint8_t *b1_out,
519 FASTLED_FORCE_INLINE
void loadAndScaleRGBW(
Rgbw rgbw, uint8_t *b0_out, uint8_t *b1_out,
520 uint8_t *b2_out, uint8_t *b3_out) {
530 EOrderW w_placement = rgbw.w_placement;
532 rgbw_partial_reorder(
533 w_placement, out[0], out[1], out[2],
535 b0_out, b1_out, b2_out, b3_out);
537 const uint8_t b0_index = RGB_BYTE0(RGB_ORDER);
538 const uint8_t b1_index = RGB_BYTE1(RGB_ORDER);
539 const uint8_t b2_index = RGB_BYTE2(RGB_ORDER);
543 rgb_2_rgbw(rgbw.rgbw_mode,
544 rgbw.white_color_temp,
546 mColorAdjustment.premixed.
r, mColorAdjustment.premixed.
g, mColorAdjustment.premixed.
b,
547 &rgb.
r, &rgb.
g, &rgb.
b, &w);
549 rgbw_partial_reorder(
555 b0_out, b1_out, b2_out, b3_out);
central include file for FastLED, defines the CFastLED class/object
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
uint8_t raw[3]
Access the red, green, and blue data as an array.
uint8_t r
Red channel value.
uint8_t g
Green channel value.
uint8_t b
Blue channel value.
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Representation of an RGB pixel (Red, Green, Blue)
FASTLED_FORCE_INLINE uint8_t loadAndScale0(int lane)
non-template alias of loadAndScale<0>()
static FASTLED_FORCE_INLINE uint8_t scale(PixelController &pc, uint8_t b)
Scale a value using the per-channel scale data.
FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0()
stepDithering() and advanceAndLoadAndScale0()
int8_t mAdvance
how many bytes to advance the pointer by each time. For CRGB this is 3.
FASTLED_FORCE_INLINE uint8_t loadAndScale1(int lane, uint8_t scale)
non-template alias of loadAndScale<1>()
FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0(int lane)
stepDithering() and advanceAndLoadAndScale0()
static FASTLED_FORCE_INLINE uint8_t loadAndScale(PixelController &pc, int lane, uint8_t scale)
Loads and scales a single byte for a given output slot and lane.
void init_binary_dithering()
Set up the values for binary dithering.
FASTLED_FORCE_INLINE uint8_t loadAndScale1(int lane)
non-template alias of loadAndScale<1>()
FASTLED_FORCE_INLINE uint8_t getScale0()
non-template alias of getscale<0>()
int mLenRemaining
counter for the number of LEDs left to process
FASTLED_FORCE_INLINE uint8_t loadAndScale2(int lane, uint8_t scale)
non-template alias of loadAndScale<2>()
void initOffsets(int len)
Initialize the PixelController::mOffsets array based on the length of the strip.
FASTLED_FORCE_INLINE void preStepFirstByteDithering()
Some chipsets pre-cycle the first byte, which means we want to cycle byte 0's dithering separately.
FASTLED_FORCE_INLINE uint8_t loadAndScale2(int lane)
non-template alias of loadAndScale<2>()
FASTLED_FORCE_INLINE uint8_t loadAndScale0(int lane, uint8_t scale)
non-template alias of loadAndScale<0>()
FASTLED_FORCE_INLINE uint8_t loadAndScale0()
non-template alias of loadAndScale<0>()
FASTLED_FORCE_INLINE int advanceBy()
Get the amount to advance the pointer by.
const uint8_t * mData
pointer to the underlying LED data
static FASTLED_FORCE_INLINE uint8_t loadAndScale(PixelController &pc)
Loads, dithers, and scales a single byte for a given output slot, using class dither and scale values...
uint8_t d[3]
values for the scaled dither signal
FASTLED_FORCE_INLINE int lanes()
Get the number of lanes of the Controller.
int mOffsets[LANES]
the number of bytes to offset each lane from the starting pointer
FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0(int lane, uint8_t scale)
non-template alias of advanceAndLoadAndScale<0>()
PixelController(const CRGB &d, int len, ColorAdjustment color_adjustment, EDitherMode dither)
Constructor.
FASTLED_FORCE_INLINE uint8_t getScale2()
non-template alias of getscale<2>()
static FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale(PixelController &pc)
A version of loadAndScale() that advances the output data pointer.
int mLen
number of LEDs in the data for one lane
static FASTLED_FORCE_INLINE uint8_t loadAndScale(PixelController &pc, int lane)
Loads, dithers, and scales a single byte for a given output slot and lane, using class dither and sca...
static FASTLED_FORCE_INLINE uint8_t loadByte(PixelController &pc)
Read a byte of LED data.
static FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale(PixelController &pc, int lane, uint8_t scale)
A version of loadAndScale() that advances the output data pointer without dithering.
static FASTLED_FORCE_INLINE uint8_t loadAndScale(PixelController &pc, int lane, uint8_t d, uint8_t scale)
Loads, dithers, and scales a single byte for a given output slot and lane.
FASTLED_FORCE_INLINE int size()
Get the length of the LED strip.
static FASTLED_FORCE_INLINE uint8_t getd(PixelController &pc)
Gets the dithering data for the provided output slot.
FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0(int lane)
non-template alias of advanceAndLoadAndScale<0>()
uint8_t e[3]
values for the scaled dither signal
static FASTLED_FORCE_INLINE uint8_t getscale(PixelController &pc)
Gets the scale data for the provided output slot.
static FASTLED_FORCE_INLINE uint8_t dither(PixelController &, uint8_t b, uint8_t d)
Calculate a dither value.
static FASTLED_FORCE_INLINE uint8_t dither(PixelController &pc, uint8_t b)
Calculate a dither value using the per-channel dither data.
FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0()
non-template alias of advanceAndLoadAndScale<0>()
void enable_dithering(EDitherMode dither)
Toggle dithering enable If dithering is set to enabled, this will re-init the dithering values (init_...
static FASTLED_FORCE_INLINE uint8_t scale(PixelController &, uint8_t b, uint8_t scale)
Scale a value.
FASTLED_FORCE_INLINE void advanceData()
Advance the data pointer forward, adjust position counter.
FASTLED_FORCE_INLINE bool has(int n)
Do we have n pixels left to process?
PixelController(const CRGB *d, int len, ColorAdjustment color_adjustment, EDitherMode dither)
Constructor.
FASTLED_FORCE_INLINE void stepDithering()
Step the dithering forward.
FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0(int lane, uint8_t scale)
stepDithering() and advanceAndLoadAndScale0()
PixelController(const uint8_t *d, int len, ColorAdjustment color_adjustment, EDitherMode dither, bool advance, uint8_t skip)
Constructor.
PixelController(const PixelController &other)
Copy constructor.
FASTLED_FORCE_INLINE uint8_t loadAndScale1()
non-template alias of loadAndScale<1>()
static FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale(PixelController &pc, int lane)
A version of loadAndScale() that advances the output data pointer.
FASTLED_FORCE_INLINE uint8_t getScale1()
non-template alias of getscale<1>()
static FASTLED_FORCE_INLINE uint8_t loadByte(PixelController &pc, int lane)
Read a byte of LED data for parallel output.
FASTLED_FORCE_INLINE uint8_t loadAndScale2()
non-template alias of loadAndScale<2>()