Skip to content

Commit

Permalink
Version 1.0.5
Browse files Browse the repository at this point in the history
- added 18-bit color handling for native SPI use on ILI9486
  • Loading branch information
ZinggJM committed Nov 11, 2021
1 parent f0d3f43 commit 9738977
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 83 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

This library supports some TFTs using GFX_IO (my Adafruit_SPITFT clone)

### Version 1.0.4
### Version 1.0.5
- added 18-bit color handling for native SPI use on ILI9486
#### Version 1.0.4
- renamed SPI display classes GFX_ILI9486, GFX_ILI9488 to GFX_SPI_ILI9486, GFX_SPI_ILI9488
- added display classes GFX_ILI9486, GFX_ILI9488, GFX_NT35510, GFX_ST7796S
- added IO plugins GFX_STM32F103ZET6 and GFX_STM32F103ZET6_FSMC
Expand Down
10 changes: 8 additions & 2 deletions examples/GFX_SPI_TFT_graphicstest/GFX_SPI_TFT_graphicstest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ GFX_SSD1283A tft(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9, /*LED=*/ 7); //hardware sp

#if defined(_GFX_SPI_ILI9486_H_)
#if defined (ESP8266)
GFX_SPI_ILI9486 tft(/*CS=D8*/ SS, /*DC=D4*/ 2, /*RST=D3*/ 0); // my proto board
GFX_SPI_ILI9486 tft(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2); // my D1 mini connection shield for e-paper displays
//GFX_SPI_ILI9486 tft(/*CS=D8*/ SS, /*DC=D4*/ 2, /*RST=D3*/ 0); // my proto board for RPi display
#elif defined(ARDUINO_ARCH_SAM)
GFX_SPI_ILI9486 tft(/*CS=10*/ SS, /*DC=*/ 6, /*RST=*/ 5); // my proto board
#elif defined(ARDUINO_ARCH_SAMD)
Expand All @@ -64,7 +65,7 @@ GFX_SPI_ILI9486 tft(/*CS=10*/ SS, /*DC=*/ 6, /*RST=*/ 5); // my proto board
// BUSY -> 5, RST -> 6, DC -> 7, CS-> 4, CLK -> 9, DIN -> 8 // my e-paper connector
GFX_SPI_ILI9486 tft(/*CS=*/ 4, /*DC=*/ 7, /*RST=*/ 6); // to my proto board
#elif defined(ARDUINO_ARCH_STM32)
GFX_SPI_ILI9486 tft(/*CS=*/ SS, /*DC=*/ 6, /*RST=*/ 5); // to my proto board
GFX_SPI_ILI9486 tft(/*CS=*/ 9, /*DC=*/ 6, /*RST=*/ 5); // to my proto board
#else
// catch all other default
GFX_SPI_ILI9486 tft(/*CS=10*/ SS, /*DC=*/ 8, /*RST=*/ 9); //
Expand Down Expand Up @@ -122,6 +123,11 @@ void setup()
Serial.println("setup");
//Serial.println(String(controller.name) + " Test on " + String(io.name));

#if defined(_GFX_SPI_ILI9486_H_)
// uncomment for normal SPI mode; default true used for "special" SPI circuit found e.g. on 3.5" RPI HVGA display
tft.setSpiKludge(false); // false to disable rpi_spi16_mode
#endif

tft.init();

Serial.println("tft.init() done");
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=GFX_TFT
version=1.0.4
version=1.0.5
author=Jean-Marc Zingg
maintainer=Jean-Marc Zingg
sentence=TFT Display Classes based on GFX_ROOT and GFX_Extensions
Expand Down
169 changes: 165 additions & 4 deletions src/GFX_SPI_TFT/GFX_SPI_ILI9486.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#include "GFX_SPI_ILI9486.h"

#define SPI_SPEED 20000000 // max reliable speed is 20Mhz for RPi SPI kludge
#define SPI_SPEED 20000000ul // max reliable speed is 20Mhz for RPi SPI kludge
//#define SPI_SPEED 4000000

#define ILI9486_CASET 0x2A
Expand Down Expand Up @@ -42,7 +42,7 @@ GFX_SPI_ILI9486::GFX_SPI_ILI9486(int8_t cs_pin, int8_t dc_pin, int8_t mosi_pin,
}

GFX_SPI_ILI9486::GFX_SPI_ILI9486(uint16_t width, uint16_t height,
SPIClass *spi, int8_t cs_pin, int8_t dc_pin, int8_t rst_pin) :
SPIClass *spi, int8_t cs_pin, int8_t dc_pin, int8_t rst_pin) :
#if defined(ESP8266)
SPI_GFX_Class(width, height, cs_pin, dc_pin, rst_pin)
#else
Expand All @@ -55,7 +55,7 @@ GFX_SPI_ILI9486::GFX_SPI_ILI9486(uint16_t width, uint16_t height,
}

GFX_SPI_ILI9486::GFX_SPI_ILI9486(uint16_t width, uint16_t height,
int8_t cs_pin, int8_t dc_pin, int8_t mosi_pin, int8_t sclk_pin, int8_t rst_pin) :
int8_t cs_pin, int8_t dc_pin, int8_t mosi_pin, int8_t sclk_pin, int8_t rst_pin) :
SPI_GFX_Class(width, height, cs_pin, dc_pin, mosi_pin, sclk_pin, rst_pin, -1)
{
_spi16_mode = true;
Expand Down Expand Up @@ -142,7 +142,7 @@ void GFX_SPI_ILI9486::init(uint32_t freq)
else
{
writeCommand(0x3A);
spiWrite(0x55); // use 16 bits per pixel color
spiWrite(0x66); // 18 bit colour for native SPI
writeCommand(0x36);
spiWrite(0x48); // MX, BGR == rotation 0
// PGAMCTRL(Positive Gamma Control)
Expand Down Expand Up @@ -307,3 +307,164 @@ void GFX_SPI_ILI9486::enableDisplay(bool enable)
else writeCommand(enable ? 0x29 : 0x28); // Display ON / Display OFF
endWrite();
}

void GFX_SPI_ILI9486::writePixel(int16_t x, int16_t y, uint16_t color)
{
// Clip first...
if ((x >= 0) && (x < _width) && (y >= 0) && (y < _height))
{
// THEN set up transaction (if needed) and draw...
setAddrWindow(x, y, 1, 1);
_writeColor16(color, 1);
}
//Serial.print(".");
}

void GFX_SPI_ILI9486::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
// if ((x < 0) || (y < 0) || (w < 1) || (h < 1) || (x + w > _width) || (y + h > _height))
// {
// Serial.print("writeFillRect("); Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(w); Serial.print(", "); Serial.print(h); Serial.println(") oops? "); delay(1);
// }
// a correct clipping is the goal. try to achieve this
if (x < 0) w += x, x = 0;
if (y < 0) h += y, y = 0;
if (x + w > _width) w = _width - x;
if (y + h > _height) h = _height - y;
if ((w < 1) || (h < 1)) return;
setAddrWindow(x, y, w, h);
_writeColor16(color, uint32_t(w) * uint32_t(h));
}

void GFX_SPI_ILI9486::drawPixel(int16_t x, int16_t y, uint16_t color)
{
// Clip first...
if ((x >= 0) && (x < _width) && (y >= 0) && (y < _height))
{
// THEN set up transaction (if needed) and draw...
startWrite();
setAddrWindow(x, y, 1, 1);
_writeColor16(color, 1);
endWrite();
}
//Serial.print(".");
}

void GFX_SPI_ILI9486::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
// if ((x < 0) || (y < 0) || (w < 1) || (h < 1) || (x + w > _width) || (y + h > _height))
// {
// Serial.print("fillRect("); Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(w); Serial.print(", "); Serial.print(h); Serial.println(") oops? "); delay(1);
// }
// a correct clipping is the goal. try to achieve this
if (x < 0) w += x, x = 0;
if (y < 0) h += y, y = 0;
if (x + w > _width) w = _width - x;
if (y + h > _height) h = _height - y;
if ((w < 1) || (h < 1)) return;
startWrite();
setAddrWindow(x, y, w, h);
_writeColor16(color, uint32_t(w) * uint32_t(h));
endWrite();
}

void GFX_SPI_ILI9486::writeColor(uint16_t color, uint32_t len)
{
_writeColor16(color, len);
}

void GFX_SPI_ILI9486::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
writeFillRect(x, y, w, 1, color);
}

void GFX_SPI_ILI9486::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
writeFillRect(x, y, 1, h, color);
}

void GFX_SPI_ILI9486::_writeColor16(uint16_t data, uint32_t n)
{
if (_spi16_mode) return writeData16(data, n);
if (0 == connection) // TFT_HARD_SPI
{
#if (defined (ESP8266) || defined(ESP32))
uint8_t rgb888[] = {uint8_t((data & 0xF800) >> 8), uint8_t((data & 0x07E0) >> 3), uint8_t((data & 0x001F) << 3)};
SPI.writePattern(rgb888, 3, n);
#else // wdt on ESP8266
while (n-- > 0)
{
spiWrite(uint8_t((data & 0xF800) >> 8));
spiWrite(uint8_t((data & 0x07E0) >> 3));
spiWrite(uint8_t((data & 0x001F) << 3));
}
#endif
}
else
{
while (n-- > 0)
{
spiWrite(uint8_t((data & 0xF800) >> 8));
spiWrite(uint8_t((data & 0x07E0) >> 3));
spiWrite(uint8_t((data & 0x001F) << 3));
}
}
}

#if (defined (ESP8266) || defined(ESP32))
#define SPI_WRITE_BYTES(data, n) SPI.transferBytes(data, 0, n)
#elif defined(ARDUINO_ARCH_SAM)
#define SPI_WRITE_BYTES(data, n) SPI.transfer(SS, data, n)
#elif (TEENSYDUINO == 147)
#define SPI_WRITE_BYTES(data, n) SPI.transfer(data, 0, n)
#elif defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F4)
#define SPI_WRITE_BYTES(data, n) SPI.write(data, n)
#else
// valid for all other platforms? else comment out next line
#define SPI_WRITE_BYTES(data, n) SPI.transfer(data, n)
#endif


void GFX_SPI_ILI9486::_writeColor16(const uint16_t* data, uint32_t n)
{
if (_spi16_mode) return writeData16(data, n);
if (0 == connection) // TFT_HARD_SPI
{
#if defined(SPI_WRITE_BYTES)
static const uint16_t rgb888_buffer_size = 60; // 64 optimal for ESP8266 SPI
static const uint32_t max_chunk = rgb888_buffer_size / 3; // rgb888
uint8_t rgb888_buffer[rgb888_buffer_size];
while (n > 0)
{
uint32_t chunk = min(max_chunk, n);
n -= chunk;
uint8_t* p = rgb888_buffer;
uint16_t ncopy = chunk;
while (ncopy-- > 0)
{
*p++ = uint8_t((*data & 0xF800) >> 8);
*p++ = uint8_t((*data & 0x07E0) >> 3);
*p++ = uint8_t((*data & 0x001F) << 3);
data++;
}
SPI_WRITE_BYTES(rgb888_buffer, 3 * chunk);
}
#else
while (n-- > 0)
{
spiWrite(uint8_t((*data & 0xF800) >> 8));
spiWrite(uint8_t((*data & 0x07E0) >> 3));
spiWrite(uint8_t((*data & 0x001F) << 3));
}
#endif
}
else
{
while (n-- > 0)
{
spiWrite(uint8_t((*data & 0xF800) >> 8));
spiWrite(uint8_t((*data & 0x07E0) >> 3));
spiWrite(uint8_t((*data & 0x001F) << 3));
}
}
}
13 changes: 13 additions & 0 deletions src/GFX_SPI_TFT/GFX_SPI_ILI9486.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ class GFX_SPI_ILI9486 : public SPI_GFX_Class
void invert(bool i);
void enableDisplay(bool enable);
void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void writePixel(int16_t x, int16_t y, uint16_t color);
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
//void writePixels(uint16_t *colors, uint32_t len, bool block = true, bool bigEndian = false); // TO BE ADDED
void writeColor(uint16_t color, uint32_t len);
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
private:
void _writeCommand16(uint16_t cmd);
// note: only use for pixel data, RGB888 on ILI9486
void _writeColor16(uint16_t data, uint32_t n);
void _writeColor16(const uint16_t* data, uint32_t n);
private:
bool _spi16_mode;
int8_t _bgr;
Expand Down
75 changes: 0 additions & 75 deletions src/GFX_SPI_TFT/GFX_SPI_ILI9488.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ void GFX_SPI_ILI9488::init(uint32_t freq)
if (!freq) freq = SPI_SPEED;
initSPI(freq);
startWrite();
#if 1
writeCommand(0xE0); // Positive Gamma Control
spiWrite(0x00);
spiWrite(0x03);
Expand All @@ -88,7 +87,6 @@ void GFX_SPI_ILI9488::init(uint32_t freq)
spiWrite(0x16);
spiWrite(0x1A);
spiWrite(0x0F);

writeCommand(0XE1); // Negative Gamma Control
spiWrite(0x00);
spiWrite(0x16);
Expand All @@ -105,113 +103,40 @@ void GFX_SPI_ILI9488::init(uint32_t freq)
spiWrite(0x35);
spiWrite(0x37);
spiWrite(0x0F);

writeCommand(0XC0); // Power Control 1
spiWrite(0x17);
spiWrite(0x15);

writeCommand(0xC1); // Power Control 2
spiWrite(0x41);

writeCommand(0xC5); // VCOM Control
spiWrite(0x00);
spiWrite(0x12);
spiWrite(0x80);

writeCommand(ILI9488_MADCTL); // Memory Access Control
spiWrite(0x48); // MX, BGR

writeCommand(0x3A); // Pixel Interface Format
spiWrite(0x66); // 18 bit colour for SPI

writeCommand(0xB0); // Interface Mode Control
spiWrite(0x00);

writeCommand(0xB1); // Frame Rate Control
spiWrite(0xA0);

writeCommand(0xB4); // Display Inversion Control
spiWrite(0x02);

writeCommand(0xB6); // Display Function Control
spiWrite(0x02);
spiWrite(0x02);
spiWrite(0x3B);

writeCommand(0xB7); // Entry Mode Set
spiWrite(0xC6);

writeCommand(0xF7); // Adjust Control 3
spiWrite(0xA9);
spiWrite(0x51);
spiWrite(0x2C);
spiWrite(0x82);

writeCommand(0x11); //Exit Sleep
delay(120);

writeCommand(0x29); //Display on
delay(25);
#else
writeCommand(0x3A);
spiWrite(0x55); // use 16 bits per pixel color
writeCommand(0x36);
spiWrite(0x48); // MX, BGR == rotation 0
// PGAMCTRL(Positive Gamma Control)
writeCommand(0xE0);
spiWrite(0x0F);
spiWrite(0x1F);
spiWrite(0x1C);
spiWrite(0x0C);
spiWrite(0x0F);
spiWrite(0x08);
spiWrite(0x48);
spiWrite(0x98);
spiWrite(0x37);
spiWrite(0x0A);
spiWrite(0x13);
spiWrite(0x04);
spiWrite(0x11);
spiWrite(0x0D);
spiWrite(0x00);
// NGAMCTRL(Negative Gamma Control)
writeCommand(0xE1);
spiWrite(0x0F);
spiWrite(0x32);
spiWrite(0x2E);
spiWrite(0x0B);
spiWrite(0x0D);
spiWrite(0x05);
spiWrite(0x47);
spiWrite(0x75);
spiWrite(0x37);
spiWrite(0x06);
spiWrite(0x10);
spiWrite(0x03);
spiWrite(0x24);
spiWrite(0x20);
spiWrite(0x00);
// Digital Gamma Control 1
writeCommand(0xE2);
spiWrite(0x0F);
spiWrite(0x32);
spiWrite(0x2E);
spiWrite(0x0B);
spiWrite(0x0D);
spiWrite(0x05);
spiWrite(0x47);
spiWrite(0x75);
spiWrite(0x37);
spiWrite(0x06);
spiWrite(0x10);
spiWrite(0x03);
spiWrite(0x24);
spiWrite(0x20);
spiWrite(0x00);
writeCommand(0x11); // Sleep OUT
delay(150); // wait some time
writeCommand(0x29); // Display ON
#endif
if (_bl_pin >= 0)
{
pinMode(_bl_pin, OUTPUT);
Expand Down

0 comments on commit 9738977

Please sign in to comment.