1/*--------------------------------------------------------------------
2 This file is part of the Adafruit NeoPixel library.
3
4 NeoPixel is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of
7 the License, or (at your option) any later version.
8
9 NeoPixel is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with NeoPixel. If not, see
16 <http://www.gnu.org/licenses/>.
17 --------------------------------------------------------------------*/
18
19#ifndef ADAFRUIT_NEOPIXEL_H
20#define ADAFRUIT_NEOPIXEL_H
21
22#if (ARDUINO >= 100)
23 #include <Arduino.h>
24#else
25 #include <WProgram.h>
26 #include <pins_arduino.h>
27#endif
28
29// 'type' flags for LED pixels (third parameter to constructor):
30#define NEO_RGB 0x00 // Wired for RGB data order
31#define NEO_GRB 0x01 // Wired for GRB data order
32#define NEO_BRG 0x04
33
34#define NEO_COLMASK 0x01
35#define NEO_KHZ800 0x02 // 800 KHz datastream
36#define NEO_SPDMASK 0x02
37// Trinket flash space is tight, v1 NeoPixels aren't handled by default.
38// Remove the ifndef/endif to add support -- but code will be bigger.
39// Conversely, can comment out the #defines to save space on other MCUs.
40#ifndef __AVR_ATtiny85__
41#define NEO_KHZ400 0x00 // 400 KHz datastream
42#endif
43
44class MitovEmbedded_Adafruit_NeoPixel {
45
46 public:
47
48 // Constructor: number of LEDs, pin number, LED type
49 MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p=6, uint8_t t=NEO_GRB + NEO_KHZ800);
50 ~MitovEmbedded_Adafruit_NeoPixel();
51
52 void
53 begin(void),
54 show(void),
55 setPin(uint8_t p),
56 setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
57 setPixelColor(uint16_t n, uint32_t c),
58 setBrightness(uint8_t),
59 clear();
60 uint8_t
61 *getPixels(void) const,
62 getBrightness(void) const;
63 uint16_t
64 numPixels(void) const;
65 static uint32_t
66 Color(uint8_t r, uint8_t g, uint8_t b);
67 uint32_t
68 getPixelColor(uint16_t n) const;
69 inline bool
70 canShow(void) { return (micros() - endTime) >= 50L; }
71
72 private:
73
74 const uint16_t
75 numLEDs, // Number of RGB LEDs in strip
76 numBytes; // Size of 'pixels' buffer below
77 uint8_t
78 pin, // Output pin number
79 brightness,
80 *pixels, // Holds LED color values (3 bytes each)
81 rOffset, // Index of red byte within each 3-byte pixel
82 gOffset, // Index of green byte
83 bOffset; // Index of blue byte
84 const uint8_t
85 type; // Pixel flags (400 vs 800 KHz, RGB vs GRB color)
86 uint32_t
87 endTime; // Latch timing reference
88#ifdef __AVR__
89 const volatile uint8_t
90 *port; // Output PORT register
91 uint8_t
92 pinMask; // Output PORT bitmask
93#endif
94
95};
96
97MitovEmbedded_Adafruit_NeoPixel::MitovEmbedded_Adafruit_NeoPixel(uint16_t n, uint8_t p, uint8_t t) :
98 numLEDs(n), numBytes(n * 3), pin(p), brightness(0),
99 pixels(NULL), type(t), endTime(0)
100#ifdef __AVR__
101 ,port(portOutputRegister(digitalPinToPort(p))),
102 pinMask(digitalPinToBitMask(p))
103#endif
104{
105 if((pixels = (uint8_t *)malloc(numBytes))) {
106 memset(pixels, 0, numBytes);
107 }
108 if(t & NEO_GRB) { // GRB vs RGB; might add others if needed
109 rOffset = 1;
110 gOffset = 0;
111 bOffset = 2;
112 } else if (t & NEO_BRG) {
113 rOffset = 1;
114 gOffset = 2;
115 bOffset = 0;
116 } else {
117 rOffset = 0;
118 gOffset = 1;
119 bOffset = 2;
120 }
121
122}
123
124MitovEmbedded_Adafruit_NeoPixel::~MitovEmbedded_Adafruit_NeoPixel() {
125 if(pixels) free(pixels);
126 pinMode(pin, INPUT);
127}
128
129void MitovEmbedded_Adafruit_NeoPixel::begin(void) {
130 pinMode(pin, OUTPUT);
131 digitalWrite(pin, LOW);
132}
133
134void MitovEmbedded_Adafruit_NeoPixel::show(void) {
135
136 if(!pixels) return;
137
138 // Data latch = 50+ microsecond pause in the output stream. Rather than
139 // put a delay at the end of the function, the ending time is noted and
140 // the function will simply hold off (if needed) on issuing the
141 // subsequent round of data until the latch time has elapsed. This
142 // allows the mainline code to start generating the next frame of data
143 // rather than stalling for the latch.
144 while(!canShow());
145 // endTime is a private member (rather than global var) so that mutliple
146 // instances on different pins can be quickly issued in succession (each
147 // instance doesn't delay the next).
148
149 // In order to make this code runtime-configurable to work with any pin,
150 // SBI/CBI instructions are eschewed in favor of full PORT writes via the
151 // OUT or ST instructions. It relies on two facts: that peripheral
152 // functions (such as PWM) take precedence on output pins, so our PORT-
153 // wide writes won't interfere, and that interrupts are globally disabled
154 // while data is being issued to the LEDs, so no other code will be
155 // accessing the PORT. The code takes an initial 'snapshot' of the PORT
156 // state, computes 'pin high' and 'pin low' values, and writes these back
157 // to the PORT register as needed.
158
159 noInterrupts(); // Need 100% focus on instruction timing
160
161#ifdef __AVR__
162
163 volatile uint16_t
164 i = numBytes; // Loop counter
165 volatile uint8_t
166 *ptr = pixels, // Pointer to next byte
167 b = *ptr++, // Current byte value
168 hi, // PORT w/output bit set high
169 lo; // PORT w/output bit set low
170
171 // Hand-tuned assembly code issues data to the LED drivers at a specific
172 // rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
173 // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The
174 // datastream timing for the LED drivers allows a little wiggle room each
175 // way (listed in the datasheets), so the conditions for compiling each
176 // case are set up for a range of frequencies rather than just the exact
177 // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on
178 // devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based
179 // on the datasheet figures and have not been extensively tested outside
180 // the canonical 8/12/16 MHz speeds; there's no guarantee these will work
181 // close to the extremes (or possibly they could be pushed further).
182 // Keep in mind only one CPU speed case actually gets compiled; the
183 // resulting program isn't as massive as it might look from source here.
184
185// 8 MHz(ish) AVR ---------------------------------------------------------
186#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
187
188#ifdef NEO_KHZ400
189 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
190#endif
191
192 volatile uint8_t n1, n2 = 0; // First, next bits out
193
194 // Squeezing an 800 KHz stream out of an 8 MHz chip requires code
195 // specific to each PORT register. At present this is only written
196 // to work with pins on PORTD or PORTB, the most likely use case --
197 // this covers all the pins on the Adafruit Flora and the bulk of
198 // digital pins on the Arduino Pro 8 MHz (keep in mind, this code
199 // doesn't even get compiled for 16 MHz boards like the Uno, Mega,
200 // Leonardo, etc., so don't bother extending this out of hand).
201 // Additional PORTs could be added if you really need them, just
202 // duplicate the else and loop and change the PORT. Each add'l
203 // PORT will require about 150(ish) bytes of program space.
204
205 // 10 instruction clocks per bit: HHxxxxxLLL
206 // OUT instructions: ^ ^ ^ (T=0,2,7)
207
208#ifdef PORTD // PORTD isn't present on ATtiny85, etc.
209
210 if(port == &PORTD) {
211
212 hi = PORTD | pinMask;
213 lo = PORTD & ~pinMask;
214 n1 = lo;
215 if(b & 0x80) n1 = hi;
216
217 // Dirty trick: RJMPs proceeding to the next instruction are used
218 // to delay two clock cycles in one instruction word (rather than
219 // using two NOPs). This was necessary in order to squeeze the
220 // loop down to exactly 64 words -- the maximum possible for a
221 // relative branch.
222
223 asm volatile(
224 "headD:" "\n\t" // Clk Pseudocode
225 // Bit 7:
226 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
227 "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
228 "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
229 "rjmp .+0" "\n\t" // 2 nop nop
230 "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40)
231 "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
232 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
233 "rjmp .+0" "\n\t" // 2 nop nop
234 // Bit 6:
235 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
236 "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
237 "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
238 "rjmp .+0" "\n\t" // 2 nop nop
239 "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20)
240 "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
241 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
242 "rjmp .+0" "\n\t" // 2 nop nop
243 // Bit 5:
244 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
245 "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
246 "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
247 "rjmp .+0" "\n\t" // 2 nop nop
248 "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10)
249 "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
250 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
251 "rjmp .+0" "\n\t" // 2 nop nop
252 // Bit 4:
253 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
254 "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
255 "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
256 "rjmp .+0" "\n\t" // 2 nop nop
257 "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08)
258 "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
259 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
260 "rjmp .+0" "\n\t" // 2 nop nop
261 // Bit 3:
262 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
263 "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
264 "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
265 "rjmp .+0" "\n\t" // 2 nop nop
266 "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04)
267 "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
268 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
269 "rjmp .+0" "\n\t" // 2 nop nop
270 // Bit 2:
271 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
272 "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
273 "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
274 "rjmp .+0" "\n\t" // 2 nop nop
275 "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02)
276 "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
277 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
278 "rjmp .+0" "\n\t" // 2 nop nop
279 // Bit 1:
280 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
281 "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo
282 "out %[port] , %[n1]" "\n\t" // 1 PORT = n1
283 "rjmp .+0" "\n\t" // 2 nop nop
284 "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01)
285 "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi
286 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
287 "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet)
288 // Bit 0:
289 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi
290 "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo
291 "out %[port] , %[n2]" "\n\t" // 1 PORT = n2
292 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++
293 "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80)
294 "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi
295 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo
296 "brne headD" "\n" // 2 while(i) (Z flag set above)
297 : [byte] "+r" (b),
298 [n1] "+r" (n1),
299 [n2] "+r" (n2),
300 [count] "+w" (i)
301 : [port] "I" (_SFR_IO_ADDR(PORTD)),
302 [ptr] "e" (ptr),
303 [hi] "r" (hi),
304 [lo] "r" (lo));
305
306 } else if(port == &PORTB) {
307
308#endif // PORTD
309
310 // Same as above, just switched to PORTB and stripped of comments.
311 hi = PORTB | pinMask;
312 lo = PORTB & ~pinMask;
313 n1 = lo;
314 if(b & 0x80) n1 = hi;
315
316 asm volatile(
317 "headB:" "\n\t"
318 "out %[port] , %[hi]" "\n\t"
319 "mov %[n2] , %[lo]" "\n\t"
320 "out %[port] , %[n1]" "\n\t"
321 "rjmp .+0" "\n\t"
322 "sbrc %[byte] , 6" "\n\t"
323 "mov %[n2] , %[hi]" "\n\t"
324 "out %[port] , %[lo]" "\n\t"
325 "rjmp .+0" "\n\t"
326 "out %[port] , %[hi]" "\n\t"
327 "mov %[n1] , %[lo]" "\n\t"
328 "out %[port] , %[n2]" "\n\t"
329 "rjmp .+0" "\n\t"
330 "sbrc %[byte] , 5" "\n\t"
331 "mov %[n1] , %[hi]" "\n\t"
332 "out %[port] , %[lo]" "\n\t"
333 "rjmp .+0" "\n\t"
334 "out %[port] , %[hi]" "\n\t"
335 "mov %[n2] , %[lo]" "\n\t"
336 "out %[port] , %[n1]" "\n\t"
337 "rjmp .+0" "\n\t"
338 "sbrc %[byte] , 4" "\n\t"
339 "mov %[n2] , %[hi]" "\n\t"
340 "out %[port] , %[lo]" "\n\t"
341 "rjmp .+0" "\n\t"
342 "out %[port] , %[hi]" "\n\t"
343 "mov %[n1] , %[lo]" "\n\t"
344 "out %[port] , %[n2]" "\n\t"
345 "rjmp .+0" "\n\t"
346 "sbrc %[byte] , 3" "\n\t"
347 "mov %[n1] , %[hi]" "\n\t"
348 "out %[port] , %[lo]" "\n\t"
349 "rjmp .+0" "\n\t"
350 "out %[port] , %[hi]" "\n\t"
351 "mov %[n2] , %[lo]" "\n\t"
352 "out %[port] , %[n1]" "\n\t"
353 "rjmp .+0" "\n\t"
354 "sbrc %[byte] , 2" "\n\t"
355 "mov %[n2] , %[hi]" "\n\t"
356 "out %[port] , %[lo]" "\n\t"
357 "rjmp .+0" "\n\t"
358 "out %[port] , %[hi]" "\n\t"
359 "mov %[n1] , %[lo]" "\n\t"
360 "out %[port] , %[n2]" "\n\t"
361 "rjmp .+0" "\n\t"
362 "sbrc %[byte] , 1" "\n\t"
363 "mov %[n1] , %[hi]" "\n\t"
364 "out %[port] , %[lo]" "\n\t"
365 "rjmp .+0" "\n\t"
366 "out %[port] , %[hi]" "\n\t"
367 "mov %[n2] , %[lo]" "\n\t"
368 "out %[port] , %[n1]" "\n\t"
369 "rjmp .+0" "\n\t"
370 "sbrc %[byte] , 0" "\n\t"
371 "mov %[n2] , %[hi]" "\n\t"
372 "out %[port] , %[lo]" "\n\t"
373 "sbiw %[count], 1" "\n\t"
374 "out %[port] , %[hi]" "\n\t"
375 "mov %[n1] , %[lo]" "\n\t"
376 "out %[port] , %[n2]" "\n\t"
377 "ld %[byte] , %a[ptr]+" "\n\t"
378 "sbrc %[byte] , 7" "\n\t"
379 "mov %[n1] , %[hi]" "\n\t"
380 "out %[port] , %[lo]" "\n\t"
381 "brne headB" "\n"
382 : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
383 : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
384 [lo] "r" (lo));
385
386#ifdef PORTD
387 } // endif PORTB
388#endif
389
390#ifdef NEO_KHZ400
391 } else { // end 800 KHz, do 400 KHz
392
393 // Timing is more relaxed; unrolling the inner loop for each bit is
394 // not necessary. Still using the peculiar RJMPs as 2X NOPs, not out
395 // of need but just to trim the code size down a little.
396 // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical
397 // to the 800-on-16 code later -- the hi/lo timing between WS2811 and
398 // WS2812 is not simply a 2:1 scale!
399
400 // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL
401 // ST instructions: ^ ^ ^ (T=0,4,10)
402
403 volatile uint8_t next, bit;
404
405 hi = *port | pinMask;
406 lo = *port & ~pinMask;
407 next = lo;
408 bit = 8;
409
410 asm volatile(
411 "head20:" "\n\t" // Clk Pseudocode (T = 0)
412 "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
413 "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
414 "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
415 "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6)
416 "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
417 "dec %[bit]" "\n\t" // 1 bit-- (T = 8)
418 "breq nextbyte20" "\n\t" // 1-2 if(bit == 0)
419 "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
420 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
421 "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
422 "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
423 "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
424 "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
425 "nextbyte20:" "\n\t" // (T = 10)
426 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12)
427 "nop" "\n\t" // 1 nop (T = 13)
428 "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14)
429 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16)
430 "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
431 "brne head20" "\n" // 2 if(i != 0) -> (next byte)
432 : [port] "+e" (port),
433 [byte] "+r" (b),
434 [bit] "+r" (bit),
435 [next] "+r" (next),
436 [count] "+w" (i)
437 : [hi] "r" (hi),
438 [lo] "r" (lo),
439 [ptr] "e" (ptr));
440 }
441#endif
442
443// 12 MHz(ish) AVR --------------------------------------------------------
444#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)
445
446#ifdef NEO_KHZ400
447 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
448#endif
449
450 // In the 12 MHz case, an optimized 800 KHz datastream (no dead time
451 // between bytes) requires a PORT-specific loop similar to the 8 MHz
452 // code (but a little more relaxed in this case).
453
454 // 15 instruction clocks per bit: HHHHxxxxxxLLLLL
455 // OUT instructions: ^ ^ ^ (T=0,4,10)
456
457 volatile uint8_t next;
458
459#ifdef PORTD
460
461 if(port == &PORTD) {
462
463 hi = PORTD | pinMask;
464 lo = PORTD & ~pinMask;
465 next = lo;
466 if(b & 0x80) next = hi;
467
468 // Don't "optimize" the OUT calls into the bitTime subroutine;
469 // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
470 asm volatile(
471 "headD:" "\n\t" // (T = 0)
472 "out %[port], %[hi]" "\n\t" // (T = 1)
473 "rcall bitTimeD" "\n\t" // Bit 7 (T = 15)
474 "out %[port], %[hi]" "\n\t"
475 "rcall bitTimeD" "\n\t" // Bit 6
476 "out %[port], %[hi]" "\n\t"
477 "rcall bitTimeD" "\n\t" // Bit 5
478 "out %[port], %[hi]" "\n\t"
479 "rcall bitTimeD" "\n\t" // Bit 4
480 "out %[port], %[hi]" "\n\t"
481 "rcall bitTimeD" "\n\t" // Bit 3
482 "out %[port], %[hi]" "\n\t"
483 "rcall bitTimeD" "\n\t" // Bit 2
484 "out %[port], %[hi]" "\n\t"
485 "rcall bitTimeD" "\n\t" // Bit 1
486 // Bit 0:
487 "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1)
488 "rjmp .+0" "\n\t" // 2 nop nop (T = 3)
489 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5)
490 "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6)
491 "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7)
492 "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
493 "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9)
494 "nop" "\n\t" // 1 (T = 10)
495 "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11)
496 "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13)
497 "brne headD" "\n\t" // 2 if(i != 0) -> (next byte)
498 "rjmp doneD" "\n\t"
499 "bitTimeD:" "\n\t" // nop nop nop (T = 4)
500 "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5)
501 "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6)
502 "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7)
503 "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8)
504 "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9)
505 "nop" "\n\t" // 1 (T = 10)
506 "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11)
507 "ret" "\n\t" // 4 nop nop nop nop (T = 15)
508 "doneD:" "\n"
509 : [byte] "+r" (b),
510 [next] "+r" (next),
511 [count] "+w" (i)
512 : [port] "I" (_SFR_IO_ADDR(PORTD)),
513 [ptr] "e" (ptr),
514 [hi] "r" (hi),
515 [lo] "r" (lo));
516
517 } else if(port == &PORTB) {
518
519#endif // PORTD
520
521 hi = PORTB | pinMask;
522 lo = PORTB & ~pinMask;
523 next = lo;
524 if(b & 0x80) next = hi;
525
526 // Same as above, just set for PORTB & stripped of comments
527 asm volatile(
528 "headB:" "\n\t"
529 "out %[port], %[hi]" "\n\t"
530 "rcall bitTimeB" "\n\t"
531 "out %[port], %[hi]" "\n\t"
532 "rcall bitTimeB" "\n\t"
533 "out %[port], %[hi]" "\n\t"
534 "rcall bitTimeB" "\n\t"
535 "out %[port], %[hi]" "\n\t"
536 "rcall bitTimeB" "\n\t"
537 "out %[port], %[hi]" "\n\t"
538 "rcall bitTimeB" "\n\t"
539 "out %[port], %[hi]" "\n\t"
540 "rcall bitTimeB" "\n\t"
541 "out %[port], %[hi]" "\n\t"
542 "rcall bitTimeB" "\n\t"
543 "out %[port] , %[hi]" "\n\t"
544 "rjmp .+0" "\n\t"
545 "ld %[byte] , %a[ptr]+" "\n\t"
546 "out %[port] , %[next]" "\n\t"
547 "mov %[next] , %[lo]" "\n\t"
548 "sbrc %[byte] , 7" "\n\t"
549 "mov %[next] , %[hi]" "\n\t"
550 "nop" "\n\t"
551 "out %[port] , %[lo]" "\n\t"
552 "sbiw %[count], 1" "\n\t"
553 "brne headB" "\n\t"
554 "rjmp doneB" "\n\t"
555 "bitTimeB:" "\n\t"
556 "out %[port], %[next]" "\n\t"
557 "mov %[next], %[lo]" "\n\t"
558 "rol %[byte]" "\n\t"
559 "sbrc %[byte], 7" "\n\t"
560 "mov %[next], %[hi]" "\n\t"
561 "nop" "\n\t"
562 "out %[port], %[lo]" "\n\t"
563 "ret" "\n\t"
564 "doneB:" "\n"
565 : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
566 : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
567 [lo] "r" (lo));
568
569#ifdef PORTD
570 }
571#endif
572
573#ifdef NEO_KHZ400
574 } else { // 400 KHz
575
576 // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL
577 // ST instructions: ^ ^ ^ (T=0,6,15)
578
579 volatile uint8_t next, bit;
580
581 hi = *port | pinMask;
582 lo = *port & ~pinMask;
583 next = lo;
584 bit = 8;
585
586 asm volatile(
587 "head30:" "\n\t" // Clk Pseudocode (T = 0)
588 "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
589 "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
590 "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
591 "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
592 "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8)
593 "rjmp .+0" "\n\t" // 2 nop nop (T = 10)
594 "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
595 "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
596 "nop" "\n\t" // 1 nop (T = 15)
597 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17)
598 "rjmp .+0" "\n\t" // 2 nop nop (T = 19)
599 "dec %[bit]" "\n\t" // 1 bit-- (T = 20)
600 "breq nextbyte30" "\n\t" // 1-2 if(bit == 0)
601 "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22)
602 "rjmp .+0" "\n\t" // 2 nop nop (T = 24)
603 "rjmp .+0" "\n\t" // 2 nop nop (T = 26)
604 "rjmp .+0" "\n\t" // 2 nop nop (T = 28)
605 "rjmp head30" "\n\t" // 2 -> head30 (next bit out)
606 "nextbyte30:" "\n\t" // (T = 22)
607 "nop" "\n\t" // 1 nop (T = 23)
608 "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24)
609 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26)
610 "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28)
611 "brne head30" "\n" // 1-2 if(i != 0) -> (next byte)
612 : [port] "+e" (port),
613 [byte] "+r" (b),
614 [bit] "+r" (bit),
615 [next] "+r" (next),
616 [count] "+w" (i)
617 : [hi] "r" (hi),
618 [lo] "r" (lo),
619 [ptr] "e" (ptr));
620 }
621#endif
622
623// 16 MHz(ish) AVR --------------------------------------------------------
624#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)
625
626#ifdef NEO_KHZ400
627 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
628#endif
629
630 // WS2811 and WS2812 have different hi/lo duty cycles; this is
631 // similar but NOT an exact copy of the prior 400-on-8 code.
632
633 // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL
634 // ST instructions: ^ ^ ^ (T=0,5,13)
635
636 volatile uint8_t next, bit;
637
638 hi = *port | pinMask;
639 lo = *port & ~pinMask;
640 next = lo;
641 bit = 8;
642
643 asm volatile(
644 "head20:" "\n\t" // Clk Pseudocode (T = 0)
645 "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
646 "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128)
647 "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4)
648 "dec %[bit]" "\n\t" // 1 bit-- (T = 5)
649 "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7)
650 "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8)
651 "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above)
652 "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10)
653 "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
654 "nop" "\n\t" // 1 nop (T = 13)
655 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
656 "nop" "\n\t" // 1 nop (T = 16)
657 "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
658 "rjmp head20" "\n\t" // 2 -> head20 (next bit out)
659 "nextbyte20:" "\n\t" // (T = 10)
660 "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11)
661 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13)
662 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15)
663 "nop" "\n\t" // 1 nop (T = 16)
664 "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18)
665 "brne head20" "\n" // 2 if(i != 0) -> (next byte)
666 : [port] "+e" (port),
667 [byte] "+r" (b),
668 [bit] "+r" (bit),
669 [next] "+r" (next),
670 [count] "+w" (i)
671 : [ptr] "e" (ptr),
672 [hi] "r" (hi),
673 [lo] "r" (lo));
674
675#ifdef NEO_KHZ400
676 } else { // 400 KHz
677
678 // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version.
679
680 // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
681 // ST instructions: ^ ^ ^ (T=0,8,20)
682
683 volatile uint8_t next, bit;
684
685 hi = *port | pinMask;
686 lo = *port & ~pinMask;
687 next = lo;
688 bit = 8;
689
690 asm volatile(
691 "head40:" "\n\t" // Clk Pseudocode (T = 0)
692 "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2)
693 "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128)
694 "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4)
695 "rjmp .+0" "\n\t" // 2 nop nop (T = 6)
696 "rjmp .+0" "\n\t" // 2 nop nop (T = 8)
697 "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10)
698 "rjmp .+0" "\n\t" // 2 nop nop (T = 12)
699 "rjmp .+0" "\n\t" // 2 nop nop (T = 14)
700 "rjmp .+0" "\n\t" // 2 nop nop (T = 16)
701 "rjmp .+0" "\n\t" // 2 nop nop (T = 18)
702 "rjmp .+0" "\n\t" // 2 nop nop (T = 20)
703 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22)
704 "nop" "\n\t" // 1 nop (T = 23)
705 "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24)
706 "dec %[bit]" "\n\t" // 1 bit-- (T = 25)
707 "breq nextbyte40" "\n\t" // 1-2 if(bit == 0)
708 "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27)
709 "nop" "\n\t" // 1 nop (T = 28)
710 "rjmp .+0" "\n\t" // 2 nop nop (T = 30)
711 "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
712 "rjmp .+0" "\n\t" // 2 nop nop (T = 34)
713 "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
714 "rjmp .+0" "\n\t" // 2 nop nop (T = 38)
715 "rjmp head40" "\n\t" // 2 -> head40 (next bit out)
716 "nextbyte40:" "\n\t" // (T = 27)
717 "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28)
718 "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30)
719 "rjmp .+0" "\n\t" // 2 nop nop (T = 32)
720 "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34)
721 "rjmp .+0" "\n\t" // 2 nop nop (T = 36)
722 "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38)
723 "brne head40" "\n" // 1-2 if(i != 0) -> (next byte)
724 : [port] "+e" (port),
725 [byte] "+r" (b),
726 [bit] "+r" (bit),
727 [next] "+r" (next),
728 [count] "+w" (i)
729 : [ptr] "e" (ptr),
730 [hi] "r" (hi),
731 [lo] "r" (lo));
732 }
733#endif
734
735#else
736 #error "CPU SPEED NOT SUPPORTED"
737#endif
738
739#elif defined(__arm__)
740
741#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1
742#define CYCLES_800_T0H (F_CPU / 4000000)
743#define CYCLES_800_T1H (F_CPU / 1250000)
744#define CYCLES_800 (F_CPU / 800000)
745#define CYCLES_400_T0H (F_CPU / 2000000)
746#define CYCLES_400_T1H (F_CPU / 833333)
747#define CYCLES_400 (F_CPU / 400000)
748
749 uint8_t *p = pixels,
750 *end = p + numBytes, pix, mask;
751 volatile uint8_t *set = portSetRegister(pin),
752 *clr = portClearRegister(pin);
753 uint32_t cyc;
754
755 ARM_DEMCR |= ARM_DEMCR_TRCENA;
756 ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
757
758#ifdef NEO_KHZ400
759 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
760#endif
761 cyc = ARM_DWT_CYCCNT + CYCLES_800;
762 while(p < end) {
763 pix = *p++;
764 for(mask = 0x80; mask; mask >>= 1) {
765 while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
766 cyc = ARM_DWT_CYCCNT;
767 *set = 1;
768 if(pix & mask) {
769 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
770 } else {
771 while(ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
772 }
773 *clr = 1;
774 }
775 }
776 while(ARM_DWT_CYCCNT - cyc < CYCLES_800);
777#ifdef NEO_KHZ400
778 } else { // 400 kHz bitstream
779 cyc = ARM_DWT_CYCCNT + CYCLES_400;
780 while(p < end) {
781 pix = *p++;
782 for(mask = 0x80; mask; mask >>= 1) {
783 while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
784 cyc = ARM_DWT_CYCCNT;
785 *set = 1;
786 if(pix & mask) {
787 while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
788 } else {
789 while(ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
790 }
791 *clr = 1;
792 }
793 }
794 while(ARM_DWT_CYCCNT - cyc < CYCLES_400);
795 }
796#endif
797
798
799
800
801
802#elif defined(__MKL26Z64__) // Teensy-LC
803
804#if F_CPU == 48000000
805 uint8_t *p = pixels,
806 pix, count, dly,
807 bitmask = digitalPinToBitMask(pin);
808 volatile uint8_t *reg = portSetRegister(pin);
809 uint32_t num = numBytes;
810 asm volatile(
811 "L%=_begin:" "\n\t"
812 "ldrb %[pix], [%[p], #0]" "\n\t"
813 "lsl %[pix], #24" "\n\t"
814 "movs %[count], #7" "\n\t"
815 "L%=_loop:" "\n\t"
816 "lsl %[pix], #1" "\n\t"
817 "bcs L%=_loop_one" "\n\t"
818 "L%=_loop_zero:"
819 "strb %[bitmask], [%[reg], #0]" "\n\t"
820 "movs %[dly], #4" "\n\t"
821 "L%=_loop_delay_T0H:" "\n\t"
822 "sub %[dly], #1" "\n\t"
823 "bne L%=_loop_delay_T0H" "\n\t"
824 "strb %[bitmask], [%[reg], #4]" "\n\t"
825 "movs %[dly], #13" "\n\t"
826 "L%=_loop_delay_T0L:" "\n\t"
827 "sub %[dly], #1" "\n\t"
828 "bne L%=_loop_delay_T0L" "\n\t"
829 "b L%=_next" "\n\t"
830 "L%=_loop_one:"
831 "strb %[bitmask], [%[reg], #0]" "\n\t"
832 "movs %[dly], #13" "\n\t"
833 "L%=_loop_delay_T1H:" "\n\t"
834 "sub %[dly], #1" "\n\t"
835 "bne L%=_loop_delay_T1H" "\n\t"
836 "strb %[bitmask], [%[reg], #4]" "\n\t"
837 "movs %[dly], #4" "\n\t"
838 "L%=_loop_delay_T1L:" "\n\t"
839 "sub %[dly], #1" "\n\t"
840 "bne L%=_loop_delay_T1L" "\n\t"
841 "nop" "\n\t"
842 "L%=_next:" "\n\t"
843 "sub %[count], #1" "\n\t"
844 "bne L%=_loop" "\n\t"
845 "lsl %[pix], #1" "\n\t"
846 "bcs L%=_last_one" "\n\t"
847 "L%=_last_zero:"
848 "strb %[bitmask], [%[reg], #0]" "\n\t"
849 "movs %[dly], #4" "\n\t"
850 "L%=_last_delay_T0H:" "\n\t"
851 "sub %[dly], #1" "\n\t"
852 "bne L%=_last_delay_T0H" "\n\t"
853 "strb %[bitmask], [%[reg], #4]" "\n\t"
854 "movs %[dly], #10" "\n\t"
855 "L%=_last_delay_T0L:" "\n\t"
856 "sub %[dly], #1" "\n\t"
857 "bne L%=_last_delay_T0L" "\n\t"
858 "b L%=_repeat" "\n\t"
859 "L%=_last_one:"
860 "strb %[bitmask], [%[reg], #0]" "\n\t"
861 "movs %[dly], #13" "\n\t"
862 "L%=_last_delay_T1H:" "\n\t"
863 "sub %[dly], #1" "\n\t"
864 "bne L%=_last_delay_T1H" "\n\t"
865 "strb %[bitmask], [%[reg], #4]" "\n\t"
866 "movs %[dly], #1" "\n\t"
867 "L%=_last_delay_T1L:" "\n\t"
868 "sub %[dly], #1" "\n\t"
869 "bne L%=_last_delay_T1L" "\n\t"
870 "nop" "\n\t"
871 "L%=_repeat:" "\n\t"
872 "add %[p], #1" "\n\t"
873 "sub %[num], #1" "\n\t"
874 "bne L%=_begin" "\n\t"
875 "L%=_done:" "\n\t"
876 : [p] "+r" (p),
877 [pix] "=&r" (pix),
878 [count] "=&r" (count),
879 [dly] "=&r" (dly),
880 [num] "+r" (num)
881 : [bitmask] "r" (bitmask),
882 [reg] "r" (reg)
883 );
884#else
885#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
886#endif
887
888
889#else // Arduino Due
890
891 #define SCALE VARIANT_MCK / 2UL / 1000000UL
892 #define INST (2UL * F_CPU / VARIANT_MCK)
893 #define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
894 #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
895 #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
896 #define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
897 #define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
898 #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))
899
900 int pinMask, time0, time1, period, t;
901 Pio *port;
902 volatile WoReg *portSet, *portClear, *timeValue, *timeReset;
903 uint8_t *p, *end, pix, mask;
904
905 pmc_set_writeprotect(false);
906 pmc_enable_periph_clk((uint32_t)TC3_IRQn);
907 TC_Configure(TC1, 0,
908 TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1);
909 TC_Start(TC1, 0);
910
911 pinMask = g_APinDescription[pin].ulPin; // Don't 'optimize' these into
912 port = g_APinDescription[pin].pPort; // declarations above. Want to
913 portSet = &(port->PIO_SODR); // burn a few cycles after
914 portClear = &(port->PIO_CODR); // starting timer to minimize
915 timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'.
916 timeReset = &(TC1->TC_CHANNEL[0].TC_CCR);
917 p = pixels;
918 end = p + numBytes;
919 pix = *p++;
920 mask = 0x80;
921
922#ifdef NEO_KHZ400
923 if((type & NEO_SPDMASK) == NEO_KHZ800) { // 800 KHz bitstream
924#endif
925 time0 = TIME_800_0;
926 time1 = TIME_800_1;
927 period = PERIOD_800;
928#ifdef NEO_KHZ400
929 } else { // 400 KHz bitstream
930 time0 = TIME_400_0;
931 time1 = TIME_400_1;
932 period = PERIOD_400;
933 }
934#endif
935
936 for(t = time0;; t = time0) {
937 if(pix & mask) t = time1;
938 while(*timeValue < period);
939 *portSet = pinMask;
940 *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG;
941 while(*timeValue < t);
942 *portClear = pinMask;
943 if(!(mask >>= 1)) { // This 'inside-out' loop logic utilizes
944 if(p >= end) break; // idle time to minimize inter-byte delays.
945 pix = *p++;
946 mask = 0x80;
947 }
948 }
949 while(*timeValue < period); // Wait for last bit
950 TC_Stop(TC1, 0);
951
952#endif // end Arduino Due
953
954#endif // end Architecture select
955
956 interrupts();
957 endTime = micros(); // Save EOD time for latch on next call
958}
959
960// Set the output pin number
961void MitovEmbedded_Adafruit_NeoPixel::setPin(uint8_t p) {
962 pinMode(pin, INPUT);
963 pin = p;
964 pinMode(p, OUTPUT);
965 digitalWrite(p, LOW);
966#ifdef __AVR__
967 port = portOutputRegister(digitalPinToPort(p));
968 pinMask = digitalPinToBitMask(p);
969#endif
970}
971
972// Set pixel color from separate R,G,B components:
973void MitovEmbedded_Adafruit_NeoPixel::setPixelColor(
974 uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
975 if(n < numLEDs) {
976 if(brightness) { // See notes in setBrightness()
977 r = (r * brightness) >> 8;
978 g = (g * brightness) >> 8;
979 b = (b * brightness) >> 8;
980 }
981 uint8_t *p = &pixels[n * 3];
982 p[rOffset] = r;
983 p[gOffset] = g;
984 p[bOffset] = b;
985 }
986}
987
988// Set pixel color from 'packed' 32-bit RGB color:
989void MitovEmbedded_Adafruit_NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
990 if(n < numLEDs) {
991 uint8_t
992 r = (uint8_t)(c >> 16),
993 g = (uint8_t)(c >> 8),
994 b = (uint8_t)c;
995 if(brightness) { // See notes in setBrightness()
996 r = (r * brightness) >> 8;
997 g = (g * brightness) >> 8;
998 b = (b * brightness) >> 8;
999 }
1000 uint8_t *p = &pixels[n * 3];
1001 p[rOffset] = r;
1002 p[gOffset] = g;
1003 p[bOffset] = b;
1004 }
1005}
1006
1007// Convert separate R,G,B into packed 32-bit RGB color.
1008// Packed format is always RGB, regardless of LED strand color order.
1009uint32_t MitovEmbedded_Adafruit_NeoPixel::Color(uint8_t r, uint8_t g, uint8_t b) {
1010 return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
1011}
1012
1013// Query color from previously-set pixel (returns packed 32-bit RGB value)
1014uint32_t MitovEmbedded_Adafruit_NeoPixel::getPixelColor(uint16_t n) const {
1015 if(n >= numLEDs) {
1016 // Out of bounds, return no color.
1017 return 0;
1018 }
1019 uint8_t *p = &pixels[n * 3];
1020 uint32_t c = ((uint32_t)p[rOffset] << 16) |
1021 ((uint32_t)p[gOffset] << 8) |
1022 (uint32_t)p[bOffset];
1023 // Adjust this back up to the true color, as setting a pixel color will
1024 // scale it back down again.
1025 if(brightness) { // See notes in setBrightness()
1026 //Cast the color to a byte array
1027 uint8_t * c_ptr =reinterpret_cast<uint8_t*>(&c);
1028 c_ptr[0] = (c_ptr[0] << 8)/brightness;
1029 c_ptr[1] = (c_ptr[1] << 8)/brightness;
1030 c_ptr[2] = (c_ptr[2] << 8)/brightness;
1031 }
1032 return c; // Pixel # is out of bounds
1033}
1034
1035// Returns pointer to pixels[] array. Pixel data is stored in device-
1036// native format and is not translated here. Application will need to be
1037// aware whether pixels are RGB vs. GRB and handle colors appropriately.
1038uint8_t *MitovEmbedded_Adafruit_NeoPixel::getPixels(void) const {
1039 return pixels;
1040}
1041
1042uint16_t MitovEmbedded_Adafruit_NeoPixel::numPixels(void) const {
1043 return numLEDs;
1044}
1045
1046// Adjust output brightness; 0=darkest (off), 255=brightest. This does
1047// NOT immediately affect what's currently displayed on the LEDs. The
1048// next call to show() will refresh the LEDs at this level. However,
1049// this process is potentially "lossy," especially when increasing
1050// brightness. The tight timing in the WS2811/WS2812 code means there
1051// aren't enough free cycles to perform this scaling on the fly as data
1052// is issued. So we make a pass through the existing color data in RAM
1053// and scale it (subsequent graphics commands also work at this
1054// brightness level). If there's a significant step up in brightness,
1055// the limited number of steps (quantization) in the old data will be
1056// quite visible in the re-scaled version. For a non-destructive
1057// change, you'll need to re-render the full strip data. C'est la vie.
1058void MitovEmbedded_Adafruit_NeoPixel::setBrightness(uint8_t b) {
1059 // Stored brightness value is different than what's passed.
1060 // This simplifies the actual scaling math later, allowing a fast
1061 // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
1062 // adding 1 here may (intentionally) roll over...so 0 = max brightness
1063 // (color values are interpreted literally; no scaling), 1 = min
1064 // brightness (off), 255 = just below max brightness.
1065 uint8_t newBrightness = b + 1;
1066 if(newBrightness != brightness) { // Compare against prior value
1067 // Brightness has changed -- re-scale existing data in RAM
1068 uint8_t c,
1069 *ptr = pixels,
1070 oldBrightness = brightness - 1; // De-wrap old brightness value
1071 uint16_t scale;
1072 if(oldBrightness == 0) scale = 0; // Avoid /0
1073 else if(b == 255) scale = 65535 / oldBrightness;
1074 else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;
1075 for(uint16_t i=0; i<numBytes; i++) {
1076 c = *ptr;
1077 *ptr++ = (c * scale) >> 8;
1078 }
1079 brightness = newBrightness;
1080 }
1081}
1082
1083//Return the brightness value
1084uint8_t MitovEmbedded_Adafruit_NeoPixel::getBrightness(void) const {
1085 return brightness - 1;
1086}
1087
1088void MitovEmbedded_Adafruit_NeoPixel::clear() {
1089 memset(pixels, 0, numBytes);
1090}
1091
1092#endif // ADAFRUIT_NEOPIXEL_H