Lib for the new LCD Display with ILI9341 controller with rounded (outlined and filled) rectangles added
Fork of SPI_TFT_ILI9341 by
Revision 14:70665f0a182f, committed 2015-03-24
- Comitter:
- JackB
- Date:
- Tue Mar 24 01:33:24 2015 +0000
- Parent:
- 13:b2b3e5430f81
- Commit message:
- Rounded rectangles, rounded filled rectangles added
Changed in this revision
--- a/SPI_TFT_ILI9341.cpp Wed Jun 25 16:51:27 2014 +0000 +++ b/SPI_TFT_ILI9341.cpp Tue Mar 24 01:33:24 2015 +0000 @@ -381,6 +381,42 @@ } +void SPI_TFT_ILI9341::circleGFX(int x0, int y0, int r, int color) +{ + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + pixel(x0, y0+r, color); + pixel(x0, y0-r, color); + pixel(x0+r, y0, color); + pixel(x0-r, y0, color); + + while (x<y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + pixel(x0 + x, y0 + y, color); + pixel(x0 - x, y0 + y, color); + pixel(x0 + x, y0 - y, color); + pixel(x0 - x, y0 - y, color); + pixel(x0 + y, y0 + x, color); + pixel(x0 - y, y0 + x, color); + pixel(x0 + y, y0 - x, color); + pixel(x0 - y, y0 - x, color); + } +} + void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) { int x = -r, y = 0, err = 2-2*r, e2;
--- a/SPI_TFT_ILI9341.h Wed Jun 25 16:51:27 2014 +0000 +++ b/SPI_TFT_ILI9341.h Tue Mar 24 01:33:24 2015 +0000 @@ -42,6 +42,15 @@ #define Orange 0xFD20 /* 255, 165, 0 */ #define GreenYellow 0xAFE5 /* 173, 255, 47 */ +static inline void swap(int16_t &a, int16_t &b) +{ + int16_t t = a; + + a = b; + b = t; +} + + /** Display control class, based on GraphicsDisplay and TextDisplay * @@ -121,8 +130,20 @@ * @param color 16 bit color * * */ - void circle(int x, int y, int r, int colour); - + void circle(int x0, int y0, int r, int color); + void drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color); + void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); + + void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color); + void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color); + +void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); +void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); + + +void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); +void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color); + /** draw a filled circle * * @param x0,y0 center @@ -130,7 +151,9 @@ * @param color 16 bit color * */ void fillcircle(int x, int y, int r, int colour); - + void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color); + + /** draw a 1 pixel line * @@ -140,7 +163,7 @@ * */ void line(int x0, int y0, int x1, int y1, int colour); - + /** draw a rect * * @param x0,y0 top left corner @@ -224,7 +247,6 @@ */ void Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap); - /** paint a 16 bit BMP from filesytem on the TFT (slow) * * @param x,y : position of upper left corner @@ -276,14 +298,14 @@ * @returns ID */ int Read_ID(void); - + + DigitalOut _cs; DigitalOut _reset; DigitalOut _dc; unsigned char* font; - - + protected: @@ -320,9 +342,7 @@ * @param h window height in pixels */ virtual void window (unsigned int x,unsigned int y, unsigned int w, unsigned int h); - - /** Init the ILI9341 controller * */ @@ -404,7 +424,6 @@ unsigned int char_y; unsigned char spi_num; - }; #endif
--- a/SPI_TFT_ILI9341_NUCLEO.cpp Wed Jun 25 16:51:27 2014 +0000 +++ b/SPI_TFT_ILI9341_NUCLEO.cpp Tue Mar 24 01:33:24 2015 +0000 @@ -503,6 +503,42 @@ } while (x <= 0); } +void SPI_TFT_ILI9341::circleGFX(int x0, int y0, int r, int color) +{ + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + pixel(x0, y0+r, color); + pixel(x0, y0-r, color); + pixel(x0+r, y0, color); + pixel(x0-r, y0, color); + + while (x<y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + pixel(x0 + x, y0 + y, color); + pixel(x0 - x, y0 + y, color); + pixel(x0 + x, y0 - y, color); + pixel(x0 - x, y0 - y, color); + pixel(x0 + y, y0 + x, color); + pixel(x0 - y, y0 + x, color); + pixel(x0 + y, y0 - x, color); + pixel(x0 - y, y0 - x, color); + } +} + void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) { int x = -r, y = 0, err = 2-2*r, e2;
--- a/SPI_TFT_ILI9341_NXP.cpp Wed Jun 25 16:51:27 2014 +0000 +++ b/SPI_TFT_ILI9341_NXP.cpp Tue Mar 24 01:33:24 2015 +0000 @@ -378,7 +378,7 @@ // optimized // write direct to SPI1 register ! -void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) +void SPI_TFT_ILI9341::window(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { wr_cmd(0x2A); spi_16(1); @@ -398,7 +398,7 @@ } -void SPI_TFT_ILI9341::WindowMax (void) +void SPI_TFT_ILI9341::WindowMax(void) { window (0, 0, width(), height()); } @@ -413,20 +413,116 @@ void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + pixel(x0, y0+r, color); + pixel(x0, y0-r, color); + pixel(x0+r, y0, color); + pixel(x0-r, y0, color); + + while (x<y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + pixel(x0 + x, y0 + y, color); + pixel(x0 - x, y0 + y, color); + pixel(x0 + x, y0 - y, color); + pixel(x0 - x, y0 - y, color); + pixel(x0 + y, y0 + x, color); + pixel(x0 - y, y0 + x, color); + pixel(x0 + y, y0 - x, color); + pixel(x0 - y, y0 - x, color); + } +} - int x = -r, y = 0, err = 2-2*r, e2; - do { - pixel(x0-x, y0+y,color); - pixel(x0+x, y0+y,color); - pixel(x0+x, y0-y,color); - pixel(x0-x, y0-y,color); - e2 = err; - if (e2 <= y) { - err += ++y*2+1; - if (-x == y && e2 <= x) e2 = 0; + +void SPI_TFT_ILI9341::drawCircleHelper( int16_t x0, int16_t y0, int16_t r, uint8_t cornername, uint16_t color) +{ + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x<y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x4) + { + pixel(x0 + x, y0 + y, color); + pixel(x0 + y, y0 + x, color); + } + + if (cornername & 0x2) + { + pixel(x0 + x, y0 - y, color); + pixel(x0 + y, y0 - x, color); + } + + if (cornername & 0x8) + { + pixel(x0 - y, y0 + x, color); + pixel(x0 - x, y0 + y, color); } - if (e2 > x) err += ++x*2+1; - } while (x <= 0); + + if (cornername & 0x1) + { + pixel(x0 - y, y0 - x, color); + pixel(x0 - x, y0 - y, color); + } + } +} + +void SPI_TFT_ILI9341::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) +{ + fillrect(x, y, x+w-1, y+h-1, color); +} + +// draw a rounded rectangle! +void SPI_TFT_ILI9341::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) +{ + // smarter version + drawFastHLine(x+r , y , w-2*r, color); // Top + drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom + drawFastVLine( x , y+r , h-2*r, color); // Left + drawFastVLine( x+w-1, y+r , h-2*r, color); // Right + // draw four corners + drawCircleHelper(x+r , y+r , r, 1, color); + drawCircleHelper(x+w-r-1, y+r , r, 2, color); + drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); + drawCircleHelper(x+r , y+h-r-1, r, 8, color); +} + +// fill a rounded rectangle! +void SPI_TFT_ILI9341::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color) +{ + // smarter version + fillRect(x+r, y, w-2*r, h, color); + + // draw four corners + fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); } void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) @@ -444,6 +540,51 @@ } while (x <= 0); } +// used to do circles and roundrects! +void SPI_TFT_ILI9341::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, uint16_t color) +{ + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x<y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) + { + drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + + if (cornername & 0x2) + { + drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +void SPI_TFT_ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) +{ + hline(x, x+w-1, y, color); +} + +void SPI_TFT_ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) +{ + vline(x, y, y+h-1, color); +} + // optimized for speed void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color) @@ -563,6 +704,101 @@ return; } +// draw a triangle! +void SPI_TFT_ILI9341::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) +{ + line(x0, y0, x1, y1, color); + line(x1, y1, x2, y2, color); + line(x2, y2, x0, y0, color); +} + +// fill a triangle! +void SPI_TFT_ILI9341::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) +{ + int16_t a, b, y, last; + + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) + swap(y0, y1); swap(x0, x1); + + if (y1 > y2) + swap(y2, y1); swap(x2, x1); + + if (y0 > y1) + swap(y0, y1); swap(x0, x1); + + + if(y0 == y2) + { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if(x1 < a) + a = x1; + else if(x1 > b) + b = x1; + + if(x2 < a) + a = x2; + else if(x2 > b) b = x2; + drawFastHLine(a, y0, b-a+1, color); + return; + } + + int16_t + dx01 = x1 - x0, + dy01 = y1 - y0, + dx02 = x2 - x0, + dy02 = y2 - y0, + dx12 = x2 - x1, + dy12 = y2 - y1, + sa = 0, + sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if(y1 == y2) + last = y1; // Include y1 scanline + else + last = y1-1; // Skip it + + for(y=y0; y<=last; y++) + { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + swap(a,b); + drawFastHLine(a, y, b-a+1, color); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for(; y<=y2; y++) + { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + swap(a,b); + drawFastHLine(a, y, b-a+1, color); + } +} + void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color) { @@ -825,7 +1061,6 @@ WindowMax(); } - // local filesystem is not implemented but you can add a SD card to a different SPI int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)