Browse Source

Merge pull request #8 from KurtE/T4

T4 Support
main_ledos
Paul Stoffregen 5 years ago
parent
commit
520b6bdc7f
No account linked to committer's email address
5 changed files with 103 additions and 9 deletions
  1. +90
    -1
      WS2812Serial.cpp
  2. +3
    -0
      WS2812Serial.h
  3. +1
    -0
      examples/BasicTest/BasicTest.ino
  4. +1
    -0
      examples/FastLED_Cylon/FastLED_Cylon.ino
  5. +8
    -8
      readme.md

+ 90
- 1
WS2812Serial.cpp View File



bool WS2812Serial::begin() bool WS2812Serial::begin()
{ {
#if defined(__IMXRT1062__) // Teensy 3.x
uint32_t hwtrigger;
#else
uint32_t divisor, portconfig, hwtrigger; uint32_t divisor, portconfig, hwtrigger;
KINETISK_UART_t *uart; KINETISK_UART_t *uart;

#endif
switch (pin) { switch (pin) {
#if defined(KINETISK) // Teensy 3.x #if defined(KINETISK) // Teensy 3.x
case 1: // Serial1 case 1: // Serial1
#elif defined(KINETISL) // Teensy LC #elif defined(KINETISL) // Teensy LC
case 1: // Serial1 case 1: // Serial1
case 5: case 5:
// NOT SURE HOW THIS WORKS ON LC?????
uart = &KINETISK_UART0; uart = &KINETISK_UART0;
divisor = 1; divisor = 1;
portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
hwtrigger = DMAMUX_SOURCE_UART0_TX; hwtrigger = DMAMUX_SOURCE_UART0_TX;
SIM_SCGC4 |= SIM_SCGC4_UART0; SIM_SCGC4 |= SIM_SCGC4_UART0;
break; break;

#elif defined(__IMXRT1062__)
case 1: // Serial1
uart = &IMXRT_LPUART6;
CCM_CCGR3 |= CCM_CCGR3_LPUART6(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART6_TX;
break;
case 8: // Serial2
uart = &IMXRT_LPUART4;
CCM_CCGR1 |= CCM_CCGR1_LPUART4(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART4_TX;
break;
case 14: // Serial3
uart = &IMXRT_LPUART2;
CCM_CCGR0 |= CCM_CCGR0_LPUART2(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART2_TX;
break;
case 17: // Serial4
uart = &IMXRT_LPUART3;
CCM_CCGR0 |= CCM_CCGR0_LPUART3(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART3_TX;
break;
case 20: // Serial5
case 39: // Serial5 alt
uart = &IMXRT_LPUART8;
CCM_CCGR6 |= CCM_CCGR6_LPUART8(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART8_TX;
break;
case 24: // Serial6
uart = &IMXRT_LPUART1;
CCM_CCGR5 |= CCM_CCGR5_LPUART1(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART1_TX;
break;
case 29: // Serial7
uart = &IMXRT_LPUART7;
CCM_CCGR5 |= CCM_CCGR5_LPUART7(CCM_CCGR_ON);
hwtrigger = DMAMUX_SOURCE_LPUART7_TX;
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(__IMXRT1062__)
// Convert Baud
// Computed values for 4mhz
uart->CTRL = 0; // clear everything
uart->BAUD = LPUART_BAUD_OSR(5) | LPUART_BAUD_SBR(1) | LPUART_BAUD_TDMAE; // set baud configure for transfer DMA
uart->PINCFG = 0;
uint16_t tx_fifo_size = (((uart->FIFO >> 4) & 0x7) << 2);
uint8_t tx_water = (tx_fifo_size < 16) ? tx_fifo_size >> 1 : 7;
// uart->WATER = LPUART_WATER_TXWATER(1); // guessing here?
// uart->FIFO = 0; // disable the fifo.
uart->WATER = LPUART_WATER_TXWATER(tx_water);
uart->FIFO |= LPUART_FIFO_TXFE;

uart->CTRL = (LPUART_CTRL_TE /*| LPUART_CTRL_TIE */ | LPUART_CTRL_TXINV); // enable transmitter and invert
// We need to configure the TX pin now.
*(portControlRegister(pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);
*(portConfigRegister(pin)) = 2; // from hardware table for each one, but I think they are all 2...

dma->destination((volatile uint8_t&)uart->DATA);
//Serial.printf("HWTrigger: %x\n", hwtrigger);
#else
#if defined(KINETISK) #if defined(KINETISK)
if (divisor < 32) divisor = 32; if (divisor < 32) divisor = 32;
uart->BDH = (divisor >> 13) & 0x1F; uart->BDH = (divisor >> 13) & 0x1F;
#endif #endif
*(portConfigRegister(pin)) = portconfig; *(portConfigRegister(pin)) = portconfig;
dma->destination(uart->D); dma->destination(uart->D);
#endif

dma->triggerAtHardwareEvent(hwtrigger); dma->triggerAtHardwareEvent(hwtrigger);
memset(drawBuffer, 0, numled * 3); memset(drawBuffer, 0, numled * 3);
return true; return true;
while ((dma->CFG->DCR & DMA_DCR_ERQ)) { while ((dma->CFG->DCR & DMA_DCR_ERQ)) {
yield(); yield();
} }
#elif defined(__IMXRT1062__)
//Serial.println("Show called");
while ((DMA_ERQ & (1 << dma->channel))) {
yield();
}
//Serial.println("After Yield");
#endif #endif
// copy drawing buffer to frame buffer // copy drawing buffer to frame buffer
const uint8_t *p = drawBuffer; const uint8_t *p = drawBuffer;
dma->CFG->DSR_BCR = numled * 12; dma->CFG->DSR_BCR = numled * 12;
dma->CFG->DCR = DMA_DCR_ERQ | DMA_DCR_CS | DMA_DCR_SSIZE(1) | dma->CFG->DCR = DMA_DCR_ERQ | DMA_DCR_CS | DMA_DCR_SSIZE(1) |
DMA_DCR_SINC | DMA_DCR_DSIZE(1) | DMA_DCR_D_REQ; DMA_DCR_SINC | DMA_DCR_DSIZE(1) | DMA_DCR_D_REQ;
#elif defined(__IMXRT1062__)
// See if we need to muck with DMA cache...
if ((uint32_t)frameBuffer >= 0x20200000u) arm_dcache_flush(frameBuffer, numled * 12);
dma->sourceBuffer(frameBuffer, numled * 12);
// dma->transferSize(1);
dma->transferCount(numled * 12);
dma->disableOnCompletion();

/* Serial.printf("%x %x:", (uint32_t)dma, (uint32_t)dma->TCD);

Serial.printf("SA:%x SO:%d AT:%x NB:%x SL:%d DA:%x DO: %d CI:%x DL:%x CS:%x BI:%x\n", (uint32_t)dma->TCD->SADDR,
dma->TCD->SOFF, dma->TCD->ATTR, dma->TCD->NBYTES, dma->TCD->SLAST, (uint32_t)dma->TCD->DADDR,
dma->TCD->DOFF, dma->TCD->CITER, dma->TCD->DLASTSGA, dma->TCD->CSR, dma->TCD->BITER);
*/
uart->STAT = 0; // try clearing out the status
dma->enable();

#endif #endif
} }



+ 3
- 0
WS2812Serial.h View File

uint8_t *drawBuffer; uint8_t *drawBuffer;
DMAChannel *dma = nullptr; DMAChannel *dma = nullptr;
uint32_t prior_micros = 0; uint32_t prior_micros = 0;
#if defined(__IMXRT1062__) // Teensy 3.x
IMXRT_LPUART_t *uart = nullptr;
#endif
}; };


#endif #endif

+ 1
- 0
examples/BasicTest/BasicTest.ino View File

// Teensy 3.2: 1, 5, 8, 10, 31 (overclock to 120 MHz for pin 8) // Teensy 3.2: 1, 5, 8, 10, 31 (overclock to 120 MHz for pin 8)
// Teensy 3.5: 1, 5, 8, 10, 26, 32, 33, 48 // Teensy 3.5: 1, 5, 8, 10, 26, 32, 33, 48
// Teensy 3.6: 1, 5, 8, 10, 26, 32, 33 // Teensy 3.6: 1, 5, 8, 10, 26, 32, 33
// Teensy 4.0: 1, 8, 14, 16, 20, 24, 29, 39


byte drawingMemory[numled*3]; // 3 bytes per LED byte drawingMemory[numled*3]; // 3 bytes per LED
DMAMEM byte displayMemory[numled*12]; // 12 bytes per LED DMAMEM byte displayMemory[numled*12]; // 12 bytes per LED

+ 1
- 0
examples/FastLED_Cylon/FastLED_Cylon.ino View File

// Teensy 3.2: 1, 5, 8, 10, 31 (overclock to 120 MHz for pin 8) // Teensy 3.2: 1, 5, 8, 10, 31 (overclock to 120 MHz for pin 8)
// Teensy 3.5: 1, 5, 8, 10, 26, 32, 33, 48 // Teensy 3.5: 1, 5, 8, 10, 26, 32, 33, 48
// Teensy 3.6: 1, 5, 8, 10, 26, 32, 33 // Teensy 3.6: 1, 5, 8, 10, 26, 32, 33
// Teensy 4.0: 1, 8, 14, 16, 20, 24, 29, 39
#define DATA_PIN 1 #define DATA_PIN 1


// Define the array of leds // Define the array of leds

+ 8
- 8
readme.md View File



## Supported Pins & Serial Ports ## Supported Pins & Serial Ports


| Port | Teensy LC | Teensy 3.2 | Teensy 3.5 | Teensy 3.6 |
| :------ | :---------: | :--------: | :--------: | :--------: |
| Serial1 | 1, 4, 5, 24 | 1, 5 | 1, 5, 26 | 1, 5, 26 |
| Serial2 | | 10, 31 | 10 | 10 |
| Serial3 | | 8 | 8 | 8 |
| Serial4 | | | 32 | 32 |
| Serial5 | | | 33 | 33 |
| Serial6 | | | 48 | |
| Port | Teensy LC | Teensy 3.2 | Teensy 3.5 | Teensy 3.6 | Teensy 4.0 |
| :------ | :---------: | :--------: | :--------: | :--------: | :--------: |
| Serial1 | 1, 4, 5, 24 | 1, 5 | 1, 5, 26 | 1, 5, 26 | 1 |
| Serial2 | | 10, 31 | 10 | 10 | 8 |
| Serial3 | | 8 | 8 | 8 | 14 |
| Serial4 | | | 32 | 32 | 17 |
| Serial5 | | | 33 | 33 | 20,39? |
| Serial6 | | | 48 | | 29 |


Serial2 & Serial3 on Teensy LC are not supported, due to lack of configurable Serial2 & Serial3 on Teensy LC are not supported, due to lack of configurable
oversampling needed to run at the high speed required. oversampling needed to run at the high speed required.

Loading…
Cancel
Save