diff --git a/Processors/TFT_eSPI_STM32.c b/Processors/TFT_eSPI_STM32.c index c3acaa7..162e732 100644 --- a/Processors/TFT_eSPI_STM32.c +++ b/Processors/TFT_eSPI_STM32.c @@ -10,8 +10,11 @@ // No globals #else // Use STM32 default SPI port - SPIClass& spi = SPI; - + #if !defined (TFT_MOSI) || !defined (TFT_MISO) || !defined (TFT_SCLK) + SPIClass& spi = SPI; + #else + SPIClass spi(TFT_MOSI, TFT_MISO, TFT_SCLK); + #endif // SPI HAL peripheral handle SPI_HandleTypeDef spiHal; #endif @@ -484,15 +487,20 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t // The DMA functions here work with SPI only (not parallel) #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) /*************************************************************************************** -** Function name: DMA2_StreamX_IRQHandler -** Description: Override the default HAL stream 3 interrupt handler +** Function name: DMAX_StreamX_IRQHandler +** Description: Override the default HAL stream X interrupt handler ***************************************************************************************/ -extern "C" void DMA2_Stream3_IRQHandler(); -void DMA2_Stream3_IRQHandler(void) -{ - // Call the default end of buffer handler - HAL_DMA_IRQHandler(&dmaHal); -} + #if (TFT_SPI_PORT == 1) + extern "C" void DMA2_Stream3_IRQHandler(); + void DMA2_Stream3_IRQHandler(void) + #elif (TFT_SPI_PORT == 2) + extern "C" void DMA1_Stream4_IRQHandler(); + void DMA1_Stream4_IRQHandler(void) + #endif + { + // Call the default end of buffer handler + HAL_DMA_IRQHandler(&dmaHal); + } /*************************************************************************************** ** Function name: initDMA @@ -503,9 +511,14 @@ void DMA2_Stream3_IRQHandler(void) // https://electronics.stackexchange.com/questions/379813/configuring-the-dma-request-multiplexer-on-a-stm32h7-mcu bool TFT_eSPI::initDMA(void) { - __HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock + #if (TFT_SPI_PORT == 1) + __HAL_RCC_DMA2_CLK_ENABLE(); // Enable DMA2 clock + dmaHal.Init.Channel = DMA_CHANNEL_3; // DMA channel 3 is for SPI1 TX + #elif (TFT_SPI_PORT == 2) + __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA2 clock + dmaHal.Init.Channel = DMA_CHANNEL_0; // DMA channel 0 is for SPI2 TX + #endif - dmaHal.Init.Channel = DMA_CHANNEL_3; // DMA channel 3 is for SPI1 TX dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH; // Copy memory to the peripheral dmaHal.Init.PeriphInc = DMA_PINC_DISABLE; // Don't increment peripheral address @@ -517,10 +530,13 @@ bool TFT_eSPI::initDMA(void) // Insert error message here? return DMA_Enabled = false; }; + #if (TFT_SPI_PORT == 1) + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); // Enable DMA end interrupt handler + #elif (TFT_SPI_PORT == 2) + HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn); // Enable DMA end interrupt handler + #endif - HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); // Enable DMA end interrupt handler - - __HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral + __HAL_LINKDMA(&spiHal, hdmatx, dmaHal); // Attach DMA engine to SPI peripheral return DMA_Enabled = true; } @@ -530,13 +546,18 @@ bool TFT_eSPI::initDMA(void) ** Function name: DMA1_ChannelX_IRQHandler ** Description: Override the default HAL stream 3 interrupt handler ***************************************************************************************/ -extern "C" void DMA1_Channel3_IRQHandler(); + #if (TFT_SPI_PORT == 1) + extern "C" void DMA1_Channel3_IRQHandler(); + void DMA1_Channel3_IRQHandler(void) + #elif (TFT_SPI_PORT == 2) + extern "C" void DMA1_Channel5_IRQHandler(); + void DMA1_Channel5_IRQHandler(void) + #endif + { + // Call the default end of buffer handler + HAL_DMA_IRQHandler(&dmaHal); + } -void DMA1_Channel3_IRQHandler(void) -{ - // Call the default end of buffer handler - HAL_DMA_IRQHandler(&dmaHal); -} //*/ /*************************************************************************************** ** Function name: initDMA @@ -544,7 +565,7 @@ void DMA1_Channel3_IRQHandler(void) ***************************************************************************************/ bool TFT_eSPI::initDMA(void) { - __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA2 clock + __HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA1 clock dmaHal.Init.Mode = DMA_NORMAL; //DMA_CIRCULAR; // // Normal = send buffer once dmaHal.Init.Direction = DMA_MEMORY_TO_PERIPH; // Copy memory to the peripheral @@ -561,9 +582,13 @@ bool TFT_eSPI::initDMA(void) return DMA_Enabled = false; }; - HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); // Enable DMA end interrupt handler - + #if (TFT_SPI_PORT == 1) + HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); // Enable DMA end interrupt handler + #elif (TFT_SPI_PORT == 2) + HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); // Enable DMA end interrupt handler + #endif return DMA_Enabled = true; } diff --git a/Processors/TFT_eSPI_STM32.h b/Processors/TFT_eSPI_STM32.h index 4da52f7..6fcab87 100644 --- a/Processors/TFT_eSPI_STM32.h +++ b/Processors/TFT_eSPI_STM32.h @@ -146,23 +146,49 @@ //////////////////////////////////////////////////////////////////////////////////////// #else + // Use SPI1 as default if not defined + #ifndef TFT_SPI_PORT + #define TFT_SPI_PORT 1 + #endif + // Global define is _VARIANT_ARDUINO_STM32_, see board package stm32_def.h for specific variants #if defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) + #define STM32_DMA // DMA is available with these processors - // Initialise processor specific SPI and DMA instances - used by init() - #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ - dmaHal.Instance = DMA2_Stream3 - // The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows: - // DMA_CHANNEL_3 - // DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler() + + #if (TFT_SPI_PORT == 1) + // Initialise processor specific SPI and DMA instances - used by init() + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ + dmaHal.Instance = DMA2_Stream3 + // The DMA hard-coding for SPI1 is in TFT_eSPI_STM32.c as follows: + // DMA_CHANNEL_3 + // DMA2_Stream3_IRQn and DMA2_Stream3_IRQHandler() + #elif (TFT_SPI_PORT == 2) + // Initialise processor specific SPI and DMA instances - used by init() + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \ + dmaHal.Instance = DMA1_Stream4 + // The DMA hard-coding for SPI2 is in TFT_eSPI_STM32.c as follows: + // DMA_CHANNEL_4 + // DMA1_Stream4_IRQn and DMA1_Stream4_IRQHandler() + #endif + #elif defined (STM32F1xx) // For Blue Pill and STM32F1xx processors with DMA support #define STM32_DMA // DMA is available with these processors - #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ - dmaHal.Instance = DMA1_Channel3 + #if (TFT_SPI_PORT == 1) + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1; \ + dmaHal.Instance = DMA1_Channel3 + #elif (TFT_SPI_PORT == 2) + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2; \ + dmaHal.Instance = DMA1_Channel5 + #endif #else // For STM32 processor with no implemented DMA support (yet) - #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1 + #if (TFT_SPI_PORT == 1) + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI1 + #elif (TFT_SPI_PORT == 2) + #define INIT_TFT_DATA_BUS spiHal.Instance = SPI2 + #endif #endif #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 059e644..416ad7e 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -16,7 +16,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "2.2.11" +#define TFT_ESPI_VERSION "2.2.12" /*************************************************************************************** ** Section 1: Load required header files diff --git a/User_Setup.h b/User_Setup.h index 754215f..32eea56 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -236,6 +236,31 @@ //#define TFT_D6 27 //#define TFT_D7 14 +// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ###### + +// The TFT can be connected to SPI port 1 or 2 +//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz +//#define TFT_MOSI PA7 +//#define TFT_MISO PA6 +//#define TFT_SCLK PA5 + +//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz +//#define TFT_MOSI PB15 +//#define TFT_MISO PB14 +//#define TFT_SCLK PB13 + +// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select +//#define TFT_CS D5 // Chip select control pin to TFT CS +//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select) +//#define TFT_RST D7 // Reset pin to TFT RST (or RESET) +// OR alternatively, we can use STM32 port reference names PXnn +//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5 +//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6 +//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7 + +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset + // Use an Arduino pin for initial testing as connecting to processor reset + // may not work (pulse too short at power up?) // ################################################################################## // @@ -278,8 +303,9 @@ // #define SPI_FREQUENCY 5000000 // #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +#define SPI_FREQUENCY 27000000 // #define SPI_FREQUENCY 40000000 +// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz) // #define SPI_FREQUENCY 80000000 // Optional reduced SPI frequency for reading TFT diff --git a/User_Setups/Setup29_ILI9341_STM32.h b/User_Setups/Setup29_ILI9341_STM32.h index 0a8dc82..e7ccae4 100644 --- a/User_Setups/Setup29_ILI9341_STM32.h +++ b/User_Setups/Setup29_ILI9341_STM32.h @@ -22,7 +22,18 @@ // MOSI and SCK do not need to be defined, connect: // - Arduino SCK to TFT SCK // - Arduino MOSI to TFT SDI(may be marked SDA or MOSI) -// Standard Arduino SPI pins are (SCK=D13, MOSI=D11) this is port pins PA5 and PA7 on Nucleo-F767ZI +// Typical Arduino SPI port 1 pins are (SCK=D13, MISO=D12, MOSI=D11) this is port pins PA5, PA6 and PA7 on Nucleo-F767ZI +// SPI port 2 pins are (SCK=D18, MISO=A7, MOSI=D17) this is typically port pins PB13, PB14 and PB15 + +#define TFT_SPI_PORT 1 // SPI 1 maximum clock rate is 55MHz +#define TFT_MOSI PA7 +#define TFT_MISO PA6 +#define TFT_SCLK PA5 + +//#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz +//#define TFT_MOSI PB15 +//#define TFT_MISO PB14 +//#define TFT_SCLK PB13 // Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select #define TFT_CS D5 // Chip select control pin to TFT CS diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 8c4e5e2..32eea56 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -8,6 +8,7 @@ // run without the need to make any more changes for a particular hardware setup! // Note that some sketches are designed for a particular TFT pixel width/height + // ################################################################################## // // Section 1. Call up the right driver file and any options for it @@ -22,7 +23,13 @@ //#define NUCLEO_64_TFT //#define NUCLEO_144_TFT -// Tell the library to use 8 bit parallel mode(otherwise SPI is assumed) +// STM32 8 bit parallel only: +// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7 +// then this will improve rendering performance by a factor of ~8x +//#define STM_PORTA_DATA_BUS +//#define STM_PORTA_DATA_BUS + +// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT // Display type - only define if RPi display @@ -33,6 +40,7 @@ //#define ST7735_DRIVER // Define additional parameters below for this display //#define ILI9163_DRIVER // Define additional parameters below for this display //#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI //#define HX8357D_DRIVER //#define ILI9481_DRIVER //#define ILI9486_DRIVER @@ -91,13 +99,6 @@ // #define TFT_INVERSION_ON // #define TFT_INVERSION_OFF -// If a backlight control signal is available then define the TFT_BL pin in Section 2 -// below. The backlight will be turned ON when tft.begin() is called, but the library -// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be -// driven with a PWM signal or turned OFF/ON then this must be handled by the user -// sketch. e.g. with digitalWrite(TFT_BL, LOW); - -// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options // ################################################################################## // @@ -105,6 +106,17 @@ // // ################################################################################## +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + +// #define TFT_BL 32 // LED back-light control pin +// #define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW) + + + // We must use hardware SPI, a minimum of 3 GPIO pins is needed. // Typical setup for ESP8266 NodeMCU ESP-12 is : // @@ -181,8 +193,6 @@ //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) - //#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen //#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only @@ -203,10 +213,11 @@ // Wemos D32 boards need to be modified, see diagram in Tools folder. // Only ILI9481 and ILI9341 based displays have been tested! -// Parallel bus is only supported on ESP32 -// Uncomment line below to use ESP32 Parallel interface instead of SPI +// Parallel bus is only supported for the STM32 and ESP32 +// Example below is for ESP32 Parallel interface with UNO displays -//#define ESP32_PARALLEL +// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +//#define TFT_PARALLEL_8_BIT // The ESP32 and TFT the pins used for testing are: //#define TFT_CS 33 // Chip select control pin (library pulls permanently low @@ -225,6 +236,31 @@ //#define TFT_D6 27 //#define TFT_D7 14 +// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ###### + +// The TFT can be connected to SPI port 1 or 2 +//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz +//#define TFT_MOSI PA7 +//#define TFT_MISO PA6 +//#define TFT_SCLK PA5 + +//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz +//#define TFT_MOSI PB15 +//#define TFT_MISO PB14 +//#define TFT_SCLK PB13 + +// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select +//#define TFT_CS D5 // Chip select control pin to TFT CS +//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select) +//#define TFT_RST D7 // Reset pin to TFT RST (or RESET) +// OR alternatively, we can use STM32 port reference names PXnn +//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5 +//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6 +//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7 + +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset + // Use an Arduino pin for initial testing as connecting to processor reset + // may not work (pulse too short at power up?) // ################################################################################## // @@ -262,14 +298,14 @@ // With an ILI9341 display 40MHz works OK, 80MHz sometimes fails // With a ST7735 display more than 27MHz may not work (spurious pixels and lines) // With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. // #define SPI_FREQUENCY 1000000 // #define SPI_FREQUENCY 5000000 // #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz) // #define SPI_FREQUENCY 80000000 // Optional reduced SPI frequency for reading TFT diff --git a/library.json b/library.json index f0c9182..63596f5 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.2.11", + "version": "2.2.12", "keywords": "Arduino, tft, ePaper, display, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140", "description": "A TFT and ePaper SPI graphics library with optimisation for ESP8266, ESP32 and STM32", "repository": diff --git a/library.properties b/library.properties index cb0e3f8..e3559e6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=2.2.11 +version=2.2.12 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32