Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16-bit DMA #20

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 66 additions & 15 deletions OctoWS2811.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ DMAChannel OctoWS2811::dma1;
DMAChannel OctoWS2811::dma2;
DMAChannel OctoWS2811::dma3;

static uint8_t ones = 0xFF;
static uint16_t ones = 0xFFFF;
static volatile uint8_t update_in_progress = 0;
static uint32_t update_completed_at = 0;

Expand Down Expand Up @@ -81,6 +81,8 @@ void OctoWS2811::begin(void)
drawBuffer = frameBuffer;
}

#if defined(__MK20DX128__)
// ??? Stick with 8-bit?
// configure the 8 output pins
GPIOD_PCOR = 0xFF;
pinMode(2, OUTPUT); // strip #1
Expand All @@ -92,6 +94,52 @@ void OctoWS2811::begin(void)
pinMode(21, OUTPUT); // strip #7
pinMode(5, OUTPUT); // strip #8

#elif defined(__MK20DX256__)
// Teensy 3.2
// Configure the 12 output pins
GPIOC_PCOR = 0xFFFF;
pinMode(15, OUTPUT); // PTC0
pinMode(22, OUTPUT); // PTC1
pinMode(23, OUTPUT); // PTC2
pinMode(9, OUTPUT); // PTC3
pinMode(10, OUTPUT); // PTC4
pinMode(13, OUTPUT); // PTC5
pinMode(11, OUTPUT); // PTC6
pinMode(12, OUTPUT); // PTC7
pinMode(28, OUTPUT); // PTC8
pinMode(27, OUTPUT); // PTC9
pinMode(29, OUTPUT); // PTC10
pinMode(30, OUTPUT); // PTC11

#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Teensy 3.5/3.6
GPIOC_PCOR = 0xFFFF;
pinMode(15, OUTPUT); // PTC0
pinMode(22, OUTPUT); // PTC1
pinMode(23, OUTPUT); // PTC2
pinMode(9, OUTPUT); // PTC3
pinMode(10, OUTPUT); // PTC4
pinMode(13, OUTPUT); // PTC5
pinMode(11, OUTPUT); // PTC6
pinMode(12, OUTPUT); // PTC7
pinMode(35, OUTPUT); // PTC8
pinMode(36, OUTPUT); // PTC9
pinMode(37, OUTPUT); // PTC10
pinMode(38, OUTPUT); // PTC11

// Alternatively, you could also get a total of 15 on GPIOD:
/*
pinMode(47, OUTPUT); // PTD8
pinMode(48, OUTPUT); // PTD9
//pinMode(B3??, OUTPUT); // PTD10 is not exported on Teensy 3.6 :(
pinMode(55, OUTPUT); // PTD11
pinMode(53, OUTPUT); // PTD12
pinMode(52, OUTPUT); // PTD13
pinMode(51, OUTPUT); // PTD14
pinMode(54, OUTPUT); // PTD15
*/
#endif

// create the two waveforms for WS2811 low and high bits
switch (params & 0xF0) {
case WS2811_400kHz:
Expand Down Expand Up @@ -165,22 +213,22 @@ void OctoWS2811::begin(void)

// DMA channel #1 sets WS2811 high at the beginning of each cycle
dma1.source(ones);
dma1.destination(GPIOD_PSOR);
dma1.transferSize(1);
dma1.destination(GPIOC_PSOR);
dma1.transferSize(2);
dma1.transferCount(bufsize);
dma1.disableOnCompletion();

// DMA channel #2 writes the pixel data at 23% of the cycle
dma2.sourceBuffer((uint8_t *)frameBuffer, bufsize);
dma2.destination(GPIOD_PDOR);
dma2.transferSize(1);
dma2.sourceBuffer((volatile const uint16_t *)frameBuffer, bufsize*2);
dma2.destination(GPIOC_PDOR);
dma2.transferSize(2);
dma2.transferCount(bufsize);
dma2.disableOnCompletion();

// DMA channel #3 clear all the pins low at 69% of the cycle
dma3.source(ones);
dma3.destination(GPIOD_PCOR);
dma3.transferSize(1);
dma3.destination(GPIOC_PCOR);
dma3.transferSize(2);
dma3.transferCount(bufsize);
dma3.disableOnCompletion();
dma3.interruptAtCompletion();
Expand Down Expand Up @@ -215,6 +263,7 @@ void OctoWS2811::begin(void)
//pinMode(9, OUTPUT); // testing: oscilloscope trigger
}


void OctoWS2811::isr(void)
{
//digitalWriteFast(9, HIGH);
Expand All @@ -223,7 +272,7 @@ void OctoWS2811::isr(void)
//Serial1.print(dma3.CFG->DSR_BCR > 24, HEX);
dma3.clearInterrupt();
#if defined(__MKL26Z64__)
GPIOD_PCOR = 0xFF;
GPIOD_PCOR = 0xFFFF;
#endif
//Serial1.print("*");
update_completed_at = micros();
Expand All @@ -250,7 +299,7 @@ void OctoWS2811::show(void)
if (drawBuffer != frameBuffer) {
// TODO: this could be faster with DMA, especially if the
// buffers are 32 bit aligned... but does it matter?
memcpy(frameBuffer, drawBuffer, stripLen * 24);
memcpy(frameBuffer, drawBuffer, stripLen * 24*2);
}
// wait for WS2811 reset
while (micros() - update_completed_at < 300) ;
Expand Down Expand Up @@ -310,6 +359,7 @@ void OctoWS2811::show(void)
FTM2_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); // restart FTM2 timer
//digitalWriteFast(9, LOW);


#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
FTM2_C0SC = 0x28;
FTM2_C1SC = 0x28;
Expand Down Expand Up @@ -354,7 +404,7 @@ void OctoWS2811::show(void)
dma1.transferCount(bufsize);
dma2.transferCount(bufsize);
dma3.transferCount(bufsize);
dma2.sourceBuffer((uint8_t *)frameBuffer, bufsize);
dma2.sourceBuffer((uint16_t *)frameBuffer, bufsize);
// clear any pending event flags
FTM2_SC = FTM_SC_TOF;
FTM2_C0SC = FTM_CSC_CHF | FTM_CSC_MSB | FTM_CSC_ELSB | FTM_CSC_DMA;
Expand All @@ -375,7 +425,7 @@ void OctoWS2811::show(void)
void OctoWS2811::setPixel(uint32_t num, int color)
{
uint32_t strip, offset, mask;
uint8_t bit, *p;
uint16_t bit, *p;

switch (params & 7) {
case WS2811_RBG:
Expand All @@ -397,9 +447,10 @@ void OctoWS2811::setPixel(uint32_t num, int color)
break;
}
strip = num / stripLen; // Cortex-M4 has 2 cycle unsigned divide :-)
// Note: strips 12-15 don't exist (yet?)
offset = num % stripLen;
bit = (1<<strip);
p = ((uint8_t *)drawBuffer) + offset * 24;
p = &((uint16_t *)drawBuffer)[offset * 24];
for (mask = (1<<23) ; mask ; mask >>= 1) {
if (color & mask) {
*p++ |= bit;
Expand All @@ -412,13 +463,13 @@ void OctoWS2811::setPixel(uint32_t num, int color)
int OctoWS2811::getPixel(uint32_t num)
{
uint32_t strip, offset, mask;
uint8_t bit, *p;
uint16_t bit, *p;
int color=0;

strip = num / stripLen;
offset = num % stripLen;
bit = (1<<strip);
p = ((uint8_t *)drawBuffer) + offset * 24;
p = &((uint16_t *)drawBuffer)[offset * 24];
for (mask = (1<<23) ; mask ; mask >>= 1) {
if (*p++ & bit) color |= mask;
}
Expand Down