This commit is contained in:
topicchi
2024-09-24 16:54:39 +00:00
parent e3ca99e4db
commit c7a68c0205
332 changed files with 6098 additions and 4139 deletions

View File

@@ -8,50 +8,91 @@
// Select the SPI port to use, ESP32 has 2 options
#if !defined (TFT_PARALLEL_8_BIT)
#ifdef USE_HSPI_PORT
SPIClass spi = SPIClass(HSPI);
#else // use default VSPI port
//SPIClass& spi = SPI;
SPIClass spi = SPIClass(VSPI);
#ifdef CONFIG_IDF_TARGET_ESP32
#ifdef USE_HSPI_PORT
SPIClass spi = SPIClass(HSPI);
#elif defined(USE_FSPI_PORT)
SPIClass spi = SPIClass(FSPI);
#else // use default VSPI port
SPIClass spi = SPIClass(VSPI);
#endif
#else
#ifdef USE_HSPI_PORT
SPIClass spi = SPIClass(HSPI);
#elif defined(USE_FSPI_PORT)
SPIClass spi = SPIClass(FSPI);
#else // use FSPI port
SPIClass& spi = SPI;
#endif
#endif
#endif
#ifdef ESP32_DMA
// DMA SPA handle
spi_device_handle_t dmaHAL;
#ifdef USE_HSPI_PORT
spi_host_device_t spi_host = HSPI_HOST;
#ifdef CONFIG_IDF_TARGET_ESP32
#define DMA_CHANNEL 1
#ifdef USE_HSPI_PORT
spi_host_device_t spi_host = HSPI_HOST;
#elif defined(USE_FSPI_PORT)
spi_host_device_t spi_host = SPI_HOST;
#else // use VSPI port
spi_host_device_t spi_host = VSPI_HOST;
#endif
#else
spi_host_device_t spi_host = VSPI_HOST;
#ifdef USE_HSPI_PORT
#define DMA_CHANNEL SPI_DMA_CH_AUTO
spi_host_device_t spi_host = (spi_host_device_t) SPI3_HOST; // Draws once then freezes
#else // use FSPI port
#define DMA_CHANNEL SPI_DMA_CH_AUTO
spi_host_device_t spi_host = (spi_host_device_t) SPI2_HOST; // Draws once then freezes
#endif
#endif
#endif
#if !defined (TFT_PARALLEL_8_BIT)
// Volatile for register reads:
volatile uint32_t* _spi_cmd = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT));
volatile uint32_t* _spi_user = (volatile uint32_t*)(SPI_USER_REG(SPI_PORT));
// Register writes only:
volatile uint32_t* _spi_mosi_dlen = (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT));
volatile uint32_t* _spi_w = (volatile uint32_t*)(SPI_W0_REG(SPI_PORT));
#endif
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
** Function name: beginSDA
** Description: Detach SPI from pin to permit software SPI
** Function name: beginSDA - VSPI port only, FPSI port only for S2
** Description: Detach MOSI and attach MISO to SDA for reads
***************************************************************************************/
void TFT_eSPI::begin_SDA_Read(void)
{
pinMatrixOutDetach(TFT_MOSI, false, false);
pinMode(TFT_MOSI, INPUT);
pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false);
gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_INPUT);
#ifdef CONFIG_IDF_TARGET_ESP32
pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false);
#else // S2
pinMatrixInAttach(TFT_MOSI, FSPIQ_IN_IDX, false);
#endif
SET_BUS_READ_MODE;
}
/***************************************************************************************
** Function name: endSDA
** Description: Attach SPI pins after software SPI
** Function name: endSDA - VSPI port only, FPSI port only for S2
** Description: Attach MOSI to SDA and detach MISO for writes
***************************************************************************************/
void TFT_eSPI::end_SDA_Read(void)
{
pinMode(TFT_MOSI, OUTPUT);
pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false);
pinMode(TFT_MISO, INPUT);
pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false);
gpio_set_direction((gpio_num_t)TFT_MOSI, GPIO_MODE_OUTPUT);
#ifdef CONFIG_IDF_TARGET_ESP32
pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false);
#else // S2
pinMatrixOutAttach(TFT_MOSI, FSPID_OUT_IDX, false, false);
#endif
SET_BUS_WRITE_MODE;
}
////////////////////////////////////////////////////////////////////////////////////////
#endif // #if defined (TFT_SDA_READ)
////////////////////////////////////////////////////////////////////////////////////////
@@ -59,7 +100,7 @@ void TFT_eSPI::end_SDA_Read(void)
/***************************************************************************************
** Function name: read byte - supports class functions
** Description: Read a byte from ESP32 8 bit data port
** Description: Read a byte from ESP32 8-bit data port
***************************************************************************************/
// Parallel bus MUST be set to input before calling this function!
uint8_t TFT_eSPI::readByte(void)
@@ -98,17 +139,7 @@ uint8_t TFT_eSPI::readByte(void)
***************************************************************************************/
void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
{
gpioMode(TFT_D0, mode);
gpioMode(TFT_D1, mode);
gpioMode(TFT_D2, mode);
gpioMode(TFT_D3, mode);
gpioMode(TFT_D4, mode);
gpioMode(TFT_D5, mode);
gpioMode(TFT_D6, mode);
gpioMode(TFT_D7, mode);
return;
/*
// Arduino generic native function, but slower
// Arduino generic native function
pinMode(TFT_D0, mode);
pinMode(TFT_D1, mode);
pinMode(TFT_D2, mode);
@@ -117,7 +148,6 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
pinMode(TFT_D5, mode);
pinMode(TFT_D6, mode);
pinMode(TFT_D7, mode);
return; //*/
}
/***************************************************************************************
@@ -126,14 +156,8 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
***************************************************************************************/
void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode)
{
if(mode == INPUT) GPIO.enable_w1tc = ((uint32_t)1 << gpio);
else GPIO.enable_w1ts = ((uint32_t)1 << gpio);
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[gpio].reg) // Register lookup
= ((uint32_t)2 << FUN_DRV_S) // Set drive strength 2
| (FUN_IE) // Input enable
| ((uint32_t)2 << MCU_SEL_S); // Function select 2
GPIO.pin[gpio].val = 1; // Set pin HIGH
pinMode(gpio, mode);
digitalWrite(gpio, HIGH);
}
////////////////////////////////////////////////////////////////////////////////////////
#endif // #ifdef TFT_PARALLEL_8_BIT
@@ -173,54 +197,96 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
}
////////////////////////////////////////////////////////////////////////////////////////
#elif !defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most displays
#elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
** Function name: pushBlock - for ESP32
** Description: Write a block of pixels of the same colour
***************************************************************************************/
/*
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
bool empty = true;
volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w;
if (len > 31)
{
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
*_spi_mosi_dlen = 511;
spi_w[0] = color32;
spi_w[1] = color32;
spi_w[2] = color32;
spi_w[3] = color32;
spi_w[4] = color32;
spi_w[5] = color32;
spi_w[6] = color32;
spi_w[7] = color32;
spi_w[8] = color32;
spi_w[9] = color32;
spi_w[10] = color32;
spi_w[11] = color32;
spi_w[12] = color32;
spi_w[13] = color32;
spi_w[14] = color32;
spi_w[15] = color32;
while(len>31)
{
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32);
WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32);
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
while ((*_spi_cmd)&SPI_USR);
*_spi_cmd = SPI_USR;
len -= 32;
}
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
empty = false;
}
if (len)
{
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1);
for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG(SPI_W0_REG(SPI_PORT) + i, color32);
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
if(empty) {
for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32;
}
len = (len << 4) - 1;
while (*_spi_cmd&SPI_USR);
*_spi_mosi_dlen = len;
*_spi_cmd = SPI_USR;
}
while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
}
//*/
//*
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
volatile uint32_t* spi_w = _spi_w;
uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
uint32_t i = 0;
uint32_t rem = len & 0x1F;
len = len - rem;
// Start with partial buffer pixels
if (rem)
{
while (*_spi_cmd&SPI_USR);
for (i=0; i < rem; i+=2) *spi_w++ = color32;
*_spi_mosi_dlen = (rem << 4) - 1;
*_spi_cmd = SPI_USR;
if (!len) return; //{while (*_spi_cmd&SPI_USR); return; }
i = i>>1; while(i++<16) *spi_w++ = color32;
}
while (*_spi_cmd&SPI_USR);
if (!rem) while (i++<16) *spi_w++ = color32;
*_spi_mosi_dlen = 511;
// End with full buffer to maximise useful time for downstream code
while(len)
{
while (*_spi_cmd&SPI_USR);
*_spi_cmd = SPI_USR;
len -= 32;
}
// Do not wait here
//while (*_spi_cmd&SPI_USR);
}
//*/
/***************************************************************************************
** Function name: pushSwapBytePixels - for ESP32
** Description: Write a sequence of pixels with swapped bytes
@@ -242,7 +308,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
data+=4;
}
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]);
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]);
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]);
@@ -273,7 +339,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
}
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255);
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]);
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]);
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]);
@@ -349,7 +415,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
}
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER) && !defined (TFT_PARALLEL_8_BIT)// Now code for ILI9488
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -362,7 +428,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
uint32_t r = (color & 0xF800)>>8;
uint32_t g = (color & 0x07E0)<<5;
uint32_t b = (color & 0x001F)<<19;
// Concatenate 4 pixels into three 32 bit blocks
// Concatenate 4 pixels into three 32-bit blocks
uint32_t r0 = r<<24 | b | g | r;
uint32_t r1 = r0>>8 | g<<16;
uint32_t r2 = r1>>8 | b<<8;
@@ -446,7 +512,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
}
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8 bit parallel
#elif defined (TFT_PARALLEL_8_BIT) // Now the code for ESP32 8-bit parallel
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -454,10 +520,22 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
** Description: Write a block of pixels of the same colour
***************************************************************************************/
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
#if defined (SSD1963_DRIVER)
if ( ((color & 0xF800)>> 8) == ((color & 0x07E0)>> 3) && ((color & 0xF800)>> 8)== ((color & 0x001F)<< 3) )
#else
if ( (color >> 8) == (color & 0x00FF) )
#endif
{ if (!len) return;
tft_Write_16(color);
while (--len) {WR_L; WR_H; WR_L; WR_H;}
#if defined (SSD1963_DRIVER)
while (--len) {WR_L; WR_H; WR_L; WR_H; WR_L; WR_H;}
#else
#ifdef PSEUDO_16_BIT
while (--len) {WR_L; WR_H;}
#else
while (--len) {WR_L; WR_H; WR_L; WR_H;}
#endif
#endif
}
else while (len--) {tft_Write_16(color);}
}
@@ -489,7 +567,7 @@ 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
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -534,13 +612,14 @@ void TFT_eSPI::dmaWait(void)
/***************************************************************************************
** Function name: pushImageDMA
** Function name: pushPixelsDMA
** Description: Push pixels to TFT (len must be less than 32767)
***************************************************************************************/
// This will byte swap the original image if setSwapBytes(true) was called by sketch.
void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
{
if ((len == 0) || (!DMA_Enabled)) return;
dmaWait();
if(_swapBytes) {
@@ -564,6 +643,38 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
}
/***************************************************************************************
** Function name: pushImageDMA
** Description: Push image to a window (w*h must be less than 65536)
***************************************************************************************/
// Fixed const data assumed, will NOT clip or swap bytes
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* image)
{
if ((w == 0) || (h == 0) || (!DMA_Enabled)) return;
uint32_t len = w*h;
dmaWait();
setAddrWindow(x, y, w, h);
esp_err_t ret;
static spi_transaction_t trans;
memset(&trans, 0, sizeof(spi_transaction_t));
trans.user = (void *)1;
trans.tx_buffer = image; //Data pointer
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++;
}
/***************************************************************************************
** Function name: pushImageDMA
** Description: Push image to a window (w*h must be less than 65536)
@@ -571,24 +682,27 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
// This will clip and also swap bytes if setSwapBytes(true) was called by sketch
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer)
{
if ((x >= _width) || (y >= _height) || (!DMA_Enabled)) return;
if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return;
int32_t dx = 0;
int32_t dy = 0;
int32_t dw = w;
int32_t dh = h;
if (x < 0) { dw += x; dx = -x; x = 0; }
if (y < 0) { dh += y; dy = -y; y = 0; }
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
if ((x + dw) > _width ) dw = _width - x;
if ((y + dh) > _height) dh = _height - y;
if ((x + dw) > _vpW ) dw = _vpW - x;
if ((y + dh) > _vpH ) dh = _vpH - y;
if (dw < 1 || dh < 1) return;
uint32_t len = dw*dh;
if (buffer == nullptr) { buffer = image; dmaWait(); }
if (buffer == nullptr) {
buffer = image;
dmaWait();
}
// If image is clipped, copy pixels into a contiguous block
if ( (dw != w) || (dh != h) ) {
@@ -616,7 +730,7 @@ 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
if (spiBusyCheck) dmaWait(); // In case we did not wait earlier
setAddrWindow(x, y, dw, dh);
@@ -649,15 +763,26 @@ 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;}
}
/***************************************************************************************
** Function name: dma_end_callback
** Description: Clear DMA run flag to stop retransmission loop
***************************************************************************************/
extern "C" void dma_end_callback();
void IRAM_ATTR dma_end_callback(spi_transaction_t *spi_tx)
{
WRITE_PERI_REG(SPI_DMA_CONF_REG(spi_host), 0);
}
/***************************************************************************************
** Function name: initDMA
** Description: Initialise the DMA engine - returns true if init OK
***************************************************************************************/
bool TFT_eSPI::initDMA(void)
bool TFT_eSPI::initDMA(bool ctrl_cs)
{
if (DMA_Enabled) return false;
@@ -668,10 +793,20 @@ bool TFT_eSPI::initDMA(void)
.sclk_io_num = TFT_SCLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
#ifdef xCONFIG_IDF_TARGET_ESP32S2
.data4_io_num = -1,
.data5_io_num = -1,
.data6_io_num = -1,
.data7_io_num = -1,
#endif
.max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8, // TFT screen size
.flags = 0,
.intr_flags = 0
};
int8_t pin = -1;
if (ctrl_cs) pin = TFT_CS;
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
@@ -682,13 +817,17 @@ bool TFT_eSPI::initDMA(void)
.cs_ena_posttrans = 0,
.clock_speed_hz = SPI_FREQUENCY,
.input_delay_ns = 0,
.spics_io_num = TFT_CS,
.flags = 0,
.queue_size = 7,
.pre_cb = dc_callback, //Callback to handle D/C line
.post_cb = 0
.spics_io_num = pin,
.flags = SPI_DEVICE_NO_DUMMY, //0,
.queue_size = 1,
.pre_cb = 0, //dc_callback, //Callback to handle D/C line
#ifdef CONFIG_IDF_TARGET_ESP32
.post_cb = 0
#else
.post_cb = dma_end_callback
#endif
};
ret = spi_bus_initialize(spi_host, &buscfg, 1);
ret = spi_bus_initialize(spi_host, &buscfg, DMA_CHANNEL);
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device(spi_host, &devcfg, &dmaHAL);
ESP_ERROR_CHECK(ret);
@@ -711,5 +850,5 @@ void TFT_eSPI::deInitDMA(void)
}
////////////////////////////////////////////////////////////////////////////////////////
#endif // End of DMA FUNCTIONS
#endif // End of DMA FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -11,21 +11,71 @@
// Include processor specific header
#include "soc/spi_reg.h"
#include "driver/spi_master.h"
#include "hal/gpio_ll.h"
// Processor specific code used by SPI bus transaction startWrite and endWrite functions
#define SET_BUS_WRITE_MODE // Not used
#define SET_BUS_READ_MODE // Not used
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32)
#define CONFIG_IDF_TARGET_ESP32
#endif
// Fix IDF problems with ESP32C3
#if CONFIG_IDF_TARGET_ESP32C3
// Fix ESP32C3 IDF bug for missing definition
#ifndef REG_SPI_BASE
#define REG_SPI_BASE(i) (DR_REG_SPI1_BASE + (((i)>1) ? (((i)* 0x1000) + 0x20000) : (((~(i)) & 1)* 0x1000 )))
#endif
// Fix ESP32C3 IDF bug for name change
#ifndef SPI_MOSI_DLEN_REG
#define SPI_MOSI_DLEN_REG(x) SPI_MS_DLEN_REG(x)
#endif
// Fix ESP32C3 specific register reference
#define out_w1tc out_w1tc.val
#define out_w1ts out_w1ts.val
#endif
// SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled
#if !defined (SUPPORT_TRANSACTIONS)
#define SUPPORT_TRANSACTIONS
#endif
/*
ESP32:
FSPI not defined
HSPI = 2, uses SPI2
VSPI = 3, uses SPI3
ESP32-S2:
FSPI = 1, uses SPI2
HSPI = 2, uses SPI3
VSPI not defined
ESP32 C3:
FSPI = 0, uses SPI2 ???? To be checked
HSPI = 1, uses SPI3 ???? To be checked
VSPI not defined
For ESP32/S2/C3:
SPI1_HOST = 0
SPI2_HOST = 1
SPI3_HOST = 2
*/
// ESP32 specific SPI port selection
#ifdef USE_HSPI_PORT
#define SPI_PORT HSPI
#ifdef CONFIG_IDF_TARGET_ESP32
#define SPI_PORT HSPI //HSPI is port 2 on ESP32
#else
#define SPI_PORT 3 //HSPI is port 3 on ESP32 S2
#endif
#elif defined(USE_FSPI_PORT)
#define SPI_PORT 2 //FSPI(ESP32 S2)
#else
#define SPI_PORT VSPI
#ifdef CONFIG_IDF_TARGET_ESP32
#define SPI_PORT VSPI
#else
#define SPI_PORT 2 //FSPI(ESP32 S2)
#endif
#endif
#ifdef RPI_DISPLAY_TYPE
@@ -37,22 +87,37 @@
// Initialise processor specific SPI functions, used by init()
#define INIT_TFT_DATA_BUS // Not used
// Define a generic flag for 8 bit parallel
// Define a generic flag for 8-bit parallel
#if defined (ESP32_PARALLEL) // Specific to ESP32 for backwards compatibility
#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
// 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
// Processor specific code used by SPI bus transaction startWrite and endWrite functions
#if !defined (ESP32_PARALLEL)
#if (TFT_SPI_MODE == SPI_MODE1) || (TFT_SPI_MODE == SPI_MODE2)
#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI | SPI_CK_OUT_EDGE
#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN | SPI_CK_OUT_EDGE
#else
#define SET_BUS_WRITE_MODE *_spi_user = SPI_USR_MOSI
#define SET_BUS_READ_MODE *_spi_user = SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN
#endif
#else
// Not applicable to parallel bus
#define SET_BUS_WRITE_MODE
#define SET_BUS_READ_MODE
#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)
#if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER)
#define ESP32_DMA
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
#define DMA_BUSY_CHECK dmaWait()
@@ -60,6 +125,12 @@
#define DMA_BUSY_CHECK
#endif
#if defined(TFT_PARALLEL_8_BIT)
#define SPI_BUSY_CHECK
#else
#define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR)
#endif
// If smooth font is used then it is likely SPIFFS will be needed
#ifdef SMOOTH_FONT
// Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
@@ -69,6 +140,7 @@
#define FONT_FS_AVAILABLE
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the DC (TFT Data/Command or Register Select (RS))pin drive code
////////////////////////////////////////////////////////////////////////////////////////
@@ -77,10 +149,19 @@
#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)
#elif (TFT_DC >= 32)
#define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC- 32))
#define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC- 32))
#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))
@@ -90,16 +171,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)
@@ -115,8 +200,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
@@ -130,8 +216,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)); \
@@ -140,12 +226,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
@@ -158,9 +244,22 @@
////////////////////////////////////////////////////////////////////////////////////////
// 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 >= 32)
// Note: it will be ~1.25x faster if the TFT_WR pin uses a GPIO pin lower than 32
#define WR_L GPIO.out1_w1tc.val = (1 << (TFT_WR - 32))
#define WR_H GPIO.out1_w1ts.val = (1 << (TFT_WR - 32))
#elif (TFT_WR >= 0)
// TFT_WR, for best performance, should 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
////////////////////////////////////////////////////////////////////////////////////////
@@ -182,11 +281,7 @@
#ifdef USE_HSPI_PORT
#ifndef TFT_MISO
#define TFT_MISO 12
#endif
#if (TFT_MISO == -1)
#undef TFT_MISO
#define TFT_MISO 12
#define TFT_MISO -1
#endif
#ifndef TFT_MOSI
@@ -208,11 +303,7 @@
#else // VSPI port
#ifndef TFT_MISO
#define TFT_MISO 19
#endif
#if (TFT_MISO == -1)
#undef TFT_MISO
#define TFT_MISO 19
#define TFT_MISO -1
#endif
#ifndef TFT_MOSI
@@ -231,6 +322,13 @@
#define TFT_SCLK 18
#endif
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2)
#if (TFT_MISO == -1)
#undef TFT_MISO
#define TFT_MISO TFT_MOSI
#endif
#endif
#endif
#endif
@@ -242,7 +340,7 @@
// Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically
// can then use e.g. GPIO.out_w1ts = set_mask(0xFF); to set data bus to 0xFF
#define CONSTRUCTOR_INIT_TFT_DATA_BUS \
#define PARALLEL_INIT_TFT_DATA_BUS \
for (int32_t c = 0; c<256; c++) \
{ \
xset_mask[c] = 0; \
@@ -257,10 +355,17 @@
} \
// Mask for the 8 data bits to set pin directions
#define dir_mask ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7))
#define GPIO_DIR_MASK ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7))
// Data bits and the write line are cleared to 0 in one step
#define clr_mask (dir_mask | (1 << TFT_WR))
#if (TFT_WR >= 32)
// Data bits and the write line are cleared sequentially
#define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK); WR_L
#elif (TFT_WR >= 0)
// Data bits and the write line are cleared to 0 in one step (1.25x faster)
#define GPIO_OUT_CLR_MASK (GPIO_DIR_MASK | (1 << TFT_WR))
#else
#define GPIO_OUT_CLR_MASK
#endif
// A lookup table is used to set the different bit patterns, this uses 1kByte of RAM
#define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time
@@ -271,56 +376,91 @@
//*/
// 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
#define tft_Write_8(C) GPIO.out_w1tc = GPIO_OUT_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 = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0xF800)>> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) (((C) & 0x07E0)>> 3)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_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) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
#ifdef PSEUDO_16_BIT
// One write strobe for both bytes
#define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H
#define tft_Write_16S(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_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 = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H
#endif
#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; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \
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
#define tft_Write_32(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 24)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 16)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H
// Write two concatenated 16 bit values to TFT
#define tft_Write_32C(C,D) 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; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \
GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H
// Write two concatenated 16-bit values to TFT
#define tft_Write_32C(C,D) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((D) >> 0)); WR_H
// Write 16 bit value twice to TFT - used by drawPixel()
#define tft_Write_32D(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; \
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
// Write 16-bit value twice to TFT - used by drawPixel()
#define tft_Write_32D(C) GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 8)); WR_H; \
GPIO.out_w1tc = GPIO_OUT_CLR_MASK; GPIO.out_w1ts = set_mask((uint8_t) ((C) >> 0)); WR_H
// 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
#else
#define TFT_RD -1
#define RD_L
#define RD_H
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to an ILI9488 TFT
// Macros to write commands/pixel colour data to a SPI ILI948x TFT
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
// Write 8 bits to TFT
#define tft_Write_8(C) spi.transfer(C)
// Convert 16 bit colour to 18 bit and write in 3 bytes
// Convert 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \
spi.transfer(((C) & 0x07E0)>>3); \
spi.transfer(((C) & 0x001F)<<3)
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
// Future option for transfer without wait
#define tft_Write_16N(C) tft_Write_16(C)
// Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
spi.transfer(((C) & 0x1F00)>>5)
@@ -328,10 +468,10 @@
// Write 32 bits to TFT
#define tft_Write_32(C) spi.write32(C)
// Write two concatenated 16 bit values to TFT
// Write two concatenated 16-bit values to TFT
#define tft_Write_32C(C,D) spi.write32((C)<<16 | (D))
// Write 16 bit value twice to TFT
// Write 16-bit value twice to TFT
#define tft_Write_32D(C) spi.write32((C)<<16 | (C))
////////////////////////////////////////////////////////////////////////////////////////
@@ -339,7 +479,7 @@
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (RPI_DISPLAY_TYPE)
// ESP32 low level SPI writes for 8, 16 and 32 bit values
// ESP32 low level SPI writes for 8, 16 and 32-bit values
// to avoid the function call overhead
#define TFT_WRITE_BITS(D, B) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \
@@ -350,9 +490,12 @@
// Write 8 bits
#define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16)
// Write 16 bits with corrected endianess for 16 bit colours
// Write 16 bits with corrected endianness for 16-bit colours
#define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
// Future option for transfer without wait
#define tft_Write_16N(C) tft_Write_16(C)
// Write 16 bits
#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
@@ -370,8 +513,8 @@
// Macros for all other SPI displays
////////////////////////////////////////////////////////////////////////////////////////
#else
// ESP32 low level SPI writes for 8, 16 and 32 bit values
/* Old macros
// ESP32 low level SPI writes for 8, 16 and 32-bit values
// to avoid the function call overhead
#define TFT_WRITE_BITS(D, B) \
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \
@@ -382,7 +525,7 @@
// Write 8 bits
#define tft_Write_8(C) TFT_WRITE_BITS(C, 8)
// Write 16 bits with corrected endianess for 16 bit colours
// Write 16 bits with corrected endianness for 16-bit colours
#define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
// Write 16 bits
@@ -391,12 +534,46 @@
// Write 32 bits
#define tft_Write_32(C) TFT_WRITE_BITS(C, 32)
// Write two address coordinates
#define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
// Write same value twice
#define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
//*/
//* Replacement slimmer macros
#define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \
*_spi_w = D; \
*_spi_cmd = SPI_USR; \
while (*_spi_cmd & SPI_USR);
// Write 8 bits
#define tft_Write_8(C) TFT_WRITE_BITS(C, 8)
// Write 16 bits with corrected endianness for 16-bit colours
#define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
// Future option for transfer without wait
#define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \
*_spi_w = ((C)<<8 | (C)>>8); \
*_spi_cmd = SPI_USR;
// Write 16 bits
#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
// Write 32 bits
#define tft_Write_32(C) TFT_WRITE_BITS(C, 32)
// Write two address coordinates
#define tft_Write_32C(C,D) TFT_WRITE_BITS((uint16_t)((D)<<8 | (D)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
// Write same value twice
#define tft_Write_32D(C) TFT_WRITE_BITS((uint16_t)((C)<<8 | (C)>>8)<<16 | (uint16_t)((C)<<8 | (C)>>8), 32)
//*/
#endif
#ifndef tft_Write_16N
#define tft_Write_16N tft_Write_16
#endif
////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -109,7 +109,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
}
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER)
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -122,7 +122,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
uint8_t r = (color & 0xF800)>>8;
uint8_t g = (color & 0x07E0)>>3;
uint8_t b = (color & 0x001F)<<3;
// Concatenate 4 pixels into three 32 bit blocks
// Concatenate 4 pixels into three 32-bit blocks
uint32_t r0 = r<<24 | b<<16 | g<<8 | r;
uint32_t r1 = g<<24 | r<<16 | b<<8 | g;
uint32_t r2 = b<<24 | g<<16 | r<<8 | 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) {}

View File

@@ -19,7 +19,7 @@
#define DMA_BUSY_CHECK // DMA not available, leave blank
// Initialise processor specific SPI functions, used by init()
#if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266)
#if (!defined (SUPPORT_TRANSACTIONS) && defined (ARDUINO_ARCH_ESP8266))
#define INIT_TFT_DATA_BUS \
spi.setBitOrder(MSBFIRST); \
spi.setDataMode(TFT_SPI_MODE); \
@@ -115,19 +115,19 @@
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to an ILI9488 TFT
// Macros to write commands/pixel colour data to a SPI ILI948x TFT
////////////////////////////////////////////////////////////////////////////////////////
#if defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
#if defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
// Write 8 bits to TFT
#define tft_Write_8(C) spi.transfer(C)
// Convert 16 bit colour to 18 bit and write in 3 bytes
// Convert 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \
spi.transfer(((C) & 0x07E0)>>3); \
spi.transfer(((C) & 0x001F)<<3)
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
// Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
spi.transfer(((C) & 0x1F00)>>5)
@@ -148,7 +148,7 @@
// Command is 16 bits
#define CMD_BITS 16
// ESP8266 low level SPI writes for 8, 16 and 32 bit values
// ESP8266 low level SPI writes for 8, 16 and 32-bit values
// to avoid the function call overhead
#define TFT_WRITE_BITS(D, B) \
SPI1U1 = ((B-1) << SPILMOSI); \
@@ -191,6 +191,11 @@
SPI1CMD |= SPIBUSY; \
while(SPI1CMD & SPIBUSY) {;}
#define tft_Write_16N(C) \
SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \
SPI1W0 = ((C)<<8 | (C)>>8); \
SPI1CMD |= SPIBUSY
#define tft_Write_16S(C) \
SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \
SPI1W0 = C; \
@@ -217,6 +222,10 @@
#endif
#ifndef tft_Write_16N
#define tft_Write_16N tft_Write_16
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to read from display using SPI or software SPI
////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -7,7 +7,11 @@
////////////////////////////////////////////////////////////////////////////////////////
// Select the SPI port to use
SPIClass& spi = SPI;
#ifdef TFT_SPI_PORT
SPIClass& spi = TFT_SPI_PORT;
#else
SPIClass& spi = SPI;
#endif
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
@@ -168,7 +172,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
}
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER) // For 24 bit SPI colour TFT
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -212,7 +216,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
}
////////////////////////////////////////////////////////////////////////////////////////
#else // Standard SPI 16 bit colour TFT
#else // Standard SPI 16-bit colour TFT
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************

View File

@@ -3,7 +3,7 @@
////////////////////////////////////////////////////
// This is a generic driver for Arduino boards, it supports SPI interface displays
// 8 bit parallel interface to TFT is not supported for generic processors
// 8-bit parallel interface to TFT is not supported for generic processors
#ifndef _TFT_eSPI_GENERICH_
#define _TFT_eSPI_GENERICH_
@@ -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
////////////////////////////////////////////////////////////////////////////////////////
@@ -85,19 +92,19 @@
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to an ILI9488 TFT
// Macros to write commands/pixel colour data to a SPI ILI948x TFT
////////////////////////////////////////////////////////////////////////////////////////
#if defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
#if defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
// Write 8 bits to TFT
#define tft_Write_8(C) spi.transfer(C)
// Convert 16 bit colour to 18 bit and write in 3 bytes
// Convert 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16(C) spi.transfer(((C) & 0xF800)>>8); \
spi.transfer(((C) & 0x07E0)>>3); \
spi.transfer(((C) & 0x001F)<<3)
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
// Convert swapped byte 16-bit colour to 18-bit and write in 3 bytes
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
spi.transfer(((C) & 0x1F00)>>5)
@@ -114,10 +121,29 @@
// Macros to write commands/pixel colour data to other displays
////////////////////////////////////////////////////////////////////////////////////////
#else
#if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers
#define tft_Write_8(C) spi.transfer(0); spi.transfer(C)
#if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16-bit transfers
#define tft_Write_8(C) spi.transfer(C); spi.transfer(C)
#define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
#define tft_Write_16S(C) spi.transfer((uint8_t)((C)>>0));spi.transfer((uint8_t)((C)>>8))
#define tft_Write_32(C) \
tft_Write_16((uint16_t) ((C)>>16)); \
tft_Write_16((uint16_t) ((C)>>0))
#define tft_Write_32C(C,D) \
spi.transfer(0); spi.transfer((C)>>8); \
spi.transfer(0); spi.transfer((C)>>0); \
spi.transfer(0); spi.transfer((D)>>8); \
spi.transfer(0); spi.transfer((D)>>0)
#define tft_Write_32D(C) \
spi.transfer(0); spi.transfer((C)>>8); \
spi.transfer(0); spi.transfer((C)>>0); \
spi.transfer(0); spi.transfer((C)>>8); \
spi.transfer(0); spi.transfer((C)>>0)
#else
#ifdef __AVR__ // AVR processors do not have 16 bit transfer
#ifdef __AVR__ // AVR processors do not have 16-bit transfer
#define tft_Write_8(C) {SPDR=(C); while (!(SPSR&_BV(SPIF)));}
#define tft_Write_16(C) tft_Write_8((uint8_t)((C)>>8));tft_Write_8((uint8_t)((C)>>0))
#define tft_Write_16S(C) tft_Write_8((uint8_t)((C)>>0));tft_Write_8((uint8_t)((C)>>8))
@@ -126,19 +152,23 @@
#define tft_Write_16(C) spi.transfer16(C)
#define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8))
#endif // AVR
#define tft_Write_32(C) \
tft_Write_16((uint16_t) ((C)>>16)); \
tft_Write_16((uint16_t) ((C)>>0))
#define tft_Write_32C(C,D) \
tft_Write_16((uint16_t) (C)); \
tft_Write_16((uint16_t) (D))
#define tft_Write_32D(C) \
tft_Write_16((uint16_t) (C)); \
tft_Write_16((uint16_t) (C))
#endif // RPI_DISPLAY_TYPE
#endif
#define tft_Write_32(C) \
tft_Write_16((uint16_t) ((C)>>16)); \
tft_Write_16((uint16_t) ((C)>>0))
#define tft_Write_32C(C,D) \
tft_Write_16((uint16_t) (C)); \
tft_Write_16((uint16_t) (D))
#define tft_Write_32D(C) \
tft_Write_16((uint16_t) (C)); \
tft_Write_16((uint16_t) (C))
#ifndef tft_Write_16N
#define tft_Write_16N tft_Write_16
#endif
////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -24,9 +24,6 @@
DMA_HandleTypeDef dmaHal;
#endif
// Buffer for SPI transmit byte padding and byte order manipulation
uint8_t spiBuffer[8];
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
////////////////////////////////////////////////////////////////////////////////////////
@@ -76,7 +73,7 @@ void TFT_eSPI::end_SDA_Read(void)
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_PARALLEL_8_BIT) // Code for STM32 8 bit parallel
#if defined (TFT_PARALLEL_8_BIT) // Code for STM32 8-bit parallel
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -84,24 +81,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 dramatically 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);}
}
@@ -131,7 +146,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;
@@ -139,7 +154,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;
@@ -147,6 +162,22 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
if (mode == OUTPUT) GPIOB->MODER = (GPIOB->MODER & 0xFFFF0000) | 0x00005555;
else GPIOB->MODER &= 0xFFFF0000;
#endif
#elif defined (STM_PORTC_DATA_BUS)
#if defined (STM32F1xx)
if (mode == OUTPUT) GPIOC->CRL = 0x33333333;
else GPIOC->CRL = 0x88888888;
#else
if (mode == OUTPUT) GPIOC->MODER = (GPIOC->MODER & 0xFFFF0000) | 0x00005555;
else GPIOC->MODER &= 0xFFFF0000;
#endif
#elif defined (STM_PORTD_DATA_BUS)
#if defined (STM32F1xx)
if (mode == OUTPUT) GPIOD->CRL = 0x33333333;
else GPIOD->CRL = 0x88888888;
#else
if (mode == OUTPUT) GPIOD->MODER = (GPIOD->MODER & 0xFFFF0000) | 0x00005555;
else GPIOD->MODER &= 0xFFFF0000;
#endif
#else
if (mode == OUTPUT) {
LL_GPIO_SetPinMode(D0_PIN_PORT, D0_PIN_MASK, LL_GPIO_MODE_OUTPUT);
@@ -194,16 +225,26 @@ 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;
b = (GPIOB->IDR) & 0xFF;
#elif defined (STM_PORTC_DATA_BUS)
b = GPIOC->IDR;
b = GPIOC->IDR;
b = GPIOC->IDR;
b = (GPIOC->IDR) & 0xFF;
#elif defined (STM_PORTD_DATA_BUS)
b = GPIOD->IDR;
b = GPIOD->IDR;
b = GPIOD->IDR;
b = (GPIOD->IDR) & 0xFF;
#else
b = RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0 | RD_TFT_D0; //Delay for bits to settle
@@ -242,7 +283,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
}
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER) // For 24 bit colour TFT ############# UNTESTED ###################
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -252,34 +293,19 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
#define BUF_SIZE 240*3
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
{
uint8_t col[BUF_SIZE];
//uint8_t col[BUF_SIZE];
// Always using swapped bytes is a peculiarity of this function...
//color = color>>8 | color<<8;
uint8_t r = (color & 0xF800)>>8; // Red
uint8_t g = (color & 0x07E0)>>3; // Green
uint8_t b = (color & 0x001F)<<3; // Blue
if (len<BUF_SIZE/3) {
for (uint32_t i = 0; i < len*3; i++) {
col[i] = r;
col[++i] = g;
col[++i] = b;
}
HAL_SPI_Transmit(&spiHal, col, len*3, HAL_MAX_DELAY);
return;
while(len--) {
TX_FIFO = (r);
TX_FIFO = (g);
TX_FIFO = (b);
}
for (uint32_t i = 0; i < BUF_SIZE; i++) {
col[i] = r;
col[++i] = g;
col[++i] = b;
}
do {
HAL_SPI_Transmit(&spiHal, col, BUF_SIZE, HAL_MAX_DELAY);
len -= BUF_SIZE/3;
} while ( len>=BUF_SIZE/3 ) ;
// Send remaining pixels
if (len) HAL_SPI_Transmit(&spiHal, col, len*3, HAL_MAX_DELAY); //*/
SPI_BUSY_CHECK;
}
/***************************************************************************************
** Function name: pushPixels - for STM32 and 3 byte RGB display
@@ -289,30 +315,29 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
{
uint16_t *data = (uint16_t*)data_in;
if(_swapBytes) {
if(!_swapBytes) {
while ( len-- ) {
// Split out the colours
spiBuffer[0] = (*data & 0xF8); // Red
spiBuffer[1] = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green
spiBuffer[2] = (*data & 0x1F00)>>5; // Blue
TX_FIFO = (*data & 0xF8); // Red
TX_FIFO = (*data & 0xE000)>>11 | (*data & 0x07)<<5; // Green
TX_FIFO = (*data & 0x1F00)>>5; // Blue
data++;
HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY);
}
}
else {
while ( len-- ) {
// Split out the colours
spiBuffer[0] = (*data & 0xF800)>>8; // Red
spiBuffer[1] = (*data & 0x07E0)>>3; // Green
spiBuffer[2] = (*data & 0x001F)<<3; // Blue
TX_FIFO = (*data & 0xF800)>>8; // Red
TX_FIFO = (*data & 0x07E0)>>3; // Green
TX_FIFO = (*data & 0x001F)<<3; // Blue
data++;
HAL_SPI_Transmit(&spiHal, spiBuffer, 3, HAL_MAX_DELAY);
}
}
SPI_BUSY_CHECK;
}
////////////////////////////////////////////////////////////////////////////////////////
#else // Standard SPI 16 bit colour TFT All Tested
#else // Standard SPI 16-bit colour TFT All Tested
////////////////////////////////////////////////////////////////////////////////////////
/***************************************************************************************
@@ -320,6 +345,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
** Description: Write a block of pixels of the same colour
***************************************************************************************/
#define BUF_SIZE 480
/*
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
{
uint16_t col[BUF_SIZE];
@@ -337,7 +363,47 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
len -= BUF_SIZE;
} while ( len>=BUF_SIZE ) ;
// Send remaining pixels
if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY); //*/
if (len) HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY);
}
//*/
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
// Loop unrolling improves speed dramatically 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);}
}
@@ -348,26 +414,23 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
{
uint16_t *data = (uint16_t*)data_in;
if(_swapBytes) {
uint16_t col[BUF_SIZE]; // Buffer for swapped bytes
while ( len>=BUF_SIZE ) {
for (uint32_t i = 0; i < BUF_SIZE; i++) { col[i] = (*data>>8) | (*data<<8); data++; }
HAL_SPI_Transmit(&spiHal, (uint8_t*)col, BUF_SIZE<<1, HAL_MAX_DELAY);
len -= BUF_SIZE;
while ( len-- ) {
TX_FIFO = (uint8_t)(*data>>8);
TX_FIFO = (uint8_t)(*data);
data++;
}
for (uint32_t i = 0; i < len; i++) { col[i] = (*data>>8) | (*data<<8); data++; }
HAL_SPI_Transmit(&spiHal, (uint8_t*)col, len<<1, HAL_MAX_DELAY);
}
else {
// HAL byte count for transmit is only 16 bits maximum so to avoid this constraint
// transfers of small blocks are performed until HAL capacity is reached.
while(len>0x7FFF) { // Transfer 16 bit pixels in blocks if len*2 over 65534 bytes
HAL_SPI_Transmit(&spiHal, (uint8_t*)data, 0x800<<1, HAL_MAX_DELAY);
len -= 0x800; data+= 0x800; // Arbitrarily use 2KByte blocks
while ( len-- ) {
// Split out the colours
TX_FIFO = (uint8_t)(*data);
TX_FIFO = (uint8_t)(*data>>8);
data++;
}
// Send remaining pixels (max 65534 bytes)
HAL_SPI_Transmit(&spiHal, (uint8_t*)data, len<<1, HAL_MAX_DELAY);
}
SPI_BUSY_CHECK;
}
////////////////////////////////////////////////////////////////////////////////////////
@@ -383,8 +446,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
** Function name: dmaBusy
** Description: Check if DMA is busy (usefully non-blocking!)
***************************************************************************************/
// Use "while(tft.dmaBusy());" in sketch for a blocking wait for DMA to complete
// or "while( tft.dmaBusy() ) {Do-something-useful;}"
// Use while( tft.dmaBusy() ) {Do-something-useful;}"
bool TFT_eSPI::dmaBusy(void)
{
//return (dmaHal.State == HAL_DMA_STATE_BUSY); // Do not use, SPI may still be busy
@@ -393,7 +455,18 @@ bool TFT_eSPI::dmaBusy(void)
/***************************************************************************************
** Function name: pushImageDMA
** Function name: dmaWait
** Description: Wait until DMA is over (blocking!)
***************************************************************************************/
void TFT_eSPI::dmaWait(void)
{
//return (dmaHal.State == HAL_DMA_STATE_BUSY); // Do not use, SPI may still be busy
while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
}
/***************************************************************************************
** Function name: pushPixelsDMA
** Description: Push pixels to TFT (len must be less than 32767)
***************************************************************************************/
// This will byte swap the original image if setSwapBytes(true) was called by sketch.
@@ -419,26 +492,27 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
// This will clip and also swap bytes if setSwapBytes(true) was called by sketch
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer)
{
if ((x >= _width) || (y >= _height)) return;
if ((x >= _vpW) || (y >= _vpH)) return;
int32_t dx = 0;
int32_t dy = 0;
int32_t dw = w;
int32_t dh = h;
if (x < 0) { dw += x; dx = -x; x = 0; }
if (y < 0) { dh += y; dy = -y; y = 0; }
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
if ((x + dw) > _width ) dw = _width - x;
if ((y + dh) > _height) dh = _height - y;
if ((x + dw) > _vpW ) dw = _vpW - x;
if ((y + dh) > _vpH ) dh = _vpH - y;
if (dw < 1 || dh < 1) return;
if (buffer == nullptr) buffer = image;
uint32_t len = dw*dh;
while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
if (buffer == nullptr) {
buffer = image;
while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy
}
// If image is clipped, copy pixels into a contiguous block
if ( (dw != w) || (dh != h) ) {
@@ -472,7 +546,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
// small transfers are performed using a blocking call until DMA capacity is reached.
// User sketch can prevent blocking by managing pixel count and splitting into blocks
// of 32767 pixels maximum. (equivalent to an area of ~320 x 100 pixels)
while(len>0x7FFF) { // Transfer 16 bit pixels in blocks if len*2 over 65534 bytes
while(len>0x7FFF) { // Transfer 16-bit pixels in blocks if len*2 over 65534 bytes
HAL_SPI_Transmit(&spiHal, (uint8_t*)buffer, 0x800<<1, HAL_MAX_DELAY);
len -= 0x800; buffer+= 0x800; // Arbitrarily send 1K pixel blocks (2Kbytes)
}
@@ -496,6 +570,9 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
#elif (TFT_SPI_PORT == 2)
extern "C" void DMA1_Stream4_IRQHandler();
void DMA1_Stream4_IRQHandler(void)
#elif (TFT_SPI_PORT == 3)
extern "C" void DMA1_Stream5_IRQHandler();
void DMA1_Stream5_IRQHandler(void)
#endif
{
// Call the default end of buffer handler
@@ -509,14 +586,20 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
// This initialisation is for STM32F2xx/4xx/7xx processors and may not work on others
// Dual core H7xx series not supported yet, they are different and have a DMA MUX:
// https://electronics.stackexchange.com/questions/379813/configuring-the-dma-request-multiplexer-on-a-stm32h7-mcu
bool TFT_eSPI::initDMA(void)
bool TFT_eSPI::initDMA(bool ctrl_cs)
{
ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning
#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
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock
dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI2 TX
#elif (TFT_SPI_PORT == 3)
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock
dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI3 TX
#endif
dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once
@@ -534,6 +617,8 @@ bool TFT_eSPI::initDMA(void)
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
#elif (TFT_SPI_PORT == 3)
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
#endif
__HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral
@@ -563,8 +648,10 @@ bool TFT_eSPI::initDMA(void)
** Function name: initDMA
** Description: Initialise the DMA engine - returns true if init OK
***************************************************************************************/
bool TFT_eSPI::initDMA(void)
bool TFT_eSPI::initDMA(bool ctrl_cs)
{
ctrl_cs = ctrl_cs; // Not used for STM32, so stop compiler warning
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock
dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once

View File

@@ -45,7 +45,7 @@
////////////////////////////////////////////////////////////////////////////////////////
// Write strobe timing setup
////////////////////////////////////////////////////////////////////////////////////////
#if defined (ILI9341_DRIVER) || defined (ST7796_DRIVER) || defined (ILI9486_DRIVER) // WRX twc spec is <=66ns = 15.15MHz
#if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ST7796_DRIVER) || defined (ILI9486_DRIVER) // WRX twc spec is <=66ns = 15.15MHz
// Extra write pulse low time (delay for data setup)
#if defined (STM32F1xx)
@@ -151,6 +151,15 @@
#define TFT_SPI_PORT 1
#endif
#if (TFT_SPI_PORT == 1)
#define SPIX SPI1
#elif (TFT_SPI_PORT == 2)
#define SPIX SPI2
#elif (TFT_SPI_PORT == 3)
#define SPIX SPI3
#elif (TFT_SPI_PORT == 4)
#define SPIX SPI4
#endif
// Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants
#if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx)
@@ -161,15 +170,22 @@
#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
// 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
// DMA_CHANNEL_4
// DMA1_Stream4_IRQn and DMA1_Stream4_IRQHandler()
#elif (TFT_SPI_PORT == 3)
// Initialise processor specific SPI and DMA instances - used by init()
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI3; \
dmaHal.Instance = DMA1_Stream5
// The DMA hard-coding for SPI3 is in TFT_eSPI_STM32.c as follows:
// DMA_CHANNEL_4
// DMA1_Stream5_IRQn and DMA1_Stream5_IRQHandler()
#endif
#elif defined (STM32F1xx)
@@ -219,8 +235,8 @@
#define DC_PORT digitalPinToPort(TFT_DC)
#define DC_PIN_MASK digitalPinToBitMask(TFT_DC)
// Use bit set reset register
#define DC_C DC_PORT->BSRR = DC_PIN_MASK<<16
#define DC_D DC_PORT->BSRR = DC_PIN_MASK
#define DC_C DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK<<16
#define DC_D DC_DELAY; DC_PORT->BSRR = DC_PIN_MASK
#endif
////////////////////////////////////////////////////////////////////////////////////////
@@ -243,12 +259,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
////////////////////////////////////////////////////////////////////////////////////////
@@ -290,9 +315,9 @@
#if defined (TFT_PARALLEL_8_BIT)
// Mask for the 8 data bits to set pin directions (not used)
#define dir_mask 0
#define GPIO_DIR_MASK 0
#define CONSTRUCTOR_INIT_TFT_DATA_BUS // None
#define PARALLEL_INIT_TFT_DATA_BUS // None
#define INIT_TFT_DATA_BUS // Setup built into TFT_eSPI.cpp
@@ -385,7 +410,7 @@
#define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10))
#define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10))
#define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10))
// Create bit set/reset mask for top byte of 16 bit value B
// Create bit set/reset mask for top byte of 16-bit value B
#define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10))
#define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10))
#define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10))
@@ -402,29 +427,54 @@
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
// 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; \
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; \
GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(C); \
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)
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(C); \
GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB; \
GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
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
// Write 18-bit color to TFT (untested)
#define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \
GPIOA->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D7_BSR_MASK(r6); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(r6); \
GPIOB->BSRR = D3_BSR_MASK(r6) | D4_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \
WR_STB; \
GPIOA->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D7_BSR_MASK(g6); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(g6); \
GPIOB->BSRR = D3_BSR_MASK(g6) | D4_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \
WR_STB; \
GPIOA->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D7_BSR_MASK(b6); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(b6); \
GPIOB->BSRR = D3_BSR_MASK(b6) | D4_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \
WR_STB // Need to slow down strobe
// 18-bit color write with swapped bytes
#define tft_Write_16S(C) 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; \
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; \
GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(C); \
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
// 16-bit write with swapped bytes
#define tft_Write_16S(C) GPIOA->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOC->BSRR = D1_BSR_MASK(C); \
GPIOB->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB; \
GPIOA->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
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))
@@ -500,7 +550,7 @@
#define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10))
#define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10))
#define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10))
// Create bit set/reset mask for top byte of 16 bit value B
// Create bit set/reset mask for top byte of 16-bit value B
#define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10))
#define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10))
#define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10))
@@ -518,29 +568,56 @@
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB
// 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; \
GPIOD->BSRR = D9_BSR_MASK(C); \
GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \
WR_STB;\
GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(C); \
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB
#if defined (SSD1963_DRIVER)
// 16 bit write with swapped bytes
#define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(C); \
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB; \
GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D9_BSR_MASK(C); \
GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \
WR_STB
// Write 18-bit color to TFT (untested)
#define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \
GPIOF->BSRR = D0_BSR_MASK(r6) | D2_BSR_MASK(r6) | D4_BSR_MASK(r6) | D7_BSR_MASK(r6); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(r6); \
GPIOE->BSRR = D3_BSR_MASK(r6) | D5_BSR_MASK(r6) | D6_BSR_MASK(r6); \
WR_STB; \
GPIOF->BSRR = D0_BSR_MASK(g6) | D2_BSR_MASK(g6) | D4_BSR_MASK(g6) | D7_BSR_MASK(g6); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(g6); \
GPIOE->BSRR = D3_BSR_MASK(g6) | D5_BSR_MASK(g6) | D6_BSR_MASK(g6); \
WR_STB; \
GPIOF->BSRR = D0_BSR_MASK(b6) | D2_BSR_MASK(b6) | D4_BSR_MASK(b6) | D7_BSR_MASK(b6); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(b6); \
GPIOE->BSRR = D3_BSR_MASK(b6) | D5_BSR_MASK(b6) | D6_BSR_MASK(b6); \
WR_STB // Need to slow down strobe
// 18-bit color write with swapped bytes
#define tft_Write_16S(C) 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; \
GPIOD->BSRR = D9_BSR_MASK(C); \
GPIOE->BSRR = D11_BSR_MASK(C) | D13_BSR_MASK(C) | D14_BSR_MASK(C); \
WR_STB;\
GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(C); \
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB
// 16-bit write with swapped bytes
#define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C) | D2_BSR_MASK(C) | D4_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D1_BSR_MASK(C); \
GPIOE->BSRR = D3_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB; \
GPIOF->BSRR = D8_BSR_MASK(C) | D10_BSR_MASK(C) | D12_BSR_MASK(C) | D15_BSR_MASK(C); \
WR_L; \
GPIOD->BSRR = D9_BSR_MASK(C); \
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))
@@ -591,7 +668,7 @@
#define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10))
#define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10))
#define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10))
// Create bit set/reset mask for top byte of 16 bit value B
// Create bit set/reset mask for top byte of 16-bit value B
#define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10))
#define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10))
#define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10))
@@ -624,7 +701,7 @@
GPIOE->BSRR = D3_BSR_MASK(C) | D4_BSR_MASK(C) | D5_BSR_MASK(C) | D6_BSR_MASK(C); \
WR_STB
// 16 bit write with swapped bytes
// 16-bit write with swapped bytes
#define tft_Write_16S(C) GPIOF->BSRR = D0_BSR_MASK(C); \
GPIOG->BSRR = D2_BSR_MASK(C) | D7_BSR_MASK(C); \
WR_L; \
@@ -659,18 +736,42 @@
// Support for other STM32 boards (not optimised!)
////////////////////////////////////////////////////////////////////////////////////////
#else
#if defined (STM_PORTA_DATA_BUS)
// Write 8 bits to TFT
#define tft_Write_8(C) GPIOA->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB
// 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
#if defined (STM_PORTA_DATA_BUS) || defined (STM_PORTB_DATA_BUS) || defined (STM_PORTC_DATA_BUS) || defined (STM_PORTD_DATA_BUS)
#if defined (STM_PORTA_DATA_BUS)
#define GPIOX GPIOA
#elif defined (STM_PORTB_DATA_BUS)
#define GPIOX GPIOB
#elif defined (STM_PORTC_DATA_BUS)
#define GPIOX GPIOC
#elif defined (STM_PORTD_DATA_BUS)
#define GPIOX GPIOD
#endif
// 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
// Write 8 bits to TFT
#define tft_Write_8(C) GPIOX->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) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \
GPIOX->BSRR = (0x00FF0000 | (uint8_t)(r6)); WR_L; WR_STB; \
GPIOX->BSRR = (0x00FF0000 | (uint8_t)(g6)); WR_L; WR_STB; \
GPIOX->BSRR = (0x00FF0000 | (uint8_t)(b6)); WR_L; WR_STB
// 18-bit color write with swapped bytes
#define tft_Write_16S(C) Cswap = ((C) >>8 | (C) << 8); tft_Write_16(Cswap)
#else
// Write 16 bits to TFT
#define tft_Write_16(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>8)); WR_L; WR_STB; \
GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB
// 16-bit write with swapped bytes
#define tft_Write_16S(C) GPIOX->BSRR = (0x00FF0000 | (uint8_t)(C>>0)); WR_L; WR_STB; \
GPIOX->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))
@@ -679,43 +780,14 @@
#define tft_Write_32D(C) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C))
// Read a data bit
#define RD_TFT_D0 ((GPIOA->IDR) & 0x01) // Read pin TFT_D0
#define RD_TFT_D1 ((GPIOA->IDR) & 0x02) // Read pin TFT_D1
#define RD_TFT_D2 ((GPIOA->IDR) & 0x04) // Read pin TFT_D2
#define RD_TFT_D3 ((GPIOA->IDR) & 0x08) // Read pin TFT_D3
#define RD_TFT_D4 ((GPIOA->IDR) & 0x10) // Read pin TFT_D4
#define RD_TFT_D5 ((GPIOA->IDR) & 0x20) // Read pin TFT_D5
#define RD_TFT_D6 ((GPIOA->IDR) & 0x40) // Read pin TFT_D6
#define RD_TFT_D7 ((GPIOA->IDR) & 0x80) // Read pin TFT_D7
#elif defined (STM_PORTB_DATA_BUS)
// Write 8 bits to TFT
#define tft_Write_8(C) GPIOB->BSRR = (0x00FF0000 | (uint8_t)(C)); WR_L; WR_STB
// 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
// 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
#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))
#define tft_Write_32D(C) tft_Write_16((uint16_t)(C)); tft_Write_16((uint16_t)(C))
// Read a data bit
#define RD_TFT_D0 ((GPIOB->IDR) & 0x80) // Read pin TFT_D0
#define RD_TFT_D1 ((GPIOB->IDR) & 0x40) // Read pin TFT_D1
#define RD_TFT_D2 ((GPIOB->IDR) & 0x20) // Read pin TFT_D2
#define RD_TFT_D3 ((GPIOB->IDR) & 0x10) // Read pin TFT_D3
#define RD_TFT_D4 ((GPIOB->IDR) & 0x08) // Read pin TFT_D4
#define RD_TFT_D5 ((GPIOB->IDR) & 0x04) // Read pin TFT_D5
#define RD_TFT_D6 ((GPIOB->IDR) & 0x02) // Read pin TFT_D6
#define RD_TFT_D7 ((GPIOB->IDR) & 0x01) // Read pin TFT_D7
#define RD_TFT_D0 ((GPIOX->IDR) & 0x01) // Read pin TFT_D0
#define RD_TFT_D1 ((GPIOX->IDR) & 0x02) // Read pin TFT_D1
#define RD_TFT_D2 ((GPIOX->IDR) & 0x04) // Read pin TFT_D2
#define RD_TFT_D3 ((GPIOX->IDR) & 0x08) // Read pin TFT_D3
#define RD_TFT_D4 ((GPIOX->IDR) & 0x10) // Read pin TFT_D4
#define RD_TFT_D5 ((GPIOX->IDR) & 0x20) // Read pin TFT_D5
#define RD_TFT_D6 ((GPIOX->IDR) & 0x40) // Read pin TFT_D6
#define RD_TFT_D7 ((GPIOX->IDR) & 0x80) // Read pin TFT_D7
#else
// This will work with any STM32 to parallel TFT pin mapping but will be slower
@@ -769,7 +841,7 @@
#define D5_BSR_MASK(B) ((D5_PIN_MASK<<16)>>(((B)>> 1)&0x10))
#define D6_BSR_MASK(B) ((D6_PIN_MASK<<16)>>(((B)>> 2)&0x10))
#define D7_BSR_MASK(B) ((D7_PIN_MASK<<16)>>(((B)>> 3)&0x10))
// Create bit set/reset mask for top byte of 16 bit value B
// Create bit set/reset mask for top byte of 16-bit value B
#define D8_BSR_MASK(B) ((D0_PIN_MASK<<16)>>(((B)>> 4)&0x10))
#define D9_BSR_MASK(B) ((D1_PIN_MASK<<16)>>(((B)>> 5)&0x10))
#define D10_BSR_MASK(B) ((D2_PIN_MASK<<16)>>(((B)>> 6)&0x10))
@@ -792,49 +864,90 @@
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB
// 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); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \
WR_STB;\
D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB
#if defined (SSD1963_DRIVER)
// 16 bit write with swapped bytes
#define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB; \
D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \
WR_STB
// Write 18-bit color to TFT (untested)
#define tft_Write_16(C) r6 = (((C) & 0xF800)>> 8); g6 = (((C) & 0x07E0)>> 3); b6 = (((C) & 0x001F)<< 3); \
D0_PIN_PORT->BSRR = D8_BSR_MASK(r6); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(r6); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(r6); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(r6); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(r6); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(r6); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(r6); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(r6); \
WR_STB;\
D0_PIN_PORT->BSRR = D8_BSR_MASK(g6); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(g6); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(g6); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(g6); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(g6); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(g6); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(g6); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(g6); \
WR_STB;\
D0_PIN_PORT->BSRR = D0_BSR_MASK(b6); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(b6); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(b6); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(b6); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(b6); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(b6); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(b6); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(b6); \
WR_STB
// 18-bit color write with swapped bytes
#define tft_Write_16S(C) 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); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D14_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D15_BSR_MASK(C); \
WR_STB;\
D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB
// 16-bit write with swapped bytes
#define tft_Write_16S(C) D0_PIN_PORT->BSRR = D0_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D1_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D2_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D3_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D4_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D5_BSR_MASK(C); \
D6_PIN_PORT->BSRR = D6_BSR_MASK(C); \
D7_PIN_PORT->BSRR = D7_BSR_MASK(C); \
WR_STB; \
D0_PIN_PORT->BSRR = D8_BSR_MASK(C); \
D1_PIN_PORT->BSRR = D9_BSR_MASK(C); \
D2_PIN_PORT->BSRR = D10_BSR_MASK(C); \
D3_PIN_PORT->BSRR = D11_BSR_MASK(C); \
WR_L; \
D4_PIN_PORT->BSRR = D12_BSR_MASK(C); \
D5_PIN_PORT->BSRR = D13_BSR_MASK(C); \
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))
@@ -854,68 +967,60 @@
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to a SPI ILI9488 TFT
// Macros to write commands/pixel colour data to a SPI ILI948x TFT
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
#elif defined (SPI_18BIT_DRIVER) // SPI 18-bit colour
// Write 8 bits to TFT
#define tft_Write_8(C) \
{ spiBuffer[0] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); }
#define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){}
//BSY check must allow for APB clock delay by checking TXE flag first
#define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){}
#define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR)
// Convert 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16(C) \
{ spiBuffer[0] = ((C) & 0xF800)>>8; spiBuffer[1] = ((C) & 0x07E0)>>3; spiBuffer[2] = ((C) & 0x001F)<<3; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); }
//#define tft_Write_8(C) spi.transfer(C)
#define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_16(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3; SPI_BUSY_CHECK
#define tft_Write_16S(C) TX_FIFO = (C) & 0xF8; TX_FIFO = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; TX_FIFO = ((C) & 0x1F00)>>5; SPI_BUSY_CHECK
#define tft_Write_16N(C) TX_FIFO = ((C) & 0xF800)>>8; TX_FIFO = ((C) & 0x07E0)>>3; TX_FIFO = ((C) & 0x001F)<<3
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16S(C) \
{ spiBuffer[0] = (C) & 0xF8; spiBuffer[1] = ((C) & 0xE000)>>11 | ((C) & 0x07)<<5; spiBuffer[2] = ((C) & 0x1F00)>>5; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 3, 10); }
// Write 32 bits to TFT
#define tft_Write_32(C) \
{ spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \
TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK
// Write two address coordinates
#define tft_Write_32C(C,D) \
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>8; TX_FIFO = (C); \
TX_FIFO = (D)>>8; TX_FIFO = (D); SPI_BUSY_CHECK
// Write same value twice
#define tft_Write_32D(C) \
{ spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>8; TX_FIFO = (C); \
TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to a SPI Raspberry Pi TFT
////////////////////////////////////////////////////////////////////////////////////////
#elif defined (RPI_DISPLAY_TYPE)
#define tft_Write_8(C) \
{ spiBuffer[0] = 0; spiBuffer[1] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
#define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){}
//BSY check must allow for APB clock delay by checking TXE flag first
#define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){}
#define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR)
#define tft_Write_16(C) \
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
#define tft_Write_16S(C) \
{ spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
//#define tft_Write_8(C) spi.transfer(C)
#define tft_Write_8(C) TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK
#define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C)
#define tft_Write_32(C) \
{ spiBuffer[1] = ((C)>>24); spiBuffer[3] = ((C)>>16); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); }
TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \
TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_32C(C,D) \
{ spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((D)>>8); spiBuffer[7] = D; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); }
TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \
TX_FIFO = (0); TX_FIFO = (D)>>8; TX_FIFO = (0); TX_FIFO = (D); SPI_BUSY_CHECK
#define tft_Write_32D(C) \
{ spiBuffer[1] = ((C)>>8); spiBuffer[3] = (C); spiBuffer[5] = ((C)>>8); spiBuffer[7] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 8, 10); }
TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); \
TX_FIFO = (0); TX_FIFO = (C)>>8; TX_FIFO = (0); TX_FIFO = (C); SPI_BUSY_CHECK
////////////////////////////////////////////////////////////////////////////////////////
// Macros for all other SPI displays
@@ -923,37 +1028,41 @@
#else
#if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER)
// Temporary workaround for issue #510 part 2
#define tft_Write_8(C) spi.transfer(C)
#else
#define tft_Write_8(C) \
{ spiBuffer[0] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 1, 10); delayMicroseconds(1);}
#endif
//#define DC_DELAY delayMicroseconds(1) // Premature BSY clear Hardware bug?
#define tft_Write_16(C) \
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
#define SPI_TXE_CHECK while(!__HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_TXE)){}
//BSY check must allow for APB clock delay by checking TXE flag first
#define SPI_BUSY_CHECK SPI_TXE_CHECK; while( __HAL_SPI_GET_FLAG(&spiHal, SPI_FLAG_BSY)){}
#define TX_FIFO SPI_TXE_CHECK; *((__IO uint8_t *)&SPIX->DR)
#define tft_Write_16S(C) \
{ spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
#define tft_Write_8(C) TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_16(C) TX_FIFO = (C)>>8; TX_FIFO = (C); SPI_BUSY_CHECK
#define tft_Write_16S(C) TX_FIFO = (C); TX_FIFO = (C)>>8; SPI_BUSY_CHECK
#define tft_Write_16N(C) TX_FIFO = (C)>>8; TX_FIFO = (C)
#define tft_Write_32(C) \
{ spiBuffer[0] = (C)>>24; spiBuffer[1] = (C)>>16; spiBuffer[2] = (C)>>8; spiBuffer[3] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>24; TX_FIFO = (C)>>16; \
tft_Write_16((uint16_t) ((C)>>0))
#define tft_Write_32C(C,D) \
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; spiBuffer[2] = (D)>>8; spiBuffer[3] = D; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>8; TX_FIFO = (C); \
tft_Write_16((uint16_t) (D))
#define tft_Write_32D(C) \
{ spiBuffer[0] = spiBuffer[2] = (C)>>8; spiBuffer[1] = spiBuffer[3] = C; \
HAL_SPI_Transmit(&spiHal, spiBuffer, 4, 10); }
TX_FIFO = (C)>>8; TX_FIFO = (C); \
tft_Write_16((uint16_t) (C))
#endif
#ifndef DC_DELAY
//#define DC_DELAY delayMicroseconds(1) // Premature BSY clear hardware bug?
#define DC_DELAY
#endif
#ifndef tft_Write_16N
#define tft_Write_16N tft_Write_16
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to read from display using SPI or software SPI
////////////////////////////////////////////////////////////////////////////////////////