From 84ff52b49de42a6213a6c046fae6ec26e93262a5 Mon Sep 17 00:00:00 2001 From: victorpv Date: Sun, 24 May 2015 00:21:15 -0500 Subject: [PATCH 1/3] Updated to use new DMA functions. Previous version will not work anymore due to conflict of variable name (dma1_ch3_active --- .../Adafruit_ILI9341_STM.cpp | 279 ++++++++++++------ .../Adafruit_ILI9341_STM.h | 5 +- 2 files changed, 193 insertions(+), 91 deletions(-) diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp index 7ba33cd..87a2334 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.cpp @@ -1,6 +1,7 @@ /* 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 #include @@ -10,10 +11,6 @@ This library has been modified for the Maple Mini #include "wiring_private.h" #include // 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. 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; } -inline void DMA1_CH3_Event() { - dma1_ch3_Active = 0; - dma_disable(DMA1, DMA_CH3); -} void Adafruit_ILI9341_STM::spiwrite(uint8_t c) { @@ -58,7 +51,7 @@ void Adafruit_ILI9341_STM::spiwrite(uint8_t c) { #elif defined(TEENSYDUINO) SPI.transfer(c); #elif defined (__STM32F1__) - SPI.transfer(c); + SPI.write(c); #elif defined (__arm__) SPI.setClockDivider(11); // 8-ish MHz (full! speed!) SPI.setBitOrder(MSBFIRST); @@ -87,30 +80,20 @@ void Adafruit_ILI9341_STM::spiwrite(uint8_t c) { void Adafruit_ILI9341_STM::writecommand(uint8_t c) { *dcport &= ~dcpinmask; - //digitalWrite(_dc, LOW); - //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true - //digitalWrite(_sclk, LOW); *csport &= ~cspinmask; - //digitalWrite(_cs, LOW); spiwrite(c); *csport |= cspinmask; - //digitalWrite(_cs, HIGH); } void Adafruit_ILI9341_STM::writedata(uint8_t c) { *dcport |= dcpinmask; - //digitalWrite(_dc, HIGH); - //*clkport &= ~clkpinmask; // clkport is a NULL pointer when hwSPI==true - //digitalWrite(_sclk, LOW); *csport &= ~cspinmask; - //digitalWrite(_cs, LOW); spiwrite(c); - //digitalWrite(_cs, HIGH); *csport |= cspinmask; } @@ -195,13 +178,6 @@ void Adafruit_ILI9341_STM::begin(void) { SPI.setClockDivider(SPI_CLOCK_DIV2); SPI.setBitOrder(MSBFIRST); 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__) 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, 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 writedata(x0 >> 8); 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 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(); setAddrWindow(x, y, x + 1, y + 1); - //digitalWrite(_dc, HIGH); *dcport |= dcpinmask; - //digitalWrite(_cs, LOW); *csport &= ~cspinmask; spiwrite(color >> 8); spiwrite(color); *csport |= cspinmask; - //digitalWrite(_cs, HIGH); 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) h = _height - y; + if (h < 2 ) { + drawPixel(x, y, color); + return; + } // if (hwSPI) spi_begin(); setAddrWindow(x, y, x, y + h - 1); - uint8_t hi = color >> 8, lo = color; - *dcport |= dcpinmask; - //digitalWrite(_dc, HIGH); *csport &= ~cspinmask; - //digitalWrite(_cs, LOW); #if defined (__STM32F1__) - for (int i = 0; i < (h * 2) - 1 ; i = i + 2) - { - lineBuffer[i] = hi; - lineBuffer[i + 1] = lo; - } - 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); - + SPI.setDataSize (SPI_CR1_DFF); // Set SPI 16bit mode + lineBuffer[0] = color; + SPI.dmaSend(lineBuffer, h, 0); + SPI.setDataSize (0); #else - while (h--) { - spiwrite(hi); - spiwrite(lo); - } + uint8_t hi = color >> 8, lo = color; + while (h--) { + spiwrite(hi); + spiwrite(lo); + } #endif *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 if ((x >= _width) || (y >= _height || w < 1)) return; if ((x + w - 1) >= _width) w = _width - x; - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x + w - 1, y); + if (w < 2 ) { + 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; *csport &= ~cspinmask; - //digitalWrite(_dc, HIGH); - //digitalWrite(_cs, LOW); -#if defined (__STM32F1__) - for (int i = 0; i < (w * 2) - 1 ; i = i + 2) - { - lineBuffer[i] = hi; - lineBuffer[i + 1] = 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); - +#if defined (__STM32F1__) + SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode + lineBuffer[0] = color; + SPI.dmaSend(lineBuffer, w, 0); + SPI.setDataSize (0); #else + uint8_t hi = color >> 8, lo = color; while (w--) { spiwrite(hi); spiwrite(lo); @@ -491,11 +473,23 @@ void Adafruit_ILI9341_STM::drawFastHLine(int16_t x, int16_t y, int16_t w, #endif *csport |= cspinmask; //digitalWrite(_cs, HIGH); - if (hwSPI) spi_end(); +// if (hwSPI) spi_end(); } 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); +#endif } // 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 + w - 1) >= _width) w = _width - x; if ((y + h - 1) >= _height) h = _height - y; - + if (w == 1 && h == 1) { + drawPixel(x, y, color); + return; + } + if (hwSPI) spi_begin(); setAddrWindow(x, y, x + w - 1, y + h - 1); - uint8_t hi = color >> 8, lo = color; - *dcport |= dcpinmask; - //digitalWrite(_dc, HIGH); *csport &= ~cspinmask; - //digitalWrite(_cs, LOW); #if defined (__STM32F1__) - - //moved this loop outside as we can fill the buffer once and send it multiple times. - for (int i = 0; i < (w * 2) - 1 ; i = i + 2) - { - lineBuffer[i] = hi; - lineBuffer[i + 1] = lo; + SPI.setDataSize (SPI_CR1_DFF); // Set spi 16bit mode + lineBuffer[0] = color; + if (w*h <= 65535) { + SPI.dmaSend(lineBuffer, (w*h), 0); } - - for (y = h; y > 0; y--) { - // for(x=w; x>0; x--) { - // 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); + else { + SPI.dmaSend(lineBuffer, (65535), 0); + SPI.dmaSend(lineBuffer, ((w*h) - 65535), 0); } + SPI.setDataSize (0); #else + uint8_t hi = color >> 8, lo = color; for(y=h; y>0; y--) { 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 - - //digitalWrite(_cs, HIGH); *csport |= cspinmask; 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 uint16_t Adafruit_ILI9341_STM::color565(uint8_t r, uint8_t g, uint8_t b) { diff --git a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h index 980789d..a716c27 100644 --- a/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h +++ b/STM32F1/libraries/Adafruit_ILI9341_STM/Adafruit_ILI9341_STM.h @@ -104,6 +104,9 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX { setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1), pushColor(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), 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), @@ -145,7 +148,7 @@ class Adafruit_ILI9341_STM : public Adafruit_GFX { volatile uint32 *mosiport, *clkport, *dcport, *rsport, *csport; uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; 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__) volatile RwReg *mosiport, *clkport, *dcport, *rsport, *csport; uint32_t _cs, _dc, _rst, _mosi, _miso, _sclk; From a6e0fadb82c84cdda55258153b2d7a51006baaf2 Mon Sep 17 00:00:00 2001 From: victorpv Date: Wed, 27 May 2015 20:05:35 -0500 Subject: [PATCH 2/3] Reverts changes to the ILI9341 library that should not use DMA. --- .../Adafruit_ILI9341/Adafruit_ILI9341.cpp | 74 ++++++------------- .../Adafruit_ILI9341/Adafruit_ILI9341.h | 1 + 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp b/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp index 4233716..4f1e146 100644 --- a/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp +++ b/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp @@ -253,7 +253,7 @@ void Adafruit_ILI9341::begin(void) { writedata(0x10); //SAP[2:0];BT[3:0] writecommand(ILI9341_VMCTR1); //VCM control - writedata(0x3e); //对比度调节 + writedata(0x3e); //??????? writedata(0x28); writecommand(ILI9341_VMCTR2); //VCM control2 @@ -327,11 +327,9 @@ void Adafruit_ILI9341::begin(void) { void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - byte buf[4]; writecommand(ILI9341_CASET); // Column addr set *dcport |= dcpinmask; *csport &= ~cspinmask; - SPI.write(x0 >> 8); SPI.write(x0 & 0xFF); // XSTART SPI.write(x1 >> 8); @@ -340,13 +338,11 @@ void Adafruit_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, writecommand(ILI9341_PASET); // Row addr set *dcport |= dcpinmask; *csport &= ~cspinmask; - SPI.write(y0>>8); SPI.write(y0); // YSTART SPI.write(y1>>8); SPI.write(y1); // YEND - writecommand(ILI9341_RAMWR); // write to RAM } @@ -437,58 +433,33 @@ void Adafruit_ILI9341::fillScreen(uint16_t color) { } // fill a rectangle -void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) { +void Adafruit_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, + uint16_t color) { int numPixels; + // rudimentary clipping (drawChar w/big text requires this) + if((x >= _width) || (y >= _height)) return; + if((x + w - 1) >= _width) w = _width - x; + if((y + h - 1) >= _height) h = _height - y; - unsigned char *buff; + if (hwSPI) spi_begin(); + setAddrWindow(x, y, x+w-1, y+h-1); - // rudimentary clipping (drawChar w/big text requires this) - if((x >= _width) || (y >= _height)) return; - if((x + w - 1) >= _width) w = _width - x; - if((y + h - 1) >= _height) h = _height - y; + uint8_t hi = color >> 8, lo = color; - if (hwSPI) spi_begin(); - setAddrWindow(x, y, x+w-1, y+h-1); - - uint8_t hi = color >> 8, lo = color; + *dcport |= dcpinmask; + *csport &= ~cspinmask; - *dcport |= dcpinmask; - *csport &= ~cspinmask; - if (true) + for(y=h; y>0; y--) + { + for(x=w; x>0; x--) { - // Use DMA - byte txBuf[h*2];// Buffer to be sent via DMA - byte rxBuf[h*2];// Buffer to be sent via DMA - - // need to build a buffer of the required height (h) - // Note I suspect there is a faster way to do this - for(int i=0;i0; y--) - { - for(x=w; x>0; x--) - { - SPI.write(hi); - SPI.write(lo); - } - } - } - - if (hwSPI) spi_end(); - *csport |= cspinmask; + SPI.write(hi); + SPI.write(lo); + } + } + + if (hwSPI) spi_end(); + *csport |= cspinmask; } @@ -658,3 +629,4 @@ uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) { } */ + diff --git a/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h b/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h index 1ce359a..1e9bf60 100644 --- a/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h +++ b/STM32F1/libraries/Adafruit_ILI9341/Adafruit_ILI9341.h @@ -167,3 +167,4 @@ class Adafruit_ILI9341 : public Adafruit_GFX { }; #endif + From d165e4d01343b67e9bab5ac2099ddcd23e2677db Mon Sep 17 00:00:00 2001 From: victorpv Date: Wed, 27 May 2015 20:16:15 -0500 Subject: [PATCH 3/3] SPI updated to eliminate warnings The same write function works for both 8bit and 16bit transfers, so eliminated the 8bit one and that takes out warnings when the compiler is not sure of the width. Tested with both ILI libraries (_STM and not STM) --- STM32F1/libraries/SPI/src/SPI.cpp | 10 +++++----- STM32F1/libraries/SPI/src/SPI.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/STM32F1/libraries/SPI/src/SPI.cpp b/STM32F1/libraries/SPI/src/SPI.cpp index bffe7eb..da936fa 100644 --- a/STM32F1/libraries/SPI/src/SPI.cpp +++ b/STM32F1/libraries/SPI/src/SPI.cpp @@ -324,7 +324,7 @@ void SPIClass::write(uint16 data) { while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." } -void SPIClass::write(uint8 byte) { +//void SPIClass::write(uint8 byte) { // this->write(&byte, 1); /* Roger Clark @@ -333,10 +333,10 @@ void SPIClass::write(uint8 byte) { * This almost doubles the speed of this function. */ - spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." - while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." - while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." -} +// spi_tx_reg(this->spi_d, byte); // "2. Write the first data item to be transmitted into the SPI_DR register (this clears the TXE flag)." +// while (spi_is_tx_empty(this->spi_d) == 0); // "5. Wait until TXE=1 ..." +// while (spi_is_busy(this->spi_d) != 0); // "... and then wait until BSY=0 before disabling the SPI." +//} void SPIClass::write(const uint8 *data, uint32 length) { uint32 txed = 0; diff --git a/STM32F1/libraries/SPI/src/SPI.h b/STM32F1/libraries/SPI/src/SPI.h index d4fa9f3..4ec2723 100644 --- a/STM32F1/libraries/SPI/src/SPI.h +++ b/STM32F1/libraries/SPI/src/SPI.h @@ -215,7 +215,7 @@ public: * @brief Transmit a byte. * @param data Byte to transmit. */ - void write(uint8 data); +// void write(uint8 data); /** * @brief Transmit a half word.