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