8
8
#define RO (X ) RGB_BYTE(RGB_ORDER, X)
9
9
#define RGB_BYTE (RO,X ) (((RO)>>(3 *(2 -(X)))) & 0x3 )
10
10
11
- #define RGB_BYTE0 (RO ) ((RO>>6 ) & 0x3 )
12
- #define RGB_BYTE1 (RO ) ((RO>>3 ) & 0x3 )
11
+ #define RGB_BYTE0 (RO ) ((RO>>6 ) & 0x3 )
12
+ #define RGB_BYTE1 (RO ) ((RO>>3 ) & 0x3 )
13
13
#define RGB_BYTE2 (RO ) ((RO) & 0x3 )
14
14
15
15
// operator byte *(struct CRGB[] arr) { return (byte*)arr; }
19
19
typedef uint8_t EDitherMode;
20
20
21
21
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
22
- //
22
+ //
23
23
// LED Controller interface definition
24
24
//
25
25
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
26
26
27
- // / Base definition for an LED controller. Pretty much the methods that every LED controller object will make available.
27
+ // / Base definition for an LED controller. Pretty much the methods that every LED controller object will make available.
28
28
// / Note that the showARGB method is not impelemented for all controllers yet. Note also the methods for eventual checking
29
29
// / of background writing of data (I'm looking at you, teensy 3.0 DMA controller!). If you want to pass LED controllers around
30
30
// / to methods, make them references to this type, keeps your code saner. However, most people won't be seeing/using these objects
31
31
// / directly at all
32
- class CLEDController {
32
+ class CLEDController {
33
33
protected:
34
34
friend class CFastLED ;
35
- const CRGB *m_Data;
35
+ CRGB *m_Data;
36
36
CLEDController *m_pNext;
37
37
CRGB m_ColorCorrection;
38
38
CRGB m_ColorTemperature;
@@ -44,7 +44,7 @@ class CLEDController {
44
44
// set all the leds on the controller to a given color
45
45
virtual void showColor (const struct CRGB & data, int nLeds, CRGB scale) = 0;
46
46
47
- // note that the uint8_ts will be in the order that you want them sent out to the device.
47
+ // note that the uint8_ts will be in the order that you want them sent out to the device.
48
48
// nLeds is the number of RGB leds being written to
49
49
virtual void show (const struct CRGB *data, int nLeds, CRGB scale) = 0;
50
50
@@ -77,11 +77,11 @@ class CLEDController {
77
77
}
78
78
79
79
// show function using the "attached to this controller" led data
80
- void showLeds (uint8_t brightness=255 ) {
80
+ void showLeds (uint8_t brightness=255 ) {
81
81
show (m_Data, m_nLeds, getAdjustment (brightness));
82
82
}
83
83
84
- void showColor (const struct CRGB & data, uint8_t brightness=255 ) {
84
+ void showColor (const struct CRGB & data, uint8_t brightness=255 ) {
85
85
showColor (data, m_nLeds, getAdjustment (brightness));
86
86
}
87
87
@@ -95,19 +95,28 @@ class CLEDController {
95
95
show (data, nLeds, getAdjustment (brightness))
96
96
}
97
97
#endif
98
-
99
- CLEDController & setLeds (const CRGB *data, int nLeds) {
98
+
99
+ CLEDController & setLeds (CRGB *data, int nLeds) {
100
100
m_Data = data;
101
101
m_nLeds = nLeds;
102
102
return *this ;
103
103
}
104
104
105
105
void clearLedData () {
106
- if (m_Data) {
106
+ if (m_Data) {
107
107
memset8 ((void *)m_Data, 0 , sizeof (struct CRGB ) * m_nLeds);
108
108
}
109
109
}
110
110
111
+ // How many leds does this controller manage?
112
+ int size () { return m_nLeds; }
113
+
114
+ // Pointer to the CRGB array for this controller
115
+ CRGB* leds () { return m_Data; }
116
+
117
+ // Reference to the n'th item in the controller
118
+ CRGB &operator [](int x) { return m_Data[x]; }
119
+
111
120
inline CLEDController & setDither (uint8_t ditherMode = BINARY_DITHER) { m_DitherMode = ditherMode; return *this ; }
112
121
inline uint8_t getDither () { return m_DitherMode; }
113
122
@@ -119,17 +128,17 @@ class CLEDController {
119
128
CLEDController & setTemperature (ColorTemperature temperature) { m_ColorTemperature = temperature; return *this ; }
120
129
CRGB getTemperature () { return m_ColorTemperature; }
121
130
122
- CRGB getAdjustment (uint8_t scale) {
131
+ CRGB getAdjustment (uint8_t scale) {
123
132
#if defined(NO_CORRECTION) && (NO_CORRECTION==1)
124
133
return CRGB (scale,scale,scale);
125
134
#else
126
135
CRGB adj (0 ,0 ,0 );
127
136
128
- if (scale > 0 ) {
129
- for (uint8_t i = 0 ; i < 3 ; i++) {
137
+ if (scale > 0 ) {
138
+ for (uint8_t i = 0 ; i < 3 ; i++) {
130
139
uint8_t cc = m_ColorCorrection.raw [i];
131
140
uint8_t ct = m_ColorTemperature.raw [i];
132
- if (cc > 0 && ct > 0 ) {
141
+ if (cc > 0 && ct > 0 ) {
133
142
uint32_t work = (((uint32_t )cc)+1 ) * (((uint32_t )ct)+1 ) * scale;
134
143
work /= 0x10000L ;
135
144
adj.raw [i] = work & 0xFF ;
@@ -143,11 +152,11 @@ class CLEDController {
143
152
};
144
153
145
154
// Pixel controller class. This is the class that we use to centralize pixel access in a block of data, including
146
- // support for things like RGB reordering, scaling, dithering, skipping (for ARGB data), and eventually, we will
155
+ // support for things like RGB reordering, scaling, dithering, skipping (for ARGB data), and eventually, we will
147
156
// centralize 8/12/16 conversions here as well.
148
157
template <EOrder RGB_ORDER>
149
158
struct PixelController {
150
- const uint8_t *mData ;
159
+ const uint8_t *mData ;
151
160
int mLen ;
152
161
uint8_t d[3 ];
153
162
uint8_t e[3 ];
@@ -186,7 +195,7 @@ struct PixelController {
186
195
#ifdef SUPPORT_ARGB
187
196
PixelController (const CARGB &d, int len, CRGB & s, EDitherMode dither = BINARY_DITHER) : mData((const uint8_t *)&d), mLen(len), mScale(s) {
188
197
enable_dithering (dither);
189
- // skip the A in CARGB
198
+ // skip the A in CARGB
190
199
mData += 1 ;
191
200
mAdvance = 0 ;
192
201
}
@@ -195,7 +204,7 @@ struct PixelController {
195
204
enable_dithering (dither);
196
205
// skip the A in CARGB
197
206
mData += 1 ;
198
- mAdvance = 4 ;
207
+ mAdvance = 4 ;
199
208
}
200
209
#endif
201
210
@@ -239,7 +248,7 @@ struct PixelController {
239
248
// It's initialized to the reversed bits of R.
240
249
// If 'ditherBits' is 2, Q here will cycle through (0,128,64,192)
241
250
byte Q = 0 ;
242
-
251
+
243
252
// Reverse bits in a byte
244
253
{
245
254
if (R & 0x01 ) { Q |= 0x80 ; }
@@ -251,21 +260,21 @@ struct PixelController {
251
260
if (R & 0x40 ) { Q |= 0x02 ; }
252
261
if (R & 0x80 ) { Q |= 0x01 ; }
253
262
}
254
-
263
+
255
264
// Now we adjust Q to fall in the center of each range,
256
265
// instead of at the start of the range.
257
266
// If ditherBits is 2, Q will be (0, 128, 64, 192) at first,
258
267
// and this adjustment makes it (31, 159, 95, 223).
259
268
if ( ditherBits < 8 ) {
260
269
Q += 0x01 << (7 - ditherBits);
261
270
}
262
-
271
+
263
272
// D and E form the "scaled dither signal"
264
273
// which is added to pixel values to affect the
265
274
// actual dithering.
266
-
275
+
267
276
// Setup the initial D and E values
268
- for (int i = 0 ; i < 3 ; i++) {
277
+ for (int i = 0 ; i < 3 ; i++) {
269
278
byte s = mScale .raw [i];
270
279
e[i] = s ? (256 /s) + 1 : 0 ;
271
280
d[i] = scale8 (Q, e[i]);
@@ -275,10 +284,10 @@ struct PixelController {
275
284
}
276
285
277
286
// Do we have n pixels left to process?
278
- __attribute__ ((always_inline)) inline bool has (int n) {
287
+ __attribute__ ((always_inline)) inline bool has (int n) {
279
288
return mLen >= n;
280
289
}
281
-
290
+
282
291
// toggle dithering enable
283
292
void enable_dithering (EDitherMode dither) {
284
293
switch (dither) {
@@ -287,23 +296,23 @@ struct PixelController {
287
296
}
288
297
}
289
298
290
- // get the amount to advance the pointer by
299
+ // get the amount to advance the pointer by
291
300
__attribute__ ((always_inline)) inline int advanceBy () { return mAdvance ; }
292
-
301
+
293
302
// advance the data pointer forward, adjust position counter
294
303
__attribute__ ((always_inline)) inline void advanceData () { mData += mAdvance ; mLen --;}
295
304
296
- // step the dithering forward
305
+ // step the dithering forward
297
306
__attribute__ ((always_inline)) inline void stepDithering () {
298
- // IF UPDATING HERE, BE SURE TO UPDATE THE ASM VERSION IN
307
+ // IF UPDATING HERE, BE SURE TO UPDATE THE ASM VERSION IN
299
308
// clockless_trinket.h!
300
309
d[0 ] = e[0 ] - d[0 ];
301
310
d[1 ] = e[1 ] - d[1 ];
302
311
d[2 ] = e[2 ] - d[2 ];
303
312
}
304
313
305
314
// Some chipsets pre-cycle the first byte, which means we want to cycle byte 0's dithering separately
306
- __attribute__ ((always_inline)) inline void preStepFirstByteDithering () {
315
+ __attribute__ ((always_inline)) inline void preStepFirstByteDithering () {
307
316
d[RO (0 )] = e[RO (0 )] - d[RO (0 )];
308
317
}
309
318
@@ -316,11 +325,11 @@ struct PixelController {
316
325
template <int SLOT> __attribute__ ((always_inline)) inline static uint8_t advanceAndLoadAndScale(PixelController & pc) { pc.advanceData (); return pc.loadAndScale <SLOT>(pc); }
317
326
318
327
// Helper functions to get around gcc stupidities
319
- __attribute__ ((always_inline)) inline uint8_t loadAndScale0 () { return loadAndScale<0 >(*this ); }
320
- __attribute__ ((always_inline)) inline uint8_t loadAndScale1 () { return loadAndScale<1 >(*this ); }
321
- __attribute__ ((always_inline)) inline uint8_t loadAndScale2 () { return loadAndScale<2 >(*this ); }
322
- __attribute__ ((always_inline)) inline uint8_t advanceAndLoadAndScale0 () { return advanceAndLoadAndScale<0 >(*this ); }
323
- __attribute__ ((always_inline)) inline uint8_t stepAdvanceAndLoadAndScale0 () { stepDithering (); return advanceAndLoadAndScale<0 >(*this ); }
328
+ __attribute__ ((always_inline)) inline uint8_t loadAndScale0 () { return loadAndScale<0 >(*this ); }
329
+ __attribute__ ((always_inline)) inline uint8_t loadAndScale1 () { return loadAndScale<1 >(*this ); }
330
+ __attribute__ ((always_inline)) inline uint8_t loadAndScale2 () { return loadAndScale<2 >(*this ); }
331
+ __attribute__ ((always_inline)) inline uint8_t advanceAndLoadAndScale0 () { return advanceAndLoadAndScale<0 >(*this ); }
332
+ __attribute__ ((always_inline)) inline uint8_t stepAdvanceAndLoadAndScale0 () { stepDithering (); return advanceAndLoadAndScale<0 >(*this ); }
324
333
};
325
334
326
- #endif
335
+ #endif
0 commit comments