Updated to use new DMA functions.

Previous version will not work anymore due to conflict of variable name
(dma1_ch3_active
This commit is contained in:
victorpv 2015-05-24 00:21:15 -05:00
parent 66b3a0394e
commit 84ff52b49d
2 changed files with 193 additions and 91 deletions

View File

@ -1,6 +1,7 @@
/* /*
See rights and use declaration in License.h See rights and use declaration in License.h
This library has been modified for the Maple Mini This library has been modified for the Maple Mini.
Includes DMA transfers on DMA1 CH2 and CH3.
*/ */
#include <Adafruit_ILI9341_STM.h> #include <Adafruit_ILI9341_STM.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
@ -10,10 +11,6 @@ This library has been modified for the Maple Mini
#include "wiring_private.h" #include "wiring_private.h"
#include <SPI.h> // Using library SPI in folder: D:\Documents\Arduino\hardware\STM32\STM32F1XX\libraries\SPI #include <SPI.h> // Using library SPI in folder: D:\Documents\Arduino\hardware\STM32\STM32F1XX\libraries\SPI
//Used for DMA transfers in STM32F1XX
#if defined (__STM32F1__)
volatile bool dma1_ch3_Active = false;
#endif
// Constructor when using software SPI. All output pins are configurable. // Constructor when using software SPI. All output pins are configurable.
Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t mosi, Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t mosi,
@ -38,10 +35,6 @@ Adafruit_ILI9341_STM::Adafruit_ILI9341_STM(int8_t cs, int8_t dc, int8_t rst) : A
_mosi = _sclk = 0; _mosi = _sclk = 0;
} }
inline void DMA1_CH3_Event() {
dma1_ch3_Active = 0;
dma_disable(DMA1, DMA_CH3);
}
void Adafruit_ILI9341_STM::spiwrite(uint8_t c) { void Adafruit_ILI9341_STM::spiwrite(uint8_t c) {
@ -58,7 +51,7 @@ void Adafruit_ILI9341_STM::spiwrite(uint8_t c) {
#elif defined(TEENSYDUINO) #elif defined(TEENSYDUINO)
SPI.transfer(c); SPI.transfer(c);
#elif defined (__STM32F1__) #elif defined (__STM32F1__)
SPI.transfer(c); SPI.write(c);
#elif defined (__arm__) #elif defined (__arm__)
SPI.setClockDivider(11); // 8-ish MHz (full! speed!) SPI.setClockDivider(11); // 8-ish MHz (full! speed!)
SPI.setBitOrder(MSBFIRST); SPI.setBitOrder(MSBFIRST);
@ -87,30 +80,20 @@ void Adafruit_ILI9341_STM::spiwrite(uint8_t c) {
void Adafruit_ILI9341_STM::writecommand(uint8_t c) { void Adafruit_ILI9341_STM::writecommand(uint8_t c) {
*dcport &= ~dcpinmask; *dcport &= ~dcpinmask;
//digitalWrite(_dc, LOW);
//*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
//digitalWrite(_sclk, LOW);
*csport &= ~cspinmask; *csport &= ~cspinmask;
//digitalWrite(_cs, LOW);
spiwrite(c); spiwrite(c);
*csport |= cspinmask; *csport |= cspinmask;
//digitalWrite(_cs, HIGH);
} }
void Adafruit_ILI9341_STM::writedata(uint8_t c) { void Adafruit_ILI9341_STM::writedata(uint8_t c) {
*dcport |= dcpinmask; *dcport |= dcpinmask;
//digitalWrite(_dc, HIGH);
//*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true
//digitalWrite(_sclk, LOW);
*csport &= ~cspinmask; *csport &= ~cspinmask;
//digitalWrite(_cs, LOW);
spiwrite(c); spiwrite(c);
//digitalWrite(_cs, HIGH);
*csport |= cspinmask; *csport |= cspinmask;
} }
@ -195,13 +178,6 @@ void Adafruit_ILI9341_STM::begin(void) {
SPI.setClockDivider(SPI_CLOCK_DIV2); SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setBitOrder(MSBFIRST); SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0); SPI.setDataMode(SPI_MODE0);
// DMA setup stuff. We use a line buffer and usa DMA for filling lines and blocks.
spi_tx_dma_enable(SPI1);
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH3, DMA1_CH3_Event);
dma_setup_transfer(DMA1, DMA_CH3, &SPI1->regs->DR, DMA_SIZE_8BITS,
lineBuffer, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT));
#elif defined (__arm__) #elif defined (__arm__)
SPI.begin(); SPI.begin();
@ -361,7 +337,26 @@ void Adafruit_ILI9341_STM::begin(void) {
void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1,
uint16_t y1) { uint16_t y1) {
#if defined (__STM32F1__)
writecommand(ILI9341_CASET); // Column addr set
*dcport |= dcpinmask;
*csport &= ~cspinmask;
SPI.setDataSize (SPI_CR1_DFF);
SPI.write(x0);
SPI.write(x1);
// SPI.setDataSize (0);
writecommand(ILI9341_PASET); // Row addr set
*dcport |= dcpinmask;
*csport &= ~cspinmask;
// SPI.setDataSize (SPI_CR1_DFF);
SPI.write(y0);
SPI.write(y1);
SPI.setDataSize (0);
writecommand(ILI9341_RAMWR); // write to RAM
#else
writecommand(ILI9341_CASET); // Column addr set writecommand(ILI9341_CASET); // Column addr set
writedata(x0 >> 8); writedata(x0 >> 8);
writedata(x0 & 0xFF); // XSTART writedata(x0 & 0xFF); // XSTART
@ -375,6 +370,7 @@ void Adafruit_ILI9341_STM::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1,
writedata(y1); // YEND writedata(y1); // YEND
writecommand(ILI9341_RAMWR); // write to RAM writecommand(ILI9341_RAMWR); // write to RAM
#endif
} }
@ -400,16 +396,13 @@ void Adafruit_ILI9341_STM::drawPixel(int16_t x, int16_t y, uint16_t color) {
if (hwSPI) spi_begin(); if (hwSPI) spi_begin();
setAddrWindow(x, y, x + 1, y + 1); setAddrWindow(x, y, x + 1, y + 1);
//digitalWrite(_dc, HIGH);
*dcport |= dcpinmask; *dcport |= dcpinmask;
//digitalWrite(_cs, LOW);
*csport &= ~cspinmask; *csport &= ~cspinmask;
spiwrite(color >> 8); spiwrite(color >> 8);
spiwrite(color); spiwrite(color);
*csport |= cspinmask; *csport |= cspinmask;
//digitalWrite(_cs, HIGH);
if (hwSPI) spi_end(); if (hwSPI) spi_end();
} }
@ -422,37 +415,30 @@ void Adafruit_ILI9341_STM::drawFastVLine(int16_t x, int16_t y, int16_t h,
if ((y + h - 1) >= _height) if ((y + h - 1) >= _height)
h = _height - y; h = _height - y;
if (h < 2 ) {
drawPixel(x, y, color);
return;
}
// if (hwSPI) spi_begin(); // if (hwSPI) spi_begin();
setAddrWindow(x, y, x, y + h - 1); setAddrWindow(x, y, x, y + h - 1);
uint8_t hi = color >> 8, lo = color;
*dcport |= dcpinmask; *dcport |= dcpinmask;
//digitalWrite(_dc, HIGH);
*csport &= ~cspinmask; *csport &= ~cspinmask;
//digitalWrite(_cs, LOW);
#if defined (__STM32F1__) #if defined (__STM32F1__)
for (int i = 0; i < (h * 2) - 1 ; i = i + 2) SPI.setDataSize (SPI_CR1_DFF); // Set SPI 16bit mode
{ lineBuffer[0] = color;
lineBuffer[i] = hi; SPI.dmaSend(lineBuffer, h, 0);
lineBuffer[i + 1] = lo; SPI.setDataSize (0);
}
dma_set_num_transfers(DMA1, DMA_CH3, h * 2); // 2 bytes per pixel
dma1_ch3_Active = true;
dma_enable(DMA1, DMA_CH3);
while (dma1_ch3_Active);
#else #else
while (h--) { uint8_t hi = color >> 8, lo = color;
spiwrite(hi); while (h--) {
spiwrite(lo); spiwrite(hi);
} spiwrite(lo);
}
#endif #endif
*csport |= cspinmask; *csport |= cspinmask;
//digitalWrite(_cs, HIGH);
// if (hwSPI) spi_end();
} }
@ -463,27 +449,23 @@ void Adafruit_ILI9341_STM::drawFastHLine(int16_t x, int16_t y, int16_t w,
// Rudimentary clipping // Rudimentary clipping
if ((x >= _width) || (y >= _height || w < 1)) return; if ((x >= _width) || (y >= _height || w < 1)) return;
if ((x + w - 1) >= _width) w = _width - x; if ((x + w - 1) >= _width) w = _width - x;
if (hwSPI) spi_begin(); if (w < 2 ) {
setAddrWindow(x, y, x + w - 1, y); drawPixel(x, y, color);
return;
}
uint8_t hi = color >> 8, lo = color; // if (hwSPI) spi_begin();
setAddrWindow(x, y, x + w - 1, y);
*dcport |= dcpinmask; *dcport |= dcpinmask;
*csport &= ~cspinmask; *csport &= ~cspinmask;
//digitalWrite(_dc, HIGH);
//digitalWrite(_cs, LOW);
#if defined (__STM32F1__)
for (int i = 0; i < (w * 2) - 1 ; i = i + 2) #if defined (__STM32F1__)
{ SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
lineBuffer[i] = hi; lineBuffer[0] = color;
lineBuffer[i + 1] = lo; SPI.dmaSend(lineBuffer, w, 0);
} SPI.setDataSize (0);
dma_set_num_transfers(DMA1, DMA_CH3, w * 2); // 2 bytes per pixel
dma1_ch3_Active = true;
dma_enable(DMA1, DMA_CH3);
while (dma1_ch3_Active) delayMicroseconds(1);
#else #else
uint8_t hi = color >> 8, lo = color;
while (w--) { while (w--) {
spiwrite(hi); spiwrite(hi);
spiwrite(lo); spiwrite(lo);
@ -491,11 +473,23 @@ void Adafruit_ILI9341_STM::drawFastHLine(int16_t x, int16_t y, int16_t w,
#endif #endif
*csport |= cspinmask; *csport |= cspinmask;
//digitalWrite(_cs, HIGH); //digitalWrite(_cs, HIGH);
if (hwSPI) spi_end(); // if (hwSPI) spi_end();
} }
void Adafruit_ILI9341_STM::fillScreen(uint16_t color) { void Adafruit_ILI9341_STM::fillScreen(uint16_t color) {
#if defined (__STM32F1__)
setAddrWindow(0, 0, _width - 1, _height - 1);
*dcport |= dcpinmask;
*csport &= ~cspinmask;
SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
lineBuffer[0] = color;
SPI.dmaSend(lineBuffer, (65535), 0);
SPI.dmaSend(lineBuffer, ((_width * _height) - 65535), 0);
SPI.setDataSize (0);
#else
fillRect(0, 0, _width, _height, color); fillRect(0, 0, _width, _height, color);
#endif
} }
// fill a rectangle // fill a rectangle
@ -506,36 +500,29 @@ void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
if ((x >= _width) || (y >= _height || h < 1 || w < 1)) return; if ((x >= _width) || (y >= _height || h < 1 || w < 1)) return;
if ((x + w - 1) >= _width) w = _width - x; if ((x + w - 1) >= _width) w = _width - x;
if ((y + h - 1) >= _height) h = _height - y; if ((y + h - 1) >= _height) h = _height - y;
if (w == 1 && h == 1) {
drawPixel(x, y, color);
return;
}
if (hwSPI) spi_begin(); if (hwSPI) spi_begin();
setAddrWindow(x, y, x + w - 1, y + h - 1); setAddrWindow(x, y, x + w - 1, y + h - 1);
uint8_t hi = color >> 8, lo = color;
*dcport |= dcpinmask; *dcport |= dcpinmask;
//digitalWrite(_dc, HIGH);
*csport &= ~cspinmask; *csport &= ~cspinmask;
//digitalWrite(_cs, LOW);
#if defined (__STM32F1__) #if defined (__STM32F1__)
SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode
//moved this loop outside as we can fill the buffer once and send it multiple times. lineBuffer[0] = color;
for (int i = 0; i < (w * 2) - 1 ; i = i + 2) if (w*h <= 65535) {
{ SPI.dmaSend(lineBuffer, (w*h), 0);
lineBuffer[i] = hi;
lineBuffer[i + 1] = lo;
} }
else {
for (y = h; y > 0; y--) { SPI.dmaSend(lineBuffer, (65535), 0);
// for(x=w; x>0; x--) { SPI.dmaSend(lineBuffer, ((w*h) - 65535), 0);
// spiwrite(hi);
// spiwrite(lo);
// }
dma_set_num_transfers(DMA1, DMA_CH3, w * 2); // 2 bytes per pixel
dma1_ch3_Active = true;
dma_enable(DMA1, DMA_CH3);
while (dma1_ch3_Active) delayMicroseconds(1);
} }
SPI.setDataSize (0);
#else #else
uint8_t hi = color >> 8, lo = color;
for(y=h; y>0; y--) for(y=h; y>0; y--)
{ {
for(x=w; x>0; x--) for(x=w; x>0; x--)
@ -545,12 +532,124 @@ void Adafruit_ILI9341_STM::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
} }
} }
#endif #endif
//digitalWrite(_cs, HIGH);
*csport |= cspinmask; *csport |= cspinmask;
if (hwSPI) spi_end(); if (hwSPI) spi_end();
} }
/*
* Draw lines faster by calculating straight sections and drawing them with fastVline and fastHline.
*/
#if defined (__STM32F1__)
void Adafruit_ILI9341_STM::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color)
{
if ((y0 < 0 && y1 <0) || (y0 > _height && y1 > _height)) return;
if ((x0 < 0 && x1 <0) || (x0 > _width && x1 > _width)) return;
if (x0 < 0) x0 = 0;
if (x1 < 0) x1 = 0;
if (y0 < 0) y0 = 0;
if (y1 < 0) y1 = 0;
if (y0 == y1) {
if (x1 > x0) {
drawFastHLine(x0, y0, x1 - x0 + 1, color);
}
else if (x1 < x0) {
drawFastHLine(x1, y0, x0 - x1 + 1, color);
}
else {
drawPixel(x0, y0, color);
}
return;
}
else if (x0 == x1) {
if (y1 > y0) {
drawFastVLine(x0, y0, y1 - y0 + 1, color);
}
else {
drawFastVLine(x0, y1, y0 - y1 + 1, color);
}
return;
}
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t err = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
}
else {
ystep = -1;
}
int16_t xbegin = x0;
lineBuffer[0] = color;
*csport &= ~cspinmask;
if (steep) {
for (; x0 <= x1; x0++) {
err -= dy;
if (err < 0) {
int16_t len = x0 - xbegin;
if (len) {
drawFastVLine (y0, xbegin, len + 1, color);
//writeVLine_cont_noCS_noFill(y0, xbegin, len + 1);
}
else {
drawPixel(y0, x0, color);
//writePixel_cont_noCS(y0, x0, color);
}
xbegin = x0 + 1;
y0 += ystep;
err += dx;
}
}
if (x0 > xbegin + 1) {
//writeVLine_cont_noCS_noFill(y0, xbegin, x0 - xbegin);
drawFastVLine(y0, xbegin, x0 - xbegin, color);
}
}
else {
for (; x0 <= x1; x0++) {
err -= dy;
if (err < 0) {
int16_t len = x0 - xbegin;
if (len) {
drawFastHLine(xbegin, y0, len + 1, color);
//writeHLine_cont_noCS_noFill(xbegin, y0, len + 1);
}
else {
drawPixel(x0, y0, color);
//writePixel_cont_noCS(x0, y0, color);
}
xbegin = x0 + 1;
y0 += ystep;
err += dx;
}
}
if (x0 > xbegin + 1) {
//writeHLine_cont_noCS_noFill(xbegin, y0, x0 - xbegin);
drawFastHLine(xbegin, y0, x0 - xbegin, color);
}
}
*csport |= cspinmask;
}
#endif
// Pass 8-bit (each) R,G,B, get back 16-bit packed color // Pass 8-bit (each) R,G,B, get back 16-bit packed color
uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) { uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) {

View File

@ -104,6 +104,9 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX {
setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1), setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),
pushColor(uint16_t color), pushColor(uint16_t color),
fillScreen(uint16_t color), fillScreen(uint16_t color),
#if defined (__STM32F1__)
drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color),
#endif
drawPixel(int16_t x, int16_t y, uint16_t color), drawPixel(int16_t x, int16_t y, uint16_t color),
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
@ -145,7 +148,7 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX {
volatile uint32 *mosiport, *clkport, *dcport, *rsport, *csport; volatile uint32 *mosiport, *clkport, *dcport, *rsport, *csport;
uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk;
uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask; uint32_t mosipinmask, clkpinmask, cspinmask, dcpinmask;
volatile byte lineBuffer[640]; uint16_t lineBuffer[ILI9341_TFTHEIGHT]; // DMA buffer. 16bit color data per pixel
#elif defined (__arm__) #elif defined (__arm__)
volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport; volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport;
uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk;