60#include "platforms/arm/teensy/is_teensy.h"
62#ifndef FL_IS_TEENSY_4X
71#define MIN(a,b) ((a)<(b)?(a):(b))
75#define MAX(a,b) ((a)>(b)?(a):(b))
80volatile bool dma_first;
88 if (numPins > NUM_DIGITAL_PINS) numPins = NUM_DIGITAL_PINS;
103extern "C" void xbar_connect(
unsigned int input,
unsigned int output);
140 auto& dma = ObjectFLEDDmaManager::getInstance();
150 if (!validation.valid) {
151 FL_WARN(
"================================================================================");
152 FL_WARN(
"FASTLED ERROR: Pin " << (
int)pin <<
" is INVALID and has been disabled");
153 FL_WARN(validation.error_message);
154 FL_WARN(
"================================================================================");
159 if (validation.error_message !=
nullptr) {
160 FL_WARN(
"================================================================================");
161 FL_WARN(
"FASTLED WARNING: Pin " << (
int)pin <<
" may have issues");
162 FL_WARN(validation.error_message);
163 FL_WARN(
"================================================================================");
166 uint8_t bit = digitalPinToBit(pin);
170 FL_WARN(
"================================================================================");
171 FL_WARN(
"FASTLED ERROR: Pin " << (
int)pin <<
" does not map to GPIO6-9 (offset=" << (
int)
offset <<
")");
172 FL_WARN(
"This pin may be a ground/power/read-only pin - strip disabled");
173 FL_WARN(
"================================================================================");
181 tempBitmask[
offset] |= mask;
183 *portControlRegister(pin) &= ~0xF9;
187 *(&IOMUXC_GPR_GPR26 +
offset) &= ~mask;
188 *standard_gpio_addr(portModeRegister(pin)) |= mask;
192 if (validPinCount == 0) {
193 FL_WARN(
"================================================================================");
194 FL_WARN(
"FASTLED CRITICAL ERROR: No valid pins configured!");
196 FL_WARN(
"ObjectFLED driver is disabled - no LEDs will be updated.");
197 FL_WARN(
"================================================================================");
202 FL_WARN(
"================================================================================");
203 FL_WARN(
"FASTLED WARNING: Only " << (
int)validPinCount <<
" of " << (
int)
numpinsLocal <<
" pins are valid");
204 FL_WARN(
"Strips on invalid pins will not function.");
205 FL_WARN(
"================================================================================");
218 TMR4_SCTRL0 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE | TMR_SCTRL_MSTR;
219 TMR4_CSCTRL0 = TMR_CSCTRL_CL1(1) | TMR_CSCTRL_TCF1EN;
224 TMR4_CTRL0 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_LENGTH | TMR_CTRL_OUTMODE(3);
225 TMR4_SCTRL1 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
230 TMR4_CTRL1 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_COINIT | TMR_CTRL_OUTMODE(3);
231 TMR4_SCTRL2 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
236 TMR4_CTRL2 = TMR_CTRL_CM(1) | TMR_CTRL_PCS(8) | TMR_CTRL_COINIT | TMR_CTRL_OUTMODE(3);
239 CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);
240 xbar_connect(XBARA1_IN_QTIMER4_TIMER0, XBARA1_OUT_DMA_CH_MUX_REQ30);
241 xbar_connect(XBARA1_IN_QTIMER4_TIMER1, XBARA1_OUT_DMA_CH_MUX_REQ31);
242 xbar_connect(XBARA1_IN_QTIMER4_TIMER2, XBARA1_OUT_DMA_CH_MUX_REQ94);
243 XBARA1_CTRL0 = XBARA_CTRL_STS1 | XBARA_CTRL_EDGE1(3) | XBARA_CTRL_DEN1 |
244 XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;
245 XBARA1_CTRL1 = XBARA_CTRL_STS0 | XBARA_CTRL_EDGE0(3) | XBARA_CTRL_DEN0;
249 dma.dma1.TCD->SADDR = dma.bitmask;
250 dma.dma1.TCD->SOFF = 8;
253 dma.dma1.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_SMOD(4) | DMA_TCD_ATTR_DSIZE(2);
254 dma.dma1.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
255 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
256 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
257 dma.dma1.TCD->SLAST = 0;
258 dma.dma1.TCD->DADDR = &GPIO1_DR_SET;
259 dma.dma1.TCD->DOFF = 16384;
261 dma.dma1.TCD->DLASTSGA = -65536;
263 dma.dma1.TCD->CSR = DMA_TCD_CSR_DREQ;
264 dma.dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_0);
266 dma.dma2next.TCD->SADDR = dma.bitdata;
267 dma.dma2next.TCD->SOFF = 8;
268 dma.dma2next.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_DSIZE(2);
269 dma.dma2next.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
270 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
271 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
272 dma.dma2next.TCD->SLAST = 0;
273 dma.dma2next.TCD->DADDR = &GPIO1_DR_CLEAR;
274 dma.dma2next.TCD->DOFF = 16384;
276 dma.dma2next.TCD->DLASTSGA = (
int32_t)(dma.dma2next.TCD);
278 dma.dma2next.TCD->CSR = 0;
281 dma.dma2 = dma.dma2next;
282 dma.dma2.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_1);
283 dma.dma2.attachInterrupt(
isr);
286 dma.dma3.TCD->SADDR = dma.bitmask;
287 dma.dma3.TCD->SOFF = 8;
288 dma.dma3.TCD->ATTR = DMA_TCD_ATTR_SSIZE(3) | DMA_TCD_ATTR_SMOD(4) | DMA_TCD_ATTR_DSIZE(2);
289 dma.dma3.TCD->NBYTES_MLOFFYES = DMA_TCD_NBYTES_DMLOE |
290 DMA_TCD_NBYTES_MLOFFYES_MLOFF(-65536) |
291 DMA_TCD_NBYTES_MLOFFYES_NBYTES(16);
292 dma.dma3.TCD->SLAST = 0;
293 dma.dma3.TCD->DADDR = &GPIO1_DR_CLEAR;
294 dma.dma3.TCD->DOFF = 16384;
296 dma.dma3.TCD->DLASTSGA = -65536;
298 dma.dma3.TCD->CSR = DMA_TCD_CSR_DREQ | DMA_TCD_CSR_DONE;
299 dma.dma3.triggerAtHardwareEvent(DMAMUX_SOURCE_XBAR1_2);
310 if (!(pix & 0x80)) *dest |= mask;
312 if (!(pix & 0x40)) *dest |= mask;
314 if (!(pix & 0x20)) *dest |= mask;
316 if (!(pix & 0x10)) *dest |= mask;
318 if (!(pix & 0x08)) *dest |= mask;
320 if (!(pix & 0x04)) *dest |= mask;
322 if (!(pix & 0x02)) *dest |= mask;
324 if (!(pix & 0x01)) *dest |= mask;
395 if (i % (serp * 4) == 0) {
396 if (jChange < 0) { j = i / 4 * 3; jChange = 3; }
397 else { j = (i / 4 + serp - 1) * 3; jChange = -3; }
408 if (i % (serp * 3) == 0) {
409 if (jChange < 0) { j = i; jChange = 3; }
410 else { j = i + (serp - 1) * 3; jChange = -3; }
420 if (i % (serp * 3) == 0) {
421 if (jChange < 0) { j = i; jChange = 3; }
422 else { j = i + (serp - 1) * 3; jChange = -3; }
432 if (i % (serp * 3) == 0) {
433 if (jChange < 0) { j = i; jChange = 3; }
434 else { j = i + (serp - 1) * 3; jChange = -3; }
444 if (i % (serp * 3) == 0) {
445 if (jChange < 0) { j = i; jChange = 3; }
446 else { j = i + (serp - 1) * 3; jChange = -3; }
457 if (i % (serp * 3) == 0) {
458 if (jChange < 0) { j = i; jChange = 3; }
459 else { j = i + (serp - 1) * 3; jChange = -3; }
477 auto& dma = ObjectFLEDDmaManager::getInstance();
490 arm_dcache_flush_delete(dma.bitmask,
sizeof(dma.bitmask));
499 dma.dma1.TCD->CITER_ELINKNO = dma.numbytes * 8;
500 dma.dma1.TCD->BITER_ELINKNO = dma.numbytes * 8;
501 dma.dma3.TCD->CITER_ELINKNO = dma.numbytes * 8;
502 dma.dma3.TCD->BITER_ELINKNO = dma.numbytes * 8;
509 TMR4_ENBL = enable & ~7;
512 TMR4_SCTRL0 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE | TMR_SCTRL_MSTR;
513 TMR4_SCTRL1 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
514 TMR4_SCTRL2 = TMR_SCTRL_OEN | TMR_SCTRL_FORCE;
517 XBARA1_CTRL0 |= XBARA_CTRL_STS1 | XBARA_CTRL_STS0;
518 XBARA1_CTRL1 |= XBARA_CTRL_STS0;
521 memset(dma.bitdata, 0,
sizeof(dma.bitdata));
524 dma.framebuffer_index = count;
527 for (
uint32_t i=0; i < dma.numpins; i++) {
528 fillbits(dma.bitdata + dma.pin_offset[i], (
uint8_t *)dma.frameBuffer + i*dma.numbytes,
529 count, 1<<dma.pin_bitnum[i]);
531 arm_dcache_flush_delete(dma.bitdata, count * 128);
535 dma.dma2.TCD->SADDR = dma.bitdata;
536 dma.dma2.TCD->DADDR = &GPIO1_DR_CLEAR;
537 dma.dma2.TCD->CITER_ELINKNO = count * 8;
538 dma.dma2.TCD->CSR = DMA_TCD_CSR_DREQ;
540 dma.dma2.TCD->SADDR = dma.bitdata;
541 dma.dma2.TCD->DADDR = &GPIO1_DR_CLEAR;
543 dma.dma2.TCD->CSR = 0;
544 dma.dma2.TCD->CSR = DMA_TCD_CSR_INTMAJOR | DMA_TCD_CSR_ESG;
548 dma.dma2next.TCD->CSR = DMA_TCD_CSR_ESG;
550 dma.dma2next.TCD->CSR = DMA_TCD_CSR_ESG | DMA_TCD_CSR_INTMAJOR;
554 dma.dma3.clearComplete();
568 TMR4_ENBL = enable | 7;
581 auto& dma = ObjectFLEDDmaManager::getInstance();
584 dma.dma2.clearInterrupt();
596 memset(dest, 0,
sizeof(dma.bitdata)/2);
597 uint32_t index = dma.framebuffer_index;
598 uint32_t count = dma.numbytes - dma.framebuffer_index;
600 dma.framebuffer_index = index + count;
601 for (
int i=0; i < dma.numpins; i++) {
602 fillbits(dest + dma.pin_offset[i], (
uint8_t *)dma.frameBuffer + index + i*dma.numbytes,
603 count, 1<<dma.pin_bitnum[i]);
605 arm_dcache_flush_delete(dest, count * 128);
609 dma.dma2next.TCD->SADDR = dest;
610 dma.dma2next.TCD->CITER_ELINKNO = count * 8;
611 uint32_t remain = dma.numbytes - (index + count);
613 dma.dma2next.TCD->CSR = DMA_TCD_CSR_DREQ;
615 dma.dma2next.TCD->CSR = DMA_TCD_CSR_ESG;
617 dma.dma2next.TCD->CSR = DMA_TCD_CSR_ESG | DMA_TCD_CSR_INTMAJOR;
624 auto& dma = ObjectFLEDDmaManager::getInstance();
653 (( ((color >> 16) & 0xFF) * (1 + fadeAmt)) >> 8);
656 (( ((color >> 8) & 0xFF) * (1 + fadeAmt)) >> 8);
659 (( (color & 0xFF) * (1 + fadeAmt)) >> 8);
666 if (size != 0) { size--; }
668 for (
int x = xCorner;
x <= xCorner + (int)size;
x++) {
670 if ((
x >= 0) && (
x < planeX)) {
671 if ((yCorner >= 0) && (yCorner < planeY)) {
672 *((
uint8_t*)
leds + (yCorner * planeX +
x) * 3) = ((color >> 16) & 0xFF);
673 *((
uint8_t*)
leds + (yCorner * planeX +
x) * 3 + 1) = ((color >> 8) & 0xFF);
674 *((
uint8_t*)
leds + (yCorner * planeX +
x) * 3 + 2) = (color & 0xFF);
681 if ((yCorner + (
int)size >= 0) && (yCorner + (
int)size < planeY)) {
682 *((
uint8_t*)
leds + ((yCorner + (
int)size) * planeX +
x) * 3) = ((color >> 16) & 0xFF);
683 *((
uint8_t*)
leds + ((yCorner + (
int)size) * planeX +
x) * 3 + 1) = ((color >> 8) & 0xFF);
684 *((
uint8_t*)
leds + ((yCorner + (
int)size) * planeX +
x) * 3 + 2) = (color & 0xFF);
688 for (
int y = yCorner;
y <= yCorner + (int)size;
y++) {
689 if ((
y >= 0) && (
y < planeY)) {
690 if ((xCorner >= 0) && (xCorner < planeX)) {
691 *((
uint8_t*)
leds + (xCorner +
y * planeX) * 3) = ((color >> 16) & 0xFF);
692 *((
uint8_t*)
leds + (xCorner +
y * planeX) * 3 + 1) = ((color >> 8) & 0xFF);
693 *((
uint8_t*)
leds + (xCorner +
y * planeX) * 3 + 2) = (color & 0xFF);
696 if ((xCorner + (
int)size >= 0) && (xCorner + (
int)size < planeX)) {
697 *((
uint8_t*)
leds + (xCorner + (
int)size +
y * planeX) * 3) = ((color >> 16) & 0xFF);
698 *((
uint8_t*)
leds + (xCorner + (
int)size +
y * planeX) * 3 + 1) = ((color >> 8) & 0xFF);
699 *((
uint8_t*)
leds + (xCorner + (
int)size +
y * planeX) * 3 + 2) = (color & 0xFF);
717 ObjectFLEDDmaManager::getInstance().waitForCompletion();
uint8_t * frameBufferLocal
uint8_t pin_bitnumLocal[NUM_DIGITAL_PINS]
uint8_t pinlist[NUM_DIGITAL_PINS]
uint32_t update_begin_micros
void setBalance(uint32_t)
void genFrameBuffer(uint32_t)
ObjectFLED(uint16_t numLEDs, void *drawBuf, uint8_t config, uint8_t numPins, const uint8_t *pinList, uint8_t serpentine=0)
void waitForDmaToFinish()
void setBrightness(uint8_t)
void beginInternal(uint16_t, uint16_t, uint16_t, uint16_t=300)
uint8_t pin_offsetLocal[NUM_DIGITAL_PINS]
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
Centralized logging categories for FastLED hardware interfaces and subsystems.
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
void drawSquare(void *, uint16_t, uint16_t, int, int, uint32_t, uint32_t)
fl::u32 micros()
Universal microsecond timer - returns microseconds since system startup.
void fadeToColorBy(void *, uint16_t, uint32_t, uint8_t)
Base definition for an LED controller.
PinValidationResult validate_teensy4_pin(uint8_t pin)