libDaisy
Hardware Library for Daisy
Loading...
Searching...
No Matches
neopixel.h
Go to the documentation of this file.
1#pragma once
2#ifndef DSY_NEO_PIXEL_H
3#define DSY_NEO_PIXEL_H
4
5#define NEO_TRELLIS_ADDR_NEOPIXEL (0x2E)
6
7// RGB NeoPixel permutations; white and red offsets are always same
8// Offset: W R G B
9#define NEO_RGB ((0 << 6) | (0 << 4) | (1 << 2) | (2))
10#define NEO_RBG ((0 << 6) | (0 << 4) | (2 << 2) | (1))
11#define NEO_GRB ((1 << 6) | (1 << 4) | (0 << 2) | (2))
12#define NEO_GBR ((2 << 6) | (2 << 4) | (0 << 2) | (1))
13#define NEO_BRG ((1 << 6) | (1 << 4) | (2 << 2) | (0))
14#define NEO_BGR ((2 << 6) | (2 << 4) | (1 << 2) | (0))
15
16// RGBW NeoPixel permutations; all 4 offsets are distinct
17// Offset: W R G B
18#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
19#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
20#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
21#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
22#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
23#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
24
25#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
26#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
27#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
28#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
29#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
30#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
31
32#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
33#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
34#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
35#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
36#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
37#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
38
39#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
40#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
41#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
42#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
43#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
44#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
45
46// If 400 KHz support is enabled, the third parameter to the constructor
47// requires a 16-bit value (in order to select 400 vs 800 KHz speed).
48// If only 800 KHz is enabled (as is default on ATtiny), an 8-bit value
49// is sufficient to encode pixel color order, saving some space.
50
51#define NEO_KHZ800 0x0000 // 800 KHz datastream
52#define NEO_KHZ400 0x0100 // 400 KHz datastream
53
54namespace daisy
55{
62{
63 public:
66
87
88 inline void Init(Config config)
89 {
90 config_ = config;
91
92 I2CHandle::Config i2c_config;
94 i2c_config.periph = config.periph;
95 i2c_config.speed = config.speed;
96
97 i2c_config.pin_config.scl = config.scl;
98 i2c_config.pin_config.sda = config.sda;
99
100 error_ |= I2CHandle::Result::OK != i2c_.Init(i2c_config);
101 }
102
104 {
105 error_ |= I2CHandle::Result::OK
106 != i2c_.TransmitBlocking(config_.address, data, size, 10);
107 }
108
110 {
111 error_ |= I2CHandle::Result::OK
112 != i2c_.ReceiveBlocking(config_.address, data, size, 10);
113 }
114
115 void
117 {
118 uint8_t reg[2] = {reg_high, reg_low};
119 Write(reg, 2);
120 Read(buff, size);
121 }
122
123 void
125 {
126 // max write size of 126...
127 if(size >= 126)
128 {
129 return;
130 }
131
132 uint8_t reg[128];
133
134 reg[0] = reg_high;
135 reg[1] = reg_low;
136
137 for(int i = 0; i < size; i++)
138 {
139 reg[i + 2] = buff[i];
140 }
141
142 Write(reg, size + 2);
143 }
144
150 {
151 uint8_t buffer[3];
152
153 buffer[0] = reg_high;
154 buffer[1] = reg_low;
155 buffer[2] = value;
156
157 Write(buffer, 3);
158 }
159
170
171 bool GetError()
172 {
173 bool tmp = error_;
174 error_ = false;
175 return tmp;
176 }
177
178 private:
179 I2CHandle i2c_;
180 Config config_;
181
182 // true if error has occured since last check
183 bool error_;
184};
185
190template <typename Transport>
192{
193 public:
196
197 struct Config
198 {
199 typename Transport::Config transport_config;
203
205 {
207 numLEDs = 16;
208 output_pin = 3;
209 }
210 };
211
213 {
214 OK = 0,
215 ERR
216 };
217
219
241
252
262
267 {
268 config_ = config;
269
270 type = config_.type;
271 numLEDs = config_.numLEDs;
272 pin = config_.output_pin;
273 pixels = pixelsd;
274
275 transport_.Init(config_.transport_config);
276
277 SWReset();
278
279 // 10 ms delay
280 System::Delay(10);
281
284 SetPin(pin);
285
286 return GetTransportError();
287 }
288
290 {
291 transport_.WriteLen(reg_high, reg_low, buff, size);
292 }
293
299 {
300 return transport_.Write8(reg_high, reg_low, value);
301 }
302
308 {
309 return transport_.Read8(reg_high, reg_low);
310 }
311
313 {
314 transport_.ReadLen(reg_high, reg_low, buff, len);
315 }
316
320 Result GetTransportError() { return transport_.GetError() ? ERR : OK; }
321
326 void SWReset()
327 {
329 }
330
332 {
333 // Allocate new data -- note: ALL PIXELS ARE CLEARED
334 numBytes = n * ((wOffset == rOffset) ? 3 : 4);
335 mymemset(pixels, 0, numBytes);
336 numLEDs = n;
337
338 uint8_t buf[] = {(uint8_t)(numBytes >> 8), (uint8_t)(numBytes & 0xFF)};
340 }
341
343 {
344 bool oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW
345
346 wOffset = (t >> 6) & 0b11; // See notes in header file
347 rOffset = (t >> 4) & 0b11; // regarding R/G/B/W offsets
348 gOffset = (t >> 2) & 0b11;
349 bOffset = t & 0b11;
350 is800KHz = (t < 256); // 400 KHz flag is 1<<8
351
353
354 // If bytes-per-pixel has changed (and pixel data was previously
355 // allocated), re-allocate to new size. Will clear any data.
359 }
360
361 inline bool CanShow(void) { return (System::GetUs() - endTime) >= 300L; }
362
363 void Show(void)
364 {
365 // Data latch = 300+ microsecond pause in the output stream. Rather than
366 // put a delay at the end of the function, the ending time is noted and
367 // the function will simply hold off (if needed) on issuing the
368 // subsequent round of data until the latch time has elapsed. This
369 // allows the mainline code to start generating the next frame of data
370 // rather than stalling for the latch.
371 while(!CanShow())
372 ;
373
375
376 endTime = System::GetUs(); // Save EOD time for latch on next call
377 }
378
379 // Set the output pin number
385
386 // Set pixel color from separate R,G,B components:
388 {
389 if(n < numLEDs)
390 {
391 if(brightness)
392 { // See notes in setBrightness()
393 r = (r * brightness) >> 8;
394 g = (g * brightness) >> 8;
395 b = (b * brightness) >> 8;
396 }
397 uint8_t *p;
398 if(wOffset == rOffset)
399 { // Is an RGB-type strip
400 p = &pixels[n * 3]; // 3 bytes per pixel
401 }
402 else
403 { // Is a WRGB-type strip
404 p = &pixels[n * 4]; // 4 bytes per pixel
405 p[wOffset] = 0; // But only R,G,B passed -- set W to 0
406 }
407 p[rOffset] = r; // R,G,B always stored
408 p[gOffset] = g;
409 p[bOffset] = b;
410
411 uint8_t len = (wOffset == rOffset ? 3 : 4);
412 uint16_t offset = n * len;
413
414 uint8_t writeBuf[6];
415 writeBuf[0] = (offset >> 8);
416 writeBuf[1] = offset;
417 mymemcpy(&writeBuf[2], p, len);
418
420 }
421 }
422
424 {
425 if(n < numLEDs)
426 {
427 if(brightness)
428 { // See notes in setBrightness()
429 r = (r * brightness) >> 8;
430 g = (g * brightness) >> 8;
431 b = (b * brightness) >> 8;
432 w = (w * brightness) >> 8;
433 }
434 uint8_t *p;
435 if(wOffset == rOffset)
436 { // Is an RGB-type strip
437 p = &pixels[n * 3]; // 3 bytes per pixel (ignore W)
438 }
439 else
440 { // Is a WRGB-type strip
441 p = &pixels[n * 4]; // 4 bytes per pixel
442 p[wOffset] = w; // Store W
443 }
444 p[rOffset] = r; // Store R,G,B
445 p[gOffset] = g;
446 p[bOffset] = b;
447
448 uint8_t len = (wOffset == rOffset ? 3 : 4);
449 uint16_t offset = n * len;
450
451 uint8_t writeBuf[6];
452 writeBuf[0] = (offset >> 8);
453 writeBuf[1] = offset;
454 mymemcpy(&writeBuf[2], p, len);
455
457 }
458 }
459
460 // Set pixel color from 'packed' 32-bit RGB color:
462 {
463 if(n < numLEDs)
464 {
465 uint8_t *p, r = (uint8_t)(c >> 16), g = (uint8_t)(c >> 8),
466 b = (uint8_t)c;
467 if(brightness)
468 { // See notes in setBrightness()
469 r = (r * brightness) >> 8;
470 g = (g * brightness) >> 8;
471 b = (b * brightness) >> 8;
472 }
473 if(wOffset == rOffset)
474 {
475 p = &pixels[n * 3];
476 }
477 else
478 {
479 p = &pixels[n * 4];
480 uint8_t w = (uint8_t)(c >> 24);
481 p[wOffset] = brightness ? ((w * brightness) >> 8) : w;
482 }
483 p[rOffset] = r;
484 p[gOffset] = g;
485 p[bOffset] = b;
486
487 uint8_t len = (wOffset == rOffset ? 3 : 4);
488 uint16_t offset = n * len;
489
490 uint8_t writeBuf[6];
491 writeBuf[0] = (offset >> 8);
492 writeBuf[1] = offset;
493 mymemcpy(&writeBuf[2], p, len);
494
496 }
497 }
498
499 // Convert separate R,G,B into packed 32-bit RGB color.
500 // Packed format is always RGB, regardless of LED strand color order.
502 {
503 return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
504 }
505
506 // Convert separate R,G,B,W into packed 32-bit WRGB color.
507 // Packed format is always WRGB, regardless of LED strand color order.
509 {
510 return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8)
511 | b;
512 }
513
514 // Query color from previously-set pixel (returns packed 32-bit RGB value)
516 {
517 if(n >= numLEDs)
518 return 0; // Out of bounds, return no color.
519
520 uint8_t *p;
521
522 if(wOffset == rOffset)
523 { // Is RGB-type device
524 p = &pixels[n * 3];
525 if(brightness)
526 {
527 // Stored color was decimated by setBrightness(). Returned value
528 // attempts to scale back to an approximation of the original 24-bit
529 // value used when setting the pixel color, but there will always be
530 // some error -- those bits are simply gone. Issue is most
531 // pronounced at low brightness levels.
532 return (((uint32_t)(p[rOffset] << 8) / brightness) << 16)
533 | (((uint32_t)(p[gOffset] << 8) / brightness) << 8)
534 | ((uint32_t)(p[bOffset] << 8) / brightness);
535 }
536 else
537 {
538 // No brightness adjustment has been made -- return 'raw' color
539 return ((uint32_t)p[rOffset] << 16)
540 | ((uint32_t)p[gOffset] << 8) | (uint32_t)p[bOffset];
541 }
542 }
543 else
544 { // Is RGBW-type device
545 p = &pixels[n * 4];
546 if(brightness)
547 { // Return scaled color
548 return (((uint32_t)(p[wOffset] << 8) / brightness) << 24)
549 | (((uint32_t)(p[rOffset] << 8) / brightness) << 16)
550 | (((uint32_t)(p[gOffset] << 8) / brightness) << 8)
551 | ((uint32_t)(p[bOffset] << 8) / brightness);
552 }
553 else
554 { // Return raw color
555 return ((uint32_t)p[wOffset] << 24)
556 | ((uint32_t)p[rOffset] << 16)
557 | ((uint32_t)p[gOffset] << 8) | (uint32_t)p[bOffset];
558 }
559 }
560 }
561
562 // Returns pointer to pixels[] array. Pixel data is stored in device-
563 // native format and is not translated here. Application will need to be
564 // aware of specific pixel data format and handle colors appropriately.
565 uint8_t *GetPixels(void) const { return pixels; }
566
567 uint16_t NumPixels(void) const { return numLEDs; }
568
569 void Clear()
570 {
571 // Clear local pixel buffer
572 mymemset(pixels, 0, numBytes);
573
574 // Now clear the pixels on the seesaw
575 uint8_t writeBuf[32];
576 mymemset(writeBuf, 0, 32);
577 for(uint8_t offset = 0; offset < numBytes; offset += 32 - 4)
578 {
579 writeBuf[0] = (offset >> 8);
580 writeBuf[1] = offset;
582 }
583 }
584
586
587 private:
588 void mymemcpy(uint8_t *dest, uint8_t *src, uint8_t len)
589 {
590 for(uint8_t i = 0; i < len; i++)
591 {
592 dest[i] = src[i];
593 }
594 }
595
596 void mymemset(uint8_t *addr, uint8_t val, uint8_t len)
597 {
598 for(uint8_t i = 0; i < len; i++)
599 {
600 addr[i] = val;
601 }
602 }
603
604 Config config_;
605 Transport transport_;
606
607 protected:
608 bool is800KHz, // ...true if 800 KHz pixels
609 begun; // true if begin() previously called
610 uint16_t numLEDs, // Number of RGB LEDs in strip
611 numBytes; // Size of 'pixels' buffer below (3 or 4 bytes/pixel)
613
614 uint8_t pixelsd[256]; // hopefully we won't need more than this...
615
617 *pixels, // Holds LED color values (3 or 4 bytes each)
618 rOffset, // Index of red byte within each 3- or 4-byte pixel
619 gOffset, // Index of green byte
620 bOffset, // Index of blue byte
621 wOffset; // Index of white byte (same as rOffset if no white)
622 uint32_t endTime; // Latch timing reference
623
625
626}; // namespace daisy
627
631} // namespace daisy
632#endif
Definition i2c.h:26
Result Init(const Config &config)
Result ReceiveBlocking(uint16_t address, uint8_t *data, uint16_t size, uint32_t timeout)
Result TransmitBlocking(uint16_t address, uint8_t *data, uint16_t size, uint32_t timeout)
Definition leddriver.h:33
void Init(I2CHandle i2c, const uint8_t(&addresses)[numDrivers], DmaBuffer dma_buffer_a, DmaBuffer dma_buffer_b, Pin oe_pin=Pin(PORTX, 0))
Definition leddriver.h:65
Device support for Adafruit Neopixel Device.
Definition neopixel.h:192
ModBaseAdd
Definition neopixel.h:224
@ SEESAW_STATUS_BASE
Definition neopixel.h:225
@ SEESAW_KEYPAD_BASE
Definition neopixel.h:237
@ SEESAW_SPECTRUM_BASE
Definition neopixel.h:239
@ SEESAW_TOUCH_BASE
Definition neopixel.h:236
@ SEESAW_SERCOM0_BASE
Definition neopixel.h:227
@ SEESAW_INTERRUPT_BASE
Definition neopixel.h:232
@ SEESAW_NEOPIXEL_BASE
Definition neopixel.h:235
@ SEESAW_DAC_BASE
Definition neopixel.h:231
@ SEESAW_ENCODER_BASE
Definition neopixel.h:238
@ SEESAW_DAP_BASE
Definition neopixel.h:233
@ SEESAW_ADC_BASE
Definition neopixel.h:230
@ SEESAW_TIMER_BASE
Definition neopixel.h:229
@ SEESAW_GPIO_BASE
Definition neopixel.h:226
@ SEESAW_EEPROM_BASE
Definition neopixel.h:234
uint16_t NumPixels(void) const
Definition neopixel.h:567
void Show(void)
Definition neopixel.h:363
~NeoPixel()
Definition neopixel.h:195
uint8_t brightness
Definition neopixel.h:616
void Write(uint8_t reg_high, uint8_t reg_low, uint8_t *buff, uint8_t size)
Definition neopixel.h:289
uint8_t * pixels
Definition neopixel.h:617
bool begun
Definition neopixel.h:609
uint8_t bOffset
Definition neopixel.h:620
void UpdateType(neoPixelType t)
Definition neopixel.h:342
Result Init(Config config)
Definition neopixel.h:266
uint8_t rOffset
Definition neopixel.h:618
int8_t pin
Definition neopixel.h:612
uint32_t endTime
Definition neopixel.h:622
void SetPin(uint8_t p)
Definition neopixel.h:380
void ReadLen(uint8_t reg_high, uint8_t reg_low, uint8_t *buff, uint8_t len)
Definition neopixel.h:312
uint16_t numLEDs
Definition neopixel.h:610
void Clear()
Definition neopixel.h:569
uint32_t Color(uint8_t r, uint8_t g, uint8_t b)
Definition neopixel.h:501
void SetBrightness(uint8_t b)
Definition neopixel.h:585
bool CanShow(void)
Definition neopixel.h:361
uint8_t Read8(uint8_t reg_high, uint8_t reg_low)
Definition neopixel.h:307
void SetPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
Definition neopixel.h:423
uint8_t gOffset
Definition neopixel.h:619
void UpdateLength(uint16_t n)
Definition neopixel.h:331
NeoPixel()
Definition neopixel.h:194
ModAddReg
Definition neopixel.h:244
@ SEESAW_NEOPIXEL_SHOW
Definition neopixel.h:250
@ SEESAW_NEOPIXEL_PIN
Definition neopixel.h:246
@ SEESAW_NEOPIXEL_BUF_LENGTH
Definition neopixel.h:248
@ SEESAW_NEOPIXEL_SPEED
Definition neopixel.h:247
@ SEESAW_NEOPIXEL_STATUS
Definition neopixel.h:245
@ SEESAW_NEOPIXEL_BUF
Definition neopixel.h:249
uint8_t wOffset
Definition neopixel.h:621
uint16_t neoPixelType
Definition neopixel.h:218
void SetPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
Definition neopixel.h:387
void SWReset()
Definition neopixel.h:326
uint8_t pixelsd[256]
Definition neopixel.h:614
bool is800KHz
Definition neopixel.h:608
uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w)
Definition neopixel.h:508
Result GetTransportError()
Definition neopixel.h:320
uint8_t * GetPixels(void) const
Definition neopixel.h:565
uint32_t GetPixelColor(uint16_t n) const
Definition neopixel.h:515
void Write8(uint8_t reg_high, uint8_t reg_low, uint8_t value)
Definition neopixel.h:298
uint16_t numBytes
Definition neopixel.h:611
StatAddReg
Definition neopixel.h:255
@ SEESAW_STATUS_OPTIONS
Definition neopixel.h:258
@ SEESAW_STATUS_TEMP
Definition neopixel.h:259
@ SEESAW_STATUS_VERSION
Definition neopixel.h:257
@ SEESAW_STATUS_SWRST
Definition neopixel.h:260
@ SEESAW_STATUS_HW_ID
Definition neopixel.h:256
uint16_t type
Definition neopixel.h:624
void SetPixelColor(uint16_t n, uint32_t c)
Definition neopixel.h:461
Result
Definition neopixel.h:213
@ OK
Definition neopixel.h:214
@ ERR
Definition neopixel.h:215
Definition neopixel.h:62
void WriteLen(uint8_t reg_high, uint8_t reg_low, uint8_t *buff, uint16_t size)
Definition neopixel.h:124
uint8_t Read8(uint8_t reg_high, uint8_t reg_low)
Definition neopixel.h:164
bool GetError()
Definition neopixel.h:171
void Read(uint8_t *data, uint16_t size)
Definition neopixel.h:109
void Write(uint8_t *data, uint16_t size)
Definition neopixel.h:103
void Init(Config config)
Definition neopixel.h:88
~NeoPixelI2CTransport()
Definition neopixel.h:65
void Write8(uint8_t reg_high, uint8_t reg_low, uint8_t value)
Definition neopixel.h:149
void ReadLen(uint8_t reg_high, uint8_t reg_low, uint8_t *buff, uint16_t size)
Definition neopixel.h:116
NeoPixelI2CTransport()
Definition neopixel.h:64
static void Delay(uint32_t delay_ms)
static uint32_t GetUs()
Hardware defines and helpers for daisy field platform.
Definition index.h:2
@ PORTB
Definition daisy_core.h:178
#define NEO_KHZ800
Definition neopixel.h:51
#define NEO_GRB
Definition neopixel.h:11
#define NEO_TRELLIS_ADDR_NEOPIXEL
Default Neotrellis I2C address.
Definition neopixel.h:5
Definition i2c.h:30
struct daisy::I2CHandle::Config::@15 pin_config
Mode mode
Definition i2c.h:65
Speed
Definition i2c.h:51
Speed speed
Definition i2c.h:64
Peripheral periph
Definition i2c.h:57
Peripheral
Definition i2c.h:40
Definition neopixel.h:198
Transport::Config transport_config
Definition neopixel.h:199
uint16_t type
Definition neopixel.h:200
Config()
Definition neopixel.h:204
int8_t output_pin
Definition neopixel.h:202
uint16_t numLEDs
Definition neopixel.h:201
Definition neopixel.h:68
I2CHandle::Config::Peripheral periph
Definition neopixel.h:69
Pin sda
Definition neopixel.h:72
Config()
Definition neopixel.h:76
uint8_t address
Definition neopixel.h:74
Pin scl
Definition neopixel.h:71
I2CHandle::Config::Speed speed
Definition neopixel.h:70
representation of hardware port/pin combination
Definition daisy_core.h:193