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
This commit is contained in:
jonesfu 2021-10-22 22:44:36 +08:00
parent 9e64092f58
commit e2f7bc1735
4 changed files with 129 additions and 2 deletions

View File

@ -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);}
}

View File

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

View File

@ -16,7 +16,9 @@
#include "TFT_eSPI.h" #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" #include "Processors/TFT_eSPI_ESP32.c"
#elif defined (ESP8266) #elif defined (ESP8266)
#include "Processors/TFT_eSPI_ESP8266.c" #include "Processors/TFT_eSPI_ESP8266.c"
@ -106,8 +108,10 @@ inline void TFT_eSPI::begin_tft_read(void){
CS_L; CS_L;
} }
#else #else
#ifndef TFT_eSPI_USE_SWSPI
#if !defined(TFT_PARALLEL_8_BIT) #if !defined(TFT_PARALLEL_8_BIT)
spi.setFrequency(SPI_READ_FREQUENCY); spi.setFrequency(SPI_READ_FREQUENCY);
#endif
#endif #endif
CS_L; CS_L;
#endif #endif
@ -339,8 +343,10 @@ inline void TFT_eSPI::end_tft_read(void){
} }
} }
#else #else
#ifndef TFT_eSPI_USE_SWSPI
#if !defined(TFT_PARALLEL_8_BIT) #if !defined(TFT_PARALLEL_8_BIT)
spi.setFrequency(SPI_FREQUENCY); spi.setFrequency(SPI_FREQUENCY);
#endif
#endif #endif
if(!inTransaction) {CS_H;} if(!inTransaction) {CS_H;}
#endif #endif
@ -552,12 +558,14 @@ void TFT_eSPI::init(uint8_t tc)
#else #else
#if !defined(TFT_PARALLEL_8_BIT) #if !defined(TFT_PARALLEL_8_BIT)
#ifndef TFT_eSPI_USE_SWSPI
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040) #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) && !defined(ARDUINO_ARCH_RP2040)
spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
#else #else
spi.begin(); spi.begin();
#endif #endif
#endif #endif
#endif
#endif #endif
lockTransaction = false; lockTransaction = false;
inTransaction = false; inTransaction = false;
@ -566,6 +574,10 @@ void TFT_eSPI::init(uint8_t tc)
INIT_TFT_DATA_BUS; INIT_TFT_DATA_BUS;
#ifdef TFT_eSPI_USE_SWSPI
pinMode(TFT_SCLK, OUTPUT);
pinMode(TFT_MOSI, OUTPUT);
#endif
#ifdef TFT_CS #ifdef TFT_CS
// Set to output once again in case ESP8266 D6 (MISO) is used for 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 TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index)
{ {
uint8_t reg = 0; uint8_t reg = 0;
#ifndef TFT_eSPI_USE_SWSPI
#ifdef TFT_PARALLEL_8_BIT #ifdef TFT_PARALLEL_8_BIT
writecommand(cmd_function); // Sets DC and CS high 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(); reg = tft_Read_8();
end_tft_read(); end_tft_read();
#endif
#endif #endif
return reg; 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) uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
{ {
#ifdef TFT_eSPI_USE_SWSPI
return 0;
#else
if (_vpOoB) return 0; if (_vpOoB) return 0;
x0+= _xDatum; x0+= _xDatum;
@ -1041,6 +1058,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
return color; return color;
#endif
#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 ; PI_CLIP ;
#ifndef TFT_eSPI_USE_SWSPI
#if defined(TFT_PARALLEL_8_BIT) #if defined(TFT_PARALLEL_8_BIT)
CS_L; 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 // Reinstate the transaction if one was in progress
if(wasInTransaction) { begin_tft_write(); inTransaction = true; } if(wasInTransaction) { begin_tft_write(); inTransaction = true; }
#endif #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 // 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) 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) #if defined(TFT_PARALLEL_8_BIT)
uint32_t len = w * h; 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(); end_tft_read();
#endif
#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) 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 //begin_tft_write(); // Must be called before readAddrWindow or CS set low
int32_t xe = xs + w - 1; 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; DC_D;
#endif // RP2040 SPI #endif // RP2040 SPI
#endif
//end_tft_write(); // Must be called after readAddrWindow or CS set high //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 ** Function name: getSPIinstance
** Description: Get the instance of the SPI class ** Description: Get the instance of the SPI class
***************************************************************************************/ ***************************************************************************************/
#ifndef TFT_eSPI_USE_SWSPI
#if !defined (TFT_PARALLEL_8_BIT) #if !defined (TFT_PARALLEL_8_BIT)
SPIClass& TFT_eSPI::getSPIinstance(void) SPIClass& TFT_eSPI::getSPIinstance(void)
{ {
return spi; return spi;
} }
#endif #endif
#endif
/*************************************************************************************** /***************************************************************************************
** Function name: getSetup ** Function name: getSetup

View File

@ -61,7 +61,9 @@
#endif #endif
// Include the processor specific drivers // 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" #include "Processors/TFT_eSPI_ESP32.h"
#elif defined (ESP8266) #elif defined (ESP8266)
#include "Processors/TFT_eSPI_ESP8266.h" #include "Processors/TFT_eSPI_ESP8266.h"