Merge pull request #1 from Bodmer/master

Merge to upstream master
This commit is contained in:
UT2UH 2020-10-03 08:49:04 +03:00 committed by GitHub
commit b221648823
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 3836 additions and 908 deletions

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,23 @@ class TFT_eSprite : public TFT_eSPI {
public:
TFT_eSprite(TFT_eSPI *tft);
explicit TFT_eSprite(TFT_eSPI *tft);
~TFT_eSprite(void);
// Create a sprite of width x height pixels, return a pointer to the RAM area
// Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
// RAM required is:
// - 1 bit per pixel for 1 bit colour depth
// - 1 nibble per pixel for 4 bit colour
// - 1 byte per pixel for 8 bit colour
// - 2 bytes per pixel for 16 bit color depth
~TFT_eSprite(void);
void* createSprite(int16_t width, int16_t height, uint8_t frames = 1);
void* createSprite(int16_t width, int16_t height, uint8_t frames = 1);
// Returns a pointer to the sprite or nullptr if not created, user must cast to pointer type
void* getPointer(void);
// Returns true if sprite has been created
bool created(void);
// Delete the sprite to free up the RAM
void deleteSprite(void);
@ -34,8 +40,8 @@ class TFT_eSprite : public TFT_eSPI {
int8_t getColorDepth(void);
// Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used.
void createPalette(uint16_t *palette, int colors = 16); // Palette in RAM
void createPalette(const uint16_t *palette, int colors = 16); // Palette in FLASH
void createPalette(uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in RAM
void createPalette(const uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in FLASH
// Set a single palette index to the given color
void setPaletteColor(uint8_t index, uint16_t color);
@ -114,7 +120,7 @@ class TFT_eSprite : public TFT_eSPI {
// 16bpp = colour, 8bpp = byte, 4bpp = colour index, 1bpp = 1 or 0
uint16_t readPixelValue(int32_t x, int32_t y);
// Write an image (colour bitmap) to the sprite. Not implemented for _bpp == 4.
// Write an image (colour bitmap) to the sprite.
void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data);
void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data);
@ -127,6 +133,14 @@ class TFT_eSprite : public TFT_eSPI {
void pushSprite(int32_t x, int32_t y);
void pushSprite(int32_t x, int32_t y, uint16_t transparent);
// Push a windowed area of the sprite to the TFT at tx, ty
bool pushSprite(int32_t tx, int32_t ty, int32_t sx, int32_t sy, int32_t sw, int32_t sh);
// Push the sprite to another sprite at x,y. This fn calls pushImage() in the destination sprite (dspr) class.
// >>>>>> Using a transparent color is not supported at the moment <<<<<<
bool pushToSprite(TFT_eSprite *dspr, int32_t x, int32_t y);
bool pushToSprite(TFT_eSprite *dspr, int32_t x, int32_t y, uint16_t transparent);
int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font),
drawChar(uint16_t uniCode, int32_t x, int32_t y);
@ -154,15 +168,15 @@ class TFT_eSprite : public TFT_eSPI {
uint8_t _bpp; // bits per pixel (1, 8 or 16)
uint16_t *_img; // pointer to 16 bit sprite
uint8_t *_img8; // pointer to 8 bit sprite
uint8_t *_img4; // pointer to 4 bit sprite (uses color map)
uint8_t *_img8_1; // pointer to frame 1
uint8_t *_img8_2; // pointer to frame 2
uint8_t *_img8; // pointer to 8 bit sprite frame 1 or frame 2
uint8_t *_img4; // pointer to 4 bit sprite (uses color map)
uint8_t *_img8_1; // pointer to frame 1
uint8_t *_img8_2; // pointer to frame 2
uint16_t *_colorMap; // color map: 16 entries, used with 4 bit color map.
int16_t _xpivot; // x pivot point coordinate
int16_t _ypivot; // y pivot point coordinate
int16_t _xPivot; // x pivot point coordinate
int16_t _yPivot; // y pivot point coordinate
int32_t _sinra;
int32_t _cosra;

View File

@ -457,7 +457,11 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
if ( (color >> 8) == (color & 0x00FF) )
{ if (!len) return;
tft_Write_16(color);
#if defined (SSD1963_DRIVER)
while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;}
#else
while (--len) {WR_L; WR_H; WR_L; WR_H;}
#endif
}
else while (len--) {tft_Write_16(color);}
}
@ -489,28 +493,35 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
////////////////////////////////////////////////////////////////////////////////////////
#if defined ESP32_DMA && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS
#if defined (ESP32_DMA) && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
** Function name: dmaBusy
** Description: Check if DMA is busy (currently blocking!)
** Description: Check if DMA is busy
***************************************************************************************/
bool TFT_eSPI::dmaBusy(void)
{
if (!DMA_Enabled || !spiBusyCheck) return false;
//spi_transaction_t rtrans;
//bool trans_result=spi_device_polling_transmit(dmaHAL, &rtrans);
//return trans_result;
// This works but blocks
dmaWait();
return false;
spi_transaction_t *rtrans;
esp_err_t ret;
uint8_t checks = spiBusyCheck;
for (int i = 0; i < checks; ++i)
{
ret = spi_device_get_trans_result(dmaHAL, &rtrans, 0);
if (ret == ESP_OK) spiBusyCheck--;
}
//Serial.print("spiBusyCheck=");Serial.println(spiBusyCheck);
if (spiBusyCheck ==0) return false;
return true;
}
/***************************************************************************************
** Function name: dmaWait
** Description: Check if DMA is busy (blocking!)
** Description: Wait until DMA is over (blocking!)
***************************************************************************************/
void TFT_eSPI::dmaWait(void)
{
@ -535,6 +546,11 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
{
if ((len == 0) || (!DMA_Enabled)) return;
dmaWait();
if(_swapBytes) {
for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8);
}
esp_err_t ret;
static spi_transaction_t trans;
@ -548,7 +564,7 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
assert(ret == ESP_OK);
spiBusyCheck = 1;
spiBusyCheck++;
}
@ -574,12 +590,10 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
if (dw < 1 || dh < 1) return;
if (buffer == nullptr) buffer = image;
uint32_t len = dw*dh;
dmaWait();
if (buffer == nullptr) { buffer = image; dmaWait(); }
// If image is clipped, copy pixels into a contiguous block
if ( (dw != w) || (dh != h) ) {
if(_swapBytes) {
@ -606,43 +620,24 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
}
}
if (spiBusyCheck) dmaWait(); // Incase we did not wait earlier
setAddrWindow(x, y, dw, dh);
esp_err_t ret;
static spi_transaction_t trans[6];
for (int i = 0; i < 6; i++)
{
memset(&trans[i], 0, sizeof(spi_transaction_t));
if ((i & 1) == 0)
{
trans[i].length = 8;
trans[i].user = (void *)0;
}
else
{
trans[i].length = 8 * 4;
trans[i].user = (void *)1;
}
trans[i].flags = SPI_TRANS_USE_TXDATA;
}
trans[0].tx_data[0] = 0x2A; //Column Address Set
trans[1].tx_data[0] = x >> 8; //Start Col High
trans[1].tx_data[1] = x & 0xFF; //Start Col Low
trans[1].tx_data[2] = (x + dw - 1) >> 8; //End Col High
trans[1].tx_data[3] = (x + dw - 1) & 0xFF; //End Col Low
trans[2].tx_data[0] = 0x2B; //Page address set
trans[3].tx_data[0] = y >> 8; //Start page high
trans[3].tx_data[1] = y & 0xFF; //start page low
trans[3].tx_data[2] = (y + dh - 1) >> 8; //end page high
trans[3].tx_data[3] = (y + dh - 1) & 0xFF; //end page low
trans[4].tx_data[0] = 0x2C; //memory write
trans[5].tx_buffer = buffer; //finally send the line data
trans[5].length = dw * 2 * 8 * dh; //Data length, in bits
trans[5].flags = 0; //undo SPI_TRANS_USE_TXDATA flag
for (int i = 0; i < 6; i++)
{
ret = spi_device_queue_trans(dmaHAL, &trans[i], portMAX_DELAY);
assert(ret == ESP_OK);
}
spiBusyCheck = 6;
static spi_transaction_t trans;
memset(&trans, 0, sizeof(spi_transaction_t));
trans.user = (void *)1;
trans.tx_buffer = buffer; //finally send the line data
trans.length = len * 16; //Data length, in bits
trans.flags = 0; //SPI_TRANS_USE_TXDATA flag
ret = spi_device_queue_trans(dmaHAL, &trans, portMAX_DELAY);
assert(ret == ESP_OK);
spiBusyCheck++;
}
////////////////////////////////////////////////////////////////////////////////////////
@ -658,8 +653,8 @@ extern "C" void dc_callback();
void IRAM_ATTR dc_callback(spi_transaction_t *spi_tx)
{
if ((bool)spi_tx->user) DC_D;
else DC_C;
if ((bool)spi_tx->user) {DC_D;}
else {DC_C;}
}
/***************************************************************************************
@ -714,7 +709,7 @@ bool TFT_eSPI::initDMA(void)
void TFT_eSPI::deInitDMA(void)
{
if (!DMA_Enabled) return;
spi_bus_remove_device(dmaHAL);
spi_bus_free(spi_host);
DMA_Enabled = false;
}

View File

@ -39,9 +39,26 @@
// Define a generic flag for 8 bit parallel
#if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
#define TFT_PARALLEL_8_BIT // Generic parallel flag
#if !defined (TFT_PARALLEL_8_BIT)
#define TFT_PARALLEL_8_BIT // Generic parallel flag
#endif
#endif
// Ensure ESP32 specific flag is defined for 8 bit parallel
#if defined (TFT_PARALLEL_8_BIT)
#if !defined (ESP32_PARALLEL)
#define ESP32_PARALLEL
#endif
#endif
// Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
#if !defined(TFT_PARALLEL_8_BIT) && !defined(ILI9488_DRIVER) && !defined (RPI_DISPLAY_TYPE)
#define ESP32_DMA
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
#define DMA_BUSY_CHECK dmaWait()
#else
#define DMA_BUSY_CHECK
#endif
// If smooth font is used then it is likely SPIFFS will be needed
#ifdef SMOOTH_FONT
@ -60,10 +77,16 @@
#define DC_D // No macro allocated so it generates no code
#else
#if defined (TFT_PARALLEL_8_BIT)
#define DC_C GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1ts = (1 << TFT_DC)
// TFT_DC, by design, must be in range 0-31 for single register parallel write
#if (TFT_DC >= 0) && (TFT_DC < 32)
#define DC_C GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1ts = (1 << TFT_DC)
#else
#define DC_C
#define DC_D
#endif
#else
#if TFT_DC >= 32
#if (TFT_DC >= 32)
#ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change
#define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \
GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
@ -73,16 +96,20 @@
#define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))
#define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))
#endif
#elif TFT_DC >= 0
#ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower DC change
#define DC_C GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1ts = (1 << TFT_DC)
#elif defined (RPI_DISPLAY_TYPE) // Other RPi displays need a slower C->D change
#define DC_C GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1ts = (1 << TFT_DC)
#elif (TFT_DC >= 0)
#if defined (RPI_DISPLAY_TYPE)
#if defined (ILI9486_DRIVER)
// RPi ILI9486 display needs a slower DC change
#define DC_C GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1ts = (1 << TFT_DC)
#else
// Other RPi displays need a slower C->D change
#define DC_C GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1tc = (1 << TFT_DC); \
GPIO.out_w1ts = (1 << TFT_DC)
#endif
#else
#define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC)
#define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC)
@ -98,8 +125,9 @@
// Define the CS (TFT chip select) pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#ifndef TFT_CS
#define CS_L // No macro allocated so it generates no code
#define CS_H // No macro allocated so it generates no code
#define TFT_CS -1 // Keep DMA code happy
#define CS_L // No macro allocated so it generates no code
#define CS_H // No macro allocated so it generates no code
#else
#if defined (TFT_PARALLEL_8_BIT)
#if TFT_CS >= 32
@ -113,8 +141,8 @@
#define CS_H
#endif
#else
#if TFT_CS >= 32
#ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change
#if (TFT_CS >= 32)
#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change
#define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \
GPIO.out1_w1tc.val = (1 << (TFT_CS - 32))
#define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \
@ -123,12 +151,12 @@
#define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32))
#define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))
#endif
#elif TFT_CS >= 0
#ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change
#elif (TFT_CS >= 0)
#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change
#define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
#define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS)
#else
#define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS)
#define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
#define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS)
#endif
#else
@ -141,9 +169,18 @@
////////////////////////////////////////////////////////////////////////////////////////
// Define the WR (TFT Write) pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#ifdef TFT_WR
#define WR_L GPIO.out_w1tc = (1 << TFT_WR)
#define WR_H GPIO.out_w1ts = (1 << TFT_WR)
#if defined (TFT_WR)
#if (TFT_WR >= 0)
// TFT_WR, by design, must be in range 0-31 for single register parallel write
#define WR_L GPIO.out_w1tc = (1 << TFT_WR)
#define WR_H GPIO.out_w1ts = (1 << TFT_WR)
#else
#define WR_L
#define WR_H
#endif
#else
#define WR_L
#define WR_H
#endif
////////////////////////////////////////////////////////////////////////////////////////
@ -158,12 +195,64 @@
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Make sure TFT_MISO is defined if not used to avoid an error message
// Make sure SPI default pins are assigned if not specified by user or set to -1
////////////////////////////////////////////////////////////////////////////////////////
#if !defined (TFT_PARALLEL_8_BIT)
#ifndef TFT_MISO
#define TFT_MISO -1
#ifdef USE_HSPI_PORT
#ifndef TFT_MISO
#define TFT_MISO 12
#endif
#if (TFT_MISO == -1)
#undef TFT_MISO
#define TFT_MISO 12
#endif
#ifndef TFT_MOSI
#define TFT_MOSI 13
#endif
#if (TFT_MOSI == -1)
#undef TFT_MOSI
#define TFT_MOSI 13
#endif
#ifndef TFT_SCLK
#define TFT_SCLK 14
#endif
#if (TFT_SCLK == -1)
#undef TFT_SCLK
#define TFT_SCLK 14
#endif
#else // VSPI port
#ifndef TFT_MISO
#define TFT_MISO 19
#endif
#if (TFT_MISO == -1)
#undef TFT_MISO
#define TFT_MISO 19
#endif
#ifndef TFT_MOSI
#define TFT_MOSI 23
#endif
#if (TFT_MOSI == -1)
#undef TFT_MOSI
#define TFT_MOSI 23
#endif
#ifndef TFT_SCLK
#define TFT_SCLK 18
#endif
#if (TFT_SCLK == -1)
#undef TFT_SCLK
#define TFT_SCLK 18
#endif
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////
@ -204,13 +293,26 @@
// Write 8 bits to TFT
#define tft_Write_8(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C)); WR_H
// Write 16 bits to TFT
#define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 8)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)((C) >> 0)); WR_H
#if defined (SSD1963_DRIVER)
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H
// Write 18 bit color to TFT
#define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x001F)<< 3)); WR_H
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H
#endif
// Write 32 bits to TFT
#define tft_Write_32(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \
@ -232,10 +334,18 @@
// Read pin
#ifdef TFT_RD
#define RD_L GPIO.out_w1tc = (1 << TFT_RD)
//#define RD_L digitalWrite(TFT_WR, LOW)
#define RD_H GPIO.out_w1ts = (1 << TFT_RD)
//#define RD_H digitalWrite(TFT_WR, HIGH)
#if (TFT_RD >= 32)
#define RD_L GPIO.out1_w1tc.val = = (1 << (TFT_RD - 32))
#define RD_H GPIO.out1_w1ts.val = = (1 << (TFT_RD - 32))
#elif (TFT_RD >= 0)
#define RD_L GPIO.out_w1tc = (1 << TFT_RD)
//#define RD_L digitalWrite(TFT_WR, LOW)
#define RD_H GPIO.out_w1ts = (1 << TFT_RD)
//#define RD_H digitalWrite(TFT_WR, HIGH)
#else
#define RD_L
#define RD_H
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////
@ -302,16 +412,6 @@
////////////////////////////////////////////////////////////////////////////////////////
#else
#define ESP32_DMA // DMA is available for SPI
// Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
#ifdef ESP32_DMA
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
#define DMA_BUSY_CHECK { if (DMA_Enabled) dmaWait(); }
#else
#define DMA_BUSY_CHECK
#endif
// ESP32 low level SPI writes for 8, 16 and 32 bit values
// to avoid the function call overhead
#define TFT_WRITE_BITS(D, B) \

View File

@ -304,7 +304,7 @@ return;
SPI1U1 = (511 << SPILMOSI);
while(len>31)
{
#if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000)
#if (defined (SPI_FREQUENCY) && (SPI_FREQUENCY == 80000000))
if(SPI1CMD & SPIBUSY) // added to sync with flag change
#endif
while(SPI1CMD & SPIBUSY) {}

View File

@ -19,7 +19,7 @@
#define DMA_BUSY_CHECK // DMA not available, leave blank
// Initialise processor specific SPI functions, used by init()
#if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266)
#if (!defined (SUPPORT_TRANSACTIONS) && defined (ESP8266))
#define INIT_TFT_DATA_BUS \
spi.setBitOrder(MSBFIRST); \
spi.setDataMode(TFT_SPI_MODE); \

View File

@ -58,6 +58,13 @@
#define CS_H digitalWrite(TFT_CS, HIGH)
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Make sure TFT_RD is defined if not used to avoid an error message
////////////////////////////////////////////////////////////////////////////////////////
#ifndef TFT_RD
#define TFT_RD -1
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the WR (TFT Write) pin drive code
////////////////////////////////////////////////////////////////////////////////////////

View File

@ -10,8 +10,11 @@
// No globals
#else
// Use STM32 default SPI port
SPIClass& spi = SPI;
#if !defined (TFT_MOSI) || !defined (TFT_MISO) || !defined (TFT_SCLK)
SPIClass& spi = SPI;
#else
SPIClass spi(TFT_MOSI, TFT_MISO, TFT_SCLK);
#endif
// SPI HAL peripheral handle
SPI_HandleTypeDef spiHal;
#endif
@ -81,24 +84,42 @@ void TFT_eSPI::end_SDA_Read(void)
** Description: Write a block of pixels of the same colour
***************************************************************************************/
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
// Loop unrolling improves speed dramtically graphics test 0.634s => 0.374s
while (len>31) {
// 32D macro writes 16 bits twice
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
len-=32;
}
while (len>7) {
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
len-=8;
}
// Loop unrolling improves speed dramtically graphics test 0.634s => 0.374s
while (len>31) {
#if !defined (SSD1963_DRIVER)
// 32D macro writes 16 bits twice
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
#else
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
#endif
len-=32;
}
while (len>7) {
#if !defined (SSD1963_DRIVER)
tft_Write_32D(color); tft_Write_32D(color);
tft_Write_32D(color); tft_Write_32D(color);
#else
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
tft_Write_16(color); tft_Write_16(color); tft_Write_16(color); tft_Write_16(color);
#endif
len-=8;
}
while (len--) {tft_Write_16(color);}
}
@ -128,7 +149,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
***************************************************************************************/
void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
{
#ifdef STM_PORTA_DATA_BUS
#if defined (STM_PORTA_DATA_BUS)
#if defined (STM32F1xx)
if (mode == OUTPUT) GPIOA->CRL = 0x33333333;
else GPIOA->CRL = 0x88888888;
@ -136,7 +157,7 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
if (mode == OUTPUT) GPIOA->MODER = (GPIOA->MODER & 0xFFFF0000) | 0x00005555;
else GPIOA->MODER &= 0xFFFF0000;
#endif
#elif STM_PORTB_DATA_BUS
#elif defined (STM_PORTB_DATA_BUS)
#if defined (STM32F1xx)
if (mode == OUTPUT) GPIOB->CRL = 0x33333333;
else GPIOB->CRL = 0x88888888;
@ -191,12 +212,12 @@ uint8_t TFT_eSPI::readByte(void)
uint8_t b = 0;
RD_L;
#ifdef STM_PORTA_DATA_BUS
#if defined (STM_PORTA_DATA_BUS)
b = GPIOA->IDR;
b = GPIOA->IDR;
b = GPIOA->IDR;
b = (GPIOA->IDR) & 0xFF;
#elif STM_PORTB_DATA_BUS
#elif defined (STM_PORTB_DATA_BUS)
b = GPIOB->IDR;
b = GPIOB->IDR;
b = GPIOB->IDR;
@ -484,15 +505,20 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
// The DMA functions here work with SPI only (not parallel)
#if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx)
/***************************************************************************************
** Function name: DMA2_StreamX_IRQHandler
** Description: Override the default HAL stream 3 interrupt handler
** Function name: DMAX_StreamX_IRQHandler
** Description: Override the default HAL stream X interrupt handler
***************************************************************************************/
extern "C" void DMA2_Stream3_IRQHandler();
void DMA2_Stream3_IRQHandler(void)
{
// Call the default end of buffer handler
HAL_DMA_IRQHandler(&dmaHal);
}
#if (TFT_SPI_PORT == 1)
extern "C" void DMA2_Stream3_IRQHandler();
void DMA2_Stream3_IRQHandler(void)
#elif (TFT_SPI_PORT == 2)
extern "C" void DMA1_Stream4_IRQHandler();
void DMA1_Stream4_IRQHandler(void)
#endif
{
// Call the default end of buffer handler
HAL_DMA_IRQHandler(&dmaHal);
}
/***************************************************************************************
** Function name: initDMA
@ -503,9 +529,14 @@ void DMA2_Stream3_IRQHandler(void)
// https://electronics.stackexchange.com/questions/379813/configuring-the-dma-request-multiplexer-on-a-stm32h7-mcu
bool TFT_eSPI::initDMA(void)
{
__HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock
#if (TFT_SPI_PORT == 1)
__HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock
dmaHal.Init.Channel = DMA_CHANNEL_3; // DMA channel 3 is for SPI1 TX
#elif (TFT_SPI_PORT == 2)
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA2 clock
dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI2 TX
#endif
dmaHal.Init.Channel = DMA_CHANNEL_3; // DMA channel 3 is for SPI1 TX
dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once
dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH; // Copy memory to the peripheral
dmaHal.Init.PeriphInc = DMA_PINC_DISABLE; // Don't increment peripheral address
@ -517,10 +548,13 @@ bool TFT_eSPI::initDMA(void)
// Insert error message here?
return DMA_Enabled = false;
};
#if (TFT_SPI_PORT == 1)
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); // Enable DMA end interrupt handler
#elif (TFT_SPI_PORT == 2)
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); // Enable DMA end interrupt handler
#endif
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); // Enable DMA end interrupt handler
__HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral
__HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral
return DMA_Enabled = true;
}
@ -530,13 +564,18 @@ bool TFT_eSPI::initDMA(void)
** Function name: DMA1_ChannelX_IRQHandler
** Description: Override the default HAL stream 3 interrupt handler
***************************************************************************************/
extern "C" void DMA1_Channel3_IRQHandler();
#if (TFT_SPI_PORT == 1)
extern "C" void DMA1_Channel3_IRQHandler();
void DMA1_Channel3_IRQHandler(void)
#elif (TFT_SPI_PORT == 2)
extern "C" void DMA1_Channel5_IRQHandler();
void DMA1_Channel5_IRQHandler(void)
#endif
{
// Call the default end of buffer handler
HAL_DMA_IRQHandler(&dmaHal);
}
void DMA1_Channel3_IRQHandler(void)
{
// Call the default end of buffer handler
HAL_DMA_IRQHandler(&dmaHal);
}
//*/
/***************************************************************************************
** Function name: initDMA
@ -544,7 +583,7 @@ void DMA1_Channel3_IRQHandler(void)
***************************************************************************************/
bool TFT_eSPI::initDMA(void)
{
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA2 clock
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock
dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once
dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH; // Copy memory to the peripheral
@ -561,9 +600,13 @@ bool TFT_eSPI::initDMA(void)
return DMA_Enabled = false;
};
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); // Enable DMA end interrupt handler
#if (TFT_SPI_PORT == 1)
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); // Enable DMA end interrupt handler
#elif (TFT_SPI_PORT == 2)
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); // Enable DMA end interrupt handler
#endif
return DMA_Enabled = true;
}

View File

@ -146,23 +146,49 @@
////////////////////////////////////////////////////////////////////////////////////////
#else
// Use SPI1 as default if not defined
#ifndef TFT_SPI_PORT
#define TFT_SPI_PORT 1
#endif
// Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants
#if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx)
#define STM32_DMA // DMA is available with these processors
// Initialise processor specific SPI and DMA instances - used by init()
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \
dmaHal.Instance = DMA2_Stream3
// The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows:
// DMA_CHANNEL_3
// DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler()
#if (TFT_SPI_PORT == 1)
// Initialise processor specific SPI and DMA instances - used by init()
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \
dmaHal.Instance = DMA2_Stream3
// The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows:
// DMA_CHANNEL_3
// DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler()
#elif (TFT_SPI_PORT == 2)
// Initialise processor specific SPI and DMA instances - used by init()
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \
dmaHal.Instance = DMA1_Stream4
// The DMA hard-coding for SPI2 is in TFT_eSPI_STM32.c as follows:
// DMA_CHANNEL_4
// DMA1_Stream4_IRQn and DMA1_Stream4_IRQHandler()
#endif
#elif defined (STM32F1xx)
// For Blue Pill and STM32F1xx processors with DMA support
#define STM32_DMA // DMA is available with these processors
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \
dmaHal.Instance = DMA1_Channel3
#if (TFT_SPI_PORT == 1)
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \
dmaHal.Instance = DMA1_Channel3
#elif (TFT_SPI_PORT == 2)
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \
dmaHal.Instance = DMA1_Channel5
#endif
#else
// For STM32 processor with no implemented DMA support (yet)
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1
#if (TFT_SPI_PORT == 1)
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1
#elif (TFT_SPI_PORT == 2)
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI2
#endif
#endif
#endif
@ -217,12 +243,21 @@
// Define the RD (TFT Read) pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#ifdef TFT_RD
// Convert Arduino pin reference Dx or STM pin reference PXn to port and mask
#define RD_PORT digitalPinToPort(TFT_RD)
#define RD_PIN_MASK digitalPinToBitMask(TFT_RD)
// Use bit set reset register
#define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16
#define RD_H RD_PORT->BSRR = RD_PIN_MASK
#if (TFT_RD >= 0)
// Convert Arduino pin reference Dx or STM pin reference PXn to port and mask
#define RD_PORT digitalPinToPort(TFT_RD)
#define RD_PIN_MASK digitalPinToBitMask(TFT_RD)
// Use bit set reset register
#define RD_L RD_PORT->BSRR = RD_PIN_MASK<<16
#define RD_H RD_PORT->BSRR = RD_PIN_MASK
#else
#define RD_L
#define RD_H
#endif
#else
#define TFT_RD -1
#define RD_L
#define RD_H
#endif
////////////////////////////////////////////////////////////////////////////////////////
@ -376,6 +411,31 @@
GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB // Need to slow down strobe
#if defined (SSD1963_DRIVER)
// Write 18 bit color to TFT (untested)
#define tft_Write_16(C) uint8_t r = (((C) & 0xF800)>> 8); uint8_t g = (((C) & 0x07E0)>> 3); uint8_t b = (((C) & 0x001F)<< 3); \
GPIOA->BSRR = D0_BSR_MASK(r) | D2_BSR_MASK(r) | D7_BSR_MASK(r); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(r); \
GPIOB->BSRR = D3_BSR_MASK(r) | D4_BSR_MASK(r) | D5_BSR_MASK(r) | D6_BSR_MASK(r); \
WR_STB; \
GPIOA->BSRR = D0_BSR_MASK(g) | D2_BSR_MASK(g) | D7_BSR_MASK(g); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(g); \
GPIOB->BSRR = D3_BSR_MASK(g) | D4_BSR_MASK(g) | D5_BSR_MASK(g) | D6_BSR_MASK(g); \
WR_STB; \
GPIOA->BSRR = D0_BSR_MASK(b) | D2_BSR_MASK(b) | D7_BSR_MASK(b); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(b); \
GPIOB->BSRR = D3_BSR_MASK(b) | D4_BSR_MASK(b) | D5_BSR_MASK(b) | D6_BSR_MASK(b); \
WR_STB // Need to slow down strobe
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
@ -399,6 +459,7 @@
GPIOC->BSRR = D9_BSR_MASK(C); \
GPIOB->BSRR = D11_BSR_MASK(C) | D12_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \
WR_STB
#endif
#define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C))
@ -492,6 +553,31 @@
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB
#if defined (SSD1963_DRIVER)
// Write 18 bit color to TFT (untested)
#define tft_Write_16(C) uint8_t r = (((C) & 0xF800)>> 8); uint8_t g = (((C) & 0x07E0)>> 3); uint8_t b = (((C) & 0x001F)<< 3); \
GPIOF->BSRR = D0_BSR_MASK(r) | D2_BSR_MASK(r) | D4_BSR_MASK(r) | D7_BSR_MASK(r); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(r); \
GPIOE->BSRR = D3_BSR_MASK(r) | D5_BSR_MASK(r) | D6_BSR_MASK(r); \
WR_STB; \
GPIOF->BSRR = D0_BSR_MASK(g) | D2_BSR_MASK(g) | D4_BSR_MASK(g) | D7_BSR_MASK(g); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(g); \
GPIOE->BSRR = D3_BSR_MASK(g) | D5_BSR_MASK(g) | D6_BSR_MASK(g); \
WR_STB; \
GPIOF->BSRR = D0_BSR_MASK(b) | D2_BSR_MASK(b) | D4_BSR_MASK(b) | D7_BSR_MASK(b); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(b); \
GPIOE->BSRR = D3_BSR_MASK(b) | D5_BSR_MASK(b) | D6_BSR_MASK(b); \
WR_STB // Need to slow down strobe
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
@ -516,6 +602,8 @@
GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \
WR_STB
#endif
#define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C))
#define tft_Write_32C(C,D) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(D))
@ -637,7 +725,20 @@
// Write 8 bits to TFT
#define tft_Write_8(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB
#if defined (SSD1963_DRIVER)
// Write 18 bit color to TFT (untested)
#define tft_Write_16(C) uint8_t r = (((C) & 0xF800)>> 8); uint8_t g = (((C) & 0x07E0)>> 3); uint8_t b = (((C) & 0x001F)<< 3); \
GPIOA->BSRR = (0x00FF0000 | (uint8_t)(r)); WR_L; WR_STB; \
GPIOA->BSRR = (0x00FF0000 | (uint8_t)(g)); WR_L; WR_STB; \
GPIOA->BSRR = (0x00FF0000 | (uint8_t)(b)); WR_L; WR_STB
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \
GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB
@ -645,6 +746,7 @@
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \
GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB
#endif
#define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C))
@ -666,7 +768,20 @@
// Write 8 bits to TFT
#define tft_Write_8(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB
#if defined (SSD1963_DRIVER)
// Write 18 bit color to TFT (untested)
#define tft_Write_16(C) uint8_t r = (((C) & 0xF800)>> 8); uint8_t g = (((C) & 0x07E0)>> 3); uint8_t b = (((C) & 0x001F)<< 3); \
GPIOB->BSRR = (0x00FF0000 | (uint8_t)(r)); WR_L; WR_STB; \
GPIOB->BSRR = (0x00FF0000 | (uint8_t)(g)); WR_L; WR_STB; \
GPIOB->BSRR = (0x00FF0000 | (uint8_t)(b)); WR_L; WR_STB
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \
GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB
@ -674,6 +789,7 @@
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \
GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB
#endif
#define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C))
@ -766,6 +882,46 @@
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB
#if defined (SSD1963_DRIVER)
// Write 18 bit color to TFT (untested)
#define tft_Write_16(C) uint8_t r = (((C) & 0xF800)>> 8); uint8_t g = (((C) & 0x07E0)>> 3); uint8_t b = (((C) & 0x001F)<< 3); \
D0_PIN_PORT->BSRR = D8_BSR_MASK(r); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(r); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(r); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(r); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(r); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(r); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(r); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(r); \
WR_STB;\
D0_PIN_PORT->BSRR = D8_BSR_MASK(g); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(g); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(g); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(g); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(g); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(g); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(g); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(g); \
WR_STB;\
D0_PIN_PORT->BSRR = D0_BSR_MASK(b); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(b); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(b); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(b); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(b); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(b); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(b); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(b); \
WR_STB
// 18 bit color write with swapped bytes
#define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \
@ -809,6 +965,7 @@
D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \
WR_STB
#endif
#define tft_Write_32(C) tft_Write_16((uint16_t)((C)>>16)); tft_Write_16((uint16_t)(C))

View File

@ -1,41 +1,24 @@
# Tips
If you load a new copy of TFT_eSPI then it will over-write your setups if they are kept within the TFT_eSPI folder. One way around this is to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there. After an upgrade simply edit the User_Setup_Select.h file to point to your custom setup file e.g.:
```
#include <../TFT_eSPI_Setups/my_custom_setup.h>
```
You must make sure only one setup file is called. In the the custom setup file I add the file path as a commented out first line that can be cut and pasted back into the upgraded User_Setup_Select.h file. The ../ at the start of the path means go up one directory level. Clearly you could use different file paths or directory names as long as it does not clash with another library or folder name.
You can take this one step further and have your own setup select file and then you only need to replace the Setup.h line reference in User_Setup_Select.h to, for example:
```
#include <../TFT_eSPI_Setups/my_setup_select.h>
```
To select a new setup you then edit your own my_setup_select.h file (which will not get over-written during an upgrade).
# Sprite class change
The Sprite class has been updated to remove an inconsistency for the setSwapBytes() function. Although all the examples are unchanged, user sketches may be affected. If the colors of the sprite change when loading this new version 2.2.16 then it may be necessary to change the swap bytes setting, e.g. for a sprite instance "spr" use either: spr.setSwapBytes(true) or spr.setSwapBytes(false) to correct the colour.
# News
1. The library now supports SPI DMA transfers for both ESP32 and STM32 processors. The DMA Test examples now work on the ESP32 for SPI displays (excluding RPi type and ILI9488).
1. A companion library [U8g2_for_TFT_eSPI](https://github.com/Bodmer/U8g2_for_TFT_eSPI) has been created to allow U8g2 library fonts to be used with TFT_eSPI.
2. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h".
2. The library now supports SPI DMA transfers for both ESP32 and STM32 processors. The DMA Test examples now work on the ESP32 for SPI displays (excluding RPi type and ILI9488).
3. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program.
3. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h".
4. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program.
![Animated_dial](https://i.imgur.com/S736Rg6.png)
4. Anti-aliased (smooth) fonts can now be stored as arrays in FLASH (program) memory. This means that processors such as STM32 that do not have SPIFFS support can use the fonts. The processor must have sufficient FLASH memory to store the fonts used.
5. Anti-aliased (smooth) fonts can now be stored as arrays in FLASH (program) memory. This means that processors such as STM32 that do not have SPIFFS support can use the fonts. The processor must have sufficient FLASH memory to store the fonts used.
5. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added.
6. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added.
6. The library has been upgraded to support STM32 processors when used with SPI or 8 bit parallel displays. DMA capability for SPI displays has been added for STM32F103 (e.g. "Blue Pill") and STM32F2xx/4xx/7xx (e.g. 32/64/144 Nucleo boards). New DMA demo examples have been added (for STM32 only).
7. The ST7796 display controller has been added. The ST7796 RPi MHS-4.0 inch Display-B type display is supported (this is fast for a SPI display as an ESP32 can clock it at 80MHz (ESP8266 at 40MHz)), see setups 27 and 28.
8. A callback function has been added, this allows antialiased fonts to be rendered over colour gradients or images. Two new examples have been added to illustrate this new capability:
"Smooth_font_reading_TFT"
"Smooth_font_gradient"
![AA_gradien](https://i.imgur.com/YMBcPHp.png)
7. The library has been upgraded to support STM32 processors when used with SPI or 8 bit parallel displays. DMA capability for SPI displays has been added for STM32F103 (e.g. "Blue Pill") and STM32F2xx/4xx/7xx (e.g. 32/64/144 Nucleo boards). New DMA demo examples have been added (for STM32 only).
8. The ST7796 display controller has been added. The ST7796 RPi MHS-4.0 inch Display-B type display is supported (this is fast for a SPI display as an ESP32 can clock it at 80MHz (ESP8266 at 40MHz)), see setups 27 and 28.
# TFT_eSPI
@ -126,6 +109,19 @@ IO32 wired to IO36
If the display board is fitted with a resistance based touch screen then this can be used by performing the modifications described here and the fork of the Adafruit library:
https://github.com/s60sc/Adafruit_TouchScreen
# Tips
If you load a new copy of TFT_eSPI then it will over-write your setups if they are kept within the TFT_eSPI folder. One way around this is to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there. After an upgrade simply edit the User_Setup_Select.h file to point to your custom setup file e.g.:
```
#include <../TFT_eSPI_Setups/my_custom_setup.h>
```
You must make sure only one setup file is called. In the the custom setup file I add the file path as a commented out first line that can be cut and pasted back into the upgraded User_Setup_Select.h file. The ../ at the start of the path means go up one directory level. Clearly you could use different file paths or directory names as long as it does not clash with another library or folder name.
You can take this one step further and have your own setup select file and then you only need to replace the Setup.h line reference in User_Setup_Select.h to, for example:
```
#include <../TFT_eSPI_Setups/my_setup_select.h>
```
To select a new setup you then edit your own my_setup_select.h file (which will not get over-written during an upgrade).
# ePaper displays
The library was intended to support only TFT displays but using a Sprite as a 1 bit per pixel screen buffer permits support for the Waveshare 2 and 3 colour SPI ePaper displays. This addition to the library is experimental and only one example is provided. Further examples will be added.

View File

@ -0,0 +1,56 @@
// Change the width and height if required (defined in portrait mode)
// or use the constructor to over-ride defaults
#if defined (SSD1963_480_DRIVER)
#define TFT_WIDTH 272
#define TFT_HEIGHT 480
#elif defined (SSD1963_800_DRIVER)
#define TFT_WIDTH 480
#define TFT_HEIGHT 800
#elif defined (SSD1963_800ALT_DRIVER)
#define TFT_WIDTH 480
#define TFT_HEIGHT 800
#elif defined (SSD1963_800BD_DRIVER)
#define TFT_WIDTH 480
#define TFT_HEIGHT 800
#endif
//Set driver type common to all initialisation options
#ifndef SSD1963_DRIVER
#define SSD1963_DRIVER
#endif
// Delay between some initialisation commands
#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked
// Generic commands used by TFT_eSPI.cpp
#define TFT_NOP 0x00
#define TFT_SWRST 0x01
#define TFT_CASET 0x2A
#define TFT_PASET 0x2B
#define TFT_RAMWR 0x2C
#define TFT_RAMRD 0x2E
#define TFT_IDXRD 0xDD // ILI9341 only, indexed control register read
#define TFT_MADCTL 0x36
#define TFT_MAD_MY 0x80
#define TFT_MAD_MX 0x40
#define TFT_MAD_MV 0x20
#define TFT_MAD_ML 0x10
#define TFT_MAD_BGR 0x08
#define TFT_MAD_MH 0x04
#define TFT_MAD_RGB 0x00
#ifdef TFT_RGB_ORDER
#if (TFT_RGB_ORDER == 1)
#define TFT_MAD_COLOR_ORDER TFT_MAD_RGB
#else
#define TFT_MAD_COLOR_ORDER TFT_MAD_BGR
#endif
#else
#define TFT_MAD_COLOR_ORDER TFT_MAD_BGR
#endif
#define TFT_INVOFF 0x20
#define TFT_INVON 0x21

398
TFT_Drivers/SSD1963_Init.h Normal file
View File

@ -0,0 +1,398 @@
#if defined (SSD1963_480_DRIVER)
writecommand(0xE2); //PLL multiplier, set PLL clock to 120M
writedata(0x23); //N=0x36 for 6.5M, 0x23 for 10M crystal
writedata(0x02);
writedata(0x54);
writecommand(0xE0); // PLL enable
writedata(0x01);
delay(10);
writecommand(0xE0);
writedata(0x03);
delay(10);
writecommand(0x01); // software reset
delay(100);
writecommand(0xE6); //PLL setting for PCLK, depends on resolution
writedata(0x01);
writedata(0x1F);
writedata(0xFF);
writecommand(0xB0); //LCD SPECIFICATION
writedata(0x20);
writedata(0x00);
writedata(0x01); //Set HDP 479
writedata(0xDF);
writedata(0x01); //Set VDP 271
writedata(0x0F);
writedata(0x00);
writecommand(0xB4); //HSYNC
writedata(0x02); //Set HT 531
writedata(0x13);
writedata(0x00); //Set HPS 8
writedata(0x08);
writedata(0x2B); //Set HPW 43
writedata(0x00); //Set LPS 2
writedata(0x02);
writedata(0x00);
writecommand(0xB6); //VSYNC
writedata(0x01); //Set VT 288
writedata(0x20);
writedata(0x00); //Set VPS 4
writedata(0x04);
writedata(0x0c); //Set VPW 12
writedata(0x00); //Set FPS 2
writedata(0x02);
writecommand(0xBA);
writedata(0x0F); //GPIO[3:0] out 1
writecommand(0xB8);
writedata(0x07); //GPIO3=input, GPIO[2:0]=output
writedata(0x01); //GPIO0 normal
writecommand(0x36); //rotation
writedata(0x21 | TFT_MAD_COLOR_ORDER);
writecommand(0xF0); //pixel data interface
writedata(0x00); //8 bit bus
delay(1);
writecommand(0xB8);
writedata(0x0f); //GPIO is controlled by host GPIO[3:0]=output GPIO[0]=1 LCD ON GPIO[0]=1 LCD OFF
writedata(0x01); //GPIO0 normal
writecommand(0xBA);
writedata(0x01); //GPIO[0] out 1 --- LCD display on/off control PIN
writecommand(0x2A);
writedata(0);
writedata(0);
writedata((271 & 0xFF00)>>8);
writedata(271 & 0xFF);
writecommand(0x2B);
writedata(0);
writedata(0);
writedata((479 & 0xFF00)>>8);
writedata(479 & 0xFF);
writecommand(0x2C);
writecommand(0x29); //display on
writecommand(0xBE); //set PWM for B/L
writedata(0x06);
writedata(0xf0);
writedata(0x01);
writedata(0xf0);
writedata(0x00);
writedata(0x00);
writecommand(0xd0);
writedata(0x0d);
writecommand(0x2C);
#elif defined (SSD1963_800_DRIVER)
writecommand(0xE2); //PLL multiplier, set PLL clock to 120M
writedata(0x1E); //N=0x36 for 6.5M, 0x23 for 10M crystal
writedata(0x02);
writedata(0x54);
writecommand(0xE0); // PLL enable
writedata(0x01);
delay(10);
writecommand(0xE0);
writedata(0x03);
delay(10);
writecommand(0x01); // software reset
delay(100);
writecommand(0xE6); //PLL setting for PCLK, depends on resolution
writedata(0x03);
writedata(0xFF);
writedata(0xFF);
writecommand(0xB0); //LCD SPECIFICATION
writedata(0x20);
writedata(0x00);
writedata(0x03); //Set HDP 799
writedata(0x1F);
writedata(0x01); //Set VDP 479
writedata(0xDF);
writedata(0x00);
writecommand(0xB4); //HSYNC
writedata(0x03); //Set HT 928
writedata(0xA0);
writedata(0x00); //Set HPS 46
writedata(0x2E);
writedata(0x30); //Set HPW 48
writedata(0x00); //Set LPS 15
writedata(0x0F);
writedata(0x00);
writecommand(0xB6); //VSYNC
writedata(0x02); //Set VT 525
writedata(0x0D);
writedata(0x00); //Set VPS 16
writedata(0x10);
writedata(0x10); //Set VPW 16
writedata(0x00); //Set FPS 8
writedata(0x08);
writecommand(0xBA);
writedata(0x0F); //GPIO[3:0] out 1
writecommand(0xB8);
writedata(0x07); //GPIO3=input, GPIO[2:0]=output
writedata(0x01); //GPIO0 normal
writecommand(0x36); //rotation
writedata(0x21 | TFT_MAD_COLOR_ORDER);
writecommand(0xF0); //pixel data interface
writedata(0x00); //8 bit bus
delay(1);
writecommand(0xB8);
writedata(0x0f); //GPIO is controlled by host GPIO[3:0]=output GPIO[0]=1 LCD ON GPIO[0]=1 LCD OFF
writedata(0x01); //GPIO0 normal
writecommand(0xBA);
writedata(0x01); //GPIO[0] out 1 --- LCD display on/off control PIN
writecommand(0x2A);
writedata(0);
writedata(0);
writedata((479 & 0xFF00)>>8);
writedata(479 & 0xFF);
writecommand(0x2B);
writedata(0);
writedata(0);
writedata((799 & 0xFF00)>>8);
writedata(799 & 0xFF);
writecommand(0x2C);
writecommand(0x29); //display on
writecommand(0xBE); //set PWM for B/L
writedata(0x06);
writedata(0xf0);
writedata(0x01);
writedata(0xf0);
writedata(0x00);
writedata(0x00);
writecommand(0xd0);
writedata(0x0d);
writecommand(0x2C);
#elif defined (SSD1963_800ALT_DRIVER)
writecommand(0xE2); //PLL multiplier, set PLL clock to 120M
writedata(0x23); //N=0x36 for 6.5M, 0x23 for 10M crystal
writedata(0x02);
writedata(0x04);
writecommand(0xE0); // PLL enable
writedata(0x01);
delay(10);
writecommand(0xE0);
writedata(0x03);
delay(10);
writecommand(0x01); // software reset
delay(100);
writecommand(0xE6); //PLL setting for PCLK, depends on resolution
writedata(0x04);
writedata(0x93);
writedata(0xE0);
writecommand(0xB0); //LCD SPECIFICATION
writedata(0x00); // 0x24
writedata(0x00);
writedata(0x03); //Set HDP 799
writedata(0x1F);
writedata(0x01); //Set VDP 479
writedata(0xDF);
writedata(0x00);
writecommand(0xB4); //HSYNC
writedata(0x03); //Set HT 928
writedata(0xA0);
writedata(0x00); //Set HPS 46
writedata(0x2E);
writedata(0x30); //Set HPW 48
writedata(0x00); //Set LPS 15
writedata(0x0F);
writedata(0x00);
writecommand(0xB6); //VSYNC
writedata(0x02); //Set VT 525
writedata(0x0D);
writedata(0x00); //Set VPS 16
writedata(0x10);
writedata(0x10); //Set VPW 16
writedata(0x00); //Set FPS 8
writedata(0x08);
writecommand(0xBA);
writedata(0x05); //GPIO[3:0] out 1
writecommand(0xB8);
writedata(0x07); //GPIO3=input, GPIO[2:0]=output
writedata(0x01); //GPIO0 normal
writecommand(0x36); //rotation
writedata(0x21 | TFT_MAD_COLOR_ORDER); // -- Set rotation
writecommand(0xF0); //pixel data interface
writedata(0x00); //8 bit bus
delay(10);
writecommand(0x2A);
writedata(0);
writedata(0);
writedata((479 & 0xFF00)>>8);
writedata(479 & 0xFF);
writecommand(0x2B);
writedata(0);
writedata(0);
writedata((799 & 0xFF00)>>8);
writedata(799 & 0xFF);
writecommand(0x2C);
writecommand(0x29); //display on
writecommand(0xBE); //set PWM for B/L
writedata(0x06);
writedata(0xF0);
writedata(0x01);
writedata(0xF0);
writedata(0x00);
writedata(0x00);
writecommand(0xD0);
writedata(0x0D);
writecommand(0x2C);
#elif defined (SSD1963_800BD_DRIVER) // Copied from Buy Display code
writecommand(0xE2); //PLL multiplier, set PLL clock to 120M
writedata(0x23); //N=0x36 for 6.5M, 0x23 for 10M crystal
writedata(0x02);
writedata(0x54);
writecommand(0xE0); // PLL enable
writedata(0x01);
delay(10);
writecommand(0xE0);
writedata(0x03);
delay(10);
writecommand(0x01); // software reset
delay(100);
writecommand(0xE6); //PLL setting for PCLK, depends on resolution
writedata(0x03);
writedata(0x33);
writedata(0x33);
writecommand(0xB0); //LCD SPECIFICATION
writedata(0x20);
writedata(0x00);
writedata(799 >> 8); //Set HDP 799
writedata(799 & 0xFF);
writedata(479 >> 8); //Set VDP 479
writedata(479 & 0xFF);
writedata(0x00);
writecommand(0xB4); //HSYNC
writedata(0x04); //Set HT
writedata(0x1F);
writedata(0x00); //Set HPS
writedata(0xD2);
writedata(0x00); //Set HPW
writedata(0x00); //Set LPS
writedata(0x00);
writedata(0x00);
writecommand(0xB6); //VSYNC
writedata(0x02); //Set VT
writedata(0x0C);
writedata(0x00); //Set VPS
writedata(0x22);
writedata(0x00); //Set VPW
writedata(0x00); //Set FPS
writedata(0x00);
writecommand(0xB8);
writedata(0x0F); //GPIO3=input, GPIO[2:0]=output
writedata(0x01); //GPIO0 normal
writecommand(0xBA);
writedata(0x01); //GPIO[0] out 1 --- LCD display on/off control PIN
writecommand(0x36); //rotation
writedata(0x21 | TFT_MAD_COLOR_ORDER); //set to rotate
//writecommand(0x003A); //Set the current pixel format for RGB image data
//writedata(0x0050); //16-bit/pixel
writecommand(0xF0); //pixel data interface
writedata(0x00); //000 = 8 bit bus, 011 = 16 bit, 110 = 9 bit
writecommand(0xBC);
writedata(0x40); //contrast value
writedata(0x80); //brightness value
writedata(0x40); //saturation value
writedata(0x01); //Post Processor Enable
delay(10);
writecommand(0x29); //display on
writecommand(0xBE); //set PWM for B/L
writedata(0x06);
writedata(0x80);
writedata(0x01);
writedata(0xF0);
writedata(0x00);
writedata(0x00);
writecommand(0xD0);
writedata(0x0D);
#endif

View File

@ -0,0 +1,29 @@
// This is the command sequence that rotates the SSD1963 driver coordinate frame
rotation = m % 4; // Limit the range of values to 0-3
writecommand(TFT_MADCTL);
switch (rotation) {
case 0:
writedata(0x21 | TFT_MAD_COLOR_ORDER);
_width = _init_width;
_height = _init_height;
break;
case 1:
writedata(0x00 | TFT_MAD_COLOR_ORDER);
_width = _init_height;
_height = _init_width;
break;
case 2:
writedata(0x22 | TFT_MAD_COLOR_ORDER);
_width = _init_width;
_height = _init_height;
break;
case 3:
writedata(0x03 | TFT_MAD_COLOR_ORDER);
_width = _init_height;
_height = _init_width;
break;
}

View File

@ -5,8 +5,16 @@
switch (rotation) {
case 0: // Portrait
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 0;
if (_init_width == 135)
{
colstart = 52;
rowstart = 40;
}
else
{
colstart = 0;
rowstart = 0;
}
#endif
writedata(TFT_MAD_COLOR_ORDER);
@ -16,8 +24,16 @@
case 1: // Landscape (Portrait + 90)
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 0;
if (_init_width == 135)
{
colstart = 40;
rowstart = 53;
}
else
{
colstart = 0;
rowstart = 0;
}
#endif
writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
@ -27,8 +43,16 @@
case 2: // Inverter portrait
#ifdef CGRAM_OFFSET
colstart = 0;
rowstart = 80;
if (_init_width == 135)
{
colstart = 53;
rowstart = 40;
}
else
{
colstart = 0;
rowstart = 80;
}
#endif
writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
@ -37,8 +61,16 @@
break;
case 3: // Inverted landscape
#ifdef CGRAM_OFFSET
colstart = 80;
rowstart = 0;
if (_init_width == 135)
{
colstart = 40;
rowstart = 52;
}
else
{
colstart = 80;
rowstart = 0;
}
#endif
writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);

View File

@ -105,6 +105,11 @@ inline void TFT_eSPI::end_tft_read(void){
if(!inTransaction) {CS_H;}
#endif
SET_BUS_WRITE_MODE;
// The ST7796 appears to need a 4ms delay after a CGRAM read, otherwise subsequent writes will fail!
#ifdef ST7796_DRIVER
delay(4);
#endif
}
/***************************************************************************************
@ -335,8 +340,6 @@ void TFT_eSPI::init(uint8_t tc)
} // end of: if just _booted
// Toggle RST low to reset
begin_tft_write();
#ifdef TFT_RST
if (TFT_RST >= 0) {
digitalWrite(TFT_RST, HIGH);
@ -350,8 +353,6 @@ void TFT_eSPI::init(uint8_t tc)
writecommand(TFT_SWRST); // Software reset
#endif
end_tft_write();
delay(150); // Wait for reset to complete
begin_tft_write();
@ -399,6 +400,9 @@ void TFT_eSPI::init(uint8_t tc)
#elif defined (ST7789_2_DRIVER)
#include "TFT_Drivers/ST7789_2_Init.h"
#elif defined (SSD1963_DRIVER)
#include "TFT_Drivers/SSD1963_Init.h"
#endif
#ifdef TFT_INVERSION_ON
@ -475,6 +479,9 @@ void TFT_eSPI::setRotation(uint8_t m)
#elif defined (ST7789_2_DRIVER)
#include "TFT_Drivers/ST7789_2_Rotation.h"
#elif defined (SSD1963_DRIVER)
#include "TFT_Drivers/SSD1963_Rotation.h"
#endif
delayMicroseconds(10);
@ -703,6 +710,8 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
bool wasInTransaction = inTransaction;
if (inTransaction) { inTransaction= false; end_tft_write();}
uint16_t color = 0;
begin_tft_read();
readAddrWindow(x0, y0, 1, 1); // Sets CS low
@ -716,11 +725,18 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
//#if !defined (ILI9488_DRIVER)
// Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
// as the TFT stores colours as 18 bits
uint8_t r = tft_Read_8();
uint8_t g = tft_Read_8();
uint8_t b = tft_Read_8();
#if defined (ST7796_DRIVER)
// Read the 2 bytes
color = ((tft_Read_8()) << 8) | (tft_Read_8());
#else
// Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
// as the TFT stores colours as 18 bits
uint8_t r = tft_Read_8();
uint8_t g = tft_Read_8();
uint8_t b = tft_Read_8();
color = color565(r, g, b);
#endif
/*
#else
@ -729,6 +745,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
uint8_t r = (tft_Read_8()&0x7E)<<1;
uint8_t g = (tft_Read_8()&0x7E)<<1;
uint8_t b = (tft_Read_8()&0x7E)<<1;
color = color565(r, g, b);
#endif
*/
@ -743,7 +760,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
// Reinstate the transaction if one was in progress
if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
return color565(r, g, b);
return color;
#endif
}
@ -810,6 +827,8 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
#else // SPI interface
uint16_t color = 0;
begin_tft_read();
readAddrWindow(x, y, w, h);
@ -825,29 +844,35 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
uint32_t len = w * h;
while (len--) {
#if !defined (ILI9488_DRIVER)
// Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
// as the TFT stores colours as 18 bits
uint8_t r = tft_Read_8();
uint8_t g = tft_Read_8();
uint8_t b = tft_Read_8();
#if !defined (ILI9488_DRIVER)
#if defined (ST7796_DRIVER)
// Read the 2 bytes
color = ((tft_Read_8()) << 8) | (tft_Read_8());
#else
// Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte
// as the TFT stores colours as 18 bits
uint8_t r = tft_Read_8();
uint8_t g = tft_Read_8();
uint8_t b = tft_Read_8();
color = color565(r, g, b);
#endif
#else
// The 6 colour bits are in MS 6 bits of each byte but we do not include the extra clock pulse
// so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left
uint8_t r = (tft_Read_8()&0x7E)<<1;
uint8_t g = (tft_Read_8()&0x7E)<<1;
uint8_t b = (tft_Read_8()&0x7E)<<1;
#endif
color = color565(r, g, b);
#endif
// Swapped colour byte order for compatibility with pushRect()
*data++ = (r & 0xF8) | (g & 0xE0) >> 5 | (b & 0xF8) << 5 | (g & 0x1C) << 11;
*data++ = color << 8 | color >> 8;
}
CS_H;
//CS_H;
#ifdef TFT_SDA_READ
end_SDA_Read();
@ -860,14 +885,14 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
/***************************************************************************************
** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
** Function name: push rectangle
** Description: push 565 pixel colours into a defined area
***************************************************************************************/
void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
{
// Function deprecated, remains for backwards compatibility
// New pushImage() is better as it will crop partly off-screen image blocks
bool swap = _swapBytes; _swapBytes = false;
pushImage(x, y, w, h, data);
_swapBytes = swap;
}
@ -946,6 +971,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
uint16_t lineBuf[dw]; // Use buffer to minimise setWindow call count
// The little endian transp color must be byte swapped if the image is big endian
if (!_swapBytes) transp = transp >> 8 | transp << 8;
while (dh--)
@ -1062,6 +1088,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
uint16_t lineBuf[dw];
// The little endian transp color must be byte swapped if the image is big endian
if (!_swapBytes) transp = transp >> 8 | transp << 8;
while (dh--) {
@ -1247,7 +1274,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
}
pushPixels(lineBuf, dw);
dy++;
}
_swapBytes = swap; // Restore old value
@ -2614,8 +2640,12 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{
//begin_tft_write(); // Must be called before setWindow
addr_col = 0xFFFF;
#if defined (SSD1963_DRIVER)
if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
#endif
addr_row = 0xFFFF;
addr_col = 0xFFFF;
#ifdef CGRAM_OFFSET
x0+=colstart;
@ -2624,16 +2654,11 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
y1+=rowstart;
#endif
// Column addr set
DC_C; tft_Write_8(TFT_CASET);
DC_D; tft_Write_32C(x0, x1);
// Row addr set
DC_C; tft_Write_8(TFT_PASET);
DC_D; tft_Write_32C(y0, y1);
DC_C; tft_Write_8(TFT_RAMWR);
DC_D;
//end_tft_write(); // Must be called after setWindow
@ -2661,6 +2686,10 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
ye += rowstart;
#endif
#if defined (SSD1963_DRIVER)
if ((rotation & 0x1) == 0) { swap_coord(xs, ys); swap_coord(xe, ye); }
#endif
// Column addr set
DC_C; tft_Write_8(TFT_CASET);
DC_D; tft_Write_32C(xs, xe);
@ -2692,21 +2721,33 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
y+=rowstart;
#endif
#if defined (SSD1963_DRIVER)
if ((rotation & 0x1) == 0) { swap_coord(x, y); }
#endif
begin_tft_write();
#ifdef MULTI_TFT_SUPPORT
// No optimisation
DC_C; tft_Write_8(TFT_CASET);
DC_D; tft_Write_32D(x);
DC_C; tft_Write_8(TFT_PASET);
DC_D; tft_Write_32D(y);
#else
// No need to send x if it has not changed (speeds things up)
if (addr_col != x) {
if (addr_col != (x<<16 | x)) {
DC_C; tft_Write_8(TFT_CASET);
DC_D; tft_Write_32D(x);
addr_col = x;
addr_col = (x<<16 | x);
}
// No need to send y if it has not changed (speeds things up)
if (addr_row != y) {
if (addr_row != (y<<16 | y)) {
DC_C; tft_Write_8(TFT_PASET);
DC_D; tft_Write_32D(y);
addr_row = y;
addr_row = (y<<16 | y);
}
#endif
DC_C; tft_Write_8(TFT_RAMWR);
DC_D; tft_Write_16(color);
@ -3529,8 +3570,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
inTransaction = true;
w *= height; // Now w is total number of pixels in the character
if ((textsize != 1) || (textcolor == textbgcolor)) {
if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor);
if (textcolor == textbgcolor) {
int32_t px = 0, py = pY; // To hold character block start and end column and row values
int32_t pc = 0; // Pixel count
uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel
@ -3576,21 +3616,60 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
}
}
}
else { // Text colour != background && textsize = 1
// so use faster drawing of characters and background using block write
setWindow(x, y, x + width - 1, y + height - 1);
else {
// Text colour != background and textsize = 1 and character is within screen area
// so use faster drawing of characters and background using block write
if ((textsize == 1) && (x >= 0) && (x + width <= _width) && (y >= 0) && (y + height <= _height))
{
setWindow(x, y, x + width - 1, y + height - 1);
// Maximum font size is equivalent to 180x180 pixels in area
while (w > 0) {
line = pgm_read_byte((uint8_t *)flash_address++); // 8 bytes smaller when incrementing here
if (line & 0x80) {
line &= 0x7F;
line++; w -= line;
pushBlock(textcolor,line);
// Maximum font size is equivalent to 180x180 pixels in area
while (w > 0) {
line = pgm_read_byte((uint8_t *)flash_address++); // 8 bytes smaller when incrementing here
if (line & 0x80) {
line &= 0x7F;
line++; w -= line;
pushBlock(textcolor,line);
}
else {
line++; w -= line;
pushBlock(textbgcolor,line);
}
}
else {
line++; w -= line;
pushBlock(textbgcolor,line);
}
else
{
int32_t px = 0, py = 0; // To hold character pixel coords
int32_t tx = 0, ty = 0; // To hold character TFT pixel coords
int32_t pc = 0; // Pixel count
int32_t pl = 0; // Pixel line length
uint16_t pcol = 0; // Pixel color
while (pc < w) {
line = pgm_read_byte((uint8_t *)flash_address);
flash_address++;
if (line & 0x80) { pcol = textcolor; line &= 0x7F; }
else pcol = textbgcolor;
line++;
px = pc % width;
tx = x + textsize * px;
py = pc / width;
ty = y + textsize * py;
pl = 0;
pc += line;
while (line--) {
pl++;
if ((px+pl) >= width) {
fillRect(tx, ty, pl * textsize, textsize, pcol);
pl = 0;
px = 0;
tx = x;
py ++;
ty += textsize;
}
}
if (pl) fillRect(tx, ty, pl * textsize, textsize, pcol);
}
}
}
@ -3726,11 +3805,11 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
padding += 2;
break;
}
// Check coordinates are OK, adjust if not
/* // Check coordinates are OK, adjust if not
if (poX < 0) poX = 0;
if (poX+cwidth > width()) poX = width() - cwidth;
if (poY < 0) poY = 0;
if (poY+cheight-baseline> height()) poY = height() - cheight;
if (poY+cheight-baseline> height()) poY = height() - cheight; //*/
}
@ -3808,9 +3887,8 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
break;
case 2:
fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
padXc = (padX-cwidth)>>1;
if (padXc>poX) padXc = poX;
fillRect(poX - padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
padXc = poX - ((padX-cwidth)>>1);
fillRect(padXc,poY,(padX-cwidth)>>1,cheight, textbgcolor);
break;
case 3:
if (padXc>padX) padXc = padX;
@ -3839,7 +3917,6 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
case 2:
drawRect(padXc,poY,(padX-sumX)>>1, cheight, TFT_WHITE);
padXc = (padX-sumX)>>1;
if (padXc>poX) padXc = poX;
drawRect(poX - padXc,poY,(padX-sumX)>>1,cheight, TFT_WHITE);
break;
case 3:
@ -4204,6 +4281,14 @@ void TFT_eSPI::getSetup(setup_t &tft_settings)
tft_settings.pin_tft_d7 = -1;
#endif
#if defined (TFT_BL)
tft_settings.pin_tft_led = TFT_BL;
#endif
#if defined (TFT_BACKLIGHT_ON)
tft_settings.pin_tft_led_on = TFT_BACKLIGHT_ON;
#endif
#if defined (TOUCH_CS)
tft_settings.pin_tch_cs = TOUCH_CS;
tft_settings.tch_spi_freq = SPI_TOUCH_FREQUENCY/100000;

View File

@ -16,7 +16,7 @@
#ifndef _TFT_eSPIH_
#define _TFT_eSPIH_
#define TFT_ESPI_VERSION "2.2.4"
#define TFT_ESPI_VERSION "2.2.23"
/***************************************************************************************
** Section 1: Load required header files
@ -335,6 +335,9 @@ int8_t pin_tft_d5;
int8_t pin_tft_d6;
int8_t pin_tft_d7;
int8_t pin_tft_led;
int8_t pin_tft_led_on;
int8_t pin_tch_cs; // Touch chip select pin
int16_t tft_spi_freq;// TFT write SPI frequency
@ -450,7 +453,7 @@ class TFT_eSPI : public Print {
// The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location
// Read a block of pixels to a data buffer, buffer is 16 bit and the size must be at least w * h
void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data);
// Write a block of pixels to the screen - this is a deprecated alternative to pushImage()
// Write a block of pixels to the screen which have been read by readRect()
void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data);
// These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites)
@ -575,7 +578,7 @@ class TFT_eSPI : public Print {
uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0);
// DMA support functions - these are currently just for SPI writes whe using the STM32 processors
// DMA support functions - these are currently just for SPI writes when using the ESP32 or STM32 processors
// Bear in mind DMA will only be of benefit in particular circumstances and can be tricky
// to manage by noobs. The functions have however been designed to be noob friendly and
// avoid a few DMA behaviour "gotchas".
@ -590,7 +593,7 @@ class TFT_eSPI : public Print {
// processor leaves a function or its content being changed while the DMA engine is reading it.
//
// The compiler MAY change the implied scope of a buffer which has been set aside by creating
// and an array. For example a buffer defined before a "for-next" loop may get de-allocated when
// an array. For example a buffer defined before a "for-next" loop may get de-allocated when
// the loop ends. To avoid this use, for example, malloc() and free() to take control of when
// the buffer space is available and ensure it is not released until DMA is complete.
//
@ -605,7 +608,7 @@ class TFT_eSPI : public Print {
// Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
// Use the buffer if the image data will get over-written or destroyed while DMA is in progress
// If swapping colour bytes is defined, and the double buffer option is NOT used then the bytes
// If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes
// in the original data image will be swapped by the function before DMA is initiated.
// The function will wait for the last DMA to complete if it is called while a previous DMA is still
// in progress, this simplifies the sketch and helps avoid "gotchas".
@ -615,9 +618,8 @@ class TFT_eSPI : public Print {
void pushPixelsDMA(uint16_t* image, uint32_t len);
// Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait
// Note: for ESP32 the dmaBusy() function is blocking at the moment - to be updated
bool dmaBusy(void);
void dmaWait(void);
bool dmaBusy(void); // returns true if DMA is still in progress
void dmaWait(void); // wait until DMA is complete
bool DMA_Enabled = false; // Flag for DMA enabled state
uint8_t spiBusyCheck = 0; // Number of ESP32 transfer buffers to check

26
Tools/Images/README.md Normal file
View File

@ -0,0 +1,26 @@
## bmp2array4bit
bmp2array4bit.py reads a bmp file, and creates C (or C++) code that contains two arrays for adding images to four-bit sprites. See [Sprite_image_4bit](../../examples/Sprite/Sprite_image_4bit) for an example.
It is loosely based on Spark Fun's bmp2array script, https://github.com/sparkfun/BMPtoArray/blob/master/bmp2array.py. The bmp file format is documented in https://en.wikipedia.org/wiki/BMP_file_format.
You'll need python 3.6 (the original uses Python 2.7)
`usage: python bmp2array4bit.py [-v] star.bmp [-o myfile.c]`
Create the bmp file in Gimp (www.gimp.org) from any image as follows:
* Remove the alpha channel (if it has one)
Layer -> Transparency -> Remove Alpha Channel
* Set the mode to indexed.
Image -> Mode -> Indexed...
* Select Generate optimum palette with 16 colors (max)
* Export the file with a .bmp extension. Do **NOT** select options:
* Run-Length Encoded
* Compatibility Options: "Do not write color space information"
* There are no Advanced Options available with these settings
(There are other tools that will produce bmp files, and these should work provided you don't use run-length encoding or other advanced features).
The first array produced is the palette for the image.
The second is the image itself.

View File

@ -0,0 +1,251 @@
'''
This script takes in a bitmap and outputs a text file that is a
byte array used in Arduino files.
It is loosely based on Spark Fun's bmp2array script.
You'll need python 3.6 (the original use Python 2.7)
usage: python fourbitbmp2array.py [-v] star.bmp [-o myfile.c]
Create the bmp file in Gimp by :
. Remove the alpha channel (if it has one) Layer -> Transparency -> Remove Alpha Channel
. Set the mode to indexed. Image -> Mode -> Indexed...
. Select Generate optimum palette with 16 colors (max)
. Export the file with a .bmp extension. Options are:
. Run-Length Encoded: not selected
. Compatibility Options: "Do not write color space information" not selected
. There are no Advanced Options available with these settings
'''
import sys
import struct
import math
import argparse
import os
debug = None
def debugOut(s):
if debug:
print(s)
# look at arguments
parser = argparse.ArgumentParser(description="Convert bmp file to C array")
parser.add_argument("-v", "--verbose", help="debug output", action="store_true")
parser.add_argument("input", help="input file name")
parser.add_argument("-o", "--output", help="output file name")
args = parser.parse_args()
if not os.path.exists(args.input):
parser.print_help()
print("The input file {} does not exist".format(args.input))
sys.exit(1)
if args.output == None:
output = os.path.basename(args.input).replace(".bmp", ".c")
else:
output = args.output
debug = args.verbose
try:
#Open our input file which is defined by the first commandline argument
#then dump it into a list of bytes
infile = open(args.input,"rb") #b is for binary
contents = bytearray(infile.read())
infile.close()
except:
print("could not read input file {}".format(args.input))
sys.exit(1)
# first two bytes should be "BM"
upto = 2
#Get the size of this image
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
fileSize = struct.unpack("I", bytearray(data))
upto += 4
# four bytes are reserved
upto += 4
debugOut("Size of file: {}".format(fileSize[0]))
#Get the header offset amount
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
offset = struct.unpack("I", bytearray(data))
debugOut("Offset: {}".format(offset[0]))
upto += 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
headersize = struct.unpack("I", bytearray(data))
headerLength = headersize[0]
startOfDefinitions = headerLength + upto
debugOut("header size: {}, up to {}, startOfDefinitions {}".format(headersize[0], upto, startOfDefinitions))
upto += 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("width: {}".format(t[0]))
width = t[0]
upto += 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("height: {}".format(t[0]))
height = t[0]
# 26
upto += 4
data = struct.pack("BB", contents[upto], contents[upto+1])
t = struct.unpack("H", bytearray(data))
debugOut("planes: {}".format(t[0]))
upto = upto + 2
data = struct.pack("BB", contents[upto], contents[upto+1])
t = struct.unpack("H", bytearray(data))
debugOut("bits per pixel: {}".format(t[0]))
bitsPerPixel = t[0]
upto = upto + 2
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biCompression: {}".format(t[0]))
upto = upto + 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biSizeImage: {}".format(t[0]))
upto = upto + 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biXPelsPerMeter: {}".format(t[0]))
upto = upto + 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biYPelsPerMeter: {}".format(t[0]))
upto = upto + 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biClrUsed: {}".format(t[0]))
colorsUsed = t
upto = upto + 4
data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
t = struct.unpack("I", bytearray(data))
debugOut("biClrImportant: {}".format(t[0]))
upto += 4
debugOut("Upto: {} Number of colors used: {} definitions start at: {}".format(upto, colorsUsed[0], startOfDefinitions))
#Create color definition array and init the array of color values
colorIndex = [] #(colorsUsed[0])
for i in range(colorsUsed[0]):
colorIndex.append(0)
#Assign the colors to the array. upto = 54
# startOfDefinitions = upto
for i in range(colorsUsed[0]):
upto = startOfDefinitions + (i * 4)
blue = contents[upto]
green = contents[upto + 1]
red = contents[upto + 2]
# ignore the alpha channel.
# data = struct.pack("BBBB", contents[upto], contents[upto+1], contents[upto+2], contents[upto+3])
# t = struct.unpack("I", bytearray(data))
# colorIndex[i] = t[0]
colorIndex[i] = (((red & 0xf8)<<8) + ((green & 0xfc)<<3)+(blue>>3))
debugOut("color at index {0} is {1:04x}, (r,g,b,a) = ({2:02x}, {3:02x}, {4:02x}, {5:02x})".format(i, colorIndex[i], red, green, blue, contents[upto+3]))
#debugOut(the color definitions
# for i in range(colorsUsed[0]):
# print hex(colorIndex[i])
# perfect, except upside down.
#Make a string to hold the output of our script
arraySize = (len(contents) - offset[0])
outputString = "/* This was generated using a script based on the SparkFun BMPtoArray python script" + '\n'
outputString += " See https://github.com/sparkfun/BMPtoArray for more info */" + '\n\n'
outputString += "static const uint16_t palette[" + str(colorsUsed[0]) + "] = {";
for i in range(colorsUsed[0]):
# print hexlify(colorIndex[i])
if i % 4 == 0:
outputString += "\n\t"
outputString += "0x{:04x}, ".format(colorIndex[i])
outputString = outputString[:-2]
outputString += "\n};\n\n"
outputString += "// width is " + str(width) + ", height is " + str(height) + "\n"
outputString += "static const uint8_t myGraphic[" + str(arraySize) + "] PROGMEM = {" + '\n'
if bitsPerPixel != 4:
print("Expected 4 bits per pixel; found {}".format(bitsPerPixel))
sys.exit(1)
#Start converting spots to values
#Start at the offset and go to the end of the file
dropLastNumber = True #(width % 4) == 2 or (width % 4) == 1
paddedWidth = int(math.ceil(bitsPerPixel * width / 32.0) * 4)
debugOut("array range is {} {} len(contents) is {} paddedWidth is {} width is {}".format(offset[0], fileSize[0], len(contents), paddedWidth, width))
r = 0
width = int(width / 2)
#for i in range(offset[0], fileSize[0]): # close but image is upside down. Each row is correct but need to swap columns.
#for i in range(fileSize[0], offset[0], -1):
for col in range(height-1, -1, -1):
i = 0
for row in range(width):
colorCode1 = contents[row + col*paddedWidth + offset[0]]
if r > 0 and r % width == 0:
i = 0
outputString += '\n\n'
elif (i + 1) % 12 == 0 :
outputString += '\n'
i = 0
#debugOut("cell ({0}, {1})".format(row, col)
r = r + 1
i = i + 1
outputString += "0x{:02x}, ".format(colorCode1)
#Once we've reached the end of our input string, pull the last two
#characters off (the last comma and space) since we don't need
#them. Top it off with a closing bracket and a semicolon.
outputString = outputString[:-2]
outputString += "};"
try:
#Write the output string to our output file
outfile = open(output, "w")
outfile.write(outputString)
outfile.close()
except:
print("could not write output to file {}".format(output))
sys.exit(1)
debugOut("{} complete".format(output))
debugOut("Copy and paste this array into a image.h or other header file")
if not debug:
print("Completed; the output is in {}".format(output))

BIN
Tools/Images/star.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -50,6 +50,9 @@
//#define R61581_DRIVER
//#define RM68140_DRIVER
//#define ST7796_DRIVER
//#define SSD1963_480_DRIVER // Untested
//#define SSD1963_800_DRIVER // Untested
//#define SSD1963_800ALT_DRIVER // Untested
// Some displays support SPI reads via the MISO pin, other displays have a single
// bi-directional SDA pin and the library will try to read this via the MOSI line.
@ -236,6 +239,31 @@
//#define TFT_D6 27
//#define TFT_D7 14
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
// The TFT can be connected to SPI port 1 or 2
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
//#define TFT_MOSI PA7
//#define TFT_MISO PA6
//#define TFT_SCLK PA5
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
//#define TFT_MOSI PB15
//#define TFT_MISO PB14
//#define TFT_SCLK PB13
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
//#define TFT_CS D5 // Chip select control pin to TFT CS
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
// OR alternatively, we can use STM32 port reference names PXnn
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
// Use an Arduino pin for initial testing as connecting to processor reset
// may not work (pulse too short at power up?)
// ##################################################################################
//
@ -278,8 +306,9 @@
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
#define SPI_FREQUENCY 27000000
// #define SPI_FREQUENCY 40000000
// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY 80000000
// Optional reduced SPI frequency for reading TFT

View File

@ -59,7 +59,7 @@
//#include <User_Setups/Setup29_ILI9341_STM32.h> // Setup for Nucleo board
//#include <User_Setups/Setup30_ILI9341_Parallel_STM32.h> // Setup for Nucleo board and parallel display
//#include <User_Setups/Setup31_ST7796_Parallel_STM32.h> // Setup for Nucleo board and parallel display
//#include <User_Setups/Setup32_ILI9341_STM32F103.h> // Setup for "Blue Pill"
//#include <User_Setups/Setup32_ILI9341_STM32F103.h> // Setup for "Blue/Black Pill"
//#include <User_Setups/Setup33_RPi_ILI9486_STM32.h> // Setup for Nucleo board
@ -69,8 +69,10 @@
//#include <User_Setups/Setup36_RPi_touch_ILI9341.h> // Setup file configured for ESP32 and RPi TFT with touch
//#include <User_Setups/Setup43_ST7735.h> // Setup file configured for my ST7735S 80x160
//#include <User_Setups/Setup44_TTGO_CameraPlus.h> // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240
//#include <User_Setups/Setup45_TTGO_T_Watch.h> // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT 240x240
//#include <User_Setups/Setup44_TTGO_CameraPlus.h> // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240
//#include <User_Setups/Setup45_TTGO_T_Watch.h> // Setup file for ESP32 and TTGO T-Watch ST7789 SPI bus TFT 240x240
//#include <User_Setups/Setup50_SSD1963_Parallel.h> // Setup file for ESP32 and SSD1963 TFT display
//#include <User_Setups/Setup135_ST7789.h> // Setup file for ESP8266 and ST7789 135 x 240 TFT
@ -154,8 +156,20 @@
#elif defined (RM68140_DRIVER)
#include "TFT_Drivers/RM68140_Defines.h"
#define TFT_DRIVER 0x6814
#elif defined (SSD1963_480_DRIVER)
#include "TFT_Drivers/SSD1963_Defines.h"
#define TFT_DRIVER 0x1963
#elif defined (SSD1963_800_DRIVER)
#include "TFT_Drivers/SSD1963_Defines.h"
#define TFT_DRIVER 0x1963
#elif defined (SSD1963_800ALT_DRIVER)
#include "TFT_Drivers/SSD1963_Defines.h"
#define TFT_DRIVER 0x1963
#elif defined (SSD1963_800BD_DRIVER)
#include "TFT_Drivers/SSD1963_Defines.h"
#define TFT_DRIVER 0x1963
// <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE
// XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.c
// XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.cpp
#elif defined (XYZZY_DRIVER)
#include "TFT_Drivers/XYZZY_Defines.h"
#define TFT_DRIVER 0x0000

View File

@ -1,6 +1,6 @@
// See SetupX_Template.h for all options available
#define ESP32_PARALLEL
#define TFT_PARALLEL_8_BIT
#define ILI9341_DRIVER

View File

@ -22,7 +22,36 @@
// MOSI and SCK do not need to be defined, connect:
// - Arduino SCK to TFT SCK
// - Arduino MOSI to TFT SDI(may be marked SDA or MOSI)
// Standard Arduino SPI pins are (SCK=D13, MOSI=D11) this is port pins PA5 and PA7 on Nucleo-F767ZI
// Typical Arduino SPI port 1 pins are (SCK=D13, MISO=D12, MOSI=D11) this is port pins PA5, PA6 and PA7 on Nucleo-F767ZI
// SPI port 2 pins are (SCK=D18, MISO=A7, MOSI=D17) this is port pins PB13, PC2 and PB15 on Nucleo-F767ZI
/*
#define TFT_SPI_PORT 1 // SPI 1 maximum clock rate is 55MHz
#define TFT_MOSI PA7
#define TFT_MISO PA6
#define TFT_SCLK PA5
//*/
/*
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
#define TFT_MOSI D17
#define TFT_MISO A7
#define TFT_SCLK D18
//*/
/*
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
#define TFT_MOSI PB15
#define TFT_MISO PC2
#define TFT_SCLK PB13
//*/
/*
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
#define TFT_MOSI PB15
#define TFT_MISO PB14
#define TFT_SCLK PB13
//*/
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
#define TFT_CS D5 // Chip select control pin to TFT CS
@ -52,7 +81,7 @@
// STM32 support for smooth fonts via program memory (FLASH) arrays
#define SMOOTH_FONT
// Nucleo-F767ZI has a ~216MHZ CPU clock, this is divided by 4, 8, 16 etc
#define SPI_FREQUENCY 27000000 // 27MHz SPI clock

View File

@ -0,0 +1,92 @@
// USER DEFINED SETTINGS
// Set driver type, fonts to be loaded, pins used and SPI control method etc
//
// See the User_Setup_Select.h file if you wish to be able to define multiple
// setups and then easily select which setup file is used by the compiler.
//
// If this file is edited correctly then all the library example sketches should
// run without the need to make any more changes for a particular hardware setup!
// ##################################################################################
//
// Section 0. Call up the right driver file and any options for it
//
// ##################################################################################
// Use ESP32 Parallel interface
#define TFT_PARALLEL_8_BIT
// Only define one driver, the other ones must be commented out
//#define SSD1963_480_DRIVER // 272 x 480 display
//#define SSD1963_800_DRIVER // 480 x 800 display
//#define SSD1963_800ALT_DRIVER // Alternative 480 x 800 display
#define SSD1963_800BD_DRIVER // 480 x 800 displau sourced from https://www.buydisplay.com/7-tft-screen-touch-lcd-display-module-w-ssd1963-controller-board-mcu
// ##################################################################################
//
// Section 1. Define the pins that are used to interface with the display here
//
// ##################################################################################
// ESP32 pins used
#define TFT_CS 33 // Chip select control pin
#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31
#define TFT_RST 32 // Reset pin
#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31
#define TFT_RD 2
#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus
#define TFT_D1 13 // so a single register write sets/clears all bits
#define TFT_D2 26
#define TFT_D3 25
#define TFT_D4 17
#define TFT_D5 16
#define TFT_D6 27
#define TFT_D7 14
// ##################################################################################
//
// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only)
//
// ##################################################################################
// ##################################################################################
//
// Section 3. Define the fonts that are to be used here
//
// ##################################################################################
// Comment out the #defines below with // to stop that font being loaded
// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not
// normally necessary. If all fonts are loaded the extra FLASH space required is
// about 17Kbytes. To save FLASH space only enable the fonts you need!
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded
// this will save ~20kbytes of FLASH
#define SMOOTH_FONT
// ##################################################################################
//
// Section 4. Not used
//
// ##################################################################################
// ##################################################################################
//
// Section 5. Other options
//
// ##################################################################################

View File

@ -8,6 +8,7 @@
// run without the need to make any more changes for a particular hardware setup!
// Note that some sketches are designed for a particular TFT pixel width/height
// ##################################################################################
//
// Section 1. Call up the right driver file and any options for it
@ -22,7 +23,13 @@
//#define NUCLEO_64_TFT
//#define NUCLEO_144_TFT
// Tell the library to use 8 bit parallel mode(otherwise SPI is assumed)
// STM32 8 bit parallel only:
// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7
// then this will improve rendering performance by a factor of ~8x
//#define STM_PORTA_DATA_BUS
//#define STM_PORTA_DATA_BUS
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
// Display type - only define if RPi display
@ -33,6 +40,7 @@
//#define ST7735_DRIVER // Define additional parameters below for this display
//#define ILI9163_DRIVER // Define additional parameters below for this display
//#define S6D02A1_DRIVER
//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI
//#define HX8357D_DRIVER
//#define ILI9481_DRIVER
//#define ILI9486_DRIVER
@ -91,13 +99,6 @@
// #define TFT_INVERSION_ON
// #define TFT_INVERSION_OFF
// If a backlight control signal is available then define the TFT_BL pin in Section 2
// below. The backlight will be turned ON when tft.begin() is called, but the library
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options
// ##################################################################################
//
@ -105,6 +106,17 @@
//
// ##################################################################################
// If a backlight control signal is available then define the TFT_BL pin in Section 2
// below. The backlight will be turned ON when tft.begin() is called, but the library
// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be
// driven with a PWM signal or turned OFF/ON then this must be handled by the user
// sketch. e.g. with digitalWrite(TFT_BL, LOW);
// #define TFT_BL 32 // LED back-light control pin
// #define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
// We must use hardware SPI, a minimum of 3 GPIO pins is needed.
// Typical setup for ESP8266 NodeMCU ESP-12 is :
//
@ -181,8 +193,6 @@
//#define TFT_RST 4 // Reset pin (could connect to RST pin)
//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin)
//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen
//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only
@ -203,10 +213,11 @@
// Wemos D32 boards need to be modified, see diagram in Tools folder.
// Only ILI9481 and ILI9341 based displays have been tested!
// Parallel bus is only supported on ESP32
// Uncomment line below to use ESP32 Parallel interface instead of SPI
// Parallel bus is only supported for the STM32 and ESP32
// Example below is for ESP32 Parallel interface with UNO displays
//#define ESP32_PARALLEL
// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed)
//#define TFT_PARALLEL_8_BIT
// The ESP32 and TFT the pins used for testing are:
//#define TFT_CS 33 // Chip select control pin (library pulls permanently low
@ -225,6 +236,31 @@
//#define TFT_D6 27
//#define TFT_D7 14
// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ######
// The TFT can be connected to SPI port 1 or 2
//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz
//#define TFT_MOSI PA7
//#define TFT_MISO PA6
//#define TFT_SCLK PA5
//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz
//#define TFT_MOSI PB15
//#define TFT_MISO PB14
//#define TFT_SCLK PB13
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
//#define TFT_CS D5 // Chip select control pin to TFT CS
//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
//#define TFT_RST D7 // Reset pin to TFT RST (or RESET)
// OR alternatively, we can use STM32 port reference names PXnn
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
// Use an Arduino pin for initial testing as connecting to processor reset
// may not work (pulse too short at power up?)
// ##################################################################################
//
@ -262,14 +298,14 @@
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
// With an ILI9163 display 27 MHz works OK.
// The RPi typically only works at 20MHz maximum.
// #define SPI_FREQUENCY 1000000
// #define SPI_FREQUENCY 5000000
// #define SPI_FREQUENCY 10000000
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
#define SPI_FREQUENCY 27000000
// #define SPI_FREQUENCY 40000000
// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY 80000000
// Optional reduced SPI frequency for reading TFT

View File

@ -1,191 +0,0 @@
/*====================================================================================
This sketch contains support functions to render the Jpeg images.
Created by Bodmer 15th Jan 2017
==================================================================================*/
// Return the minimum of two values a and b
#define minimum(a,b) (((a) < (b)) ? (a) : (b))
//====================================================================================
// Opens the image file and prime the Jpeg decoder
//====================================================================================
void drawJpeg(const char *filename, int xpos, int ypos) {
Serial.println("===========================");
Serial.print("Drawing file: "); Serial.println(filename);
Serial.println("===========================");
// Open the named file (the Jpeg decoder library will close it after rendering image)
fs::File jpegFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS
// File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library
if ( !jpegFile ) {
Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
return;
}
// Use one of the three following methods to initialise the decoder:
//boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder,
//boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder,
boolean decoded = JpegDec.decodeFsFile(filename); // or pass the filename (leading / distinguishes SPIFFS files)
// Note: the filename can be a String or character array type
if (decoded) {
// print information about the image to the serial port
jpegInfo();
// render the image onto the screen at given coordinates
jpegRender(xpos, ypos);
}
else {
Serial.println("Jpeg file format not supported!");
}
}
//====================================================================================
// Decode and render the Jpeg image onto the TFT screen
//====================================================================================
void jpegRender(int xpos, int ypos) {
// retrieve infomration about the image
uint16_t *pImg;
uint16_t mcu_w = JpegDec.MCUWidth;
uint16_t mcu_h = JpegDec.MCUHeight;
uint32_t max_x = JpegDec.width;
uint32_t max_y = JpegDec.height;
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
uint32_t min_h = minimum(mcu_h, max_y % mcu_h);
// save the current image block size
uint32_t win_w = mcu_w;
uint32_t win_h = mcu_h;
// record the current time so we can measure how long it takes to draw an image
uint32_t drawTime = millis();
// save the coordinate of the right and bottom edges to assist image cropping
// to the screen size
max_x += xpos;
max_y += ypos;
// read each MCU block until there are no more
while ( JpegDec.readSwappedBytes()) { // Swap byte order so the SPI buffer can be used
// save a pointer to the image block
pImg = JpegDec.pImage;
// calculate where the image block should be drawn on the screen
int mcu_x = JpegDec.MCUx * mcu_w + xpos; // Calculate coordinates of top left corner of current MCU
int mcu_y = JpegDec.MCUy * mcu_h + ypos;
// check if the image block size needs to be changed for the right edge
if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
else win_w = min_w;
// check if the image block size needs to be changed for the bottom edge
if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
else win_h = min_h;
// copy pixels into a contiguous block
if (win_w != mcu_w)
{
uint16_t *cImg;
int p = 0;
cImg = pImg + win_w;
for (int h = 1; h < win_h; h++)
{
p += mcu_w;
for (int w = 0; w < win_w; w++)
{
*cImg = *(pImg + w + p);
cImg++;
}
}
}
// draw image MCU block only if it will fit on the screen
if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height())
{
tft.pushRect(mcu_x, mcu_y, win_w, win_h, pImg);
}
else if ( ( mcu_y + win_h) >= tft.height()) JpegDec.abort();
}
// calculate how long it took to draw the image
drawTime = millis() - drawTime; // Calculate the time it took
// print the results to the serial port
Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms");
Serial.println("=====================================");
}
//====================================================================================
// Print information decoded from the Jpeg image
//====================================================================================
void jpegInfo() {
Serial.println("===============");
Serial.println("JPEG image info");
Serial.println("===============");
Serial.print ("Width :"); Serial.println(JpegDec.width);
Serial.print ("Height :"); Serial.println(JpegDec.height);
Serial.print ("Components :"); Serial.println(JpegDec.comps);
Serial.print ("MCU / row :"); Serial.println(JpegDec.MCUSPerRow);
Serial.print ("MCU / col :"); Serial.println(JpegDec.MCUSPerCol);
Serial.print ("Scan type :"); Serial.println(JpegDec.scanType);
Serial.print ("MCU width :"); Serial.println(JpegDec.MCUWidth);
Serial.print ("MCU height :"); Serial.println(JpegDec.MCUHeight);
Serial.println("===============");
Serial.println("");
}
//====================================================================================
// Open a Jpeg file and send it to the Serial port in a C array compatible format
//====================================================================================
void createArray(const char *filename) {
// Open the named file
fs::File jpgFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS
// File jpgFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library
if ( !jpgFile ) {
Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
return;
}
uint8_t data;
byte line_len = 0;
Serial.println("");
Serial.println("// Generated by a JPEGDecoder library example sketch:");
Serial.println("// https://github.com/Bodmer/JPEGDecoder");
Serial.println("");
Serial.println("#include <pgmspace.h>");
Serial.println("// Remove leading / from array name!");
Serial.print ("const uint8_t ");
while (*filename != '.') Serial.print(*filename++);
Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors, it is ignored by Due
while ( jpgFile.available()) {
data = jpgFile.read();
Serial.print("0x"); if (abs(data) < 16) Serial.print("0");
Serial.print(data, HEX); Serial.print(",");// Add value and comma
line_len++;
if ( line_len >= 32) {
line_len = 0;
Serial.println();
}
}
Serial.println("};\r\n");
jpgFile.close();
}
//====================================================================================

View File

@ -1,36 +0,0 @@
/*====================================================================================
This sketch contains support functions for the ESP6266 SPIFFS filing system
Created by Bodmer 15th Jan 2017
==================================================================================*/
//====================================================================================
// Print a SPIFFS directory list (root directory)
//====================================================================================
void listFiles(void) {
Serial.println();
Serial.println("SPIFFS files found:");
fs::Dir dir = SPIFFS.openDir("/"); // Root directory
String line = "=====================================";
Serial.println(line);
Serial.println(" File name Size");
Serial.println(line);
while (dir.next()) {
String fileName = dir.fileName();
Serial.print(fileName);
int spaces = 25 - fileName.length(); // Tabulate nicely
while (spaces--) Serial.print(" ");
fs::File f = dir.openFile("r");
Serial.print(f.size()); Serial.println(" bytes");
}
Serial.println(line);
Serial.println();
delay(1000);
}
//====================================================================================

View File

@ -1,129 +0,0 @@
/*====================================================================================
This sketch demonstrates loading images which have been stored as files in the
built-in FLASH memory on a NodeMCU 1.0 (ESP8266 based, ESP-12E Module) rendering the
images onto a 160 x 128 pixel TFT screen.
The images are stored in the SPI FLASH Filing System (SPIFFS), which effectively
functions like a tiny "hard drive". This filing system is built into the ESP8266
Core that can be loaded from the IDE "Boards manager" menu option. This is at
version 2.3.0 at the time of sketch creation.
The size of the SPIFFS partition can be set in the IDE as 1Mbyte or 3Mbytes. Either
will work with this sketch. Typically most sketches easily fit within 1 Mbyte so a
3 Mbyte SPIFS partition can be used, in which case it can contain 100's of Jpeg
full screem images.
The Jpeg library can be found here:
https://github.com/Bodmer/JPEGDecoder
Images in the Jpeg format can be created using Paint or IrfanView or other picture
editting software.
Place the images inside the sketch folder, in a folder called "Data". Then upload
all the files in the folder using the Arduino IDE "ESP8266 Sketch Data Upload" option
in the "Tools" menu:
http://www.esp8266.com/viewtopic.php?f=32&t=10081
https://github.com/esp8266/arduino-esp8266fs-plugin/releases
This takes some time, but the SPIFFS content is not altered when a new sketch is
uploaded, so there is no need to upload the same files again!
Note: If open, you must close the "Serial Monitor" window to upload data to SPIFFS!
The IDE will not copy the "data" folder with the sketch if you save the sketch under
another name. It is necessary to manually make a copy and place it in the sketch
folder.
This sketch includes example images in the Data folder.
Saving images, uploading and rendering on the TFT screen couldn't be much easier!
Created by Bodmer 24th Jan 2017 - Tested in Arduino IDE 1.8.0 esp8266 Core 2.3.0
==================================================================================*/
//====================================================================================
// Libraries
//====================================================================================
// Call up the SPIFFS FLASH filing system this is part of the ESP Core
#define FS_NO_GLOBALS
#include <FS.h>
// JPEG decoder library
#include <JPEGDecoder.h>
// SPI library, built into IDE
#include <SPI.h>
// Call up the TFT library
#include <TFT_eSPI.h> // Hardware-specific library for ESP8266
// The TFT control pins are set in the User_Setup.h file <<<<<<<<<<<<<<<<< NOTE!
// that can be found in the "src" folder of the library
// Invoke TFT library
TFT_eSPI tft = TFT_eSPI();
//====================================================================================
// Setup
//====================================================================================
void setup()
{
Serial.begin(250000); // Used for messages and the C array generator
delay(10);
Serial.println("NodeMCU decoder test!");
tft.begin();
tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape
tft.fillScreen(TFT_BLACK);
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nInitialisation done.");
listFiles(); // Lists the files so you can see what is in the SPIFFS
}
//====================================================================================
// Loop
//====================================================================================
void loop()
{
// Note the / before the SPIFFS file name must be present, this means the file is in
// the root directory of the SPIFFS, e.g. "/Tiger.jpg" for a file called "Tiger.jpg"
tft.setRotation(0); // portrait
tft.fillScreen(random(0xFFFF));
drawJpeg("/EagleEye160.jpg", 0, 16);
delay(2000);
tft.fillScreen(random(0xFFFF));
drawJpeg("/tiger160.jpg", 4, 0);
delay(2000);
tft.setRotation(1); // landscape
//tft.fillScreen(random(0xFFFF));
drawJpeg("/arduino160.jpg", 0, 0);
delay(2000);
tft.fillScreen(TFT_BLACK);
drawJpeg("/Baboon160.jpg", 0, 4);
delay(2000);
tft.fillScreen(random(0xFFFF));
drawJpeg("/Mouse160.jpg", 0, 11);
delay(2000);
// Create arrays from the jpeg images and send them to the serial port for copy and
// pasting into a sketch (used to make arrays fot the TFT_FLASH_Jpeg sketch)
//createArray("/EagleEye160.jpg");
//createArray("/tiger160.jpg");
//createArray("/Baboon160.jpg");
//createArray("/Mouse160.jpg");
//while(1) yield(); // Stay here
}
//====================================================================================

View File

@ -32,7 +32,7 @@ void setup() {
Serial.begin(115200);
randomSeed(analogRead(A0));
tft.init();
tft.setRotation(2);
tft.setRotation(0);
tft.fillScreen(ILI9341_BLACK);
setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
}

View File

@ -6,7 +6,7 @@
// parallel TFT's (tested with ILI9341 and ILI9481)
// The sketch will run on processors without DMA and also parallel
// interface TFT's. Comment out line 25 for no DMA.
// interface TFT's. Comment out line 29 for no DMA.
// Library here:
// https://github.com/Bodmer/TFT_eSPI

View File

@ -153,8 +153,8 @@ void jpegRender(int xpos, int ypos) {
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = min(mcu_w, max_x % mcu_w);
uint32_t min_h = min(mcu_h, max_y % mcu_h);
uint32_t min_w = jpg_min(mcu_w, max_x % mcu_w);
uint32_t min_h = jpg_min(mcu_h, max_y % mcu_h);
// save the current image block size
uint32_t win_w = mcu_w;

View File

@ -31,7 +31,6 @@
//====================================================================================
// Libraries
//====================================================================================
// Call up the SPIFFS FLASH filing system this is part of the ESP Core
#include <TFT_eSPI.h> // Hardware-specific library

View File

@ -10,7 +10,7 @@
// screen very simple. The rotation is clockwise with increasing angle. The angle is in
// degrees, an angle of 0 means no Sprite rotation.
// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites.
// The pushRotated() function works with 1, 4, 8 and 16 bit per pixel (bpp) Sprites.
// The original Sprite is unchanged so can be plotted again at a different angle.
@ -20,6 +20,10 @@
// For 1 bpp Sprites the foreground and background colours are defined with the
// function spr.setBitmapColor(foregroundColor, backgroundColor).
// For 4 bpp Sprites the colour map index is used instead of the 16 bit colour
// e.g. spr.setTextColor(5); // Green text in default colour map
// See "Transparent_Sprite_Demo_4bit" example for default colour map details
// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI
@ -46,7 +50,7 @@ void setup() {
void loop() {
int xw = tft.width()/2; // xw, yh is midle of screen
int xw = tft.width()/2; // xw, yh is middle of screen
int yh = tft.height()/2;

View File

@ -88,7 +88,7 @@ void loop(void)
// Pass the palette to the Sprite class
spr.createPalette(cmap);
// Push Sprite parially off-screen to test cropping
// Push Sprite partially off-screen to test cropping
spr.pushSprite(-40, -40);
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);

View File

@ -0,0 +1,152 @@
/*
Sketch to show how a Sprite can use a four-bit image with
a palette to change the appearance of an image while rendering
it only once.
Example for library:
https://github.com/Bodmer/TFT_eSPI
A Sprite is notionally an invisible graphics screen that is
kept in the processors RAM. Graphics can be drawn into the
Sprite just as it can be drawn directly to the screen. Once
the Sprite is completed it can be plotted onto the screen in
any position. If there is sufficient RAM then the Sprite can
be the same size as the screen and used as a frame buffer.
A 16 bit Sprite occupies (2 * width * height) bytes in RAM.
On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated,
this size requires 40kBytes of RAM for a 16 bit color depth.
When 8 bit color depth sprites are created they occupy
(width * height) bytes in RAM, so larger sprites can be
created, or the RAM required is halved.
*/
// Set delay after plotting the sprite
#define DELAY 30
// Width and height of sprite
#define WIDTH 164
#define HEIGHT 164
#include "sample_images.h"
TFT_eSPI tft = TFT_eSPI(); // Declare object "tft"
TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object
byte red = 31; // Red is the top 5 bits of a 16 bit colour value
byte green = 0;// Green is the middle 6 bits
byte blue = 0; // Blue is the bottom 5 bits
byte state = 0;
int rloop = 0;
int incr = 1;
uint16_t cmap[16];
void setup()
{
Serial.begin(9600);
Serial.println();
delay(50);
// Initialise the TFT registers
tft.init();
spr.setColorDepth(4);
// Create a sprite of defined size
spr.createSprite(WIDTH, HEIGHT);
// Clear the TFT screen to black
tft.fillScreen(TFT_BLACK);
// push the image - only need to do this once.
spr.pushImage(2, 2, 160, 160, (uint16_t *)stars);
for (int i = 0; i < 16; i++)
cmap[i] = rainbow();
}
void loop(void)
{
// create a palette with the defined colors and push it.
spr.createPalette(cmap, 16);
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
// update the colors
for (int i = 0; i < 15; i++) {
cmap[i] = cmap[i + 1];
}
if (incr == 2) {
(void)rainbow(); // skip alternate steps to go faster
}
cmap[15] = rainbow();
rloop += incr;
if (rloop > 0xc0) {
incr = incr == 2 ? 1 : 2;
rloop = 0;
}
delay(DELAY);
}
// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow()
{
switch (state) {
case 0:
green ++;
if (green == 64) {
green = 63;
state = 1;
}
break;
case 1:
red--;
if (red == 255) {
red = 0;
state = 2;
}
break;
case 2:
blue ++;
if (blue == 32) {
blue = 31;
state = 3;
}
break;
case 3:
green --;
if (green == 255) {
green = 0;
state = 4;
}
break;
case 4:
red ++;
if (red == 32) {
red = 31;
state = 5;
}
break;
case 5:
blue --;
if (blue == 255) {
blue = 0;
state = 0;
}
break;
}
return red << 11 | green << 5 | blue;
}

View File

@ -0,0 +1,3 @@
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
extern const uint8_t stars[12800] PROGMEM ;

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ if (user.tft_driver != 0xE9D) // For ePaper displays the size is defined in the
Serial.print("Display driver = "); Serial.println(user.tft_driver, HEX); // Hexadecimal code
Serial.print("Display width = "); Serial.println(user.tft_width); // Rotation 0 width and height
Serial.print("Display height = "); Serial.println(user.tft_height);
Serial.println();
}
else if (user.tft_driver == 0xE9D) Serial.println("Display driver = ePaper\n");
@ -97,6 +98,10 @@ if (user.overlap == true)
}
#endif
String pinNameRef = "GPIO ";
#ifdef ESP8266
pinNameRef = "PIN_D";
#endif
if (user.esp == 0x32F) {
Serial.println("\n>>>>> Note: STM32 pin references above D15 may not reflect board markings <<<<<");
pinNameRef = "D";
@ -119,6 +124,15 @@ if (user.pin_tft_d5 != -1) { Serial.print("TFT_D5 = " + pinNameRef); Serial.pr
if (user.pin_tft_d6 != -1) { Serial.print("TFT_D6 = " + pinNameRef); Serial.println(getPinName(user.pin_tft_d6)); }
if (user.pin_tft_d7 != -1) { Serial.print("TFT_D7 = " + pinNameRef); Serial.println(getPinName(user.pin_tft_d7)); }
#if defined (TFT_BL)
Serial.print("\nTFT_BL = " + pinNameRef); Serial.println(getPinName(user.pin_tft_led));
#if defined (TFT_BACKLIGHT_ON)
Serial.print("TFT_BACKLIGHT_ON = "); Serial.println(user.pin_tft_led_on == HIGH ? "HIGH" : "LOW");
#endif
#endif
Serial.println();
uint16_t fonts = tft.fontsLoaded();
if (fonts & (1 << 1)) Serial.print("Font GLCD loaded\n");
if (fonts & (1 << 2)) Serial.print("Font 2 loaded\n");

View File

@ -1,27 +1,34 @@
# TFT_eSPI core library
TFT_eSPI KEYWORD1
begin KEYWORD2
init KEYWORD2
drawPixel KEYWORD2
drawChar KEYWORD2
setAddrWindow KEYWORD2
setWindow KEYWORD2
startWrite KEYWORD2
writeColor KEYWORD2
endWrite KEYWORD2
pushColor KEYWORD2
pushColors KEYWORD2
fillScreen KEYWORD2
writeBegin KEYWORD2
writeEnd KEYWORD2
drawLine KEYWORD2
drawFastVLine KEYWORD2
drawFastHLine KEYWORD2
drawRect KEYWORD2
fillRect KEYWORD2
height KEYWORD2
width KEYWORD2
setRotation KEYWORD2
getRotation KEYWORD2
invertDisplay KEYWORD2
setAddrWindow KEYWORD2
setWindow KEYWORD2
pushColor KEYWORD2
pushColors KEYWORD2
pushBlock KEYWORD2
pushPixels KEYWORD2
readPixel KEYWORD2
tft_Read_8 KEYWORD2
begin_SDA_Read KEYWORD2
end_SDA_Read KEYWORD2
fillScreen KEYWORD2
drawRect KEYWORD2
drawRoundRect KEYWORD2
fillRoundRect KEYWORD2
setRotation KEYWORD2
invertDisplay KEYWORD2
drawCircle KEYWORD2
drawCircleHelper KEYWORD2
fillCircle KEYWORD2
@ -30,18 +37,40 @@ drawEllipse KEYWORD2
fillEllipse KEYWORD2
drawTriangle KEYWORD2
fillTriangle KEYWORD2
setSwapBytes KEYWORD2
getSwapBytes KEYWORD2
drawBitmap KEYWORD2
drawXBitmap KEYWORD2
setPivot KEYWORD2
getPivotX KEYWORD2
getPivotY KEYWORD2
readRect KEYWORD2
pushRect KEYWORD2
pushImage KEYWORD2
readRectRGB KEYWORD2
drawNumber KEYWORD2
drawFloat KEYWORD2
drawString KEYWORD2
drawCentreString KEYWORD2
drawRightString KEYWORD2
setCursor KEYWORD2
getCursorX KEYWORD2
getCursorY KEYWORD2
setTextColor KEYWORD2
setTextSize KEYWORD2
setTextFont KEYWORD2
setFreeFont KEYWORD2
setTextWrap KEYWORD2
setTextDatum KEYWORD2
getTextDatum KEYWORD2
setTextPadding KEYWORD2
getTextPadding KEYWORD2
setFreeFont KEYWORD2
setTextFont KEYWORD2
textWidth KEYWORD2
fontHeight KEYWORD2
decodeUTF8 KEYWORD2
write KEYWORD2
setCallback KEYWORD2
fontsLoaded KEYWORD2
spiwrite KEYWORD2
writecommand KEYWORD2
writedata KEYWORD2
@ -49,56 +78,51 @@ commandList KEYWORD2
readcommand8 KEYWORD2
readcommand16 KEYWORD2
readcommand32 KEYWORD2
readPixel KEYWORD2
readRect KEYWORD2
pushRect KEYWORD2
pushImage KEYWORD2
setSwapBytes KEYWORD2
getSwapBytes KEYWORD2
readRectRGB KEYWORD2
getRotation KEYWORD2
getTextDatum KEYWORD2
fontsLoaded KEYWORD2
color565 KEYWORD2
color16to8 KEYWORD2
color8to16 KEYWORD2
drawNumber KEYWORD2
drawFloat KEYWORD2
drawString KEYWORD2
drawCentreString KEYWORD2
drawRightString KEYWORD2
height KEYWORD2
width KEYWORD2
textWidth KEYWORD2
fontHeight KEYWORD2
getSetup KEYWORD2
setAttribute KEYWORD2
getAttribute KEYWORD2
color16to8 KEYWORD2
color16to24 KEYWORD2
color24to16 KEYWORD2
alphaBlend KEYWORD2
getSPIinstance KEYWORD2
pushBlock KEYWORD2
pushPixels KEYWORD2
alphaBlend24 KEYWORD2
initDMA KEYWORD2
deInitDMA KEYWORD2
pushImageDMA KEYWORD2
pushBlockDMA KEYWORD2
pushPixelsDMA KEYWORD2
dmaBusy KEYWORD2
dmaWait KEYWORD2
startWrite KEYWORD2
writeColor KEYWORD2
endWrite KEYWORD2
setAttribute KEYWORD2
getAttribute KEYWORD2
getSetup KEYWORD2
getSPIinstance KEYWORD2
# Touch functions
getTouchRaw KEYWORD2
convertRawXY KEYWORD2
getTouchRawZ KEYWORD2
convertRawXY KEYWORD2
getTouch KEYWORD2
calibrateTouch KEYWORD2
setTouch KEYWORD2
# Smooth font functions
loadFont KEYWORD2
unloadFont KEYWORD2
getUnicodeIndex KEYWORD2
showFont KEYWORD2
# Button class
TFT_eSPI_Button KEYWORD1
initButton KEYWORD2
textcolor KEYWORD2
initButtonUL KEYWORD2
setLabelDatum KEYWORD2
drawButton KEYWORD2
@ -109,31 +133,31 @@ justPressed KEYWORD2
justReleased KEYWORD2
# Sprite class
TFT_eSprite KEYWORD1
createSprite KEYWORD2
createPalette KEYWORD2
getPointer KEYWORD2
created KEYWORD2
deleteSprite KEYWORD2
frameBuffer KEYWORD2
setColorDepth KEYWORD2
getColorDepth KEYWORD2
deleteSprite KEYWORD2
createPalette KEYWORD2
setPaletteColor KEYWORD2
getPaletteColor KEYWORD2
setBitmapColor KEYWORD2
fillSprite KEYWORD2
setScrollRect KEYWORD2
scroll KEYWORD2
pushRotated KEYWORD2
pushRotatedHP KEYWORD2
rotatedBounds KEYWORD2
setPivot KEYWORD2
getPivotX KEYWORD2
getPivotY KEYWORD2
fillSprite KEYWORD2
pushBitmap KEYWORD2
pushSprite KEYWORD2
setScrollRect KEYWORD2
scroll KEYWORD2
printToSprite KEYWORD2
frameBuffer KEYWORD2
setBitmapColor KEYWORD2
showFont KEYWORD2
loadFont KEYWORD2
unloadFont KEYWORD2
getUnicodeIndex KEYWORD2
decodeUTF8 KEYWORD2
getRotatedBounds KEYWORD2
readPixelValue KEYWORD2
pushToSprite KEYWORD2
drawGlyph KEYWORD2
printToSprite KEYWORD2
pushSprite KEYWORD2

View File

@ -1,6 +1,6 @@
{
"name": "TFT_eSPI",
"version": "2.2.4",
"version": "2.2.23",
"keywords": "Arduino, tft, ePaper, display, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140",
"description": "A TFT and ePaper SPI graphics library with optimisation for ESP8266, ESP32 and STM32",
"repository":

View File

@ -1,5 +1,5 @@
name=TFT_eSPI
version=2.2.4
version=2.2.23
author=Bodmer
maintainer=Bodmer
sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32