|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "WS2812Serial.h" |
|
|
#include "WS2812Serial.h" |
|
|
|
|
|
|
|
|
void WS2812Serial::begin() |
|
|
|
|
|
|
|
|
bool WS2812Serial::begin() |
|
|
{ |
|
|
{ |
|
|
if (!uart) return; |
|
|
|
|
|
if (!dma) dma = new DMAChannel; |
|
|
|
|
|
if (!dma) return; |
|
|
|
|
|
|
|
|
|
|
|
SIM_SCGC4 |= SIM_SCGC4_UART0; |
|
|
|
|
|
uint32_t divisor = BAUD2DIV(2400000); |
|
|
|
|
|
|
|
|
|
|
|
CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); |
|
|
|
|
|
|
|
|
|
|
|
UART0_BDH = (divisor >> 13) & 0x1F; |
|
|
|
|
|
UART0_BDL = (divisor >> 5) & 0xFF; |
|
|
|
|
|
UART0_C4 = divisor & 0x1F; |
|
|
|
|
|
|
|
|
|
|
|
UART0_C1 = 0; |
|
|
|
|
|
UART0_PFIFO = 0; |
|
|
|
|
|
UART0_C2 = UART_C2_TE; |
|
|
|
|
|
UART0_C3 = UART_C3_TXINV; |
|
|
|
|
|
UART0_C5 = UART_C5_TDMAS; |
|
|
|
|
|
|
|
|
uint32_t divisor, portconfig, hwtrigger; |
|
|
|
|
|
KINETISK_UART_t *uart; |
|
|
|
|
|
|
|
|
|
|
|
switch (pin) { |
|
|
|
|
|
case 1: |
|
|
|
|
|
uart = &KINETISK_UART0; |
|
|
|
|
|
divisor = BAUD2DIV(2400000); |
|
|
|
|
|
portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); |
|
|
|
|
|
hwtrigger = DMAMUX_SOURCE_UART0_TX; |
|
|
|
|
|
SIM_SCGC4 |= SIM_SCGC4_UART0; |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
return false; // pin not supported |
|
|
|
|
|
} |
|
|
|
|
|
if (!dma) { |
|
|
|
|
|
dma = new DMAChannel; |
|
|
|
|
|
if (!dma) return false; // unable to allocate DMA channel |
|
|
|
|
|
} |
|
|
|
|
|
uart->BDH = (divisor >> 13) & 0x1F; |
|
|
|
|
|
uart->BDL = (divisor >> 5) & 0xFF; |
|
|
|
|
|
uart->C4 = divisor & 0x1F; |
|
|
|
|
|
uart->C1 = 0; |
|
|
|
|
|
uart->PFIFO = 0; |
|
|
|
|
|
uart->C2 = UART_C2_TE | UART_C2_TIE; |
|
|
|
|
|
uart->C3 = UART_C3_TXINV; |
|
|
|
|
|
uart->C5 = UART_C5_TDMAS; |
|
|
|
|
|
*(portConfigRegister(pin)) = portconfig; |
|
|
|
|
|
dma->destination(uart->D); |
|
|
|
|
|
dma->triggerAtHardwareEvent(hwtrigger); |
|
|
memset(drawBuffer, 0, numled * 3); |
|
|
memset(drawBuffer, 0, numled * 3); |
|
|
|
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void WS2812Serial::show() |
|
|
void WS2812Serial::show() |
|
|
{ |
|
|
{ |
|
|
|
|
|
|
|
|
//UART0_D = 0xDB; |
|
|
|
|
|
//UART0_D = 0xDA; |
|
|
|
|
|
//UART0_D = 0xDB; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: wait if prior DMA in progress |
|
|
|
|
|
// TODO: wait 300us WS2812 reset time |
|
|
const uint8_t *p = drawBuffer; |
|
|
const uint8_t *p = drawBuffer; |
|
|
const uint8_t *end = p + (numled * 3); |
|
|
const uint8_t *end = p + (numled * 3); |
|
|
uint8_t *fb = frameBuffer; |
|
|
uint8_t *fb = frameBuffer; |
|
|
|
|
|
|
|
|
case WS2812_BRG: n = (b << 16) | (r << 8) | g; break; |
|
|
case WS2812_BRG: n = (b << 16) | (r << 8) | g; break; |
|
|
case WS2812_BGR: n = (b << 16) | (g << 8) | r; break; |
|
|
case WS2812_BGR: n = (b << 16) | (g << 8) | r; break; |
|
|
} |
|
|
} |
|
|
//Serial.printf("n = %06X\n", n); |
|
|
|
|
|
const uint8_t *stop = fb + 8; |
|
|
const uint8_t *stop = fb + 8; |
|
|
do { |
|
|
do { |
|
|
uint8_t x = 0x92; |
|
|
uint8_t x = 0x92; |
|
|
|
|
|
|
|
|
*fb++ = x; |
|
|
*fb++ = x; |
|
|
} while (fb < stop); |
|
|
} while (fb < stop); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
dma->sourceBuffer(frameBuffer, numled * 8); |
|
|
dma->sourceBuffer(frameBuffer, numled * 8); |
|
|
dma->destination(UART0_D); |
|
|
|
|
|
dma->transferSize(1); |
|
|
dma->transferSize(1); |
|
|
dma->transferCount(numled * 8); |
|
|
dma->transferCount(numled * 8); |
|
|
dma->disableOnCompletion(); |
|
|
dma->disableOnCompletion(); |
|
|
dma->triggerAtHardwareEvent(DMAMUX_SOURCE_UART0_TX); |
|
|
|
|
|
dma->enable(); |
|
|
dma->enable(); |
|
|
UART0_C2 = UART_C2_TE | UART_C2_TIE; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|