Use hardware 9-bit SPI to talk to ST7787 controller.
This commit is contained in:
parent
c52327324f
commit
aa9352a7b2
|
|
@ -17,6 +17,9 @@ $RECYCLE.BIN/
|
||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*~
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Operating System Files
|
# Operating System Files
|
||||||
# =========================
|
# =========================
|
||||||
|
|
|
||||||
218
TFT_eSPI.cpp
218
TFT_eSPI.cpp
|
|
@ -24,9 +24,7 @@
|
||||||
//#include <limits.h>
|
//#include <limits.h>
|
||||||
//#include "pins_arduino.h"
|
//#include "pins_arduino.h"
|
||||||
//#include "wiring_private.h"
|
//#include "wiring_private.h"
|
||||||
#ifndef ST7787_DRIVER
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
// If it is a 16bit serial display we must transfer 16 bits every time
|
// If it is a 16bit serial display we must transfer 16 bits every time
|
||||||
#ifdef RPI_ILI9486_DRIVER
|
#ifdef RPI_ILI9486_DRIVER
|
||||||
|
|
@ -46,7 +44,13 @@ void spiWriteBlock(uint16_t color, uint32_t repeat);
|
||||||
inline void TFT_eSPI::spi_begin(void){
|
inline void TFT_eSPI::spi_begin(void){
|
||||||
#ifdef SPI_HAS_TRANSACTION
|
#ifdef SPI_HAS_TRANSACTION
|
||||||
#ifdef SUPPORT_TRANSACTIONS
|
#ifdef SUPPORT_TRANSACTIONS
|
||||||
if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));}
|
if (locked) {
|
||||||
|
locked = false;
|
||||||
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
SPI1U |= (uint32_t)(SPIUWRBYO|SPIURDBYO);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +58,15 @@ inline void TFT_eSPI::spi_begin(void){
|
||||||
inline void TFT_eSPI::spi_end(void){
|
inline void TFT_eSPI::spi_end(void){
|
||||||
#ifdef SPI_HAS_TRANSACTION
|
#ifdef SPI_HAS_TRANSACTION
|
||||||
#ifdef SUPPORT_TRANSACTIONS
|
#ifdef SUPPORT_TRANSACTIONS
|
||||||
if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}}
|
if(!inTransaction) {
|
||||||
|
if (!locked) {
|
||||||
|
locked = true;
|
||||||
|
SPI.endTransaction();
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
SPI1U &= ~(uint32_t)(SPIUWRBYO|SPIURDBYO);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -192,11 +204,12 @@ void TFT_eSPI::init(void)
|
||||||
cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
|
cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ST7787_DRIVER
|
#if !defined(IFACE_3WIRE) || defined(IFACE_3WIRE_ESP8266)
|
||||||
SPI.begin(); // This will set HMISO to input
|
SPI.begin(); // This will set HMISO to input
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP)
|
#if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP)
|
||||||
|
// ToDo: handle 3-wire interface on ESP32.
|
||||||
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1);
|
||||||
#else
|
#else
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
|
|
@ -207,12 +220,14 @@ void TFT_eSPI::init(void)
|
||||||
inTransaction = false;
|
inTransaction = false;
|
||||||
locked = true;
|
locked = true;
|
||||||
|
|
||||||
#ifdef ST7787_DRIVER
|
|
||||||
#ifndef SUPPORT_TRANSACTIONS
|
#ifndef SUPPORT_TRANSACTIONS
|
||||||
|
|
||||||
SPI.setBitOrder(MSBFIRST);
|
SPI.setBitOrder(MSBFIRST);
|
||||||
SPI.setDataMode(SPI_MODE0);
|
SPI.setDataMode(SPI_MODE0);
|
||||||
SPI.setFrequency(SPI_FREQUENCY);
|
SPI.setFrequency(SPI_FREQUENCY);
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
SPI1U |= (uint32_t)(SPIUWRBYO|SPIURDBYO);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ESP32 // Unlock the SPI hal mutex and set the lock management flags
|
#ifdef ESP32 // Unlock the SPI hal mutex and set the lock management flags
|
||||||
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
|
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
|
||||||
|
|
@ -220,7 +235,6 @@ void TFT_eSPI::init(void)
|
||||||
locked = false; // Flag to stop repeat beginTransaction calls
|
locked = false; // Flag to stop repeat beginTransaction calls
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set to output once again in case D6 (MISO) is used for CS
|
// Set to output once again in case D6 (MISO) is used for CS
|
||||||
|
|
@ -368,6 +382,62 @@ void TFT_eSPI::spiwrite(uint8_t c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef IFACE_3WIRE
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
void TFT_eSPI::docommand(uint8_t c, uint8_t *in, uint32_t in_len, uint8_t *out, uint32_t out_len)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
CS_L;
|
||||||
|
|
||||||
|
uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
|
||||||
|
mask = SPI1U1 & mask;
|
||||||
|
|
||||||
|
// Send the command byte, with a '0' DC bit.
|
||||||
|
SPI1U1 = mask | ((CMD_BITS+1) << SPILMOSI) | ((CMD_BITS+1) << SPILMISO);
|
||||||
|
SPI1W0 = (uint32_t)c << 23;
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
|
||||||
|
if (in_len) {
|
||||||
|
do {
|
||||||
|
val = *in++;
|
||||||
|
|
||||||
|
SPI1U1 = mask | ((CMD_BITS+1) << SPILMOSI) | ((CMD_BITS+1) << SPILMISO);
|
||||||
|
SPI1W0 = (uint32_t)0x80000000 | (val << 23);
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
val <<= 1;
|
||||||
|
--in_len;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
} while (in_len > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_len) {
|
||||||
|
// temporarily disable the MOSI pin while we read into MISO.
|
||||||
|
pinMode(MOSI, INPUT);
|
||||||
|
|
||||||
|
SPI1U1 = mask | ((CMD_BITS+1) << SPILMOSI) | ((CMD_BITS+1) << SPILMISO);
|
||||||
|
SPI1W0 = 0;
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
*out++ = SPI1W0 >> 23;
|
||||||
|
|
||||||
|
while (--out_len > 0) {
|
||||||
|
SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO);
|
||||||
|
SPI1W0 = 0;
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
*out++ = SPI1W0 >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(MOSI, SPECIAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
void TFT_eSPI::docommand(uint8_t c, uint8_t *in, uint32_t in_len, uint8_t *out, uint32_t out_len)
|
void TFT_eSPI::docommand(uint8_t c, uint8_t *in, uint32_t in_len, uint8_t *out, uint32_t out_len)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
@ -455,21 +525,76 @@ void TFT_eSPI::docommand(uint8_t c, uint8_t *in, uint32_t in_len, uint8_t *out,
|
||||||
delay_ns(ST7787_T_CHW);
|
delay_ns(ST7787_T_CHW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: writecommand
|
** Function name: writecommand
|
||||||
** Description: Send an 8 bit command to the TFT
|
** Description: Send an 8 bit command to the TFT
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
#ifdef IFACE_3WIRE
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
void TFT_eSPI::writecommand(uint8_t c)
|
||||||
|
{
|
||||||
|
CS_L;
|
||||||
|
|
||||||
|
uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
|
||||||
|
mask = SPI1U1 & mask;
|
||||||
|
|
||||||
|
SPI1U1 = mask | ((CMD_BITS+1) << SPILMOSI) | ((CMD_BITS+1) << SPILMISO);
|
||||||
|
|
||||||
|
SPI1W0 = (uint32_t)c << 23;
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
|
||||||
|
CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
void TFT_eSPI::writecommand(uint8_t c)
|
void TFT_eSPI::writecommand(uint8_t c)
|
||||||
{
|
{
|
||||||
docommand(c, NULL, 0, NULL, 0);
|
docommand(c, NULL, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
void TFT_eSPI::writecommand(uint8_t c)
|
||||||
|
{
|
||||||
|
DC_C;
|
||||||
|
CS_L;
|
||||||
|
#ifdef SEND_16_BITS
|
||||||
|
SPI.transfer(0);
|
||||||
|
#endif
|
||||||
|
SPI.transfer(c);
|
||||||
|
CS_H;
|
||||||
|
DC_D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* IFACE_3WIRE */
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: writedata
|
** Function name: writedata
|
||||||
** Description: Send a 8 bit data value to the TFT
|
** Description: Send a 8 bit data value to the TFT
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
#ifdef IFACE_3WIRE
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
void TFT_eSPI::writedata(uint8_t c)
|
||||||
|
{
|
||||||
|
CS_L;
|
||||||
|
|
||||||
|
uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
|
||||||
|
mask = SPI1U1 & mask;
|
||||||
|
|
||||||
|
SPI1U1 = mask | ((CMD_BITS+1) << SPILMOSI) | ((CMD_BITS+1) << SPILMISO);
|
||||||
|
|
||||||
|
SPI1W0 = (uint32_t)0x80000000 | ((uint32_t)c << 23);
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
|
||||||
|
CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
void TFT_eSPI::writedata(uint8_t c)
|
void TFT_eSPI::writedata(uint8_t c)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
@ -505,7 +630,19 @@ void TFT_eSPI::writedata(uint8_t c)
|
||||||
CS_H;
|
CS_H;
|
||||||
delay_ns(ST7787_T_CHW);
|
delay_ns(ST7787_T_CHW);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#else /* !IFACE_3WIRE */
|
||||||
|
void TFT_eSPI::writedata(uint8_t c)
|
||||||
|
{
|
||||||
|
CS_L;
|
||||||
|
#ifdef SEND_16_BITS
|
||||||
|
SPI.transfer(0);
|
||||||
|
#endif
|
||||||
|
SPI.transfer(c);
|
||||||
|
CS_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: readcommand8 (for ILI9341 Interface II i.e. IM [3:0] = "1101")
|
** Function name: readcommand8 (for ILI9341 Interface II i.e. IM [3:0] = "1101")
|
||||||
|
|
@ -3749,11 +3886,71 @@ void TFT_eSPI::setTextFont(uint8_t f)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define STARTBITS(cur_, pos_, spireg_) { cur_ = 0; pos_ = 32; spireg_ = &SPI1W0; }
|
||||||
|
#define ADDBITS(val_, bits_, cur_, pos_, spireg_) { \
|
||||||
|
if (pos_ < bits_) \
|
||||||
|
{ \
|
||||||
|
cur_ |= val_ >> (bits_ - pos_); \
|
||||||
|
*spireg_++ = cur_; \
|
||||||
|
pos_ = 32 - (bits_ - pos_); \
|
||||||
|
cur_ = ((uint32_t)val_ << pos_); \
|
||||||
|
} else { \
|
||||||
|
pos_ -= bits_; \
|
||||||
|
cur_ |= ((uint32_t)val_ << pos_); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define FLUSHBITS(cur_, spireg_) { *spireg_ = cur_; }
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: spiBlockWrite
|
** Function name: spiBlockWrite
|
||||||
** Description: Write a block of pixels of the same colour
|
** Description: Write a block of pixels of the same colour
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
#if defined(ESP8266) && defined(ST7787_DRIVER)
|
#ifdef IFACE_3WIRE
|
||||||
|
#ifdef IFACE_3WIRE_ESP8266
|
||||||
|
void spiWriteBlock(uint16_t color, uint32_t repeat)
|
||||||
|
{
|
||||||
|
uint32_t mask = ~(SPIMMOSI << SPILMOSI);
|
||||||
|
mask = SPI1U1 & mask;
|
||||||
|
|
||||||
|
// Stuff two color bytes with two '1' DC bits.
|
||||||
|
uint32_t color18 = (uint32_t)0x20100 | (((uint32_t)color & 0xff00) << 1) | (color & 0xff);
|
||||||
|
uint32_t cur, pos;
|
||||||
|
volatile uint32_t *spireg;
|
||||||
|
|
||||||
|
STARTBITS(cur, pos, spireg);
|
||||||
|
SPI1U = SPIUMOSI | SPIUSSE | SPIUWRBYO | SPIURDBYO;
|
||||||
|
|
||||||
|
uint32_t fillcount = repeat;
|
||||||
|
if (fillcount > 28)
|
||||||
|
fillcount = 28;
|
||||||
|
while (fillcount-- > 0)
|
||||||
|
ADDBITS(color18, 18, cur, pos, spireg);
|
||||||
|
FLUSHBITS(cur, spireg);
|
||||||
|
|
||||||
|
if (repeat >= 28)
|
||||||
|
{
|
||||||
|
SPI1U1 = mask | ((18*28-1) << SPILMOSI);
|
||||||
|
while(repeat>=28)
|
||||||
|
{
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
repeat -= 28;
|
||||||
|
}
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repeat)
|
||||||
|
{
|
||||||
|
repeat = (repeat * 18) - 1;
|
||||||
|
SPI1U1 = mask | (repeat << SPILMOSI);
|
||||||
|
SPI1CMD |= SPIBUSY;
|
||||||
|
while(SPI1CMD & SPIBUSY) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE | SPIUWRBYO | SPIURDBYO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
void spiWriteBlock(uint16_t color, uint32_t repeat)
|
void spiWriteBlock(uint16_t color, uint32_t repeat)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
@ -3808,6 +4005,7 @@ void spiWriteBlock(uint16_t color, uint32_t repeat)
|
||||||
DAT_I;
|
DAT_I;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* IFACE_3WIRE */
|
||||||
#elif defined (ESP8266) && (SPI_FREQUENCY != 80000000)
|
#elif defined (ESP8266) && (SPI_FREQUENCY != 80000000)
|
||||||
void spiWriteBlock(uint16_t color, uint32_t repeat)
|
void spiWriteBlock(uint16_t color, uint32_t repeat)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,15 @@
|
||||||
#define SPI_FREQUENCY 20000000
|
#define SPI_FREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ST7787_DRIVER
|
||||||
|
// ST7787 only supports a 3-wire serial interface, where the data/command bit
|
||||||
|
// is sent as a 9th bit in the SPI protocol, not on a separate wire.
|
||||||
|
#define IFACE_3WIRE 1
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define IFACE_3WIRE_ESP8266 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Only load the fonts defined in User_Setup.h (to save space)
|
// Only load the fonts defined in User_Setup.h (to save space)
|
||||||
// Set flag so RLE rendering code is optionally compiled
|
// Set flag so RLE rendering code is optionally compiled
|
||||||
#ifdef LOAD_GLCD
|
#ifdef LOAD_GLCD
|
||||||
|
|
|
||||||
|
|
@ -160,8 +160,8 @@
|
||||||
// #define SPI_FREQUENCY 1000000
|
// #define SPI_FREQUENCY 1000000
|
||||||
// #define SPI_FREQUENCY 5000000
|
// #define SPI_FREQUENCY 5000000
|
||||||
// #define SPI_FREQUENCY 10000000
|
// #define SPI_FREQUENCY 10000000
|
||||||
// #define SPI_FREQUENCY 20000000
|
#define SPI_FREQUENCY 20000000
|
||||||
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
|
// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
|
||||||
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
|
// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS
|
||||||
// #define SPI_FREQUENCY 80000000
|
// #define SPI_FREQUENCY 80000000
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue