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