FastLED 3.9.3
Loading...
Searching...
No Matches
pixel_controller.h
1#pragma once
2
5
6// Note that new code should use the PixelIterator concrete object to write out
7// led data.
8// Using this class deep in driver code is deprecated because it's templates will
9// infact everything it touches. PixelIterator is concrete and doesn't have these
10// problems. See PixelController::as_iterator() for how to create a PixelIterator.
11
12#include <stddef.h>
13
14#include "FastLED.h"
15#include "rgbw.h"
16#include "five_bit_hd_gamma.h"
17#include "force_inline.h"
18#include "namespace.h"
19#include "eorder.h"
20#include "dither_mode.h"
21#include "pixel_iterator.h"
22#include "crgb.h"
23
24FASTLED_NAMESPACE_BEGIN
25
26
33#define RO(X) RGB_BYTE(RGB_ORDER, X)
34
41#define RGB_BYTE(RO,X) (((RO)>>(3*(2-(X)))) & 0x3)
42
45#define RGB_BYTE0(RO) ((RO>>6) & 0x3)
48#define RGB_BYTE1(RO) ((RO>>3) & 0x3)
51#define RGB_BYTE2(RO) ((RO) & 0x3)
52
53// operator byte *(struct CRGB[] arr) { return (byte*)arr; }
54
56 CRGB premixed;
57 #if FASTLED_HD_COLOR_MIXING
58 CRGB color;
59 uint8_t brightness;
60 #endif
61};
62
63
70template<EOrder RGB_ORDER, int LANES=1, uint32_t MASK=0xFFFFFFFF>
72 const uint8_t *mData;
73 int mLen;
75 uint8_t d[3];
76 uint8_t e[3];
77 int8_t mAdvance;
78 int mOffsets[LANES];
79 ColorAdjustment mColorAdjustment;
80
81 enum {
82 kLanes = LANES,
83 kMask = MASK
84 };
85
86 PixelIterator as_iterator(const Rgbw& rgbw) {
87 return PixelIterator(this, rgbw);
88 }
89
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);
94 #endif
95 }
96
100 copy(other);
101 }
102
103 template<EOrder RGB_ORDER_OTHER>
105 copy(other);
106 }
107
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");
112 d[0] = other.d[0];
113 d[1] = other.d[1];
114 d[2] = other.d[2];
115 e[0] = other.e[0];
116 e[1] = other.e[1];
117 e[2] = other.e[2];
118 mData = other.mData;
119 mColorAdjustment = other.mColorAdjustment;
120 mAdvance = other.mAdvance;
121 mLenRemaining = mLen = other.mLen;
122 for(int i = 0; i < LANES; ++i) { mOffsets[i] = other.mOffsets[i]; }
123 }
124
127 void initOffsets(int len) {
128 int nOffset = 0;
129 for(int i = 0; i < LANES; ++i) {
130 mOffsets[i] = nOffset;
131 if((1<<i) & MASK) { nOffset += (len * mAdvance); }
132 }
133 }
134
143 const uint8_t *d, int len, ColorAdjustment color_adjustment,
144 EDitherMode dither, bool advance, uint8_t skip)
145 : mData(d), mLen(len), mLenRemaining(len), mColorAdjustment(color_adjustment) {
147 mData += skip;
148 mAdvance = (advance) ? 3+skip : 0;
149 initOffsets(len);
150 }
151
158 const CRGB *d, int len, ColorAdjustment color_adjustment,
159 EDitherMode dither)
160 : mData((const uint8_t*)d), mLen(len), mLenRemaining(len), mColorAdjustment(color_adjustment) {
162 mAdvance = 3;
163 initOffsets(len);
164 }
165
172 const CRGB &d, int len, ColorAdjustment color_adjustment, EDitherMode dither)
173 : mData((const uint8_t*)&d), mLen(len), mLenRemaining(len), mColorAdjustment(color_adjustment) {
175 mAdvance = 0;
176 initOffsets(len);
177 }
178
179 #if FASTLED_HD_COLOR_MIXING
180 uint8_t global_brightness() const {
181 return mColorAdjustment.brightness;
182 }
183 #endif
184
185
186#if !defined(NO_DITHERING) || (NO_DITHERING != 1)
187
189#define MAX_LIKELY_UPDATE_RATE_HZ 400
190
192#define MIN_ACCEPTABLE_DITHER_RATE_HZ 50
193
195#define UPDATES_PER_FULL_DITHER_CYCLE (MAX_LIKELY_UPDATE_RATE_HZ / MIN_ACCEPTABLE_DITHER_RATE_HZ)
196
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) )
218
220#define VIRTUAL_BITS RECOMMENDED_VIRTUAL_BITS
221
222#endif
223
224
227#if !defined(NO_DITHERING) || (NO_DITHERING != 1)
228 // R is the digther signal 'counter'.
229 static uint8_t R = 0;
230 ++R;
231
232 // R is wrapped around at 2^ditherBits,
233 // so if ditherBits is 2, R will cycle through (0,1,2,3)
234 uint8_t ditherBits = VIRTUAL_BITS;
235 R &= (0x01 << ditherBits) - 1;
236
237 // Q is the "unscaled dither signal" itself.
238 // It's initialized to the reversed bits of R.
239 // If 'ditherBits' is 2, Q here will cycle through (0,128,64,192)
240 uint8_t Q = 0;
241
242 // Reverse bits in a byte
243 {
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; }
252 }
253
254 // Now we adjust Q to fall in the center of each range,
255 // instead of at the start of the range.
256 // If ditherBits is 2, Q will be (0, 128, 64, 192) at first,
257 // and this adjustment makes it (31, 159, 95, 223).
258 if( ditherBits < 8) {
259 Q += 0x01 << (7 - ditherBits);
260 }
261
262 // D and E form the "scaled dither signal"
263 // which is added to pixel values to affect the
264 // actual dithering.
265
266 // Setup the initial D and E values
267 for(int i = 0; i < 3; ++i) {
268 uint8_t s = mColorAdjustment.premixed.raw[i];
269 e[i] = s ? (256/s) + 1 : 0;
270 d[i] = scale8(Q, e[i]);
271#if (FASTLED_SCALE8_FIXED == 1)
272 if(d[i]) (--d[i]);
273#endif
274 if(e[i]) --e[i];
275 }
276#endif
277 }
278
282 FASTLED_FORCE_INLINE bool has(int n) {
283 return mLenRemaining >= n;
284 }
285
291 void enable_dithering(EDitherMode dither) {
292 switch(dither) {
293 case BINARY_DITHER: init_binary_dithering(); break;
294 default: d[0]=d[1]=d[2]=e[0]=e[1]=e[2]=0; break;
295 }
296 }
297
300 FASTLED_FORCE_INLINE int size() { return mLen; }
301
304 FASTLED_FORCE_INLINE int lanes() { return LANES; }
305
308 FASTLED_FORCE_INLINE int advanceBy() { return mAdvance; }
309
311 FASTLED_FORCE_INLINE void advanceData() { mData += mAdvance; --mLenRemaining;}
312
315 FASTLED_FORCE_INLINE void stepDithering() {
316 // IF UPDATING HERE, BE SURE TO UPDATE THE ASM VERSION IN
317 // clockless_trinket.h!
318 d[0] = e[0] - d[0];
319 d[1] = e[1] - d[1];
320 d[2] = e[2] - d[2];
321 }
322
324 FASTLED_FORCE_INLINE void preStepFirstByteDithering() {
325 d[RO(0)] = e[RO(0)] - d[RO(0)];
326 }
327
331
335 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadByte(PixelController & pc) { return pc.mData[RO(SLOT)]; }
336
341 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadByte(PixelController & pc, int lane) { return pc.mData[pc.mOffsets[lane] + RO(SLOT)]; }
342
348 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t dither(PixelController & pc, uint8_t b) { return b ? qadd8(b, pc.d[RO(SLOT)]) : 0; }
349
354 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t dither(PixelController & , uint8_t b, uint8_t d) { return b ? qadd8(b,d) : 0; }
355
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)]); }
362
367 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t scale(PixelController & , uint8_t b, uint8_t scale) { return scale8(b, scale); }
368
374
375
379 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadAndScale(PixelController & pc) { return scale<SLOT>(pc, pc.dither<SLOT>(pc, pc.loadByte<SLOT>(pc))); }
380
385 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadAndScale(PixelController & pc, int lane) { return scale<SLOT>(pc, pc.dither<SLOT>(pc, pc.loadByte<SLOT>(pc, lane))); }
386
393 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadAndScale(PixelController & pc, int lane, uint8_t d, uint8_t scale) { return scale8(pc.dither<SLOT>(pc, pc.loadByte<SLOT>(pc, lane), d), scale); }
394
400 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t loadAndScale(PixelController & pc, int lane, uint8_t scale) { return scale8(pc.loadByte<SLOT>(pc, lane), scale); }
401
402
405 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t advanceAndLoadAndScale(PixelController & pc) { pc.advanceData(); return pc.loadAndScale<SLOT>(pc); }
406
410 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t advanceAndLoadAndScale(PixelController & pc, int lane) { pc.advanceData(); return pc.loadAndScale<SLOT>(pc, lane); }
411
416 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t advanceAndLoadAndScale(PixelController & pc, int lane, uint8_t scale) { pc.advanceData(); return pc.loadAndScale<SLOT>(pc, lane, scale); }
417
419
420
425
431 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t getd(PixelController & pc) { return pc.d[RO(SLOT)]; }
432
438 template<int SLOT> FASTLED_FORCE_INLINE static uint8_t getscale(PixelController & pc) { return pc.mColorAdjustment.premixed.raw[RO(SLOT)]; }
439
441
442
444
445 // Helper functions to get around gcc stupidities
446 FASTLED_FORCE_INLINE uint8_t loadAndScale0(int lane, uint8_t scale) { return loadAndScale<0>(*this, lane, scale); }
447 FASTLED_FORCE_INLINE uint8_t loadAndScale1(int lane, uint8_t scale) { return loadAndScale<1>(*this, lane, scale); }
448 FASTLED_FORCE_INLINE uint8_t loadAndScale2(int lane, uint8_t scale) { return loadAndScale<2>(*this, lane, scale); }
449 FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0(int lane, uint8_t scale) { return advanceAndLoadAndScale<0>(*this, lane, scale); }
450 FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0(int lane, uint8_t scale) { stepDithering(); return advanceAndLoadAndScale<0>(*this, lane, scale); }
451
452 FASTLED_FORCE_INLINE uint8_t loadAndScale0(int lane) { return loadAndScale<0>(*this, lane); }
453 FASTLED_FORCE_INLINE uint8_t loadAndScale1(int lane) { return loadAndScale<1>(*this, lane); }
454 FASTLED_FORCE_INLINE uint8_t loadAndScale2(int lane) { return loadAndScale<2>(*this, lane); }
455 FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0(int lane) { return advanceAndLoadAndScale<0>(*this, lane); }
456 FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0(int lane) { stepDithering(); return advanceAndLoadAndScale<0>(*this, lane); }
457
458 // LoadAndScale0 loads the pixel data in the order specified by RGB_ORDER and then scales it by the color correction values
459 // For example in color order GRB, loadAndScale0() will return the green channel scaled by the color correction value for green.
460 FASTLED_FORCE_INLINE uint8_t loadAndScale0() { return loadAndScale<0>(*this); }
461 FASTLED_FORCE_INLINE uint8_t loadAndScale1() { return loadAndScale<1>(*this); }
462 FASTLED_FORCE_INLINE uint8_t loadAndScale2() { return loadAndScale<2>(*this); }
463 FASTLED_FORCE_INLINE uint8_t advanceAndLoadAndScale0() { return advanceAndLoadAndScale<0>(*this); }
464 FASTLED_FORCE_INLINE uint8_t stepAdvanceAndLoadAndScale0() { stepDithering(); return advanceAndLoadAndScale<0>(*this); }
465
466 FASTLED_FORCE_INLINE uint8_t getScale0() { return getscale<0>(*this); }
467 FASTLED_FORCE_INLINE uint8_t getScale1() { return getscale<1>(*this); }
468 FASTLED_FORCE_INLINE uint8_t getScale2() { return getscale<2>(*this); }
469
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)]; }
472 // Gets the color corection and also the brightness as seperate values.
473 // This is needed for the higher precision chipsets like the APA102.
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;
479 }
480 #endif
481
482
483 FASTLED_FORCE_INLINE void loadAndScale_APA102_HD(uint8_t *b0_out, uint8_t *b1_out,
484 uint8_t *b2_out,
485 uint8_t *brightness_out) {
486 CRGB rgb = CRGB(mData[0], mData[1], mData[2]);
487 uint8_t brightness = 0;
488 if (rgb) {
489 #if FASTLED_HD_COLOR_MIXING
490 brightness = mColorAdjustment.brightness;
491 CRGB scale = mColorAdjustment.color;
492 #else
493 brightness = 255;
494 CRGB scale = mColorAdjustment.premixed;
495 #endif
496 five_bit_hd_gamma_bitshift(
497 rgb,
498 scale,
499 brightness,
500 &rgb,
501 &brightness);
502 }
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;
510 }
511
512 FASTLED_FORCE_INLINE void loadAndScaleRGB(uint8_t *b0_out, uint8_t *b1_out,
513 uint8_t *b2_out) {
514 *b0_out = loadAndScale0();
515 *b1_out = loadAndScale1();
516 *b2_out = loadAndScale2();
517 }
518
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) {
521#ifdef __AVR__
522 // Don't do RGBW conversion for AVR, just set the W pixel to black.
523 uint8_t out[4] = {
524 // Get the pixels in native order.
528 0,
529 };
530 EOrderW w_placement = rgbw.w_placement;
531 // Apply w-component insertion.
532 rgbw_partial_reorder(
533 w_placement, out[0], out[1], out[2],
534 0, // Pre-ordered RGB data with a 0 white component.
535 b0_out, b1_out, b2_out, b3_out);
536#else
537 const uint8_t b0_index = RGB_BYTE0(RGB_ORDER); // Needed to re-order RGB back into led native order.
538 const uint8_t b1_index = RGB_BYTE1(RGB_ORDER);
539 const uint8_t b2_index = RGB_BYTE2(RGB_ORDER);
540 // Get the naive RGB data order in r,g,b order.
541 CRGB rgb(mData[0], mData[1], mData[2]);
542 uint8_t w = 0;
543 rgb_2_rgbw(rgbw.rgbw_mode,
544 rgbw.white_color_temp,
545 rgb.r, rgb.b, rgb.g, // Input colors
546 mColorAdjustment.premixed.r, mColorAdjustment.premixed.g, mColorAdjustment.premixed.b, // How these colors are scaled for color balance.
547 &rgb.r, &rgb.g, &rgb.b, &w);
548 // Now finish the ordering so that the output is in the native led order for all of RGBW.
549 rgbw_partial_reorder(
550 rgbw.w_placement,
551 rgb.raw[b0_index], // in-place re-ordering for the RGB data.
552 rgb.raw[b1_index],
553 rgb.raw[b2_index],
554 w, // The white component is not ordered in this call.
555 b0_out, b1_out, b2_out, b3_out); // RGBW data now in total native led order.
556#endif
557 }
558};
559
560
561FASTLED_NAMESPACE_END
562
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.
Definition math8.h:31
uint8_t raw[3]
Access the red, green, and blue data as an array.
Definition crgb.h:60
uint8_t r
Red channel value.
Definition crgb.h:43
uint8_t g
Green channel value.
Definition crgb.h:47
uint8_t b
Blue channel value.
Definition crgb.h:51
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 ...
Definition scale8.h:34
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:39
Pixel controller class.
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>()
Definition rgbw.h:25