From e2f7bc173572e6fc5482df3702ffe04c92fa043e Mon Sep 17 00:00:00 2001 From: jonesfu Date: Fri, 22 Oct 2021 22:44:36 +0800 Subject: [PATCH] Support Software SPI processor * some project can't use MCU SPI inteface because it will break other real-time interrupt service so that user software spi instead of spi bus --- Processors/TFT_eSPI_SWSPI.c | 37 ++++++++++++++++++++++ Processors/TFT_eSPI_SWSPI.h | 62 +++++++++++++++++++++++++++++++++++++ TFT_eSPI.cpp | 28 ++++++++++++++++- TFT_eSPI.h | 4 ++- 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Processors/TFT_eSPI_SWSPI.c create mode 100644 Processors/TFT_eSPI_SWSPI.h diff --git a/Processors/TFT_eSPI_SWSPI.c b/Processors/TFT_eSPI_SWSPI.c new file mode 100644 index 0000000..bb2fd98 --- /dev/null +++ b/Processors/TFT_eSPI_SWSPI.c @@ -0,0 +1,37 @@ + //////////////////////////////////////////////////// + // TFT_eSPI Software SPI driver functions // + //////////////////////////////////////////////////// + +/*************************************************************************************** +** Function name: tft_Write8_8 +** Description: basic softare SPI write function +***************************************************************************************/ +void tft_Write_8(uint8_t c) +{ + for(uint8_t bit = 0x80; bit; bit >>= 1) { + if(c & bit) digitalWrite(TFT_MOSI, HIGH); + else digitalWrite(TFT_MOSI, LOW); + digitalWrite(TFT_SCLK, HIGH); + digitalWrite(TFT_SCLK, LOW); + } +} + +/*************************************************************************************** +** Function name: pushPixels - for software SPI +** 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-- ) {tft_Write_16(*data); data++;} + else while ( len-- ) {tft_Write_16S(*data); data++;} +} + +/*************************************************************************************** +** Function name: pushBlock - for software SPI +** Description: Write a block of pixels of the same colour +***************************************************************************************/ +void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){ + while (len--) {tft_Write_16(color);} +} \ No newline at end of file diff --git a/Processors/TFT_eSPI_SWSPI.h b/Processors/TFT_eSPI_SWSPI.h new file mode 100644 index 0000000..e41ce88 --- /dev/null +++ b/Processors/TFT_eSPI_SWSPI.h @@ -0,0 +1,62 @@ + //////////////////////////////////////////////////// + // TFT_eSPI Sotware SPI driver functions // + //////////////////////////////////////////////////// + +// This is a software api driver for Arduino boards, it supports SPI interface displays + +#ifndef _TFT_eSPI_SWSPI_ +#define _TFT_eSPI_SWSPI_ + +// Initialise processor specific SPI functions, used by init() +#define INIT_TFT_DATA_BUS // Not used + +// 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 + +// Code to check if DMA is busy, used by SPI bus transaction startWrite and endWrite functions +#define DMA_BUSY_CHECK // Not used so leave blank + +//////////////////////////////////////////////////////////////////////////////////////// +// Define the DC (TFT Data/Command or Register Select (RS))pin drive code +//////////////////////////////////////////////////////////////////////////////////////// +#ifndef TFT_DC + #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 digitalWrite(TFT_DC, LOW) + #define DC_D digitalWrite(TFT_DC, HIGH) +#endif + +//////////////////////////////////////////////////////////////////////////////////////// +// 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 +#else + #define CS_L digitalWrite(TFT_CS, LOW) + #define CS_H digitalWrite(TFT_CS, HIGH) +#endif + +//////////////////////////////////////////////////////////////////////////////////////// +// Macros to write commands/pixel colour data to a SPI +//////////////////////////////////////////////////////////////////////////////////////// + + // Write 16 bits to TFT + #define tft_Write_16(C) tft_Write_8(C>>8); tft_Write_8(C) + + // Write Swapped 16 bits to TFT + #define tft_Write_16S(C) uint16_t Cswap = ((C) >>8 | (C) << 8); \ + tft_Write_16(Cswap) + + // Future option for transfer without wait + #define tft_Write_16N(C) tft_Write_16(C) + + // Write two concatenated 16 bit values to TFT + #define tft_Write_32C(C,D) tft_Write_16(C); tft_Write_16(D); + + // Write same value twice + #define tft_Write_32D(C) tft_Write_16((uint16_t) (C)); tft_Write_16((uint16_t) (C)) + +#endif // Header end diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 493d01f..e261acc 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -16,7 +16,9 @@ #include "TFT_eSPI.h" -#if defined (ESP32) +#if defined (TFT_eSPI_USE_SWSPI) + #include "Processors/TFT_eSPI_SWSPI.c" +#elif defined (ESP32) #include "Processors/TFT_eSPI_ESP32.c" #elif defined (ESP8266) #include "Processors/TFT_eSPI_ESP8266.c" @@ -106,8 +108,10 @@ inline void TFT_eSPI::begin_tft_read(void){ CS_L; } #else + #ifndef TFT_eSPI_USE_SWSPI #if !defined(TFT_PARALLEL_8_BIT) spi.setFrequency(SPI_READ_FREQUENCY); + #endif #endif CS_L; #endif @@ -339,8 +343,10 @@ inline void TFT_eSPI::end_tft_read(void){ } } #else + #ifndef TFT_eSPI_USE_SWSPI #if !defined(TFT_PARALLEL_8_BIT) spi.setFrequency(SPI_FREQUENCY); + #endif #endif if(!inTransaction) {CS_H;} #endif @@ -552,12 +558,14 @@ void TFT_eSPI::init(uint8_t tc) #else #if !defined(TFT_PARALLEL_8_BIT) + #ifndef TFT_eSPI_USE_SWSPI #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040) spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); #else spi.begin(); #endif #endif + #endif #endif lockTransaction = false; inTransaction = false; @@ -566,6 +574,10 @@ void TFT_eSPI::init(uint8_t tc) INIT_TFT_DATA_BUS; +#ifdef TFT_eSPI_USE_SWSPI + pinMode(TFT_SCLK, OUTPUT); + pinMode(TFT_MOSI, OUTPUT); +#endif #ifdef TFT_CS // Set to output once again in case ESP8266 D6 (MISO) is used for CS @@ -852,6 +864,7 @@ void TFT_eSPI::writedata(uint8_t d) uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) { uint8_t reg = 0; +#ifndef TFT_eSPI_USE_SWSPI #ifdef TFT_PARALLEL_8_BIT writecommand(cmd_function); // Sets DC and CS high @@ -883,6 +896,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) reg = tft_Read_8(); end_tft_read(); +#endif #endif return reg; } @@ -926,6 +940,9 @@ uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) ***************************************************************************************/ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) { +#ifdef TFT_eSPI_USE_SWSPI + return 0; +#else if (_vpOoB) return 0; x0+= _xDatum; @@ -1041,6 +1058,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) return color; +#endif #endif } @@ -1058,6 +1076,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da { PI_CLIP ; +#ifndef TFT_eSPI_USE_SWSPI #if defined(TFT_PARALLEL_8_BIT) CS_L; @@ -1203,6 +1222,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da // Reinstate the transaction if one was in progress if(wasInTransaction) { begin_tft_write(); inTransaction = true; } #endif +#endif } @@ -1888,6 +1908,7 @@ bool TFT_eSPI::getSwapBytes(void) // If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) { +#ifndef TFT_eSPI_USE_SWSPI #if defined(TFT_PARALLEL_8_BIT) uint32_t len = w * h; @@ -1951,6 +1972,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ end_tft_read(); +#endif #endif } @@ -3145,6 +3167,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) ***************************************************************************************/ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { +#ifndef TFT_eSPI_USE_SWSPI //begin_tft_write(); // Must be called before readAddrWindow or CS set low int32_t xe = xs + w - 1; @@ -3216,6 +3239,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) DC_D; #endif // RP2040 SPI +#endif //end_tft_write(); // Must be called after readAddrWindow or CS set high } @@ -4814,12 +4838,14 @@ void TFT_eSPI::setTextFont(uint8_t f) ** Function name: getSPIinstance ** Description: Get the instance of the SPI class ***************************************************************************************/ +#ifndef TFT_eSPI_USE_SWSPI #if !defined (TFT_PARALLEL_8_BIT) SPIClass& TFT_eSPI::getSPIinstance(void) { return spi; } #endif +#endif /*************************************************************************************** ** Function name: getSetup diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 78a7f5b..8dd7cd8 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -61,7 +61,9 @@ #endif // Include the processor specific drivers -#if defined (ESP32) +#if defined (TFT_eSPI_USE_SWSPI) + #include "Processors/TFT_eSPI_SWSPI.h" +#elif defined (ESP32) #include "Processors/TFT_eSPI_ESP32.h" #elif defined (ESP8266) #include "Processors/TFT_eSPI_ESP8266.h"