mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-03 04:34:43 +02:00
Add RP2040 8 bit parallel support with DMA
The RP2040 can now be used with 8 bit parallel TFT interface displays. DMA is also supported for both SPI and 8 bit parallel displays.
This commit is contained in:
@@ -646,6 +646,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)
|
||||
|
@@ -6,7 +6,8 @@
|
||||
// Global variables
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
|
||||
// Select the SPI port and board package to use
|
||||
#ifdef ARDUINO_ARCH_MBED
|
||||
// Arduino RP2040 board package
|
||||
@@ -16,6 +17,26 @@
|
||||
//SPIClass& spi = SPI; // will use board package default pins
|
||||
SPIClassRP2040 spi = SPIClassRP2040(SPI_X, TFT_MISO, -1, TFT_SCLK, TFT_MOSI);
|
||||
#endif
|
||||
|
||||
#else // 8 bit parallel
|
||||
|
||||
#include "pio_8bit_parallel.pio.h"
|
||||
|
||||
// Board package specific differences
|
||||
#ifdef ARDUINO_ARCH_MBED
|
||||
// Not supported at the moment
|
||||
#error The Arduino RP2040 MBED board package is not supported. Use the community package by Earle Philhower.
|
||||
#endif
|
||||
|
||||
// Community RP2040 board package by Earle Philhower
|
||||
PIO pio = pio0; // Code will try both pio's to find a free SM
|
||||
int8_t pio_sm = 0; // pioinit will claim a free one
|
||||
|
||||
// Updated later with the loading offset of the PIO program.
|
||||
uint32_t program_offset = 0;
|
||||
uint32_t pull_stall_mask = 0;
|
||||
uint32_t pio_instr_jmp8 = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef RP2040_DMA
|
||||
@@ -69,10 +90,57 @@ void TFT_eSPI::end_SDA_Read(void)
|
||||
#endif // #if defined (TFT_SDA_READ)
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (TFT_PARALLEL_8_BIT)
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
void pioinit(uint8_t tft_d0_pin, uint8_t tft_wr_pin, uint16_t clock_div, uint16_t fract_div) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (TFT_PARALLEL_8_BIT) // Code for generic (i.e. any) processor
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find a free SM on one of the PIO's
|
||||
pio = pio0;
|
||||
pio_sm = pio_claim_unused_sm(pio, false); // false means don't panic
|
||||
// Try pio1 if SM not found
|
||||
if (pio_sm < 0) {
|
||||
pio = pio1;
|
||||
pio_sm = pio_claim_unused_sm(pio, true); // panic this time if no SM is free
|
||||
}
|
||||
|
||||
// Load the PIO program
|
||||
program_offset = pio_add_program(pio, &tft_io_program);
|
||||
|
||||
// Associate pins with the PIO
|
||||
pio_gpio_init(pio, tft_wr_pin);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
pio_gpio_init(pio, tft_d0_pin + i);
|
||||
}
|
||||
|
||||
// Configure the pins to be outputs
|
||||
pio_sm_set_consecutive_pindirs(pio, pio_sm, tft_wr_pin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, pio_sm, tft_d0_pin, 8, true);
|
||||
|
||||
// Configure the state machine
|
||||
pio_sm_config c = tft_io_program_get_default_config(program_offset);
|
||||
// Define the single side-set pin
|
||||
sm_config_set_sideset_pins(&c, tft_wr_pin);
|
||||
// Define the 8 consecutive pins that are used for data output
|
||||
sm_config_set_out_pins(&c, tft_d0_pin, 8);
|
||||
// Set clock divider and fractional divider
|
||||
sm_config_set_clkdiv_int_frac(&c, clock_div, fract_div);
|
||||
// Make a single 8 words FIFO from the 4 words TX and RX FIFOs
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
// The OSR register shifts to the right, sm designed to send MS byte of a colour first
|
||||
sm_config_set_out_shift(&c, true, false, 0);
|
||||
// Now load the configuration
|
||||
pio_sm_init(pio, pio_sm, program_offset + tft_io_offset_start_8, &c);
|
||||
|
||||
// Start the state machine.
|
||||
pio_sm_set_enabled(pio, pio_sm, true);
|
||||
|
||||
// Create the pull stall bit mask
|
||||
pull_stall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + pio_sm);
|
||||
|
||||
// Create the assembler instruction for the jump to byte send routine
|
||||
pio_instr_jmp8 = pio_encode_jmp(program_offset + tft_io_offset_start_8);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: pushBlock - for generic processor and parallel display
|
||||
@@ -80,25 +148,71 @@ void TFT_eSPI::end_SDA_Read(void)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
|
||||
|
||||
while (len>1) {tft_Write_32D(color); len-=2;}
|
||||
if (len) {tft_Write_16(color);}
|
||||
while (len > 4) {
|
||||
// 5 seems to be the optimum for maximum transfer rate
|
||||
WAIT_FOR_FIFO_FREE(5);
|
||||
TX_FIFO = color;
|
||||
TX_FIFO = color;
|
||||
TX_FIFO = color;
|
||||
TX_FIFO = color;
|
||||
TX_FIFO = color;
|
||||
|
||||
len -= 5;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
// There could be a maximum of 4 words left to send
|
||||
WAIT_FOR_FIFO_FREE(4);
|
||||
while (len--) TX_FIFO = color;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: pushPixels - for gereric processor and parallel display
|
||||
** Function name: pushPixels - for generic processor and parallel display
|
||||
** Description: Write a sequence of pixels
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
|
||||
uint16_t *data = (uint16_t*)data_in;
|
||||
if(_swapBytes) {
|
||||
while (len>1) {tft_Write_16(*data); data++; tft_Write_16(*data); data++; len -=2;}
|
||||
if (len) {tft_Write_16(*data);}
|
||||
return;
|
||||
}
|
||||
const uint16_t *data = (uint16_t*)data_in;
|
||||
|
||||
while (len>1) {tft_Write_16S(*data); data++; tft_Write_16S(*data); data++; len -=2;}
|
||||
if (len) {tft_Write_16S(*data);}
|
||||
// PIO sends MS byte first, so bytes are already swapped on transmit
|
||||
if(_swapBytes) {
|
||||
while (len > 4) {
|
||||
WAIT_FOR_FIFO_FREE(5);
|
||||
TX_FIFO = data[0];
|
||||
TX_FIFO = data[1];
|
||||
TX_FIFO = data[2];
|
||||
TX_FIFO = data[3];
|
||||
TX_FIFO = data[4];
|
||||
data += 5;
|
||||
len -= 5;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
WAIT_FOR_FIFO_FREE(4);
|
||||
while(len--) TX_FIFO = *data++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (len > 4) {
|
||||
WAIT_FOR_FIFO_FREE(5);
|
||||
TX_FIFO = data[0] << 8 | data[0] >> 8;
|
||||
TX_FIFO = data[1] << 8 | data[1] >> 8;
|
||||
TX_FIFO = data[2] << 8 | data[2] >> 8;
|
||||
TX_FIFO = data[3] << 8 | data[3] >> 8;
|
||||
TX_FIFO = data[4] << 8 | data[4] >> 8;
|
||||
data += 5;
|
||||
len -= 5;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
WAIT_FOR_FIFO_FREE(4);
|
||||
while(len--) {
|
||||
TX_FIFO = *data << 8 | *data >> 8;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -107,6 +221,10 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
|
||||
{
|
||||
// Avoid warnings
|
||||
mask = mask;
|
||||
mode = mode;
|
||||
/*
|
||||
// mask is unused for generic processor
|
||||
// Arduino native functions suited well to a generic driver
|
||||
pinMode(TFT_D0, mode);
|
||||
@@ -117,7 +235,7 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
|
||||
pinMode(TFT_D5, mode);
|
||||
pinMode(TFT_D6, mode);
|
||||
pinMode(TFT_D7, mode);
|
||||
return;
|
||||
*/
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -126,17 +244,20 @@ void TFT_eSPI::busDir(uint32_t mask, uint8_t mode)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::gpioMode(uint8_t gpio, uint8_t mode)
|
||||
{
|
||||
// No fast port based generic approach available
|
||||
// Avoid warnings
|
||||
gpio = gpio;
|
||||
mode = mode;
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: read byte - supports class functions
|
||||
** Description: Read a byte - parallel bus only
|
||||
** Description: Read a byte - parallel bus only - not supported yet
|
||||
***************************************************************************************/
|
||||
uint8_t TFT_eSPI::readByte(void)
|
||||
{
|
||||
uint8_t b = 0;
|
||||
|
||||
/*
|
||||
busDir(0, INPUT);
|
||||
digitalWrite(TFT_RD, LOW);
|
||||
|
||||
@@ -151,7 +272,7 @@ uint8_t TFT_eSPI::readByte(void)
|
||||
|
||||
digitalWrite(TFT_RD, HIGH);
|
||||
busDir(0, OUTPUT);
|
||||
|
||||
*/
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -286,11 +407,10 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (RP2040_DMA) && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS
|
||||
#ifdef RP2040_DMA // DMA functions for 16 bit SPI and 8 bit parallel displays
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Minimal function set to support DMA:
|
||||
These are created in header file:
|
||||
uint32_t dma_tx_channel;
|
||||
dma_channel_config dma_tx_config;
|
||||
*/
|
||||
@@ -303,8 +423,13 @@ bool TFT_eSPI::dmaBusy(void) {
|
||||
if (!DMA_Enabled) return false;
|
||||
|
||||
if (dma_channel_is_busy(dma_tx_channel)) return true;
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
// For SPI must also wait for FIFO to flush and reset format
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
spi_set_format(SPI_X, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -315,8 +440,12 @@ bool TFT_eSPI::dmaBusy(void) {
|
||||
void TFT_eSPI::dmaWait(void)
|
||||
{
|
||||
while (dma_channel_is_busy(dma_tx_channel));
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
// For SPI must also wait for FIFO to flush and reset format
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
spi_set_format(SPI_X, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -330,7 +459,12 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
|
||||
dmaWait();
|
||||
|
||||
channel_config_set_bswap(&dma_tx_config, !_swapBytes);
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)image, len, true);
|
||||
#else
|
||||
dma_channel_configure(dma_tx_channel, &dma_tx_config, &pio->txf[pio_sm], (uint16_t*)image, len, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -378,8 +512,12 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
|
||||
setAddrWindow(x, y, dw, dh);
|
||||
|
||||
channel_config_set_bswap(&dma_tx_config, !_swapBytes);
|
||||
dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)buffer, len, true);
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)buffer, len, true);
|
||||
#else
|
||||
dma_channel_configure(dma_tx_channel, &dma_tx_config, &pio->txf[pio_sm], (uint16_t*)buffer, len, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -396,7 +534,11 @@ bool TFT_eSPI::initDMA(bool ctrl_cs)
|
||||
dma_tx_config = dma_channel_get_default_config(dma_tx_channel);
|
||||
|
||||
channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_16);
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_X) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
|
||||
#else
|
||||
channel_config_set_dreq(&dma_tx_config, pio_get_dreq(pio, pio_sm, true));
|
||||
#endif
|
||||
|
||||
DMA_Enabled = true;
|
||||
return true;
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
// Required for both the official and community board packages
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/pio.h"
|
||||
|
||||
// Processor ID reported by getSetup()
|
||||
#define PROCESSOR_ID 0x2040
|
||||
@@ -17,23 +18,30 @@
|
||||
// Include processor specific header
|
||||
// None
|
||||
|
||||
// Use SPI0 as default if not defined
|
||||
#ifndef TFT_SPI_PORT
|
||||
#define TFT_SPI_PORT 0
|
||||
#endif
|
||||
|
||||
#if (TFT_SPI_PORT == 0)
|
||||
#define SPI_X spi0
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
// Use SPI0 as default if not defined
|
||||
#ifndef TFT_SPI_PORT
|
||||
#define TFT_SPI_PORT 0
|
||||
#endif
|
||||
|
||||
#if (TFT_SPI_PORT == 0)
|
||||
#define SPI_X spi0
|
||||
#else
|
||||
#define SPI_X spi1
|
||||
#endif
|
||||
|
||||
// Processor specific code used by SPI bus transaction begin/end_tft_write functions
|
||||
#define SET_BUS_WRITE_MODE spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
#define SET_BUS_READ_MODE // spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
#else
|
||||
#define SPI_X spi1
|
||||
// Processor specific code used by SPI bus transaction begin/end_tft_write functions
|
||||
#define SET_BUS_WRITE_MODE
|
||||
#define SET_BUS_READ_MODE
|
||||
#endif
|
||||
|
||||
// Processor specific code used by SPI bus transaction begin/end_tft_write functions
|
||||
#define SET_BUS_WRITE_MODE spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
#define SET_BUS_READ_MODE // spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
|
||||
// Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
|
||||
#if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER)
|
||||
#if !defined(SPI_18BIT_DRIVER)
|
||||
#define RP2040_DMA
|
||||
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
|
||||
#define DMA_BUSY_CHECK dmaWait()
|
||||
@@ -41,18 +49,40 @@
|
||||
#define DMA_BUSY_CHECK
|
||||
#endif
|
||||
|
||||
// Wait for tx to end, flush rx FIFO, clear rx overrun
|
||||
#define SPI_BUSY_CHECK while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
while (spi_is_readable(SPI_X)) (void)spi_get_hw(SPI_X)->dr; \
|
||||
spi_get_hw(SPI_X)->icr = SPI_SSPICR_RORIC_BITS
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
// Initialise processor specific SPI functions, used by init()
|
||||
#define INIT_TFT_DATA_BUS // Not used
|
||||
|
||||
// Wait for tx to end, flush rx FIFO, clear rx overrun
|
||||
#define SPI_BUSY_CHECK while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
while (spi_is_readable(SPI_X)) (void)spi_get_hw(SPI_X)->dr; \
|
||||
spi_get_hw(SPI_X)->icr = SPI_SSPICR_RORIC_BITS
|
||||
|
||||
// To be safe, SUPPORT_TRANSACTIONS is assumed mandatory
|
||||
#if !defined (SUPPORT_TRANSACTIONS)
|
||||
#define SUPPORT_TRANSACTIONS
|
||||
#endif
|
||||
#else
|
||||
// Initialise TFT data bus
|
||||
#define INIT_TFT_DATA_BUS
|
||||
|
||||
#define SPI_BUSY_CHECK
|
||||
|
||||
// ILI9481 needs a slower cycle time
|
||||
// Byte rate = (CPU clock/(4 * divider))
|
||||
#ifdef ILI9481_DRIVER
|
||||
#define DIV_UNITS 1
|
||||
#define DIV_FRACT 160
|
||||
#else
|
||||
#define DIV_UNITS 1
|
||||
#define DIV_FRACT 0
|
||||
#endif
|
||||
|
||||
// Set the state machine clock divider (from integer and fractional parts - 16:8)
|
||||
#define CONSTRUCTOR_INIT_TFT_DATA_BUS pioinit(TFT_D0, TFT_WR, DIV_UNITS, DIV_FRACT);
|
||||
|
||||
// To be safe, SUPPORT_TRANSACTIONS is assumed mandatory
|
||||
#if !defined (SUPPORT_TRANSACTIONS)
|
||||
#define SUPPORT_TRANSACTIONS
|
||||
#endif
|
||||
|
||||
// Initialise processor specific SPI functions, used by init()
|
||||
#define INIT_TFT_DATA_BUS // Not used
|
||||
|
||||
// If smooth fonts are enabled the filing system may need to be loaded
|
||||
#ifdef SMOOTH_FONT
|
||||
@@ -68,14 +98,23 @@
|
||||
#define DC_C // No macro allocated so it generates no code
|
||||
#define DC_D // No macro allocated so it generates no code
|
||||
#else
|
||||
//#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||
//#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||
#if defined (RPI_DISPLAY_TYPE)
|
||||
#define DC_C digitalWrite(TFT_DC, LOW);
|
||||
#define DC_D digitalWrite(TFT_DC, HIGH);
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
//#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||
//#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||
#if defined (RPI_DISPLAY_TYPE)
|
||||
#define DC_C digitalWrite(TFT_DC, LOW);
|
||||
#define DC_D digitalWrite(TFT_DC, HIGH);
|
||||
#else
|
||||
#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||
#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||
#endif
|
||||
#else
|
||||
#define DC_C sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||
#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||
// Must wait for data to flush through before changing DC line
|
||||
#define DC_C WAIT_FOR_STALL; \
|
||||
sio_hw->gpio_clr = (1ul << TFT_DC)
|
||||
|
||||
// Flush has happened before this and mode changed back to 16 bit
|
||||
#define DC_D sio_hw->gpio_set = (1ul << TFT_DC)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -98,6 +137,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Make sure TFT_RD is defined if not used to avoid an error message
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// At the moment read is not supported for parallel mode, tie TFT signal high
|
||||
#ifndef TFT_RD
|
||||
#define TFT_RD -1
|
||||
#endif
|
||||
@@ -105,20 +145,30 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Define the WR (TFT Write) pin drive code
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef TFT_WR
|
||||
#define WR_L digitalWrite(TFT_WR, LOW)
|
||||
#define WR_H digitalWrite(TFT_WR, HIGH)
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
#ifdef TFT_WR
|
||||
#define WR_L digitalWrite(TFT_WR, LOW)
|
||||
#define WR_H digitalWrite(TFT_WR, HIGH)
|
||||
#endif
|
||||
#else
|
||||
// The PIO manages the write line
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Define the touch screen chip select pin drive code
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if !defined TOUCH_CS || (TOUCH_CS < 0)
|
||||
#define T_CS_L // No macro allocated so it generates no code
|
||||
#define T_CS_H // No macro allocated so it generates no code
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
#if !defined TOUCH_CS || (TOUCH_CS < 0)
|
||||
#define T_CS_L // No macro allocated so it generates no code
|
||||
#define T_CS_H // No macro allocated so it generates no code
|
||||
#else
|
||||
#define T_CS_L digitalWrite(TOUCH_CS, LOW)
|
||||
#define T_CS_H digitalWrite(TOUCH_CS, HIGH)
|
||||
#endif
|
||||
#else
|
||||
#define T_CS_L digitalWrite(TOUCH_CS, LOW)
|
||||
#define T_CS_H digitalWrite(TOUCH_CS, HIGH)
|
||||
#ifdef TOUCH_CS
|
||||
#error Touch screen not supported in parallel mode, use a separate library.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -131,113 +181,163 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Macros to write commands/pixel colour data to a SPI ILI948x TFT
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
|
||||
// Write 8 bits to TFT
|
||||
#define tft_Write_8(C) spi_get_hw(SPI_X)->dr = (uint32_t)(C); \
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
#if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
|
||||
|
||||
//#define tft_Write_8(C) spi.transfer(C);
|
||||
#define tft_Write_8N(B) while (!spi_is_writable(SPI_X)){}; \
|
||||
spi_get_hw(SPI_X)->dr = (uint8_t)(B)
|
||||
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16(C) tft_Write_8N(((C) & 0xF800)>>8); \
|
||||
tft_Write_8N(((C) & 0x07E0)>>3); \
|
||||
tft_Write_8N(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16N(C) tft_Write_8N(((C) & 0xF800)>>8); \
|
||||
tft_Write_8N(((C) & 0x07E0)>>3); \
|
||||
tft_Write_8N(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16S(C) tft_Write_8N((C) & 0xF8); \
|
||||
tft_Write_8N(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
|
||||
tft_Write_8N(((C) & 0x1F00)>>5)
|
||||
// Write 32 bits to TFT
|
||||
#define tft_Write_32(C) tft_Write_8N(C>>24); \
|
||||
tft_Write_8N(C>>16); \
|
||||
tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C)
|
||||
|
||||
// Write two address coordinates
|
||||
#define tft_Write_32C(C,D) tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C); \
|
||||
tft_Write_8N(D>>8); \
|
||||
tft_Write_8N(D)
|
||||
|
||||
// Write same value twice
|
||||
#define tft_Write_32D(C) tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C); \
|
||||
tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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(C); spi.transfer(C)
|
||||
#define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
||||
#define tft_Write_16N(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
|
||||
|
||||
// This swaps to 8 bit mode, then back to 16 bit mode
|
||||
#define tft_Write_8(C) while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST); \
|
||||
spi_get_hw(SPI_X)->dr = (uint32_t)(C); \
|
||||
// Write 8 bits to TFT
|
||||
#define tft_Write_8(C) spi_get_hw(SPI_X)->dr = (uint32_t)(C); \
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(SPI_X, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
|
||||
// Note: the following macros do not wait for the end of transmission
|
||||
//#define tft_Write_8(C) spi.transfer(C);
|
||||
#define tft_Write_8N(B) while (!spi_is_writable(SPI_X)){}; \
|
||||
spi_get_hw(SPI_X)->dr = (uint8_t)(B)
|
||||
|
||||
#define tft_Write_16(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16(C) tft_Write_8N(((C) & 0xF800)>>8); \
|
||||
tft_Write_8N(((C) & 0x07E0)>>3); \
|
||||
tft_Write_8N(((C) & 0x001F)<<3)
|
||||
|
||||
#define tft_Write_16N(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16N(C) tft_Write_8N(((C) & 0xF800)>>8); \
|
||||
tft_Write_8N(((C) & 0x07E0)>>3); \
|
||||
tft_Write_8N(((C) & 0x001F)<<3)
|
||||
|
||||
#define tft_Write_16S(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)<<8 | (C)>>8
|
||||
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16S(C) tft_Write_8N((C) & 0xF8); \
|
||||
tft_Write_8N(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
|
||||
tft_Write_8N(((C) & 0x1F00)>>5)
|
||||
// Write 32 bits to TFT
|
||||
#define tft_Write_32(C) tft_Write_8N(C>>24); \
|
||||
tft_Write_8N(C>>16); \
|
||||
tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C)
|
||||
|
||||
#define tft_Write_32(C) spi_get_hw(SPI_X)->dr = (uint32_t)((C)>>16); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
// Write two address coordinates
|
||||
#define tft_Write_32C(C,D) tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C); \
|
||||
tft_Write_8N(D>>8); \
|
||||
tft_Write_8N(D)
|
||||
|
||||
#define tft_Write_32C(C,D) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(D)
|
||||
// Write same value twice
|
||||
#define tft_Write_32D(C) tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C); \
|
||||
tft_Write_8N(C>>8); \
|
||||
tft_Write_8N(C)
|
||||
|
||||
#define tft_Write_32D(C) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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(C); spi.transfer(C)
|
||||
#define tft_Write_16(C) spi.transfer((uint8_t)((C)>>8));spi.transfer((uint8_t)((C)>>0))
|
||||
#define tft_Write_16N(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
|
||||
|
||||
// This swaps to 8 bit mode, then back to 16 bit mode
|
||||
#define tft_Write_8(C) while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST); \
|
||||
spi_get_hw(SPI_X)->dr = (uint32_t)(C); \
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {}; \
|
||||
spi_set_format(SPI_X, 16, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
|
||||
|
||||
// Note: the following macros do not wait for the end of transmission
|
||||
|
||||
#define tft_Write_16(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_16N(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_16S(C) while (!spi_is_writable(SPI_X)){}; spi_get_hw(SPI_X)->dr = (uint32_t)(C)<<8 | (C)>>8
|
||||
|
||||
#define tft_Write_32(C) spi_get_hw(SPI_X)->dr = (uint32_t)((C)>>16); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
|
||||
#define tft_Write_32C(C,D) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(D)
|
||||
|
||||
#define tft_Write_32D(C) spi_get_hw(SPI_X)->dr = (uint32_t)(C); spi_get_hw(SPI_X)->dr = (uint32_t)(C)
|
||||
|
||||
#endif // RPI_DISPLAY_TYPE
|
||||
#endif
|
||||
|
||||
#else // Parallel 8 bit
|
||||
|
||||
// On it's own this does not appear to reliably detect a stall, found that we must wait
|
||||
// for FIFO to empty before clearing the stall flag, and then wait for it to be set
|
||||
#define WAIT_FOR_STALL pio->fdebug = pull_stall_mask; while (!(pio->fdebug & pull_stall_mask))
|
||||
|
||||
// Wait until at least "S" locations free
|
||||
#define WAIT_FOR_FIFO_FREE(S) while (((pio->flevel >> (pio_sm * 8)) & 0x000F) > (8-S)){}
|
||||
|
||||
// Wait until at least 5 locations free
|
||||
#define WAIT_FOR_FIFO_5_FREE while ((pio->flevel) & (0x000c << (pio_sm * 8))){}
|
||||
|
||||
// Wait until at least 1 location free
|
||||
#define WAIT_FOR_FIFO_1_FREE while ((pio->flevel) & (0x0008 << (pio_sm * 8))){}
|
||||
|
||||
// Wait for FIFO to empty (use before swapping to 8 bits)
|
||||
#define WAIT_FOR_FIFO_EMPTY while(!(pio->fstat & (1u << (PIO_FSTAT_TXEMPTY_LSB + pio_sm))))
|
||||
|
||||
// The write register of the TX FIFO.
|
||||
#define TX_FIFO pio->txf[pio_sm]
|
||||
|
||||
// Temporary - to be deleted
|
||||
#define dir_mask 0
|
||||
|
||||
|
||||
// This writes 8 bits, then switches back to 16 bit mode automatically
|
||||
// Have already waited for pio stalled (last data write complete) when DC switched to command mode
|
||||
// The wait for stall allows DC to be changed immediately afterwards
|
||||
#define tft_Write_8(C) pio->sm[pio_sm].instr = pio_instr_jmp8; \
|
||||
TX_FIFO = C; \
|
||||
WAIT_FOR_STALL; \
|
||||
|
||||
// Note: the following macros do not wait for the end of transmission
|
||||
|
||||
#define tft_Write_16(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = (C)
|
||||
|
||||
#define tft_Write_16N(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = (C)
|
||||
|
||||
#define tft_Write_16S(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((C)<<8) | ((C)>>8)
|
||||
|
||||
#define tft_Write_32(C) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C)>>16; TX_FIFO = (C)
|
||||
|
||||
#define tft_Write_32C(C,D) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (D)
|
||||
|
||||
#define tft_Write_32D(C) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (C)
|
||||
|
||||
#endif // RPI_DISPLAY_TYPE
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Macros to read from display using SPI or software SPI
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if defined (TFT_SDA_READ)
|
||||
// Use a bit banged function call for STM32 and bi-directional SDA pin
|
||||
#define TFT_eSPI_ENABLE_8_BIT_READ // Enable tft_Read_8(void);
|
||||
#define SCLK_L digitalWrite(TFT_SCLK, LOW)
|
||||
#define SCLK_H digitalWrite(TFT_SCLK, LOW)
|
||||
#else
|
||||
// Use a SPI read transfer
|
||||
#define tft_Read_8() spi.transfer(0)
|
||||
#if !defined (TFT_PARALLEL_8_BIT) // SPI
|
||||
#if defined (TFT_SDA_READ)
|
||||
// Use a bit banged function call for STM32 and bi-directional SDA pin
|
||||
#define TFT_eSPI_ENABLE_8_BIT_READ // Enable tft_Read_8(void);
|
||||
#define SCLK_L digitalWrite(TFT_SCLK, LOW)
|
||||
#define SCLK_H digitalWrite(TFT_SCLK, LOW)
|
||||
#else
|
||||
// Use a SPI read transfer
|
||||
#define tft_Read_8() spi.transfer(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Temporary to keep the "Arduino Mbed OS RP2040 Boards" support package happy
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
41
Processors/pio_8bit_parallel.pio
Normal file
41
Processors/pio_8bit_parallel.pio
Normal file
@@ -0,0 +1,41 @@
|
||||
// Raspberry Pi Pico PIO program to output data to a TFT
|
||||
// controller via a 8 bit 8080 style data path.
|
||||
|
||||
// Original sourced from:
|
||||
// https://github.com/zapta/pio_tft
|
||||
|
||||
// Side set: 1 output pin, TFT_WR. Active low.
|
||||
// Data set: 8 consecutive output pins, TFT_D0 .. TFT_D7
|
||||
|
||||
.program tft_io
|
||||
.side_set 1 opt ; The TFT_WR output.
|
||||
|
||||
// The C++ code switches between the 8 bits and 16 bits loops
|
||||
// by waiting for the SM to be idle and setting its PC.
|
||||
//
|
||||
public start_16:
|
||||
// Fetch into OSR the next 32 bit value from the TX FIFO.
|
||||
// This is a blocking operation. Sets WR high.
|
||||
pull side 1
|
||||
// Shift the OSR reg right by 8 bits, loading the low 8 bits
|
||||
// of reg x with the shifted data.
|
||||
out x, 8
|
||||
// Write the first byte (MSB) and sets WR low. This also
|
||||
// shift OSR by 8 bits which we don't care about.
|
||||
out pins, 8 side 0 [1]
|
||||
// Set TFT_WR back high.
|
||||
nop side 1
|
||||
// Move the LSB byte back to the OSR.
|
||||
mov osr, x
|
||||
// Output the second byte and set TFT_WRITE low.
|
||||
out pins, 8 side 0
|
||||
jmp start_16
|
||||
|
||||
// 8 bit transfer
|
||||
public start_8:
|
||||
// Fetch into OSR the next 32 bit value from the TX FIFO.
|
||||
// This is a blocking operation. Sets WR high.
|
||||
pull side 1
|
||||
// Write the first byte (LSB) and sets WR low. This also
|
||||
// shifts the OSR right by 8 bits.
|
||||
out pins, 8 side 0 [1]
|
44
Processors/pio_8bit_parallel.pio.h
Normal file
44
Processors/pio_8bit_parallel.pio.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// -------------------------------------------------- //
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
// ------ //
|
||||
// tft_io //
|
||||
// ------ //
|
||||
|
||||
#define tft_io_wrap_target 0
|
||||
#define tft_io_wrap 8
|
||||
|
||||
#define tft_io_offset_start_16 0u
|
||||
#define tft_io_offset_start_8 7u
|
||||
|
||||
static const uint16_t tft_io_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x98a0, // 0: pull block side 1
|
||||
0x6028, // 1: out x, 8
|
||||
0x7108, // 2: out pins, 8 side 0 [1]
|
||||
0xb842, // 3: nop side 1
|
||||
0xa0e1, // 4: mov osr, x
|
||||
0x7008, // 5: out pins, 8 side 0
|
||||
0x0000, // 6: jmp 0
|
||||
0x98a0, // 7: pull block side 1
|
||||
0x7108, // 8: out pins, 8 side 0 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program tft_io_program = {
|
||||
.instructions = tft_io_program_instructions,
|
||||
.length = 9,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config tft_io_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
#endif
|
20
README.md
20
README.md
@@ -1,15 +1,11 @@
|
||||
A new test branch has been created for the RP2040 processor with 8 bit parallel displays:
|
||||
|
||||
["Test branch"](https://github.com/Bodmer/TFT_eSPI/tree/RP2040_8bit_parallel)
|
||||
|
||||
A ["Discussions"](https://github.com/Bodmer/TFT_eSPI/discussions) facility has been added for Q&A etc. Use the ["Issues"](https://github.com/Bodmer/TFT_eSPI/issues) tab only for problems with the library. Thanks!
|
||||
# News
|
||||
1. Support hase been added for the ESP32 S2 processor variant. A [new user setup](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70_ESP32_S2_ILI9341.h) file has been added as an example setup with an ILI9341 TFT. You will need to load ESP32 Arduino board package 2.0.0 or later to use the updated library with an ESP32.
|
||||
|
||||
2. DMA can now be used with the Raspberry Pi Pico (RP2040) when used with 16 bit colour SPI displays such as the ILI9341. See "Bouncy_Circles" sketch.
|
||||
1. DMA can now be used with the Raspberry Pi Pico (RP2040) when used with both 8 bit parallel and 16 bit colour SPI displays. See "Bouncy_Circles" sketch.
|
||||
|
||||
["Bouncing circles"](https://www.youtube.com/watch?v=njFXIzCTQ_Q&lc=UgymaUIwOIuihvYh-Qt4AaABAg)
|
||||
|
||||
2. Support hase been added for the ESP32 S2 processor variant. A [new user setup](https://github.com/Bodmer/TFT_eSPI/blob/master/User_Setups/Setup70_ESP32_S2_ILI9341.h) file has been added as an example setup with an ILI9341 TFT. You will need to load ESP32 Arduino board package 2.0.0 or later to use the updated library with an ESP32.
|
||||
|
||||
3. The library now supports the Raspberry Pi Pico with both the [official Arduino board package](https://github.com/arduino/ArduinoCore-mbed) and the one provided by [Earle Philhower](https://github.com/earlephilhower/arduino-pico). The setup file "Setup60_RP2040_ILI9341.h" has been used for tests with an ILI9341 display. At the moment only SPI interface displays have been tested. SPI port 0 is the default but SPI port 1 can be specifed in the setup file if those SPI pins are used.
|
||||
|
||||
["Rotating cube demo"](https://www.youtube.com/watch?v=4fPxEN9ImVE)
|
||||
@@ -26,11 +22,6 @@ A ["Discussions"](https://github.com/Bodmer/TFT_eSPI/discussions) facility has b
|
||||
|
||||
9. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h".
|
||||
|
||||
10. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program.
|
||||
|
||||

|
||||
|
||||
|
||||
# TFT_eSPI
|
||||
|
||||
An Arduino IDE compatible graphics and fonts library for 32 bit processors. The library is targeted at 32 bit processors, it has been performance optimised for STM32, ESP8266 and ESP32 types. The library can be loaded using the Arduino IDE's Library Manager. Direct Memory Access (DMA) can be used with the ESP32, RP2040 and STM32 processors to improve rendering performance.
|
||||
@@ -87,6 +78,11 @@ Sprites can be plotted to the TFT with one colour being specified as "transparen
|
||||
|
||||
If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind.
|
||||
|
||||
The "Animated_dial" example shows how dials can be created using a rotated Sprite for the needle. To run this example the TFT interface must support reading from the screen RAM (not all do). The dial rim and scale is a jpeg image, created using a paint program.
|
||||
|
||||

|
||||
|
||||
|
||||
# Touch controller support
|
||||
|
||||
The XPT2046 touch screen controller is supported for SPI based displays only. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. This support will eventually be deprecated when a suitable touch screen library is available.
|
||||
|
45
TFT_eSPI.cpp
45
TFT_eSPI.cpp
@@ -22,7 +22,7 @@
|
||||
#include "Processors/TFT_eSPI_ESP8266.c"
|
||||
#elif defined (STM32) // (_VARIANT_ARDUINO_STM32_) stm32_def.h
|
||||
#include "Processors/TFT_eSPI_STM32.c"
|
||||
#elif defined (ARDUINO_ARCH_RP2040) // Raspberry Pi Pico
|
||||
#elif defined (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED) // Raspberry Pi Pico
|
||||
#include "Processors/TFT_eSPI_RP2040.c"
|
||||
#else
|
||||
#include "Processors/TFT_eSPI_Generic.c"
|
||||
@@ -78,7 +78,7 @@ inline void TFT_eSPI::begin_tft_write(void){
|
||||
***************************************************************************************/
|
||||
inline void TFT_eSPI::end_tft_write(void){
|
||||
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT)
|
||||
if(!inTransaction) { // Flag to stop ending tranaction during multiple graphics calls
|
||||
if(!inTransaction) { // Flag to stop ending transaction during multiple graphics calls
|
||||
if (!locked) { // Locked when beginTransaction has been called
|
||||
locked = true; // Flag to show SPI access now locked
|
||||
SPI_BUSY_CHECK; // Check send complete and clean out unused rx data
|
||||
@@ -345,11 +345,6 @@ inline void TFT_eSPI::end_tft_read(void){
|
||||
if(!inTransaction) {CS_H;}
|
||||
#endif
|
||||
SET_BUS_WRITE_MODE;
|
||||
|
||||
// The ST7796 appears to need a 4ms delay after a CGRAM read, otherwise subsequent writes will fail!
|
||||
#ifdef ST7796_DRIVER
|
||||
delay(4);
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
@@ -382,7 +377,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
||||
digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
|
||||
#endif
|
||||
|
||||
#ifdef TFT_WR
|
||||
// In parallel mode and with the RP2040 processor, the TFT_WR line is handled in the PIO
|
||||
#if defined (TFT_WR) && !defined (ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED)
|
||||
pinMode(TFT_WR, OUTPUT);
|
||||
digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive)
|
||||
#endif
|
||||
@@ -405,15 +401,17 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
||||
pinMode(TFT_RD, OUTPUT);
|
||||
digitalWrite(TFT_RD, HIGH);
|
||||
|
||||
// Set TFT data bus lines to output
|
||||
pinMode(TFT_D0, OUTPUT); digitalWrite(TFT_D0, HIGH);
|
||||
pinMode(TFT_D1, OUTPUT); digitalWrite(TFT_D1, HIGH);
|
||||
pinMode(TFT_D2, OUTPUT); digitalWrite(TFT_D2, HIGH);
|
||||
pinMode(TFT_D3, OUTPUT); digitalWrite(TFT_D3, HIGH);
|
||||
pinMode(TFT_D4, OUTPUT); digitalWrite(TFT_D4, HIGH);
|
||||
pinMode(TFT_D5, OUTPUT); digitalWrite(TFT_D5, HIGH);
|
||||
pinMode(TFT_D6, OUTPUT); digitalWrite(TFT_D6, HIGH);
|
||||
pinMode(TFT_D7, OUTPUT); digitalWrite(TFT_D7, HIGH);
|
||||
#if !defined (ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED)// PIO manages pins
|
||||
// Set TFT data bus lines to output
|
||||
pinMode(TFT_D0, OUTPUT); digitalWrite(TFT_D0, HIGH);
|
||||
pinMode(TFT_D1, OUTPUT); digitalWrite(TFT_D1, HIGH);
|
||||
pinMode(TFT_D2, OUTPUT); digitalWrite(TFT_D2, HIGH);
|
||||
pinMode(TFT_D3, OUTPUT); digitalWrite(TFT_D3, HIGH);
|
||||
pinMode(TFT_D4, OUTPUT); digitalWrite(TFT_D4, HIGH);
|
||||
pinMode(TFT_D5, OUTPUT); digitalWrite(TFT_D5, HIGH);
|
||||
pinMode(TFT_D6, OUTPUT); digitalWrite(TFT_D6, HIGH);
|
||||
pinMode(TFT_D7, OUTPUT); digitalWrite(TFT_D7, HIGH);
|
||||
#endif
|
||||
|
||||
CONSTRUCTOR_INIT_TFT_DATA_BUS;
|
||||
|
||||
@@ -523,7 +521,7 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
{
|
||||
if (_booted)
|
||||
{
|
||||
#if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(ARDUINO_ARCH_RP2040)
|
||||
#if !defined (ESP32) && !defined(TFT_PARALLEL_8_BIT) && !defined(ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED)
|
||||
// Legacy bitmasks for GPIO
|
||||
#if defined (TFT_CS) && (TFT_CS >= 0)
|
||||
cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
|
||||
@@ -552,7 +550,7 @@ void TFT_eSPI::init(uint8_t tc)
|
||||
|
||||
#else
|
||||
#if !defined(TFT_PARALLEL_8_BIT)
|
||||
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040)
|
||||
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040) && !defined (ARDUINO_ARCH_MBED)
|
||||
spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||
#else
|
||||
spi.begin();
|
||||
@@ -1261,7 +1259,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
|
||||
|
||||
data += dx + dy * w;
|
||||
|
||||
int32_t xe = x + dw - 1, ye = y + dh - 1;
|
||||
|
||||
uint16_t lineBuf[dw]; // Use buffer to minimise setWindow call count
|
||||
|
||||
@@ -1352,7 +1349,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
|
||||
data += dx + dy * w;
|
||||
|
||||
int32_t xe = x + dw - 1, ye = y + dh - 1;
|
||||
|
||||
uint16_t lineBuf[dw];
|
||||
|
||||
@@ -1673,7 +1669,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||
inTransaction = true;
|
||||
bool swap = _swapBytes;
|
||||
|
||||
int32_t xe = x + dw - 1, ye = y + dh - 1;
|
||||
|
||||
// Line buffer makes plotting faster
|
||||
uint16_t lineBuf[dw];
|
||||
@@ -3096,7 +3091,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||
#endif
|
||||
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
|
||||
#if (defined(ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(TFT_PARALLEL_8_BIT)
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
#if !defined (SPI_18BIT_DRIVER)
|
||||
@@ -3176,7 +3171,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||
#endif
|
||||
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#if defined(ARDUINO_ARCH_RP2040) && !defined(TFT_PARALLEL_8BIT)
|
||||
#if (defined(ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(TFT_PARALLEL_8_BIT)
|
||||
while (spi_get_hw(SPI_X)->sr & SPI_SSPSR_BSY_BITS) {};
|
||||
DC_C;
|
||||
spi_set_format(SPI_X, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST);
|
||||
@@ -3287,7 +3282,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||
#endif
|
||||
|
||||
// Temporary solution is to include the RP2040 optimised code here
|
||||
#elif defined (ARDUINO_ARCH_RP2040)
|
||||
#elif (defined (ARDUINO_ARCH_RP2040) || !defined (ARDUINO_ARCH_MBED)) && !defined(TFT_PARALLEL_8_BIT)
|
||||
|
||||
// Since the SPI functions do not terminate until transmission is complete
|
||||
// a busy check is not needed.
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#ifndef _TFT_eSPIH_
|
||||
#define _TFT_eSPIH_
|
||||
|
||||
#define TFT_ESPI_VERSION "2.3.89"
|
||||
#define TFT_ESPI_VERSION "2.4.0"
|
||||
|
||||
// Bit level feature flags
|
||||
// Bit 0 set: viewport capability
|
||||
@@ -655,6 +655,10 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
||||
// in progress, this simplifies the sketch and helps avoid "gotchas".
|
||||
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr);
|
||||
|
||||
#if defined (ESP32) // ESP32 only at the moment
|
||||
// For case where pointer is a const and the image data must not be modified (clipped or byte swapped)
|
||||
void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t const* data);
|
||||
#endif
|
||||
// Push a block of pixels into a window set up using setAddrWindow()
|
||||
void pushPixelsDMA(uint16_t* image, uint32_t len);
|
||||
|
||||
|
@@ -85,6 +85,12 @@
|
||||
|
||||
//#include <User_Setups/Setup71_ESP32_S2_ST7789.h> // Setup file for ESP32 S2 with ST7789
|
||||
|
||||
//#include <User_Setups/Setup100_RP2040_ILI9488_parallel.h>
|
||||
//#include <User_Setups/Setup101_RP2040_ILI9481_parallel.h>
|
||||
//#include <User_Setups/Setup102_RP2040_ILI9341_parallel.h>
|
||||
//#include <User_Setups/Setup103_RP2040_ILI9486_parallel.h>
|
||||
//#include <User_Setups/Setup104_RP2040_ST7796_parallel.h>
|
||||
|
||||
//#include <User_Setups/Setup135_ST7789.h> // Setup file for ESP8266 and ST7789 135 x 240 TFT
|
||||
|
||||
//#include <User_Setups/Setup136_LilyGo_TTV.h> // Setup file for ESP32 and Lilygo TTV ST7789 SPI bus TFT 135x240
|
||||
|
55
User_Setups/Setup100_RP2040_ILI9488_parallel.h
Normal file
55
User_Setups/Setup100_RP2040_ILI9488_parallel.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This setup is for the RP2040 processor only when used with 8 bit parallel displays
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Display driver type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ILI9488_DRIVER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RP2040 pins used
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#define TFT_CS -1 // Do not define, chip select control pin permanently connected to 0V
|
||||
|
||||
// These pins can be moved and are controlled directly by the library software
|
||||
#define TFT_DC 28 // Data Command control pin
|
||||
#define TFT_RST 2 // Reset pin
|
||||
|
||||
//#define TFT_RD -1 // Do not define, read pin permanently connected to 3V3
|
||||
|
||||
// Note: All the following pins are PIO hardware configured and driven
|
||||
// The pins are hard-coded at the moment and must not be changed here
|
||||
// Connections MUST use the pins below
|
||||
#define TFT_WR 22
|
||||
|
||||
// PIO requires these to be sequentially increasing - do not change
|
||||
#define TFT_D0 6
|
||||
#define TFT_D1 7
|
||||
#define TFT_D2 8
|
||||
#define TFT_D3 9
|
||||
#define TFT_D4 10
|
||||
#define TFT_D5 11
|
||||
#define TFT_D6 12
|
||||
#define TFT_D7 13
|
||||
//*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fonts to be available
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
55
User_Setups/Setup101_RP2040_ILI9481_parallel.h
Normal file
55
User_Setups/Setup101_RP2040_ILI9481_parallel.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This setup is for the RP2040 processor only when used with 8 bit parallel displays
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Display driver type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ILI9481_DRIVER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RP2040 pins used
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#define TFT_CS -1 // Do not define, chip select control pin permanently connected to 0V
|
||||
|
||||
// These pins can be moved and are controlled directly by the library software
|
||||
#define TFT_DC 28 // Data Command control pin
|
||||
#define TFT_RST 2 // Reset pin
|
||||
|
||||
//#define TFT_RD -1 // Do not define, read pin permanently connected to 3V3
|
||||
|
||||
// Note: All the following pins are PIO hardware configured and driven
|
||||
// The pins are hard-coded at the moment and must not be changed here
|
||||
// Connections MUST use the pins below
|
||||
#define TFT_WR 22
|
||||
|
||||
// PIO requires these to be sequentially increasing - do not change
|
||||
#define TFT_D0 6
|
||||
#define TFT_D1 7
|
||||
#define TFT_D2 8
|
||||
#define TFT_D3 9
|
||||
#define TFT_D4 10
|
||||
#define TFT_D5 11
|
||||
#define TFT_D6 12
|
||||
#define TFT_D7 13
|
||||
//*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fonts to be available
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
55
User_Setups/Setup102_RP2040_ILI9341_parallel.h
Normal file
55
User_Setups/Setup102_RP2040_ILI9341_parallel.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This setup is for the RP2040 processor only when used with 8 bit parallel displays
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Display driver type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ILI9341_DRIVER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RP2040 pins used
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#define TFT_CS -1 // Do not define, chip select control pin permanently connected to 0V
|
||||
|
||||
// These pins can be moved and are controlled directly by the library software
|
||||
#define TFT_DC 28 // Data Command control pin
|
||||
#define TFT_RST 2 // Reset pin
|
||||
|
||||
//#define TFT_RD -1 // Do not define, read pin permanently connected to 3V3
|
||||
|
||||
// Note: All the following pins are PIO hardware configured and driven
|
||||
// The pins are hard-coded at the moment and must not be changed here
|
||||
// Connections MUST use the pins below
|
||||
#define TFT_WR 22
|
||||
|
||||
// PIO requires these to be sequentially increasing - do not change
|
||||
#define TFT_D0 6
|
||||
#define TFT_D1 7
|
||||
#define TFT_D2 8
|
||||
#define TFT_D3 9
|
||||
#define TFT_D4 10
|
||||
#define TFT_D5 11
|
||||
#define TFT_D6 12
|
||||
#define TFT_D7 13
|
||||
//*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fonts to be available
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
55
User_Setups/Setup103_RP2040_ILI9486_parallel.h
Normal file
55
User_Setups/Setup103_RP2040_ILI9486_parallel.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This setup is for the RP2040 processor only when used with 8 bit parallel displays
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Display driver type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ILI9486_DRIVER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RP2040 pins used
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#define TFT_CS -1 // Do not define, chip select control pin permanently connected to 0V
|
||||
|
||||
// These pins can be moved and are controlled directly by the library software
|
||||
#define TFT_DC 28 // Data Command control pin
|
||||
#define TFT_RST 2 // Reset pin
|
||||
|
||||
//#define TFT_RD -1 // Do not define, read pin permanently connected to 3V3
|
||||
|
||||
// Note: All the following pins are PIO hardware configured and driven
|
||||
// The pins are hard-coded at the moment and must not be changed here
|
||||
// Connections MUST use the pins below
|
||||
#define TFT_WR 22
|
||||
|
||||
// PIO requires these to be sequentially increasing - do not change
|
||||
#define TFT_D0 6
|
||||
#define TFT_D1 7
|
||||
#define TFT_D2 8
|
||||
#define TFT_D3 9
|
||||
#define TFT_D4 10
|
||||
#define TFT_D5 11
|
||||
#define TFT_D6 12
|
||||
#define TFT_D7 13
|
||||
//*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fonts to be available
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
55
User_Setups/Setup104_RP2040_ST7796_parallel.h
Normal file
55
User_Setups/Setup104_RP2040_ST7796_parallel.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// This setup is for the RP2040 processor only when used with 8 bit parallel displays
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define TFT_PARALLEL_8_BIT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Display driver type
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define ST7796_DRIVER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RP2040 pins used
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#define TFT_CS -1 // Do not define, chip select control pin permanently connected to 0V
|
||||
|
||||
// These pins can be moved and are controlled directly by the library software
|
||||
#define TFT_DC 28 // Data Command control pin
|
||||
#define TFT_RST 2 // Reset pin
|
||||
|
||||
//#define TFT_RD -1 // Do not define, read pin permanently connected to 3V3
|
||||
|
||||
// Note: All the following pins are PIO hardware configured and driven
|
||||
// The pins are hard-coded at the moment and must not be changed here
|
||||
// Connections MUST use the pins below
|
||||
#define TFT_WR 22
|
||||
|
||||
// PIO requires these to be sequentially increasing - do not change
|
||||
#define TFT_D0 6
|
||||
#define TFT_D1 7
|
||||
#define TFT_D2 8
|
||||
#define TFT_D3 9
|
||||
#define TFT_D4 10
|
||||
#define TFT_D5 11
|
||||
#define TFT_D6 12
|
||||
#define TFT_D7 13
|
||||
//*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fonts to be available
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
#define SMOOTH_FONT
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
@@ -36,7 +36,8 @@
|
||||
//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI
|
||||
|
||||
// Only define one driver, the other ones must be commented out
|
||||
#define ILI9341_DRIVER
|
||||
#define ILI9341_DRIVER // Generic driver for common displays
|
||||
//#define ILI9341_2_DRIVER // Alternative ILI9341 driver, see https://github.com/Bodmer/TFT_eSPI/issues/1172
|
||||
//#define ST7735_DRIVER // Define additional parameters below for this display
|
||||
//#define ILI9163_DRIVER // Define additional parameters below for this display
|
||||
//#define S6D02A1_DRIVER
|
||||
@@ -50,6 +51,7 @@
|
||||
//#define R61581_DRIVER
|
||||
//#define RM68140_DRIVER
|
||||
//#define ST7796_DRIVER
|
||||
//#define SSD1351_DRIVER
|
||||
//#define SSD1963_480_DRIVER
|
||||
//#define SSD1963_800_DRIVER
|
||||
//#define SSD1963_800ALT_DRIVER
|
||||
@@ -80,12 +82,12 @@
|
||||
// #define TFT_HEIGHT 128
|
||||
// #define TFT_HEIGHT 240 // ST7789 240 x 240
|
||||
// #define TFT_HEIGHT 320 // ST7789 240 x 320
|
||||
#define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
// #define TFT_HEIGHT 240 // GC9A01 240 x 240
|
||||
|
||||
// For ST7735 ONLY, define the type of display, originally this was based on the
|
||||
// colour of the tab on the screen protector film but this is not always true, so try
|
||||
// out the different options below if the screen does not display graphics correctly,
|
||||
// e.g. colours wrong, mirror images, or tray pixels at the edges.
|
||||
// e.g. colours wrong, mirror images, or stray pixels at the edges.
|
||||
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
|
||||
// this User_Setup file, then rebuild and upload the sketch to the board again:
|
||||
|
||||
@@ -309,6 +311,12 @@
|
||||
//
|
||||
// ##################################################################################
|
||||
|
||||
// For the RP2040 processor define the SPI port channel used (default 0 if undefined)
|
||||
//#define TFT_SPI_PORT 1 // Set to 0 if SPI0 pins are used, or 1 if spi1 pins used
|
||||
|
||||
// For the STM32 processor define the SPI port channel used (default 1 if undefined)
|
||||
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2
|
||||
|
||||
// Define the SPI clock frequency, this affects the graphics rendering speed. Too
|
||||
// fast and the TFT driver will not keep up and display corruption appears.
|
||||
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
|
||||
|
@@ -1,12 +1,13 @@
|
||||
// This sketch is for the RP2040 and ILI9341 TFT display.
|
||||
// Other processors may work if they have sufficient RAM for
|
||||
// a full screen buffer (240 x 320 x 2 = 153,600 bytes).
|
||||
|
||||
// In this example 2 sprites are used to create DMA toggle
|
||||
// buffers. Each sprite is half the screen size, this allows
|
||||
// graphics to be rendered in one sprite at the same time
|
||||
// as the other sprite is being sent to the screen.
|
||||
|
||||
// RP2040 @ 62.5MHz SPI clock typically runs at 45-46 fps
|
||||
// RP2040 typically runs at 45-48 fps
|
||||
|
||||
// Created by Bodmer 20/04/2021 as an example for:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
@@ -14,6 +15,13 @@
|
||||
// Number of circles to draw
|
||||
#define CNUMBER 42
|
||||
|
||||
// Define the width and height according to the TFT and the
|
||||
// available memory. The sprites will require:
|
||||
// DWIDTH * DHEIGHT * 2 bytes of RAM
|
||||
// Note: for a 240 * 320 area this is 150 Kbytes!
|
||||
#define DWIDTH 240
|
||||
#define DHEIGHT 320
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
// Library instance
|
||||
@@ -55,12 +63,12 @@ void setup() {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Create the 2 sprites, each is half the size of the screen
|
||||
sprPtr[0] = (uint16_t*)spr[0].createSprite(tft.width(), tft.height() / 2);
|
||||
sprPtr[1] = (uint16_t*)spr[1].createSprite(tft.width(), tft.height() / 2);
|
||||
sprPtr[0] = (uint16_t*)spr[0].createSprite(DWIDTH, DHEIGHT / 2);
|
||||
sprPtr[1] = (uint16_t*)spr[1].createSprite(DWIDTH, DHEIGHT / 2);
|
||||
|
||||
// Move the sprite 1 coordinate datum upwards half the screen height
|
||||
// so from coordinate point of view it occupies the bottom of screen
|
||||
spr[1].setViewport(0, -tft.height() / 2, tft.width(), tft.height());
|
||||
spr[1].setViewport(0, -DHEIGHT / 2, DWIDTH, DHEIGHT);
|
||||
|
||||
// Define text datum for each Sprite
|
||||
spr[0].setTextDatum(MC_DATUM);
|
||||
@@ -72,8 +80,8 @@ void setup() {
|
||||
// Initialise circle parameters
|
||||
for (uint16_t i = 0; i < CNUMBER; i++) {
|
||||
circle->cr[i] = random(12, 24);
|
||||
circle->cx[i] = random(circle->cr[i], tft.width() - circle->cr[i]);
|
||||
circle->cy[i] = random(circle->cr[i], tft.height() - circle->cr[i]);
|
||||
circle->cx[i] = random(circle->cr[i], DWIDTH - circle->cr[i]);
|
||||
circle->cy[i] = random(circle->cr[i], DHEIGHT - circle->cr[i]);
|
||||
|
||||
circle->col[i] = rainbow(4 * i);
|
||||
circle->dx[i] = random(1, 5);
|
||||
@@ -82,7 +90,7 @@ void setup() {
|
||||
if (random(2)) circle->dy[i] = -circle->dy[i];
|
||||
}
|
||||
|
||||
tft.startWrite(); // TFT chip select held low permanently
|
||||
// tft.startWrite(); // TFT chip select held low permanently
|
||||
|
||||
startMillis = millis();
|
||||
}
|
||||
@@ -117,7 +125,7 @@ void drawUpdate (bool sel) {
|
||||
spr[sel].drawNumber(i + 1, 1 + circle->cx[i], circle->cy[i], 2);
|
||||
}
|
||||
|
||||
tft.pushImageDMA(0, sel * tft.height() / 2, tft.width(), tft.height() / 2, sprPtr[sel]);
|
||||
tft.pushImageDMA(0, sel * DHEIGHT / 2, DWIDTH, DHEIGHT / 2, sprPtr[sel]);
|
||||
|
||||
// Update circle positions after bottom half has been drawn
|
||||
if (sel) {
|
||||
@@ -128,16 +136,16 @@ void drawUpdate (bool sel) {
|
||||
circle->cx[i] = circle->cr[i];
|
||||
circle->dx[i] = -circle->dx[i];
|
||||
}
|
||||
else if (circle->cx[i] + circle->cr[i] >= tft.width() - 1) {
|
||||
circle->cx[i] = tft.width() - circle->cr[i] - 1;
|
||||
else if (circle->cx[i] + circle->cr[i] >= DWIDTH - 1) {
|
||||
circle->cx[i] = DWIDTH - circle->cr[i] - 1;
|
||||
circle->dx[i] = -circle->dx[i];
|
||||
}
|
||||
if (circle->cy[i] <= circle->cr[i]) {
|
||||
circle->cy[i] = circle->cr[i];
|
||||
circle->dy[i] = -circle->dy[i];
|
||||
}
|
||||
else if (circle->cy[i] + circle->cr[i] >= tft.height() - 1) {
|
||||
circle->cy[i] = tft.height() - circle->cr[i] - 1;
|
||||
else if (circle->cy[i] + circle->cr[i] >= DHEIGHT - 1) {
|
||||
circle->cy[i] = DHEIGHT - circle->cr[i] - 1;
|
||||
circle->dy[i] = -circle->dy[i];
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TFT_eSPI",
|
||||
"version": "2.3.89",
|
||||
"version": "2.4.0",
|
||||
"keywords": "Arduino, tft, ePaper, display, Pico, RP2040, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9481, ILI9486, ILI9488, ST7789, RM68140, SSD1351, SSD1963, ILI9225, HX8357D",
|
||||
"description": "A TFT and ePaper SPI graphics library with optimisation for Raspberry Pi Pico, ESP8266, ESP32 and STM32",
|
||||
"repository":
|
||||
|
@@ -1,5 +1,5 @@
|
||||
name=TFT_eSPI
|
||||
version=2.3.89
|
||||
version=2.4.0
|
||||
author=Bodmer
|
||||
maintainer=Bodmer
|
||||
sentence=TFT graphics library for Arduino processors with performance optimisation for RP2040, STM32, ESP8266 and ESP32
|
||||
|
Reference in New Issue
Block a user