FastLED 3.9.15
Loading...
Searching...
No Matches
pixel_iterator.h
Go to the documentation of this file.
1
3
4#pragma once
5
6#include "fl/stdint.h"
7#include "fl/string.h"
8
9
10#include "rgbw.h"
11
12#include "crgb.h"
13
14namespace fl {
15
16#ifndef FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
17// Takes more memory, so disable by default.
18#define FASTLED_PIXEL_ITERATOR_HAS_APA102_HD 0
19#endif
20
21// Due to to the template nature of the PixelController class, the only way we can make
22// it a concrete polymorphic class is to manually bind the functions and make our own
23// vtable. The PixelControllerVtable is cheaper than doing fl::function<>.
24template<typename PixelControllerT>
26 static void loadAndScaleRGBW(void* pixel_controller, Rgbw rgbw, uint8_t* b0_out, uint8_t* b1_out, uint8_t* b2_out, uint8_t* b3_out) {
27 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
28 pc->loadAndScaleRGBW(rgbw, b0_out, b1_out, b2_out, b3_out);
29 }
30
31 static void loadAndScaleRGB(void* pixel_controller, uint8_t* r_out, uint8_t* g_out, uint8_t* b_out) {
32 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
33 pc->loadAndScaleRGB(r_out, g_out, b_out);
34 }
35
36 #if FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
37
38 static void loadAndScale_APA102_HD(void* pixel_controller, uint8_t* b0_out, uint8_t* b1_out, uint8_t* b2_out, uint8_t* brightness_out) {
39 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
40 pc->loadAndScale_APA102_HD(b0_out, b1_out, b2_out, brightness_out);
41 }
42
43 #endif
44
45 static void loadAndScale_WS2816_HD(void* pixel_controller, uint16_t *s0_out, uint16_t* s1_out, uint16_t* s2_out) {
46 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
47 pc->loadAndScale_WS2816_HD(s0_out, s1_out, s2_out);
48 }
49
50 static void stepDithering(void* pixel_controller) {
51 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
52 pc->stepDithering();
53 }
54
55 static void advanceData(void* pixel_controller) {
56 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
57 pc->advanceData();
58 }
59
60 static int size(void* pixel_controller) {
61 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
62 return pc->size();
63 }
64 static bool has(void* pixel_controller, int n) {
65 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
66 return pc->has(n);
67 }
68
69 // function for getHdScale
70 #if FASTLED_HD_COLOR_MIXING
71 static void getHdScale(void* pixel_controller, uint8_t* c0, uint8_t* c1, uint8_t* c2, uint8_t* brightness) {
72 PixelControllerT* pc = static_cast<PixelControllerT*>(pixel_controller);
73 pc->getHdScale(c0, c1, c2, brightness);
74 }
75 #endif
76};
77
78typedef void (*loadAndScaleRGBWFunction)(void* pixel_controller, Rgbw rgbw, uint8_t* b0_out, uint8_t* b1_out, uint8_t* b2_out, uint8_t* b3_out);
79typedef void (*loadAndScaleRGBFunction)(void* pixel_controller, uint8_t* r_out, uint8_t* g_out, uint8_t* b_out);
80#if FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
81typedef void (*loadAndScale_APA102_HDFunction)(void* pixel_controller, uint8_t* b0_out, uint8_t* b1_out, uint8_t* b2_out, uint8_t* brightness_out);
82#endif
83typedef void (*loadAndScale_WS2816_HDFunction)(void* pixel_controller, uint16_t* b0_out, uint16_t* b1_out, uint16_t* b2_out);
84typedef void (*stepDitheringFunction)(void* pixel_controller);
85typedef void (*advanceDataFunction)(void* pixel_controller);
86typedef int (*sizeFunction)(void* pixel_controller);
87typedef bool (*hasFunction)(void* pixel_controller, int n);
88typedef uint8_t (*globalBrightness)(void* pixel_controller);
89typedef void (*getHdScaleFunction)(void* pixel_controller, uint8_t* c0, uint8_t* c1, uint8_t* c2, uint8_t* brightness);
90
91
92// PixelIterator is turns a PixelController<> into a concrete object that can be used to iterate
93// over pixels and transform them into driver data. See PixelController<>::as_iterator() for how
94// to create a PixelIterator.
95// Note: This is designed for micro-controllers with a lot of memory. DO NOT use this in the core library
96// as a PixelIterator consumes a *lot* more instruction data than an instance of PixelController<RGB_ORDER>.
97// This iterator is designed for code in src/platforms/**.
99 public:
100 template<typename PixelControllerT>
101 PixelIterator(PixelControllerT* pc, Rgbw rgbw)
102 : mPixelController(pc), mRgbw(rgbw) {
103 // Manually build up a vtable.
104 // Wait... what? Stupid nerds trying to show off how smart they are...
105 // Why not just use a virtual function?!
106 //
107 // Before you think this then you should know that the alternative straight
108 // forward way is to have a virtual interface class that PixelController inherits from.
109 // ...and that was already tried. And if you try to do this yourself
110 // this then let me tell you what is going to happen...
111 //
112 // EVERY SINGLE PLATFORM THAT HAS A COMPILED BINARY SIZE CHECK WILL IMMEDIATELY
113 // FAIL AS THE BINARY BLOWS UP BY 10-30%!!! It doesn't matter if only one PixelController
114 // with a vtable is used, gcc seems not to de-virtualize the calls. And we really care
115 // about binary size since FastLED needs to run on those tiny little microcontrollers like
116 // the Attiny85 (and family) which are in the sub $1 range used for commercial products.
117 //
118 // So to satisfy these tight memory requirements we make the dynamic dispatch used in PixelIterator
119 // an optional zero-cost abstraction which doesn't affect the binary size for platforms that
120 // don't use it. So that's why we are using this manual construction of the vtable that is built
121 // up using template magic. If your platform has lots of memory then you'll gladly trade
122 // a sliver of memory for the convenience of having a concrete implementation of
123 // PixelController that you can use without having to make all your driver code a template.
124 //
125 // Btw, this pattern in C++ is called the "type-erasure pattern". It allows non virtual
126 // polymorphism by leveraging the C++ template system to ensure type safety.
128 mLoadAndScaleRGBW = &Vtable::loadAndScaleRGBW;
129 mLoadAndScaleRGB = &Vtable::loadAndScaleRGB;
130 #if FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
131 mLoadAndScale_APA102_HD = &Vtable::loadAndScale_APA102_HD;
132 #endif
133 mLoadAndScale_WS2816_HD = &Vtable::loadAndScale_WS2816_HD;
134 mStepDithering = &Vtable::stepDithering;
135 mAdvanceData = &Vtable::advanceData;
136 mSize = &Vtable::size;
137 mHas = &Vtable::has;
138 #if FASTLED_HD_COLOR_MIXING
139 mGetHdScale = &Vtable::getHdScale;
140 #endif
141 }
142
143 bool has(int n) { return mHas(mPixelController, n); }
144 void loadAndScaleRGBW(uint8_t *b0_out, uint8_t *b1_out, uint8_t *b2_out, uint8_t *w_out) {
145 mLoadAndScaleRGBW(mPixelController, mRgbw, b0_out, b1_out, b2_out, w_out);
146 }
147 void loadAndScaleRGB(uint8_t *r_out, uint8_t *g_out, uint8_t *b_out) {
148 mLoadAndScaleRGB(mPixelController, r_out, g_out, b_out);
149 }
150 #if FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
151 void loadAndScale_APA102_HD(uint8_t *b0_out, uint8_t *b1_out, uint8_t *b2_out, uint8_t *brightness_out) {
152 mLoadAndScale_APA102_HD(mPixelController, b0_out, b1_out, b2_out, brightness_out);
153 }
154 #endif
155 void loadAndScale_WS2816_HD(uint16_t *s0_out, uint16_t *s1_out, uint16_t *s2_out) {
156 mLoadAndScale_WS2816_HD(mPixelController, s0_out, s1_out, s2_out);
157 }
160 int size() { return mSize(mPixelController); }
161
163 Rgbw get_rgbw() const { return mRgbw; }
164
165 #if FASTLED_HD_COLOR_MIXING
166 void getHdScale(uint8_t* c0, uint8_t* c1, uint8_t* c2, uint8_t* brightness) {
167 mGetHdScale(mPixelController, c0, c1, c2, brightness);
168 }
169 #endif
170
171 private:
172 // vtable emulation
173 void* mPixelController = nullptr;
177 #if FASTLED_PIXEL_ITERATOR_HAS_APA102_HD
178 loadAndScale_APA102_HDFunction mLoadAndScale_APA102_HD = nullptr;
179 #endif
184 hasFunction mHas = nullptr;
185 #if FASTLED_HD_COLOR_MIXING
186 getHdScaleFunction mGetHdScale = nullptr;
187 #endif
188};
189
190} // namespace
191
192
Rgbw rgbw
UISlider brightness("Brightness", 128, 0, 255, 1)
loadAndScale_WS2816_HDFunction mLoadAndScale_WS2816_HD
void loadAndScaleRGBW(uint8_t *b0_out, uint8_t *b1_out, uint8_t *b2_out, uint8_t *w_out)
stepDitheringFunction mStepDithering
void set_rgbw(Rgbw rgbw)
advanceDataFunction mAdvanceData
loadAndScaleRGBFunction mLoadAndScaleRGB
void loadAndScale_WS2816_HD(uint16_t *s0_out, uint16_t *s1_out, uint16_t *s2_out)
void loadAndScaleRGB(uint8_t *r_out, uint8_t *g_out, uint8_t *b_out)
loadAndScaleRGBWFunction mLoadAndScaleRGBW
PixelIterator(PixelControllerT *pc, Rgbw rgbw)
Rgbw get_rgbw() const
Defines the red, green, and blue (RGB) pixel struct.
void(* loadAndScale_WS2816_HDFunction)(void *pixel_controller, uint16_t *b0_out, uint16_t *b1_out, uint16_t *b2_out)
void(* stepDitheringFunction)(void *pixel_controller)
uint8_t(* globalBrightness)(void *pixel_controller)
int(* sizeFunction)(void *pixel_controller)
bool(* hasFunction)(void *pixel_controller, int n)
void(* getHdScaleFunction)(void *pixel_controller, uint8_t *c0, uint8_t *c1, uint8_t *c2, uint8_t *brightness)
void(* advanceDataFunction)(void *pixel_controller)
void(* loadAndScaleRGBWFunction)(void *pixel_controller, Rgbw rgbw, uint8_t *b0_out, uint8_t *b1_out, uint8_t *b2_out, uint8_t *b3_out)
void(* loadAndScaleRGBFunction)(void *pixel_controller, uint8_t *r_out, uint8_t *g_out, uint8_t *b_out)
IMPORTANT!
Definition crgb.h:20
fl::PixelIterator PixelIterator
Functions for red, green, blue, white (RGBW) output.
static void loadAndScaleRGBW(void *pixel_controller, Rgbw rgbw, uint8_t *b0_out, uint8_t *b1_out, uint8_t *b2_out, uint8_t *b3_out)
static void stepDithering(void *pixel_controller)
static bool has(void *pixel_controller, int n)
static void loadAndScaleRGB(void *pixel_controller, uint8_t *r_out, uint8_t *g_out, uint8_t *b_out)
static void advanceData(void *pixel_controller)
static int size(void *pixel_controller)
static void loadAndScale_WS2816_HD(void *pixel_controller, uint16_t *s0_out, uint16_t *s1_out, uint16_t *s2_out)