|
|
|
|
|
|
|
|
bool WS2812Serial::begin() |
|
|
bool WS2812Serial::begin() |
|
|
{ |
|
|
{ |
|
|
uint32_t divisor, portconfig, hwtrigger; |
|
|
uint32_t divisor, portconfig, hwtrigger; |
|
|
#if defined(KINETISK) |
|
|
|
|
|
KINETISK_UART_t *uart; |
|
|
KINETISK_UART_t *uart; |
|
|
#elif defined(KINETISL) |
|
|
|
|
|
KINETISL_UART_t *uart; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
switch (pin) { |
|
|
switch (pin) { |
|
|
#if defined(KINETISK) |
|
|
|
|
|
|
|
|
#if defined(KINETISK) // Teensy 3.x |
|
|
case 1: // Serial1 |
|
|
case 1: // Serial1 |
|
|
case 5: |
|
|
case 5: |
|
|
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) |
|
|
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) |
|
|
|
|
|
|
|
|
SIM_SCGC1 |= SIM_SCGC1_UART5; |
|
|
SIM_SCGC1 |= SIM_SCGC1_UART5; |
|
|
break; |
|
|
break; |
|
|
#endif |
|
|
#endif |
|
|
#elif defined(KINETISL) |
|
|
|
|
|
// TODO: Teesny LC support.... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#elif defined(KINETISL) // Teensy LC |
|
|
|
|
|
case 1: // Serial1 |
|
|
|
|
|
case 5: |
|
|
|
|
|
uart = &KINETISK_UART0; |
|
|
|
|
|
divisor = 2; |
|
|
|
|
|
portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); |
|
|
|
|
|
hwtrigger = DMAMUX_SOURCE_UART0_TX; |
|
|
|
|
|
SIM_SCGC4 |= SIM_SCGC4_UART0; |
|
|
|
|
|
break; |
|
|
|
|
|
case 4: |
|
|
|
|
|
uart = &KINETISK_UART0; |
|
|
|
|
|
divisor = 2; |
|
|
|
|
|
portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); |
|
|
|
|
|
hwtrigger = DMAMUX_SOURCE_UART0_TX; |
|
|
|
|
|
SIM_SCGC4 |= SIM_SCGC4_UART0; |
|
|
|
|
|
break; |
|
|
|
|
|
case 24: |
|
|
|
|
|
uart = &KINETISK_UART0; |
|
|
|
|
|
divisor = 2; |
|
|
|
|
|
portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4); |
|
|
|
|
|
hwtrigger = DMAMUX_SOURCE_UART0_TX; |
|
|
|
|
|
SIM_SCGC4 |= SIM_SCGC4_UART0; |
|
|
|
|
|
break; |
|
|
#endif |
|
|
#endif |
|
|
default: |
|
|
default: |
|
|
return false; // pin not supported |
|
|
return false; // pin not supported |
|
|
|
|
|
|
|
|
dma = new DMAChannel; |
|
|
dma = new DMAChannel; |
|
|
if (!dma) return false; // unable to allocate DMA channel |
|
|
if (!dma) return false; // unable to allocate DMA channel |
|
|
} |
|
|
} |
|
|
|
|
|
#if defined(KINETISK) |
|
|
uart->BDH = (divisor >> 13) & 0x1F; |
|
|
uart->BDH = (divisor >> 13) & 0x1F; |
|
|
uart->BDL = (divisor >> 5) & 0xFF; |
|
|
uart->BDL = (divisor >> 5) & 0xFF; |
|
|
uart->C4 = divisor & 0x1F; |
|
|
uart->C4 = divisor & 0x1F; |
|
|
|
|
|
#elif defined(KINETISL) |
|
|
|
|
|
uart->BDH = (divisor >> 8) & 0x1F; |
|
|
|
|
|
uart->BDL = divisor & 0xFF; |
|
|
|
|
|
uart->C4 = 9; |
|
|
|
|
|
#endif |
|
|
uart->C1 = 0; |
|
|
uart->C1 = 0; |
|
|
uart->PFIFO = 0; |
|
|
|
|
|
uart->C2 = UART_C2_TE | UART_C2_TIE; |
|
|
uart->C2 = UART_C2_TE | UART_C2_TIE; |
|
|
uart->C3 = UART_C3_TXINV; |
|
|
uart->C3 = UART_C3_TXINV; |
|
|
uart->C5 = UART_C5_TDMAS; |
|
|
uart->C5 = UART_C5_TDMAS; |
|
|
|
|
|
#if defined(KINETISK) |
|
|
|
|
|
uart->PFIFO = 0; // TODO: is this ok for Serial3-6? |
|
|
|
|
|
#endif |
|
|
*(portConfigRegister(pin)) = portconfig; |
|
|
*(portConfigRegister(pin)) = portconfig; |
|
|
dma->destination(uart->D); |
|
|
dma->destination(uart->D); |
|
|
dma->triggerAtHardwareEvent(hwtrigger); |
|
|
dma->triggerAtHardwareEvent(hwtrigger); |
|
|
|
|
|
|
|
|
void WS2812Serial::show() |
|
|
void WS2812Serial::show() |
|
|
{ |
|
|
{ |
|
|
// wait if prior DMA still in progress |
|
|
// wait if prior DMA still in progress |
|
|
|
|
|
#if defined(KINETISK) |
|
|
while ((DMA_ERQ & (1 << dma->channel))) { |
|
|
while ((DMA_ERQ & (1 << dma->channel))) { |
|
|
yield(); |
|
|
yield(); |
|
|
} |
|
|
} |
|
|
|
|
|
#elif defined(KINETISL) |
|
|
|
|
|
while ((dma->CFG->DCR & DMA_DCR_ERQ)) { |
|
|
|
|
|
yield(); |
|
|
|
|
|
} |
|
|
|
|
|
#elif defined(KINETISL) |
|
|
|
|
|
#endif |
|
|
// wait 300us WS2812 reset time |
|
|
// wait 300us WS2812 reset time |
|
|
uint32_t min_elapsed = ((numled * 34134) >> 10) + 300; |
|
|
uint32_t min_elapsed = ((numled * 34134) >> 10) + 300; |
|
|
if (min_elapsed < 2500) min_elapsed = 2500; |
|
|
if (min_elapsed < 2500) min_elapsed = 2500; |