This commit is contained in:
e2002
2023-01-20 13:51:27 +03:00
parent f90718f2f0
commit f48114e5e5
10 changed files with 2902 additions and 2 deletions

View File

@@ -0,0 +1,80 @@
#ifndef _GFXcanvas16T_H_
#define _GFXcanvas16T_H_
#include <Adafruit_GFX.h>
template<const uint16_t w, uint16_t h>
class GFXcanvas16T : public Adafruit_GFX
{
public:
GFXcanvas16T() : Adafruit_GFX(w, h) {};
void drawPixel(int16_t x, int16_t y, uint16_t color)
{
if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
int16_t t;
switch (rotation) {
case 1:
t = x;
x = WIDTH - 1 - y;
y = t;
break;
case 2:
x = WIDTH - 1 - x;
y = HEIGHT - 1 - y;
break;
case 3:
t = x;
x = y;
y = HEIGHT - 1 - t;
break;
}
buffer[x + y * WIDTH] = color;
}
void fillScreen(uint16_t color)
{
uint32_t i, pixels = WIDTH * HEIGHT;
for (i = 0; i < pixels; i++) buffer[i] = color;
}
uint16_t *getBuffer(void)
{
return buffer;
}
#if 1
template<class T>
void print(T target, const char* name = 0, bool as_progmem = false)
{
static const uint16_t per_line = 10;
uint32_t remain = WIDTH * HEIGHT;
uint16_t* p = buffer;
if (!name) name = "canvas16";
if (as_progmem) target.print(F("const "));
target.print(F("uint16_t ")); target.print(name); target.print(F("[] "));
if (as_progmem) target.print(F("PROGMEM "));
target.println(F("=")); target.println(F("{"));
while (remain > per_line)
{
target.print(F(" "));
for (uint16_t i = 0; i < per_line; i++)
{
target.print(F("0x")); target.print(*p++, HEX); target.print(F(", "));
}
remain -= per_line;
if (remain > 0) target.println();
#if defined (ESP8266)
yield();
#endif
}
if (remain > 0) target.print(F(" "));
while (remain-- > 0)
{
target.print(F("0x")); target.print(*p++, HEX); target.print(F(", "));
}
target.println();
target.println(F("};"));
}
#endif
private:
uint16_t buffer[w * h];
};
#endif

View File

@@ -0,0 +1,719 @@
// created by Jean-Marc Zingg to be a standalone ILI9486_SPI library (instead of the GxCTRL_ILI9486_SPI class for the GxTFT library)
// code extracts taken from https://github.com/Bodmer/TFT_HX8357
// spi kludge handling solution found in https://github.com/Bodmer/TFT_eSPI
// code extracts taken from https://github.com/adafruit/Adafruit-GFX-Library
//
// License: GNU GENERAL PUBLIC LICENSE V3, see LICENSE
//
#include "../core/options.h"
#if DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486
#include <SPI.h>
#include "ILI9486_SPI.h"
#define SPI_SPEED 40000000UL
//#define SPI_SPEED 20000000 // max reliable speed is 20Mhz for RPi SPI kludge
//#define SPI_SPEED 4000000
#define ILI9486_SPI_CASET 0x2A
#define ILI9486_SPI_PASET 0x2B
#define ILI9486_SPI_RAMWR 0x2C
#define ILI9486_SPI_RAMRD 0x2E
#define ILI9486_SPI_MADCTL 0x36
#define MADCTL_MY 0x80
#define MADCTL_MX 0x40
#define MADCTL_MV 0x20
#define MADCTL_ML 0x10
#define MADCTL_BGR 0x08
#define MADCTL_MH 0x04
#define ILI9488_INVOFF 0x20
#define ILI9488_INVON 0x21
//ILI9486_SPI::ILI9486_SPI(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(320, 480), _spi_settings(SPI_SPEED, MSBFIRST, SPI_MODE0)
ILI9486_SPI::ILI9486_SPI(int8_t cs, int8_t dc, int8_t rst) : ILI9486_SPI(&SPI, cs, dc, rst) { }
ILI9486_SPI::ILI9486_SPI(SPIClass *spiClass, int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(320, 480), _spi_settings(SPI_SPEED, MSBFIRST, SPI_MODE0)
{
_spi = spiClass;
_spi16_mode = true;
_cs = cs;
_dc = dc;
_rst = rst;
_bgr = MADCTL_BGR;
#if defined(ESP8266)
if ((_cs >= 0) && (_dc >= 0))
{
_cs_pinmask = (uint32_t) digitalPinToBitMask(_cs);
_dc_pinmask = (uint32_t) digitalPinToBitMask(_dc);
}
else
{
_cs_pinmask = 0;
_dc_pinmask = 0;
}
#endif
_x_address_set = -1;
_x_address_set = -1;
digitalWrite(_cs, HIGH);
digitalWrite(_dc, HIGH);
pinMode(_cs, OUTPUT);
pinMode(_dc, OUTPUT);
if (rst >= 0)
{
digitalWrite(rst, HIGH);
pinMode(rst, OUTPUT);
}
}
// *** (overridden) virtual methods ***
#if defined(ESP8266) && true // This is for the RPi display that needs 16 bits
#define CMD_BITS (16-1)
void ILI9486_SPI::drawPixel(int16_t x, int16_t y, uint16_t color)
{
// Range checking
if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;
if (_spi16_mode && _cs_pinmask)
{
_spi->beginTransaction(_spi_settings);
GPOC = _cs_pinmask;
SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO);
// No need to send x if it has not changed (speeds things up)
if (_x_address_set != x)
{
GPOC = _dc_pinmask;
SPI1W0 = ILI9486_SPI_CASET << (CMD_BITS + 1 - 8);
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
GPOS = _dc_pinmask;
SPI1W0 = x >> 0;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = x << 8;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = x >> 0;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = x << 8;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
_x_address_set = x;
}
// No need to send y if it has not changed (speeds things up)
if (_y_address_set != y)
{
GPOC = _dc_pinmask;
SPI1W0 = ILI9486_SPI_PASET << (CMD_BITS + 1 - 8);
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
GPOS = _dc_pinmask;
SPI1W0 = y >> 0;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = y << 8;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = y >> 0;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
SPI1W0 = y << 8;
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
_y_address_set = y;
}
GPOC = _dc_pinmask;
SPI1W0 = ILI9486_SPI_RAMWR << (CMD_BITS + 1 - 8);
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
GPOS = _dc_pinmask;
SPI1W0 = (color >> 8) | (color << 8);
SPI1CMD |= SPIBUSY;
while (SPI1CMD & SPIBUSY) {}
GPOS = _cs_pinmask;
_spi->endTransaction();
}
else
{
_startTransaction();
_setWindow(x, y, 1, 1);
_writeColor16(color, 1);
_endTransaction();
}
}
#else
void ILI9486_SPI::drawPixel(int16_t x, int16_t y, uint16_t color)
{
if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
{
return;
}
_startTransaction();
_setWindow(x, y, 1, 1);
_writeColor16(color, 1);
_endTransaction();
}
#endif
void ILI9486_SPI::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;
_startTransaction();
_setWindow(x, y, w, h);
_writeColor16(color, uint32_t(w) * uint32_t(h));
_endTransaction();
}
void ILI9486_SPI::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
fillRect(x, y, 1, h, color);
}
void ILI9486_SPI::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
fillRect(x, y, w, 1, color);
}
void ILI9486_SPI::fillScreen(uint16_t color)
{
fillRect(0, 0, _width, _height, color);
}
void ILI9486_SPI::setRotation(uint8_t r)
{
Adafruit_GFX::setRotation(r);
_startTransaction();
if (_spi16_mode)
{
_writeCommand16(ILI9486_SPI_MADCTL);
switch (r & 3)
{
case 0:
_writeData16(MADCTL_MX | _bgr);
break;
case 1:
_writeData16(MADCTL_MV | _bgr);
break;
case 2:
_writeData16(MADCTL_MY | _bgr);
break;
case 3:
_writeData16(MADCTL_MX | MADCTL_MY | MADCTL_MV | _bgr);
break;
}
}
else
{
_writeCommand(ILI9486_SPI_MADCTL);
switch (r & 3)
{
case 0:
_writeData(MADCTL_MX | _bgr);
break;
case 1:
_writeData(MADCTL_MV | _bgr);
break;
case 2:
_writeData(MADCTL_MY | _bgr);
break;
case 3:
_writeData(MADCTL_MX | MADCTL_MY | MADCTL_MV | _bgr);
break;
}
}
_endTransaction();
}
void ILI9486_SPI::invertDisplay(bool i)
{
/*_bgr = i ? MADCTL_BGR : 0x00;
setRotation(rotation);*/
sendCommand(i ? ILI9488_INVON : ILI9488_INVOFF);
}
// *** other public methods ***
void ILI9486_SPI::setSpiKludge(bool rpi_spi16_mode)
{
_spi16_mode = rpi_spi16_mode;
}
void ILI9486_SPI::init(void)
{
digitalWrite(_cs, HIGH);
_spi->begin();
_spi->beginTransaction( { SPI_SPEED, MSBFIRST, SPI_MODE0 } );
_spi->endTransaction();
if (_rst >= 0)
{
digitalWrite(_rst, LOW);
delay(20);
digitalWrite(_rst, HIGH);
}
delay(200);
_startTransaction();
if (_spi16_mode)
{
_writeCommand16(0x3A);
_writeData16(0x55); // use 16 bits per pixel color
_writeCommand16(0x36);
_writeData16(0x48); // MX, BGR == rotation 0
// PGAMCTRL(Positive Gamma Control)
_writeCommand16(0xE0);
_writeData16(0x0F);
_writeData16(0x1F);
_writeData16(0x1C);
_writeData16(0x0C);
_writeData16(0x0F);
_writeData16(0x08);
_writeData16(0x48);
_writeData16(0x98);
_writeData16(0x37);
_writeData16(0x0A);
_writeData16(0x13);
_writeData16(0x04);
_writeData16(0x11);
_writeData16(0x0D);
_writeData16(0x00);
// NGAMCTRL(Negative Gamma Control)
_writeCommand16(0xE1);
_writeData16(0x0F);
_writeData16(0x32);
_writeData16(0x2E);
_writeData16(0x0B);
_writeData16(0x0D);
_writeData16(0x05);
_writeData16(0x47);
_writeData16(0x75);
_writeData16(0x37);
_writeData16(0x06);
_writeData16(0x10);
_writeData16(0x03);
_writeData16(0x24);
_writeData16(0x20);
_writeData16(0x00);
// Digital Gamma Control 1
_writeCommand16(0xE2);
_writeData16(0x0F);
_writeData16(0x32);
_writeData16(0x2E);
_writeData16(0x0B);
_writeData16(0x0D);
_writeData16(0x05);
_writeData16(0x47);
_writeData16(0x75);
_writeData16(0x37);
_writeData16(0x06);
_writeData16(0x10);
_writeData16(0x03);
_writeData16(0x24);
_writeData16(0x20);
_writeData16(0x00);
_writeCommand16(0x11); // Sleep OUT
delay(150); // wait some time
_writeCommand16(0x29); // Display ON
}
else
{
_writeCommand(0x3A);
_writeData(0x66); // 18 bit colour for native SPI
_writeCommand(0x36);
_writeData(0x48); // MX, BGR == rotation 0
// PGAMCTRL(Positive Gamma Control)
#if DSP_MODEL==DSP_ILI9486
_writeCommand(0xE0);
_writeData(0x0F);
_writeData(0x1F);
_writeData(0x1C);
_writeData(0x0C);
_writeData(0x0F);
_writeData(0x08);
_writeData(0x48);
_writeData(0x98);
_writeData(0x37);
_writeData(0x0A);
_writeData(0x13);
_writeData(0x04);
_writeData(0x11);
_writeData(0x0D);
_writeData(0x00);
// NGAMCTRL(Negative Gamma Control)
_writeCommand(0xE1);
_writeData(0x0F);
_writeData(0x32);
_writeData(0x2E);
_writeData(0x0B);
_writeData(0x0D);
_writeData(0x05);
_writeData(0x47);
_writeData(0x75);
_writeData(0x37);
_writeData(0x06);
_writeData(0x10);
_writeData(0x03);
_writeData(0x24);
_writeData(0x20);
_writeData(0x00);
// Digital Gamma Control 1
_writeCommand(0xE2);
_writeData(0x0F);
_writeData(0x32);
_writeData(0x2E);
_writeData(0x0B);
_writeData(0x0D);
_writeData(0x05);
_writeData(0x47);
_writeData(0x75);
_writeData(0x37);
_writeData(0x06);
_writeData(0x10);
_writeData(0x03);
_writeData(0x24);
_writeData(0x20);
_writeData(0x00);
#endif
_writeCommand(0x11); // Sleep OUT
delay(150); // wait some time
_writeCommand(0x29); // Display ON
}
_endTransaction();
}
void ILI9486_SPI::setWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
_startTransaction();
_setWindow(x, y, w, h);
_endTransaction();
}
void ILI9486_SPI::pushColors(const uint16_t* data, uint16_t n)
{
_startTransaction();
_writeColor16(data, n);
_endTransaction();
}
void ILI9486_SPI::setBackLight(bool lit)
{
_startTransaction();
if (_spi16_mode) _writeCommand16(lit ? 0x29 : 0x28); // Display ON / Display OFF
else _writeCommand(lit ? 0x29 : 0x28); // Display ON / Display OFF
_endTransaction();
}
uint16_t ILI9486_SPI::color565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
// code extract taken from Adafruit_SPITFT::drawRGBBitmap https://github.com/adafruit/Adafruit-GFX-Library
void ILI9486_SPI::drawRGBBitmap(int16_t x, int16_t y, uint16_t *pcolors, int16_t w, int16_t h)
{
if (!pcolors) return; // canvas might be empty
int16_t x2, y2; // Lower-right coord
if (( x >= _width ) || // Off-edge right
( y >= _height) || // " top
((x2 = (x + w - 1)) < 0 ) || // " left
((y2 = (y + h - 1)) < 0) ) return; // " bottom
int16_t bx1 = 0, by1 = 0; // Clipped top-left within bitmap
int16_t saveW = w; // Save original bitmap width value
if (x < 0) // Clip left
{
w += x;
bx1 = -x;
x = 0;
}
if (y < 0) // Clip top
{
h += y;
by1 = -y;
y = 0;
}
if (x2 >= _width ) w = _width - x; // Clip right
if (y2 >= _height) h = _height - y; // Clip bottom
pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
_startTransaction();
_setWindow(x, y, w, h); // Clipped area
while (h--) // For each (clipped) scanline...
{
_writeColor16(pcolors, w); // Push one (clipped) row
pcolors += saveW; // Advance pointer by one full (unclipped) line
}
_endTransaction();
}
// code extract taken from Adafruit_SPITFT::drawRGBBitmap https://github.com/adafruit/Adafruit-GFX-Library
void ILI9486_SPI::drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h)
{
const uint16_t* pcolors = bitmap;
int16_t x2, y2; // Lower-right coord
if (( x >= _width ) || // Off-edge right
( y >= _height) || // " top
((x2 = (x + w - 1)) < 0 ) || // " left
((y2 = (y + h - 1)) < 0) ) return; // " bottom
int16_t bx1 = 0, by1 = 0; // Clipped top-left within bitmap
int16_t saveW = w; // Save original bitmap width value
if (x < 0) // Clip left
{
w += x;
bx1 = -x;
x = 0;
}
if (y < 0) // Clip top
{
h += y;
by1 = -y;
y = 0;
}
if (x2 >= _width ) w = _width - x; // Clip right
if (y2 >= _height) h = _height - y; // Clip bottom
pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
_startTransaction();
_setWindow(x, y, w, h); // Clipped area
while (h--) // For each (clipped) scanline...
{
for (int16_t i = 0; i < w; i++) // Push one (clipped) row
{
_writeColor16(pgm_read_word(pcolors + i), 1);
}
pcolors += saveW; // Advance pointer by one full (unclipped) line
}
_endTransaction();
}
// *** private methods
void ILI9486_SPI::_setWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
uint16_t xe = x + w - 1;
uint16_t ye = y + h - 1;
if (_spi16_mode)
{
_writeCommand16(ILI9486_SPI_CASET);
uint16_t columns[] = {uint16_t(x >> 8), uint16_t(x & 0xFF), uint16_t(xe >> 8), uint16_t(xe & 0xFF)};
_writeData16(columns, 4);
_writeCommand16(ILI9486_SPI_PASET);
uint16_t rows[] = {uint16_t(y >> 8), uint16_t(y & 0xFF), uint16_t(ye >> 8), uint16_t(ye & 0xFF)};
_writeData16(rows, 4);
_writeCommand16(ILI9486_SPI_RAMWR);
}
else
{
_writeCommand(ILI9486_SPI_CASET);
_writeData16(x);
_writeData16(xe);
_writeCommand(ILI9486_SPI_PASET);
_writeData16(y);
_writeData16(ye);
_writeCommand(ILI9486_SPI_RAMWR);
}
_x_address_set = -1;
_x_address_set = -1;
}
void ILI9486_SPI::_startTransaction()
{
_spi->beginTransaction(_spi_settings);
if (_cs >= 0) digitalWrite(_cs, LOW);
}
void ILI9486_SPI::_endTransaction()
{
if (_cs >= 0) digitalWrite(_cs, HIGH);
_spi->endTransaction();
}
void ILI9486_SPI::_writeCommand(uint8_t cmd)
{
digitalWrite(_dc, LOW);
_spi->transfer(cmd);
digitalWrite(_dc, HIGH);
}
void ILI9486_SPI::sendCommand(uint8_t cmd)
{
_startTransaction();
if (_cs >= 0)
digitalWrite(_cs, LOW);
digitalWrite(_dc, LOW); // Command mode
_spi->transfer(cmd); // Send the command byte
digitalWrite(_dc, HIGH);
if (_cs >= 0)
digitalWrite(_cs, HIGH);
_endTransaction();
/* digitalWrite(_dc, LOW);
_spi->transfer(cmd);
digitalWrite(_dc, HIGH);*/
}
void ILI9486_SPI::_writeCommand16(uint16_t cmd)
{
digitalWrite(_dc, LOW);
_writeData16(cmd);
digitalWrite(_dc, HIGH);
}
void ILI9486_SPI::_writeData(uint8_t data)
{
digitalWrite(_dc, HIGH);
_spi->transfer(data);
}
void ILI9486_SPI::_writeData16(uint16_t data)
{
#if (defined (ESP8266) || defined(ESP32))
_spi->write16(data);
#else
_spi->transfer(data >> 8);
_spi->transfer(data);
#endif
}
void ILI9486_SPI::_writeData16(uint16_t data, uint32_t n)
{
#if (defined (ESP8266) || defined(ESP32)) && true // fastest
uint16_t swapped = ((data << 8) | (data >> 8));
_spi->writePattern((uint8_t*)&swapped, 2, n);
#elif (defined (ESP8266) || defined(ESP32))
while (n-- > 0)
{
_spi->write16(data);
}
#else // wdt on ESP8266
while (n-- > 0)
{
_spi->transfer(data >> 8);
_spi->transfer(data);
}
#endif
}
void ILI9486_SPI::_writeData16(const uint16_t* data, uint32_t n)
{
#if (defined (ESP8266) || defined(ESP32) || (TEENSYDUINO == 147)) && true // fastest
static const uint16_t swap_buffer_size = 64; // optimal for ESP8266 SPI
static const uint32_t max_chunk = swap_buffer_size / 2; // uint16_t's
uint8_t swap_buffer[swap_buffer_size];
const uint8_t* p1 = reinterpret_cast<const uint8_t*> (data);
const uint8_t* p2 = p1 + 1;
while (n > 0)
{
uint32_t chunk = min(max_chunk, n);
n -= chunk;
uint8_t* p3 = swap_buffer;
uint8_t* p4 = p3 + 1;
uint16_t ncopy = chunk;
while (ncopy-- > 0)
{
*p3 = *p2; p3 += 2; p2 += 2;
*p4 = *p1; p4 += 2; p1 += 2;
}
#if (defined (ESP8266) || defined(ESP32))
_spi->transferBytes(swap_buffer, 0, 2 * chunk);
#elif defined(ARDUINO_ARCH_SAM) // same speed
_spi->transfer(SS, swap_buffer, 2 * chunk);
#else
_spi->transfer(swap_buffer, 0, 2 * chunk);
#endif
}
#else
while (n-- > 0)
{
uint16_t color = (*data++);
#if (defined (ESP8266) || defined(ESP32)) && false // faster
_spi->write16(color);
#else
_spi->transfer(color >> 8);
_spi->transfer(color);
#endif
}
#endif
}
void ILI9486_SPI::_writeColor16(uint16_t data, uint32_t n)
{
if (_spi16_mode) return _writeData16(data, n);
#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)
{
_spi->transfer(uint8_t((data & 0xF800) >> 8));
_spi->transfer(uint8_t((data & 0x07E0) >> 3));
_spi->transfer(uint8_t((data & 0x001F) << 3));
}
#endif
}
#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 ILI9486_SPI::_writeColor16(const uint16_t* data, uint32_t n)
{
if (_spi16_mode) return _writeData16(data, n);
#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)
{
_spi->transfer(uint8_t((*data & 0xF800) >> 8));
_spi->transfer(uint8_t((*data & 0x07E0) >> 3));
_spi->transfer(uint8_t((*data & 0x001F) << 3));
}
#endif
}
#endif

View File

@@ -0,0 +1,65 @@
// created by Jean-Marc Zingg to be a standalone ILI9486_SPI library (instead of the GxCTRL_ILI9486_SPI class for the GxTFT library)
// code extracts taken from https://github.com/Bodmer/TFT_HX8357
// spi kludge handling solution found in https://github.com/Bodmer/TFT_eSPI
// code extracts taken from https://github.com/adafruit/Adafruit-GFX-Library
//
// License: GNU GENERAL PUBLIC LICENSE V3, see LICENSE
//
#ifndef _ILI9486_SPI_H_
#define _ILI9486_SPI_H_
#include <Arduino.h>
#include <SPI.h>
#include "GFXcanvas16T.h"
#include <Adafruit_GFX.h>
class ILI9486_SPI : public Adafruit_GFX
{
public:
ILI9486_SPI(int8_t cs, int8_t dc, int8_t rst);
ILI9486_SPI(SPIClass *spiClass, int8_t cs, int8_t dc, int8_t rst);
// (overridden) virtual methods
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
virtual void fillScreen(uint16_t color);
virtual void setRotation(uint8_t r);
virtual void invertDisplay(bool i);
// other public methods
void setSpiKludge(bool rpi_spi16_mode = true); // call with false before init to disable
void init(void);
void setWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void pushColors(const uint16_t* data, uint16_t n); // fast one
void setBackLight(bool lit);
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
void drawRGBBitmap(int16_t x, int16_t y, uint16_t *pcolors, int16_t w, int16_t h);
void drawRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
virtual void _startTransaction();
virtual void _endTransaction();
void _writeCommand(uint8_t cmd);
void sendCommand(uint8_t cmd);
private:
void _setWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void _writeCommand16(uint16_t cmd);
void _writeData(uint8_t data);
void _writeData16(uint16_t data);
void _writeData16(uint16_t data, uint32_t n);
void _writeData16(const uint16_t* data, uint32_t n);
// note: only use for pixel data, RGB888 on ILI9488, ILI9486 native SPI
void _writeColor16(uint16_t data, uint32_t n);
void _writeColor16(const uint16_t* data, uint32_t n);
private:
bool _spi16_mode;
SPISettings _spi_settings;
SPIClass *_spi;
int8_t _cs, _dc, _rst;
int8_t _bgr;
int32_t _x_address_set, _y_address_set;
uint32_t _cs_pinmask, _dc_pinmask;
};
#endif

File diff suppressed because it is too large Load Diff