commit
b221648823
File diff suppressed because it is too large
Load Diff
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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); \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
52
README.md
52
README.md
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
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"
|
||||
|
||||

|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
197
TFT_eSPI.cpp
197
TFT_eSPI.cpp
|
|
@ -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;
|
||||
|
|
|
|||
18
TFT_eSPI.h
18
TFT_eSPI.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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))
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
31
User_Setup.h
31
User_Setup.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// See SetupX_Template.h for all options available
|
||||
|
||||
#define ESP32_PARALLEL
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
|
||||
#define ILI9341_DRIVER
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
//====================================================================================
|
||||
|
|
@ -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);
|
||||
}
|
||||
//====================================================================================
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
//====================================================================================
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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");
|
||||
|
|
|
|||
152
keywords.txt
152
keywords.txt
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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":
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue