63#include "ObjectFLED.h"
66#define MIN(a,b) ((a)<(b)?(a):(b))
70#define MAX(a,b) ((a)>(b)?(a):(b))
75volatile uint32_t framebuffer_index = 0;
76uint8_t* ObjectFLED::frameBuffer;
77uint32_t ObjectFLED::numbytes;
78uint8_t ObjectFLED::numpins;
79uint8_t ObjectFLED::pin_bitnum[NUM_DIGITAL_PINS];
80uint8_t ObjectFLED::pin_offset[NUM_DIGITAL_PINS];
81uint32_t ObjectFLED::bitdata[BYTES_PER_DMA * 64] __attribute__((used, aligned(32)));
82uint32_t ObjectFLED::bitmask[4] __attribute__((used, aligned(32)));
84DMASetting ObjectFLED::dma2next;
85DMAChannel ObjectFLED::dma1;
86DMAChannel ObjectFLED::dma2;
87DMAChannel ObjectFLED::dma3;
88volatile bool dma_first;
91ObjectFLED::ObjectFLED(uint16_t numLEDs,
void *drawBuf, uint8_t config, uint8_t numPins, \
92 const uint8_t *pinList, uint8_t serpentine) {
93 serpNumber = serpentine;
96 if (numPins > NUM_DIGITAL_PINS) numPins = NUM_DIGITAL_PINS;
98 stripLen = numLEDs / numpins;
99 memcpy(pinlist, pinList, numpins);
100 if ((params & 0x3F) < 6) {
101 frameBuffer =
new uint8_t[numLEDs * 3];
102 numbytes = stripLen * 3;
105 frameBuffer =
new uint8_t[numLEDs * 4];
106 numbytes = stripLen * 4;
109 numpinsLocal = numPins;
110 frameBufferLocal = frameBuffer;
111 numbytesLocal = numbytes;
115extern "C" void xbar_connect(
unsigned int input,
unsigned int output);
116static volatile uint32_t *standard_gpio_addr(
volatile uint32_t *fastgpio) {
117 return (
volatile uint32_t *)((uint32_t)fastgpio - 0x01E48000);
121void ObjectFLED::begin(uint16_t latchDelay) {
122 LATCH_DELAY = latchDelay;
127void ObjectFLED::begin(
double OCF, uint16_t latchDelay) {
128 OC_FACTOR = (float)OCF;
129 LATCH_DELAY = latchDelay;
134void ObjectFLED::begin(uint16_t period, uint16_t t0h, uint16_t t1h, uint16_t latchDelay) {
138 LATCH_DELAY = latchDelay;
146void ObjectFLED::begin(
void) {
147 numpins = numpinsLocal;
149 memset(bitmask, 0,
sizeof(bitmask));
150 for (uint32_t i=0; i < numpins; i++) {
151 uint8_t pin = pinlist[i];
152 if (pin >= NUM_DIGITAL_PINS)
continue;
153 uint8_t bit = digitalPinToBit(pin);
155 uint8_t offset = ((uint32_t)portOutputRegister(pin) - (uint32_t)&GPIO6_DR) >> 14;
156 if (offset > 3)
continue;
158 pin_offset[i] = offset;
159 uint32_t mask = 1 << bit;
160 bitmask[offset] |= mask;
162 *portControlRegister(pin) &= ~0xF9;
163 *portControlRegister(pin) |= ((OUTPUT_PAD_SPEED & 0x3) << 6) | \
164 ((OUTPUT_PAD_DSE & 0x7) << 3);
166 *(&IOMUXC_GPR_GPR26 + offset) &= ~mask;
167 *standard_gpio_addr(portModeRegister(pin)) |= mask;
170 memcpy(bitmaskLocal, bitmask, 16);
171 memcpy(pin_bitnumLocal, pin_bitnum, numpins);
172 memcpy(pin_offsetLocal, pin_offset, numpins);
174 arm_dcache_flush_delete(bitmask,
sizeof(bitmask));
177 comp1load[0] = (uint16_t)((
float)F_BUS_ACTUAL / 1000000000.0 * (float)TH_TL / OC_FACTOR );
178 comp1load[1] = (uint16_t)((
float)F_BUS_ACTUAL / 1000000000.0 * (float)T0H / OC_FACTOR );
179 comp1load[2] = (uint16_t)((
float)F_BUS_ACTUAL / 1000000000.0 * (float)T1H / (1.0 + ((OC_FACTOR - 1.0)/3)) );
181 TMR4_SCTRL0 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE | TMR_SCTRL_MSTR;
182 TMR4_CSCTRL0 = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_TCF1EN;
185 TMR4_COMP10 = comp1load[0];
186 TMR4_CMPLD10 = comp1load[0];
187 TMR4_CTRL0 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(3);
188 TMR4_SCTRL1 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
191 TMR4_COMP11 = comp1load[1];
192 TMR4_CMPLD11 = comp1load[1];
193 TMR4_CTRL1 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_COINIT | TMR_CTRL_OUTMODE(3);
194 TMR4_SCTRL2 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
197 TMR4_COMP12 = comp1load[2];
198 TMR4_CMPLD12 = comp1load[2];
199 TMR4_CTRL2 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_COINIT | TMR_CTRL_OUTMODE(3);
202 CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);
203 xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_DMA_CH_MUX_REQ30);
204 xbar_connect(XBARA1_IN_QTIMER4_TIMER1, XBARA1_OUT_DMA_CH_MUX_REQ31);
205 xbar_connect(XBARA1_IN_QTIMER4_TIMER2, XBARA1_OUT_DMA_CH_MUX_REQ94);
206 XBARA1_CTRL0 = XBARA_CTRL_STS1 | XBARA_CTRL_EDGE1(3) | XBARA_CTRL_DEN1 |
207 XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;
208 XBARA1_CTRL1 = XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;
212 dma1.TCD->SADDR = bitmask;
216 dma1.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_SMOD(4) | DMA_TCD_ATTR_DSIZE(2);
217 dma1.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
218 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
219 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
221 dma1.TCD->DADDR = &GPIO1_DR_SET;
222 dma1.TCD->DOFF = 16384;
223 dma1.TCD->CITER_ELINKNO = numbytes * 8;
224 dma1.TCD->DLASTSGA = -65536;
225 dma1.TCD->BITER_ELINKNO = numbytes * 8;
226 dma1.TCD->CSR = DMA_TCD_CSR_DREQ;
227 dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
229 dma2next.TCD->SADDR = bitdata;
230 dma2next.TCD->SOFF = 8;
231 dma2next.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_DSIZE(2);
232 dma2next.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
233 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
234 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
235 dma2next.TCD->SLAST = 0;
236 dma2next.TCD->DADDR = &GPIO1_DR_CLEAR;
237 dma2next.TCD->DOFF = 16384;
238 dma2next.TCD->CITER_ELINKNO = BYTES_PER_DMA * 8;
239 dma2next.TCD->DLASTSGA = (int32_t)(dma2next.TCD);
240 dma2next.TCD->BITER_ELINKNO = BYTES_PER_DMA * 8;
241 dma2next.TCD->CSR = 0;
245 dma2.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_1);
246 dma2.attachInterrupt(isr);
249 dma3.TCD->SADDR = bitmask;
251 dma3.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_SMOD(4) | DMA_TCD_ATTR_DSIZE(2);
252 dma3.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
253 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
254 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
256 dma3.TCD->DADDR = &GPIO1_DR_CLEAR;
257 dma3.TCD->DOFF = 16384;
258 dma3.TCD->CITER_ELINKNO = numbytes * 8;
259 dma3.TCD->DLASTSGA = -65536;
260 dma3.TCD->BITER_ELINKNO = numbytes * 8;
261 dma3.TCD->CSR = DMA_TCD_CSR_DREQ | DMA_TCD_CSR_DONE;
262 dma3.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_2);
270void fillbits(uint32_t *dest,
const uint8_t *pixels,
int n, uint32_t mask) {
272 uint8_t pix = *pixels++;
273 if (!(pix & 0x80)) *dest |= mask;
275 if (!(pix & 0x40)) *dest |= mask;
277 if (!(pix & 0x20)) *dest |= mask;
279 if (!(pix & 0x10)) *dest |= mask;
281 if (!(pix & 0x08)) *dest |= mask;
283 if (!(pix & 0x04)) *dest |= mask;
285 if (!(pix & 0x02)) *dest |= mask;
287 if (!(pix & 0x01)) *dest |= mask;
293void ObjectFLED::genFrameBuffer(uint32_t serp) {
297 switch (params & 0x3F) {
299 for (uint16_t i = 0; i < (numbytes * numpins); i += 4) {
300 uint8_t minRGB = MIN(*((uint8_t*)drawBuffer + j) * rLevel / 65025, \
301 *((uint8_t*)drawBuffer + j + 1) * rLevel / 65025);
302 minRGB = MIN(minRGB, *((uint8_t*)drawBuffer + j + 2) * rLevel / 65025);
303 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j) * rLevel / 65025 - minRGB;
304 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025 - minRGB;
305 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025 - minRGB;
306 *(frameBuffer + i + 3) = minRGB;
311 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
312 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
313 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
314 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
319 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
320 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
321 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
322 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
327 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
328 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
329 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
330 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
335 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
336 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
337 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
338 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
344 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
345 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
346 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
347 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
352 switch (params & 0x3F) {
354 for (uint16_t i = 0; i < (numbytes * numpins); i += 4) {
355 uint8_t minRGB = MIN(*((uint8_t*)drawBuffer + j) * rLevel / 65025, \
356 * ((uint8_t*)drawBuffer + j + 1) * rLevel / 65025);
357 minRGB = MIN(minRGB, *((uint8_t*)drawBuffer + j + 2) * rLevel / 65025);
358 if (i % (serp * 4) == 0) {
359 if (jChange < 0) { j = i / 4 * 3; jChange = 3; }
360 else { j = (i / 4 + serp - 1) * 3; jChange = -3; }
362 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j) * rLevel / 65025 - minRGB;
363 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025 - minRGB;
364 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025 - minRGB;
365 *(frameBuffer + i + 3) = minRGB;
370 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
371 if (i % (serp * 3) == 0) {
372 if (jChange < 0) { j = i; jChange = 3; }
373 else { j = i + (serp - 1) * 3; jChange = -3; }
375 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
376 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
377 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
382 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
383 if (i % (serp * 3) == 0) {
384 if (jChange < 0) { j = i; jChange = 3; }
385 else { j = i + (serp - 1) * 3; jChange = -3; }
387 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
388 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
389 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
394 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
395 if (i % (serp * 3) == 0) {
396 if (jChange < 0) { j = i; jChange = 3; }
397 else { j = i + (serp - 1) * 3; jChange = -3; }
399 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
400 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
401 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
406 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
407 if (i % (serp * 3) == 0) {
408 if (jChange < 0) { j = i; jChange = 3; }
409 else { j = i + (serp - 1) * 3; jChange = -3; }
411 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
412 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
413 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
419 for (uint16_t i = 0; i < (numbytes * numpins); i += 3) {
420 if (i % (serp * 3) == 0) {
421 if (jChange < 0) { j = i; jChange = 3; }
422 else { j = i + (serp - 1) * 3; jChange = -3; }
424 *(frameBuffer + i) = *((uint8_t*)drawBuffer + j) * rLevel / 65025;
425 *(frameBuffer + i + 1) = *((uint8_t*)drawBuffer + j + 1) * gLevel / 65025;
426 *(frameBuffer + i + 2) = *((uint8_t*)drawBuffer + j + 2) * bLevel / 65025;
439void ObjectFLED::show(
void) {
440 waitForDmaToFinish();
443 if (frameBuffer != frameBufferLocal) {
444 numpins = numpinsLocal;
445 frameBuffer = frameBufferLocal;
446 numbytes = numbytesLocal;
447 memcpy(bitmask, bitmaskLocal, 16);
448 memcpy(pin_bitnum, pin_bitnumLocal, numpins);
449 memcpy(pin_offset, pin_offsetLocal, numpins);
450 arm_dcache_flush_delete(bitmask,
sizeof(bitmask));
452 TMR4_COMP10 = comp1load[0];
453 TMR4_CMPLD10 = comp1load[0];
454 TMR4_COMP11 = comp1load[1];
455 TMR4_CMPLD11 = comp1load[1];
456 TMR4_COMP12 = comp1load[2];
457 TMR4_CMPLD12 = comp1load[2];
459 dma1.TCD->CITER_ELINKNO = numbytes * 8;
460 dma1.TCD->BITER_ELINKNO = numbytes * 8;
461 dma3.TCD->CITER_ELINKNO = numbytes * 8;
462 dma3.TCD->BITER_ELINKNO = numbytes * 8;
465 genFrameBuffer(serpNumber);
468 uint16_t enable = TMR4_ENBL;
469 TMR4_ENBL = enable & ~7;
472 TMR4_SCTRL0 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE | TMR_SCTRL_MSTR;
473 TMR4_SCTRL1 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
474 TMR4_SCTRL2 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
477 XBARA1_CTRL0 |= XBARA_CTRL_STS1 | XBARA_CTRL_STS0;
478 XBARA1_CTRL1 |= XBARA_CTRL_STS0;
481 memset(bitdata, 0,
sizeof(bitdata));
482 uint32_t count = numbytes;
483 if (count > BYTES_PER_DMA*2) count = BYTES_PER_DMA*2;
484 framebuffer_index = count;
487 for (uint32_t i=0; i < numpins; i++) {
488 fillbits(bitdata + pin_offset[i], (uint8_t *)frameBuffer + i*numbytes,
489 count, 1<<pin_bitnum[i]);
491 arm_dcache_flush_delete(bitdata, count * 128);
494 if (numbytes <= BYTES_PER_DMA*2) {
495 dma2.TCD->SADDR = bitdata;
496 dma2.TCD->DADDR = &GPIO1_DR_CLEAR;
497 dma2.TCD->CITER_ELINKNO = count * 8;
498 dma2.TCD->CSR = DMA_TCD_CSR_DREQ;
500 dma2.TCD->SADDR = bitdata;
501 dma2.TCD->DADDR = &GPIO1_DR_CLEAR;
502 dma2.TCD->CITER_ELINKNO = BYTES_PER_DMA * 8;
504 dma2.TCD->CSR = DMA_TCD_CSR_INTMAJOR | DMA_TCD_CSR_ESG;
505 dma2next.TCD->SADDR = bitdata + BYTES_PER_DMA*32;
506 dma2next.TCD->CITER_ELINKNO = BYTES_PER_DMA * 8;
507 if (numbytes <= BYTES_PER_DMA*3) {
508 dma2next.TCD->CSR = DMA_TCD_CSR_ESG;
510 dma2next.TCD->CSR = DMA_TCD_CSR_ESG | DMA_TCD_CSR_INTMAJOR;
514 dma3.clearComplete();
521 TMR4_CNTR1 = comp1load[0] + 1;
522 TMR4_CNTR2 = comp1load[0] + 1;
525 while (micros() - update_begin_micros < numbytes * 8 * TH_TL / OC_FACTOR / 1000 + LATCH_DELAY);
528 TMR4_ENBL = enable | 7;
529 update_begin_micros = micros();
536void ObjectFLED::isr(
void)
539 dma2.clearInterrupt();
549 dest = bitdata + BYTES_PER_DMA*32;
551 memset(dest, 0,
sizeof(bitdata)/2);
552 uint32_t index = framebuffer_index;
553 uint32_t count = numbytes - framebuffer_index;
554 if (count > BYTES_PER_DMA) count = BYTES_PER_DMA;
555 framebuffer_index = index + count;
556 for (
int i=0; i < numpins; i++) {
557 fillbits(dest + pin_offset[i], (uint8_t *)frameBuffer + index + i*numbytes,
558 count, 1<<pin_bitnum[i]);
560 arm_dcache_flush_delete(dest, count * 128);
564 dma2next.TCD->SADDR = dest;
565 dma2next.TCD->CITER_ELINKNO = count * 8;
566 uint32_t remain = numbytes - (index + count);
568 dma2next.TCD->CSR = DMA_TCD_CSR_DREQ;
569 }
else if (remain <= BYTES_PER_DMA) {
570 dma2next.TCD->CSR = DMA_TCD_CSR_ESG;
572 dma2next.TCD->CSR = DMA_TCD_CSR_ESG | DMA_TCD_CSR_INTMAJOR;
577int ObjectFLED::busy(
void)
579 if (micros() - update_begin_micros < numbytes * TH_TL / OC_FACTOR / 1000 * 8 + LATCH_DELAY) {
586void ObjectFLED::setBrightness(uint8_t brightLevel) {
587 brightness = brightLevel;
588 rLevel = brightness * (colorBalance >> 16);
589 gLevel = brightness * ((colorBalance >> 8) & 0xFF);
590 bLevel = brightness * (colorBalance & 0xFF);
594void ObjectFLED::setBalance(uint32_t balMask) {
595 colorBalance = balMask & 0xFFFFFF;
596 rLevel = brightness * (colorBalance >> 16);
597 gLevel = brightness * ((colorBalance >> 8) & 0xFF);
598 bLevel = brightness * (colorBalance & 0xFF);
603void fadeToColorBy(
void* leds, uint16_t count, uint32_t color, uint8_t fadeAmt) {
604 for (uint32_t x = 0; x < count * 3; x += 3) {
606 *((uint8_t*)leds + x) = (( *((uint8_t*)leds + x) * (1 + (255 - fadeAmt))) >> 8) + \
607 (( ((color >> 16) & 0xFF) * (1 + fadeAmt)) >> 8);
609 *((uint8_t*)leds + x + 1) = (( *((uint8_t*)leds + x + 1) * (1 + (255 - fadeAmt))) >> 8) + \
610 (( ((color >> 8) & 0xFF) * (1 + fadeAmt)) >> 8);
612 *((uint8_t*)leds + x + 2) = (( *((uint8_t*)leds + x + 2) * (1 + (255 - fadeAmt))) >> 8) + \
613 (( (color & 0xFF) * (1 + fadeAmt)) >> 8);
619void drawSquare(
void* leds, uint16_t planeY, uint16_t planeX,
int yCorner,
int xCorner, uint32_t size, uint32_t color) {
620 if (size != 0) { size--; }
622 for (
int x = xCorner; x <= xCorner + (int)size; x++) {
624 if ((x >= 0) && (x < planeX)) {
625 if ((yCorner >= 0) && (yCorner < planeY)) {
626 *((uint8_t*)leds + (yCorner * planeX + x) * 3) = ((color >> 16) & 0xFF);
627 *((uint8_t*)leds + (yCorner * planeX + x) * 3 + 1) = ((color >> 8) & 0xFF);
628 *((uint8_t*)leds + (yCorner * planeX + x) * 3 + 2) = (color & 0xFF);
630 if ((yCorner + size >= 0) && (yCorner + size < planeY)) {
631 *((uint8_t*)leds + ((yCorner + size) * planeX + x) * 3) = ((color >> 16) & 0xFF);
632 *((uint8_t*)leds + ((yCorner + size) * planeX + x) * 3 + 1) = ((color >> 8) & 0xFF);
633 *((uint8_t*)leds + ((yCorner + size) * planeX + x) * 3 + 2) = (color & 0xFF);
637 for (
int y = yCorner; y <= yCorner + (int)size; y++) {
638 if ((y >= 0) && (y < planeY)) {
639 if ((xCorner >= 0) && (xCorner < planeX)) {
640 *((uint8_t*)leds + (xCorner + y * planeX) * 3) = ((color >> 16) & 0xFF);
641 *((uint8_t*)leds + (xCorner + y * planeX) * 3 + 1) = ((color >> 8) & 0xFF);
642 *((uint8_t*)leds + (xCorner + y * planeX) * 3 + 2) = (color & 0xFF);
644 if ((xCorner + size >= 0) && (xCorner + size < planeX)) {
645 *((uint8_t*)leds + (xCorner + size + y * planeX) * 3) = ((color >> 16) & 0xFF);
646 *((uint8_t*)leds + (xCorner + size + y * planeX) * 3 + 1) = ((color >> 8) & 0xFF);
647 *((uint8_t*)leds + (xCorner + size + y * planeX) * 3 + 2) = (color & 0xFF);
Implements a simple red square effect for 2D LED grids.