Refactor, add new anti-alaiased functions
Beta test Minor performance improvements Improved image rendering speed for SPI 18 bit interface TFTs (e.g. ILI9488) TODO 1. Add AA circle fns to TFT_eSPI 2. Update keywords 3. Add new examples for ESP/STM processors
This commit is contained in:
parent
9a1a53edc2
commit
2f6177ed4b
|
|
@ -16,7 +16,7 @@
|
|||
***************************************************************************************/
|
||||
// The touch controller has a low SPI clock rate
|
||||
inline void TFT_eSPI::begin_touch_read_write(void){
|
||||
DMA_BUSY_CHECK;
|
||||
DMA_BUSY_CHECK; // Wait for any DMA transfer to complete before changing SPI settings
|
||||
CS_H; // Just in case it has been left low
|
||||
#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS)
|
||||
if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));}
|
||||
|
|
@ -38,7 +38,6 @@ inline void TFT_eSPI::end_touch_read_write(void){
|
|||
#else
|
||||
spi.setFrequency(SPI_FREQUENCY);
|
||||
#endif
|
||||
//SET_BUS_WRITE_MODE;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
|
|
|
|||
|
|
@ -27,12 +27,14 @@
|
|||
#endif
|
||||
|
||||
#if !defined (TFT_PARALLEL_8_BIT)
|
||||
// Volatile for register reads:
|
||||
volatile uint32_t* _spi_cmd = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT));
|
||||
volatile uint32_t* _spi_user = (volatile uint32_t*)(SPI_USER_REG(SPI_PORT));
|
||||
// Register writes only:
|
||||
volatile uint32_t* _spi_mosi_dlen = (volatile uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT));
|
||||
volatile uint32_t* _spi_w = (volatile uint32_t*)(SPI_W0_REG(SPI_PORT));
|
||||
// Write only SPI Tx/Rx register
|
||||
volatile uint32_t *const _spi_w = (uint32_t*)(SPI_W0_REG(SPI_PORT));
|
||||
// Write only SPI interface control register
|
||||
volatile uint32_t *const _spi_user = (uint32_t*)(SPI_USER_REG(SPI_PORT));
|
||||
// Bit length to transmit N bits (512 max), load with N-1
|
||||
volatile uint32_t *const _spi_mosi_dlen = (uint32_t*)(SPI_MOSI_DLEN_REG(SPI_PORT));
|
||||
// Read/write reister to initiate SPI transfer and check when completed
|
||||
volatile uint32_t *const _spi_cmd = (volatile uint32_t*)(SPI_CMD_REG(SPI_PORT));
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -187,54 +189,41 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len)
|
|||
#elif !defined (SPI_18BIT_DRIVER) && !defined (TFT_PARALLEL_8_BIT) // Most SPI displays
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: pushBlock - for ESP32
|
||||
** Description: Write a block of pixels of the same colour
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
|
||||
|
||||
volatile uint32_t* spi_w = _spi_w;
|
||||
uint32_t color32 = (color<<8 | color >>8)<<16 | (color<<8 | color >>8);
|
||||
bool empty = true;
|
||||
volatile uint32_t* spi_w = (volatile uint32_t*)_spi_w;
|
||||
if (len > 31)
|
||||
uint32_t i = 0;
|
||||
uint32_t rem = len & 0x1F;
|
||||
len = len - rem;
|
||||
|
||||
if (rem)
|
||||
{
|
||||
*_spi_mosi_dlen = 511;
|
||||
spi_w[0] = color32;
|
||||
spi_w[1] = color32;
|
||||
spi_w[2] = color32;
|
||||
spi_w[3] = color32;
|
||||
spi_w[4] = color32;
|
||||
spi_w[5] = color32;
|
||||
spi_w[6] = color32;
|
||||
spi_w[7] = color32;
|
||||
spi_w[8] = color32;
|
||||
spi_w[9] = color32;
|
||||
spi_w[10] = color32;
|
||||
spi_w[11] = color32;
|
||||
spi_w[12] = color32;
|
||||
spi_w[13] = color32;
|
||||
spi_w[14] = color32;
|
||||
spi_w[15] = color32;
|
||||
while(len>31)
|
||||
{
|
||||
while ((*_spi_cmd)&SPI_USR);
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 32;
|
||||
}
|
||||
empty = false;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
for (i=0; i < rem; i+=2) *spi_w++ = color32;
|
||||
*_spi_mosi_dlen = (rem << 4) - 1;
|
||||
*_spi_cmd = SPI_USR;
|
||||
if (!len) return;
|
||||
i = i>>1; while(i++<16) *spi_w++ = color32;
|
||||
}
|
||||
|
||||
if (len)
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
if (!rem) while (i++<16) *spi_w++ = color32;
|
||||
*_spi_mosi_dlen = 511;
|
||||
|
||||
while(len)
|
||||
{
|
||||
if(empty) {
|
||||
for (uint32_t i=0; i <= len; i+=2) *spi_w++ = color32;
|
||||
}
|
||||
len = (len << 4) - 1;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = len;
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 32;
|
||||
}
|
||||
while ((*_spi_cmd)&SPI_USR); // Move to later in code to use transmit time usefully?
|
||||
|
||||
//while (*_spi_cmd&SPI_USR);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
|
|
@ -248,33 +237,43 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
|
||||
if (len > 31)
|
||||
{
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 255;
|
||||
while(len>31)
|
||||
{
|
||||
{ // Ping-pong the transmit buffer
|
||||
uint32_t i = 0;
|
||||
while(i<8)
|
||||
{
|
||||
color[i++] = DAT8TO32(data);
|
||||
data+=4;
|
||||
}
|
||||
_spi_w[8] = color[0];
|
||||
_spi_w[9] = color[1];
|
||||
_spi_w[10] = color[2];
|
||||
_spi_w[11] = color[3];
|
||||
_spi_w[12] = color[4];
|
||||
_spi_w[13] = color[5];
|
||||
_spi_w[14] = color[6];
|
||||
_spi_w[15] = color[7];
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_user = SPI_USR_MOSI | SPI_USR_MOSI_HIGHPART;
|
||||
*_spi_cmd = SPI_USR;
|
||||
while(i<16)
|
||||
{
|
||||
color[i++] = DAT8TO32(data);
|
||||
data+=4;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
|
||||
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]);
|
||||
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]);
|
||||
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]);
|
||||
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color[4]);
|
||||
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color[5]);
|
||||
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color[6]);
|
||||
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color[7]);
|
||||
WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color[8]);
|
||||
WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color[9]);
|
||||
WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color[10]);
|
||||
WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color[11]);
|
||||
WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color[12]);
|
||||
WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color[13]);
|
||||
WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color[14]);
|
||||
WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color[15]);
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
_spi_w[0] = color[8];
|
||||
_spi_w[1] = color[9];
|
||||
_spi_w[2] = color[10];
|
||||
_spi_w[3] = color[11];
|
||||
_spi_w[4] = color[12];
|
||||
_spi_w[5] = color[13];
|
||||
_spi_w[6] = color[14];
|
||||
_spi_w[7] = color[15];
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_user = SPI_USR_MOSI;
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 32;
|
||||
}
|
||||
}
|
||||
|
|
@ -287,31 +286,31 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
color[i++] = DAT8TO32(data);
|
||||
data+=4;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 255);
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color[0]);
|
||||
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color[1]);
|
||||
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color[2]);
|
||||
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color[3]);
|
||||
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color[4]);
|
||||
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color[5]);
|
||||
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color[6]);
|
||||
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color[7]);
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 255;
|
||||
_spi_w[0] = color[0];
|
||||
_spi_w[1] = color[1];
|
||||
_spi_w[2] = color[2];
|
||||
_spi_w[3] = color[3];
|
||||
_spi_w[4] = color[4];
|
||||
_spi_w[5] = color[5];
|
||||
_spi_w[6] = color[6];
|
||||
_spi_w[7] = color[7];
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 16;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1);
|
||||
volatile uint32_t* spi_w = _spi_w;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = (len << 4) - 1;
|
||||
for (uint32_t i=0; i <= (len<<1); i+=4) {
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT)+i, DAT8TO32(data)); data+=4;
|
||||
*spi_w++ = DAT8TO32(data); data+=4;
|
||||
}
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
*_spi_cmd = SPI_USR;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
|
||||
//while (*_spi_cmd&SPI_USR);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
|
|
@ -329,39 +328,46 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
|||
|
||||
if (len > 31)
|
||||
{
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511);
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 255;
|
||||
*_spi_user = SPI_USR_MOSI;
|
||||
while(len>31)
|
||||
{
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), *data++);
|
||||
WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), *data++);
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
{ // Ping-pong the transmit buffer
|
||||
_spi_w[8] = *data++;
|
||||
_spi_w[9] = *data++;
|
||||
_spi_w[10] = *data++;
|
||||
_spi_w[11] = *data++;
|
||||
_spi_w[12] = *data++;
|
||||
_spi_w[13] = *data++;
|
||||
_spi_w[14] = *data++;
|
||||
_spi_w[15] = *data++;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
SET_BUS_WRITE_MODE | SPI_USR_MOSI_HIGHPART;
|
||||
*_spi_cmd = SPI_USR;
|
||||
_spi_w[0] = *data++;
|
||||
_spi_w[1] = *data++;
|
||||
_spi_w[2] = *data++;
|
||||
_spi_w[3] = *data++;
|
||||
_spi_w[4] = *data++;
|
||||
_spi_w[5] = *data++;
|
||||
_spi_w[6] = *data++;
|
||||
_spi_w[7] = *data++;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
SET_BUS_WRITE_MODE;
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (len << 4) - 1);
|
||||
for (uint32_t i=0; i <= (len<<1); i+=4) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + i), *data++);
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
volatile uint32_t* spi_w = _spi_w;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = (len << 4) - 1;
|
||||
for (uint32_t i=0; i <= (len<<1); i+=4) *spi_w++ = *data++;
|
||||
*_spi_cmd = SPI_USR;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
//while (*_spi_cmd&SPI_USR);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -382,59 +388,62 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
|||
uint32_t r0 = r<<24 | b | g | r;
|
||||
uint32_t r1 = r0>>8 | g<<16;
|
||||
uint32_t r2 = r1>>8 | b<<8;
|
||||
bool empty = true;
|
||||
|
||||
if (len > 19)
|
||||
{
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S);
|
||||
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 479;
|
||||
_spi_w[ 0] = r0;
|
||||
_spi_w[ 1] = r1;
|
||||
_spi_w[ 2] = r2;
|
||||
_spi_w[ 3] = r0;
|
||||
_spi_w[ 4] = r1;
|
||||
_spi_w[ 5] = r2;
|
||||
_spi_w[ 6] = r0;
|
||||
_spi_w[ 7] = r1;
|
||||
_spi_w[ 8] = r2;
|
||||
_spi_w[ 9] = r0;
|
||||
_spi_w[10] = r1;
|
||||
_spi_w[11] = r2;
|
||||
_spi_w[12] = r0;
|
||||
_spi_w[13] = r1;
|
||||
_spi_w[14] = r2;
|
||||
while(len>19)
|
||||
{
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 20;
|
||||
}
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
empty = false;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, (len * 24) - 1, SPI_USR_MOSI_DBITLEN_S);
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2);
|
||||
if (len > 8 )
|
||||
{
|
||||
WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2);
|
||||
WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0);
|
||||
WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1);
|
||||
WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2);
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = (len * 24) - 1;
|
||||
if (empty) {
|
||||
_spi_w[0] = r0;
|
||||
_spi_w[1] = r1;
|
||||
_spi_w[2] = r2;
|
||||
_spi_w[3] = r0;
|
||||
_spi_w[4] = r1;
|
||||
_spi_w[5] = r2;
|
||||
if (len > 8 )
|
||||
{
|
||||
_spi_w[ 6] = r0;
|
||||
_spi_w[ 7] = r1;
|
||||
_spi_w[ 8] = r2;
|
||||
_spi_w[ 9] = r0;
|
||||
_spi_w[10] = r1;
|
||||
_spi_w[11] = r2;
|
||||
_spi_w[12] = r0;
|
||||
_spi_w[14] = r1;
|
||||
_spi_w[14] = r2;
|
||||
}
|
||||
}
|
||||
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR);
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
*_spi_cmd = SPI_USR;
|
||||
//while (*_spi_cmd&SPI_USR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -445,9 +454,59 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
|||
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
|
||||
uint16_t *data = (uint16_t*)data_in;
|
||||
// ILI9488 write macro is not endianess dependant, hence !_swapBytes
|
||||
if(!_swapBytes) { while ( len-- ) {tft_Write_16S(*data); data++;} }
|
||||
else { while ( len-- ) {tft_Write_16(*data); data++;} }
|
||||
|
||||
if(!_swapBytes) {
|
||||
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 48-1;
|
||||
|
||||
while ( len>1 ) {
|
||||
// Split out the colours
|
||||
uint32_t r1 = (*data & 0xF8);
|
||||
uint32_t g1 = (*data & 0xE000)>>11 | (*data & 0x07)<<5;
|
||||
uint32_t b1 = (*data++ & 0x1F00)>>5;
|
||||
uint32_t r2 = (*data & 0xF8);
|
||||
uint32_t g2 = (*data & 0xE000)>>11 | (*data & 0x07)<<5;
|
||||
uint32_t b2 = (*data++ & 0x1F00)>>5;
|
||||
uint32_t rgb1 = r2<<24 | b1<<16 | g1<<8 | r1;
|
||||
uint32_t rgb2 = b2<<8 | g2;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
_spi_w[0] = rgb1;
|
||||
_spi_w[1] = rgb2;
|
||||
*_spi_cmd = SPI_USR;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
// Split out the colours
|
||||
uint32_t r = (*data & 0xF8);
|
||||
uint32_t g = (*data & 0xE000)>>11 | (*data & 0x07)<<5;
|
||||
uint32_t b = (*data++ & 0x1F00)>>5;
|
||||
uint32_t rgb = b<<16 | g<<8 | r;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 24-1;
|
||||
*_spi_w = rgb;
|
||||
*_spi_cmd = SPI_USR;
|
||||
}
|
||||
//was while ( len-- ) {tft_Write_16S(*data); data++;}
|
||||
}
|
||||
else {
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 24-1;
|
||||
|
||||
while ( len-- ) {
|
||||
// Split out the colours
|
||||
uint32_t r = (*data & 0xF800)>>8;
|
||||
uint32_t g = (*data & 0x07E0)>>3;
|
||||
uint32_t b = (*data++ & 0x001F)<<3;
|
||||
uint32_t rgb = b<<16 | g<<8 | r;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
// Concatenate pixel into 32 bits
|
||||
*_spi_w = rgb;
|
||||
*_spi_cmd = SPI_USR;
|
||||
}
|
||||
//was while ( len-- ) {tft_Write_16(*data); data++;}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
|
|
@ -458,7 +517,21 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
|
||||
uint16_t *data = (uint16_t*)data_in;
|
||||
// ILI9488 write macro is not endianess dependant, so swap byte macro not used here
|
||||
while ( len-- ) {tft_Write_16(*data); data++;}
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
*_spi_mosi_dlen = 24-1;
|
||||
|
||||
while ( len-- ) {
|
||||
// Split out the colours
|
||||
uint32_t r = (*data & 0xF800)>>8;
|
||||
uint32_t g = (*data & 0x07E0)>>3;
|
||||
uint32_t b = (*data++ & 0x001F)<<3;
|
||||
uint32_t rgb = b<<16 | g<<8 | r;
|
||||
while (*_spi_cmd&SPI_USR);
|
||||
// Concatenate pixel into 32 bits
|
||||
*_spi_w = rgb;
|
||||
*_spi_cmd = SPI_USR;
|
||||
}
|
||||
//while ( len-- ) {tft_Write_16(*data); data++;}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -575,8 +648,8 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
|
|||
|
||||
trans.user = (void *)1;
|
||||
trans.tx_buffer = image; //finally send the line data
|
||||
trans.length = len * 16; //Data length, in bits
|
||||
trans.flags = 0; //SPI_TRANS_USE_TXDATA flag
|
||||
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);
|
||||
|
|
@ -611,7 +684,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
|
|||
|
||||
if (buffer == nullptr) {
|
||||
buffer = image;
|
||||
dmaWait();
|
||||
if (spiBusyCheck) dmaWait();
|
||||
}
|
||||
|
||||
// If image is clipped, copy pixels into a contiguous block
|
||||
|
|
@ -640,13 +713,13 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
|
|||
}
|
||||
}
|
||||
|
||||
static spi_transaction_t trans;
|
||||
esp_err_t ret;
|
||||
|
||||
if (spiBusyCheck) dmaWait(); // Incase we did not wait earlier
|
||||
|
||||
setAddrWindow(x, y, dw, dh);
|
||||
|
||||
esp_err_t ret;
|
||||
static spi_transaction_t trans;
|
||||
|
||||
memset(&trans, 0, sizeof(spi_transaction_t));
|
||||
|
||||
trans.user = (void *)1;
|
||||
|
|
@ -712,7 +785,7 @@ bool TFT_eSPI::initDMA(bool ctrl_cs)
|
|||
.input_delay_ns = 0,
|
||||
.spics_io_num = pin,
|
||||
.flags = SPI_DEVICE_NO_DUMMY, //0,
|
||||
.queue_size = 1,
|
||||
.queue_size = DMA_QUEUE_SIZE,
|
||||
.pre_cb = 0, //dc_callback, //Callback to handle D/C line
|
||||
.post_cb = 0
|
||||
};
|
||||
|
|
|
|||
|
|
@ -65,12 +65,19 @@
|
|||
// Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
|
||||
#if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER)
|
||||
#define ESP32_DMA
|
||||
#define DMA_QUEUE_SIZE 1
|
||||
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
|
||||
#define DMA_BUSY_CHECK dmaWait()
|
||||
#else
|
||||
#define DMA_BUSY_CHECK
|
||||
#endif
|
||||
|
||||
#if defined(TFT_PARALLEL_8_BIT)
|
||||
#define SPI_BUSY_CHECK
|
||||
#else
|
||||
#define SPI_BUSY_CHECK while (*_spi_cmd&SPI_USR)
|
||||
#endif
|
||||
|
||||
// If smooth font is used then it is likely SPIFFS will be needed
|
||||
#ifdef SMOOTH_FONT
|
||||
// Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
|
||||
|
|
@ -167,7 +174,7 @@
|
|||
#define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
|
||||
#define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS)
|
||||
#else
|
||||
#define CS_L GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS)
|
||||
#define CS_L GPIO.out_w1tc = (1 << TFT_CS)//; GPIO.out_w1tc = (1 << TFT_CS)
|
||||
#define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS)
|
||||
#endif
|
||||
#else
|
||||
|
|
@ -198,6 +205,7 @@
|
|||
#define WR_H
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Define the touch screen chip select pin drive code
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -217,11 +225,7 @@
|
|||
#ifdef USE_HSPI_PORT
|
||||
|
||||
#ifndef TFT_MISO
|
||||
#define TFT_MISO 12
|
||||
#endif
|
||||
#if (TFT_MISO == -1)
|
||||
#undef TFT_MISO
|
||||
#define TFT_MISO 12
|
||||
#define TFT_MISO -1
|
||||
#endif
|
||||
|
||||
#ifndef TFT_MOSI
|
||||
|
|
@ -243,11 +247,7 @@
|
|||
#else // VSPI port
|
||||
|
||||
#ifndef TFT_MISO
|
||||
#define TFT_MISO 19
|
||||
#endif
|
||||
#if (TFT_MISO == -1)
|
||||
#undef TFT_MISO
|
||||
#define TFT_MISO 19
|
||||
#define TFT_MISO -1
|
||||
#endif
|
||||
|
||||
#ifndef TFT_MOSI
|
||||
|
|
@ -375,6 +375,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#elif defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
|
||||
|
||||
// ESP32 low level SPI writes for 8, 16 and 32 bit values too fast for ILI9488
|
||||
// Write 8 bits to TFT
|
||||
#define tft_Write_8(C) spi.transfer(C)
|
||||
|
||||
|
|
@ -383,6 +384,11 @@
|
|||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16N(C) spi.transfer(((C) & 0xF800)>>8); \
|
||||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
|
||||
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
|
||||
|
|
@ -404,11 +410,14 @@
|
|||
|
||||
// ESP32 low level SPI writes for 8, 16 and 32 bit values
|
||||
// to avoid the function call overhead
|
||||
#define TFT_WRITE_BITS(D, B) \
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
#define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \
|
||||
*_spi_w = D; \
|
||||
*_spi_cmd = SPI_USR; \
|
||||
while (*_spi_cmd & SPI_USR);
|
||||
|
||||
#define TFT_WRITE_BITSN(D, B) *_spi_mosi_dlen = B-1; \
|
||||
*_spi_w = D; \
|
||||
*_spi_cmd = SPI_USR;
|
||||
|
||||
// Write 8 bits
|
||||
#define tft_Write_8(C) TFT_WRITE_BITS((C)<<8, 16)
|
||||
|
|
@ -416,6 +425,10 @@
|
|||
// Write 16 bits with corrected endianess for 16 bit colours
|
||||
#define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
|
||||
|
||||
#define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \
|
||||
*_spi_w = ((C)<<8 | (C)>>8); \
|
||||
*_spi_cmd = SPI_USR;
|
||||
|
||||
// Write 16 bits
|
||||
#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
|
||||
|
||||
|
|
@ -429,18 +442,16 @@
|
|||
// Write same value twice
|
||||
#define tft_Write_32D(C) tft_Write_32C(C,C)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Macros for all other SPI displays
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#else
|
||||
|
||||
// ESP32 low level SPI writes for 8, 16 and 32 bit values
|
||||
// to avoid the function call overhead
|
||||
#define TFT_WRITE_BITS(D, B) \
|
||||
WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), B-1); \
|
||||
WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), D); \
|
||||
SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \
|
||||
while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR);
|
||||
#define TFT_WRITE_BITS(D, B) *_spi_mosi_dlen = B-1; \
|
||||
*_spi_w = D; \
|
||||
*_spi_cmd = SPI_USR; \
|
||||
while (*_spi_cmd & SPI_USR);
|
||||
|
||||
// Write 8 bits
|
||||
#define tft_Write_8(C) TFT_WRITE_BITS(C, 8)
|
||||
|
|
@ -448,6 +459,10 @@
|
|||
// Write 16 bits with corrected endianess for 16 bit colours
|
||||
#define tft_Write_16(C) TFT_WRITE_BITS((C)<<8 | (C)>>8, 16)
|
||||
|
||||
#define tft_Write_16N(C) *_spi_mosi_dlen = 16-1; \
|
||||
*_spi_w = ((C)<<8 | (C)>>8); \
|
||||
*_spi_cmd = SPI_USR;
|
||||
|
||||
// Write 16 bits
|
||||
#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
|||
uint32_t r1 = g<<24 | r<<16 | b<<8 | g;
|
||||
uint32_t r2 = b<<24 | g<<16 | r<<8 | b;
|
||||
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
SPI1W0 = r0;
|
||||
SPI1W1 = r1;
|
||||
SPI1W2 = r2;
|
||||
|
|
@ -163,15 +164,16 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
|||
SPI1CMD |= SPIBUSY;
|
||||
len -= 21;
|
||||
}
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
len = (len * 24) - 1;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
SPI1U1 = (len << SPILMOSI);
|
||||
SPI1CMD |= SPIBUSY;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -183,6 +185,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
|||
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
||||
|
||||
uint16_t *data = (uint16_t*)data_in;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
|
||||
// Send groups of 4 concatenated pixels
|
||||
if (len > 3) {
|
||||
|
|
@ -222,12 +225,8 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
|||
SPI1CMD |= SPIBUSY;
|
||||
len -= 4;
|
||||
}
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
|
||||
// ILI9488 write macro is not endianess dependant, hence !_swapBytes
|
||||
if (!_swapBytes) while ( len-- ) { tft_Write_16S(*data); data++;}
|
||||
else while ( len-- ) {tft_Write_16(*data); data++;}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
|
|
@ -257,22 +256,9 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
//
|
||||
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
|
||||
{
|
||||
/*
|
||||
while (len>1) { tft_Write_32(color<<16 | color); len-=2;}
|
||||
if (len) tft_Write_16(color);
|
||||
return;
|
||||
//*/
|
||||
uint16_t color16 = (color >> 8) | (color << 8);
|
||||
uint32_t color32 = color16 | color16 << 16;
|
||||
/*
|
||||
while(len--) {
|
||||
SPI1U1 = ((16-1) << SPILMOSI) | ((16-1) << SPILMISO);
|
||||
SPI1W0 = color16;
|
||||
SPI1CMD |= SPIBUSY;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
return;
|
||||
//*/
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
|
||||
SPI1W0 = color32;
|
||||
SPI1W1 = color32;
|
||||
|
|
@ -311,15 +297,16 @@ return;
|
|||
SPI1CMD |= SPIBUSY;
|
||||
len -= 32;
|
||||
}
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
len = (len << 4) - 1;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
SPI1U1 = (len << SPILMOSI);
|
||||
SPI1CMD |= SPIBUSY;
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -339,6 +326,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
|||
|
||||
uint32_t color[8];
|
||||
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO);
|
||||
|
||||
|
||||
|
|
@ -381,7 +369,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
|
|||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +384,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
|
||||
uint32_t color[8];
|
||||
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO);
|
||||
|
||||
while(len>15)
|
||||
|
|
@ -438,7 +427,7 @@ void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
|
|||
SPI1CMD |= SPIBUSY;
|
||||
}
|
||||
|
||||
while(SPI1CMD & SPIBUSY) {}
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
// Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions
|
||||
#define DMA_BUSY_CHECK // DMA not available, leave blank
|
||||
#define SPI_BUSY_CHECK while(SPI1CMD & SPIBUSY) {;}
|
||||
|
||||
// Initialise processor specific SPI functions, used by init()
|
||||
#if (!defined (SUPPORT_TRANSACTIONS) && defined (ESP8266))
|
||||
|
|
@ -127,6 +128,11 @@
|
|||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16N(C) spi.transfer(((C) & 0xF800)>>8); \
|
||||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
|
||||
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
|
||||
|
|
@ -160,6 +166,10 @@
|
|||
|
||||
#define tft_Write_16(C) TFT_WRITE_BITS((C)>>8 | (C)<<8, 16)
|
||||
|
||||
#define tft_Write_16N(C) SPI1U1 = ((16-1) << SPILMOSI); \
|
||||
SPI1W0 = (C)>>8 | (C)<<8; \
|
||||
SPI1CMD |= SPIBUSY; \
|
||||
|
||||
#define tft_Write_16S(C) TFT_WRITE_BITS(C, 16)
|
||||
|
||||
#define tft_Write_32(C) TFT_WRITE_BITS(C, 32)
|
||||
|
|
@ -191,6 +201,11 @@
|
|||
SPI1CMD |= SPIBUSY; \
|
||||
while(SPI1CMD & SPIBUSY) {;}
|
||||
|
||||
#define tft_Write_16N(C) \
|
||||
SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \
|
||||
SPI1W0 = ((C)<<8 | (C)>>8); \
|
||||
SPI1CMD |= SPIBUSY;
|
||||
|
||||
#define tft_Write_16S(C) \
|
||||
SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \
|
||||
SPI1W0 = C; \
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
#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
|
||||
// Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
|
||||
#define DMA_BUSY_CHECK // Not used so leave blank
|
||||
#define SPI_BUSY_CHECK // Not used so leave blank
|
||||
|
||||
// To be safe, SUPPORT_TRANSACTIONS is assumed mandatory
|
||||
#if !defined (SUPPORT_TRANSACTIONS)
|
||||
|
|
@ -104,6 +105,11 @@
|
|||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16N(C) spi.transfer(((C) & 0xF800)>>8); \
|
||||
spi.transfer(((C) & 0x07E0)>>3); \
|
||||
spi.transfer(((C) & 0x001F)<<3)
|
||||
|
||||
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
|
||||
#define tft_Write_16S(C) spi.transfer((C) & 0xF8); \
|
||||
spi.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
|
||||
|
|
@ -124,6 +130,7 @@
|
|||
#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) \
|
||||
|
|
@ -144,13 +151,15 @@
|
|||
|
||||
#else
|
||||
#ifdef __AVR__ // AVR processors do not have 16 bit transfer
|
||||
#define tft_Write_8(C) {SPDR=(C); while (!(SPSR&_BV(SPIF)));}
|
||||
#define tft_Write_16(C) tft_Write_8((uint8_t)((C)>>8));tft_Write_8((uint8_t)((C)>>0))
|
||||
#define tft_Write_16S(C) tft_Write_8((uint8_t)((C)>>0));tft_Write_8((uint8_t)((C)>>8))
|
||||
#define tft_Write_8(C) {SPDR=(C); while (!(SPSR&_BV(SPIF)));}
|
||||
#define tft_Write_16(C) tft_Write_8((uint8_t)((C)>>8));tft_Write_8((uint8_t)((C)>>0))
|
||||
#define tft_Write_16N(C) tft_Write_8((uint8_t)((C)>>8));tft_Write_8((uint8_t)((C)>>0))
|
||||
#define tft_Write_16S(C) tft_Write_8((uint8_t)((C)>>0));tft_Write_8((uint8_t)((C)>>8))
|
||||
#else
|
||||
#define tft_Write_8(C) spi.transfer(C)
|
||||
#define tft_Write_16(C) spi.transfer16(C)
|
||||
#define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8))
|
||||
#define tft_Write_8(C) spi.transfer(C)
|
||||
#define tft_Write_16(C) spi.transfer16(C)
|
||||
#define tft_Write_16N(C) spi.transfer16(C)
|
||||
#define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8))
|
||||
#endif // AVR
|
||||
|
||||
#define tft_Write_32(C) \
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@
|
|||
#define SET_BUS_WRITE_MODE // Not used
|
||||
#define SET_BUS_READ_MODE // Not used
|
||||
|
||||
#if defined(TFT_PARALLEL_8_BIT)
|
||||
#define SPI_BUSY_CHECK
|
||||
#else
|
||||
#define SPI_BUSY_CHECK while (spiHal.State == HAL_SPI_STATE_BUSY_TX)
|
||||
#endif
|
||||
|
||||
// SUPPORT_TRANSACTIONS is mandatory for STM32
|
||||
#if !defined (SUPPORT_TRANSACTIONS)
|
||||
#define SUPPORT_TRANSACTIONS
|
||||
|
|
@ -183,7 +189,8 @@
|
|||
dmaHal.Instance = DMA1_Channel5
|
||||
#endif
|
||||
#else
|
||||
// For STM32 processor with no implemented DMA support (yet)
|
||||
// For other STM32 processor with no implemented DMA support (yet)
|
||||
// #define STM32_DMA // Commented out - DMA not tested with other processors
|
||||
#if (TFT_SPI_PORT == 1)
|
||||
#define INIT_TFT_DATA_BUS spiHal.Instance = SPI1
|
||||
#elif (TFT_SPI_PORT == 2)
|
||||
|
|
@ -200,6 +207,7 @@
|
|||
#define DMA_BUSY_CHECK
|
||||
#endif
|
||||
|
||||
|
||||
// If smooth fonts are enabled the filing system may need to be loaded
|
||||
#ifdef SMOOTH_FONT
|
||||
// Call up the filing system for the anti-aliased fonts <<<==== TODO
|
||||
|
|
@ -1032,6 +1040,10 @@
|
|||
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
||||
#define tft_Write_16N(C) \
|
||||
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
||||
#define tft_Write_16S(C) \
|
||||
{ spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
|
@ -1067,6 +1079,10 @@
|
|||
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
||||
#define tft_Write_16N(C) \
|
||||
{ spiBuffer[0] = (C)>>8; spiBuffer[1] = C; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
||||
#define tft_Write_16S(C) \
|
||||
{ spiBuffer[0] = C; spiBuffer[1] = (C)>>8; \
|
||||
HAL_SPI_Transmit(&spiHal, spiBuffer, 2, 10); }
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
writecommand(0x3A); //Interface Pixel Format
|
||||
writedata(0x55); //Control interface color format set to 16
|
||||
|
||||
writecommand(0xB0); //Interface mode control
|
||||
writedata(0x00); //0x00 = SDA input and SDO output, 0x80 bidirections SDA
|
||||
|
||||
writecommand(0xB4); //Column inversion
|
||||
writedata(0x01); //1-dot inversion
|
||||
|
|
|
|||
2304
TFT_eSPI.cpp
2304
TFT_eSPI.cpp
File diff suppressed because it is too large
Load Diff
45
TFT_eSPI.h
45
TFT_eSPI.h
|
|
@ -16,7 +16,7 @@
|
|||
#ifndef _TFT_eSPIH_
|
||||
#define _TFT_eSPIH_
|
||||
|
||||
#define TFT_ESPI_VERSION "2.3.59"
|
||||
#define TFT_ESPI_VERSION "2.4.0"
|
||||
|
||||
// Bit level feature flags
|
||||
// Bit 0 set: viewport capability
|
||||
|
|
@ -295,7 +295,7 @@ typedef struct
|
|||
{
|
||||
String version = TFT_ESPI_VERSION;
|
||||
int32_t esp; // Processor code
|
||||
uint8_t trans; // SPI transaction supoort
|
||||
uint8_t trans; // SPI transaction support
|
||||
uint8_t serial; // Serial (SPI) or parallel
|
||||
uint8_t overlap; // ESP8266 overlap mode
|
||||
|
||||
|
|
@ -384,6 +384,9 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
height(void),
|
||||
width(void);
|
||||
|
||||
// Read the colour of a pixel at x,y and return value in 565 format
|
||||
virtual uint16_t readPixel(int32_t x, int32_t y);
|
||||
|
||||
void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3
|
||||
uint8_t getRotation(void); // Read the current rotation
|
||||
|
||||
|
|
@ -391,12 +394,21 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
|
||||
|
||||
// The TFT_eSprite class inherits the following functions (not all are useful to Sprite class
|
||||
void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h), // Note: start coordinates + width and height
|
||||
setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates
|
||||
void setAddrWindow(int32_t x, int32_t y, int32_t w, int32_t h); // Note: start coordinates + width and height
|
||||
void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates
|
||||
|
||||
// Viewport commands, see "Viewport_Demo" sketch
|
||||
void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true);
|
||||
bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
|
||||
// Check if whole of specified area is within viewport area, returns true if clipping is not required
|
||||
bool checkViewport (int32_t x, int32_t y, int32_t w, int32_t h); // Deprecated use checkAddrWindow
|
||||
bool checkAddrWindow(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
|
||||
// Clip input window to viewport bounds, return false if whole area is out of bounds
|
||||
bool clipAddrWindow(int32_t* x, int32_t* y, int32_t* w, int32_t* h);
|
||||
// Clip input window area to viewport bounds, return false if whole area is out of bounds
|
||||
bool clipWindow(int32_t* xs, int32_t* ys, int32_t* xe, int32_t* ye);
|
||||
|
||||
int32_t getViewportX(void);
|
||||
int32_t getViewportY(void);
|
||||
int32_t getViewportWidth(void);
|
||||
|
|
@ -417,9 +429,6 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
// Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess
|
||||
void pushPixels(const void * data_in, uint32_t len);
|
||||
|
||||
// Read the colour of a pixel at x,y and return value in 565 format
|
||||
uint16_t readPixel(int32_t x, int32_t y);
|
||||
|
||||
// Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input
|
||||
#ifdef TFT_SDA_READ
|
||||
#if defined (TFT_eSPI_ENABLE_8_BIT_READ)
|
||||
|
|
@ -435,6 +444,20 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color),
|
||||
fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color);
|
||||
|
||||
// Draw an anti-aliased wide line from ax,ay to bx,by width wd with radiused ends (radius is wd/2)
|
||||
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint16_t fg_color, uint16_t bg_color);
|
||||
// For sprites and also TFT screens where the background pixel colours can be read
|
||||
void drawWideLine(float ax, float ay, float bx, float by, float wd, uint16_t fg_color);
|
||||
|
||||
// Draw an anti-aliased wide line from ax,ay to bx,by with different width at each end aw, bw and with radiused ends
|
||||
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint16_t fg_color, uint16_t bg_color);
|
||||
// For sprites and also TFT screens where the background pixel colours can be read
|
||||
void drawWedgeLine(float ax, float ay, float bx, float by, float aw, float bw, uint16_t fg_color);
|
||||
|
||||
// Draw an anti-aliased filled circle at ax,ay with radius r (uses drawWideLine)
|
||||
void drawSpot(float ax, float ay, float r, uint16_t fg_color, uint16_t bg_color);
|
||||
// For sprites and also TFT screens where the background pixel colours can be read
|
||||
void drawSpot(float ax, float ay, float r, uint16_t fg_color);
|
||||
|
||||
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color),
|
||||
drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color),
|
||||
|
|
@ -521,6 +544,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written)
|
||||
setTextColor(uint16_t fgcolor, uint16_t bgcolor),// Set character (glyph) foreground and backgorund colour
|
||||
setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size)
|
||||
// Note: Smooth fonts cannot be scaled using setTextSize
|
||||
|
||||
void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height
|
||||
|
||||
|
|
@ -702,6 +726,11 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac
|
|||
// Same as setAddrWindow but exits with CGRAM in read mode
|
||||
void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h);
|
||||
|
||||
// Helper function: calculate distance of a point from a finite length line between two points
|
||||
float wideLineDistance(float pax, float pay, float bax, float bay, float dr) __attribute__((always_inline));
|
||||
// As above but adds delta distance for wedge shaped lines
|
||||
float wedgeLineDistance(float pax, float pay, float bax, float bay, float dr) __attribute__((always_inline));
|
||||
|
||||
// Byte read prototype
|
||||
uint8_t readByte(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
// STM32F767 27MHz SPI 0% processor load: Non DMA 97 fps, with DMA 102 fps
|
||||
|
||||
// ESP32 27MHz SPI 0% processor load: Non DMA 90 fps, with DMA 101 fps
|
||||
// ESP32 40MHz SPI 0% processor load: Non DMA 127 fps, with DMA 145 fps
|
||||
// ESP32 40MHz SPI 0% processor load: Non DMA 127 fps, with DMA 152 fps
|
||||
// NOTE: FOR SPI DISPLAYS ONLY
|
||||
#define USE_DMA_TO_TFT
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,19 @@
|
|||
// Blue Pill overclocked to 128MHz with DMA - 32MHz SPI 116 fps
|
||||
|
||||
// ESP32 - 8 bit parallel 110 fps (no DMA)
|
||||
// ESP32 - 40MHz SPI *no* DMA 93 fps
|
||||
// ESP32 - 40MHz SPI with DMA 112 fps
|
||||
// ESP32 - 27MHz SPI *no* DMA 75 fps
|
||||
// ESP32 - 27MHz SPI with DMA 110 fps
|
||||
// ESP32 - 40MHz SPI *no* DMA 94 fps
|
||||
// ESP32 - 40MHz SPI with DMA 160 fps
|
||||
// ESP32 - 80MHz SPI *no* DMA 128 fps
|
||||
// ESP32 - 80MHz SPI with DMA 187 fps
|
||||
|
||||
#define SCREENWIDTH 320
|
||||
// Comment out next line for no DMA
|
||||
#define USE_DMA
|
||||
|
||||
#define SCREENWIDTH 320
|
||||
#define SCREENHEIGHT 240
|
||||
#define BUFFER_SIZE 1024 // DMA buffers (4 kbytes reserved)
|
||||
|
||||
#include "graphic.h"
|
||||
|
||||
|
|
@ -51,7 +59,7 @@ int balloldx = ballx, balloldy = bally; // Prior ball position
|
|||
|
||||
// Working buffer for ball rendering...2 scanlines that alternate,
|
||||
// one is rendered while the other is transferred via DMA.
|
||||
uint16_t renderbuf[2][SCREENWIDTH];
|
||||
uint16_t renderbuf[2][BUFFER_SIZE];
|
||||
|
||||
uint16_t palette[16]; // Color table for ball rotation effect
|
||||
|
||||
|
|
@ -64,12 +72,12 @@ void setup() {
|
|||
tft.begin();
|
||||
tft.setRotation(3); // Landscape orientation, USB at bottom right
|
||||
tft.setSwapBytes(false);
|
||||
// Draw initial framebuffer contents:
|
||||
//tft.setBitmapColor(GRIDCOLOR, BGCOLOR);
|
||||
tft.fillScreen(BGCOLOR);
|
||||
|
||||
#ifdef USE_DMA
|
||||
tft.initDMA();
|
||||
#endif
|
||||
|
||||
// Draw initial framebuffer contents:
|
||||
tft.fillScreen(BGCOLOR);
|
||||
tft.drawBitmap(0, 0, (const uint8_t *)background, SCREENWIDTH, SCREENHEIGHT, GRIDCOLOR);
|
||||
|
||||
startTime = millis();
|
||||
|
|
@ -127,16 +135,17 @@ void loop() {
|
|||
x, y, bx1, bgx1; // Loop counters and working vars
|
||||
uint8_t p; // 'packed' value of 2 ball pixels
|
||||
int8_t bufIdx = 0;
|
||||
uint32_t pCount = 0;
|
||||
|
||||
// Start SPI transaction and drop TFT_CS - avoids transaction overhead in loop
|
||||
tft.startWrite();
|
||||
|
||||
// Set window area to pour pixels into
|
||||
tft.setAddrWindow(minx, miny, width, height);
|
||||
destPtr = &renderbuf[bufIdx][0];
|
||||
|
||||
// Draw line by line loop
|
||||
for(y=0; y<height; y++) { // For each row...
|
||||
destPtr = &renderbuf[bufIdx][0];
|
||||
|
||||
bx1 = bx; // Need to keep the original bx and bgx values,
|
||||
bgx1 = bgx; // so copies of them are made here (and changed in loop below)
|
||||
for(x=0; x<width; x++) {
|
||||
|
|
@ -156,22 +165,29 @@ void loop() {
|
|||
c = background[bgy][bgx1 / 8] & (0x80 >> (bgx1 & 7)) ? GRIDCOLOR : BGCOLOR;
|
||||
}
|
||||
*destPtr++ = c<<8 | c>>8; // Store pixel color
|
||||
pCount++;
|
||||
if (pCount >= BUFFER_SIZE) {
|
||||
#ifdef USE_DMA
|
||||
tft.pushPixelsDMA(&renderbuf[bufIdx][0], BUFFER_SIZE); // Push line to screen
|
||||
#else
|
||||
tft.pushPixels(&renderbuf[bufIdx][0], BUFFER_SIZE);
|
||||
#endif
|
||||
bufIdx = 1 - bufIdx;
|
||||
destPtr = &renderbuf[bufIdx][0];
|
||||
pCount = 0;
|
||||
}
|
||||
bx1++; // Increment bitmap position counters (X axis)
|
||||
bgx1++;
|
||||
}
|
||||
|
||||
tft.pushPixelsDMA(&renderbuf[bufIdx][0], width); // Push line to screen
|
||||
|
||||
// Push line to screen (swap bytes false for STM/ESP32)
|
||||
//tft.pushPixels(&renderbuf[bufIdx][0], width);
|
||||
|
||||
bufIdx = 1 - bufIdx;
|
||||
by++; // Increment bitmap position counters (Y axis)
|
||||
bgy++;
|
||||
}
|
||||
//if (random(100) == 1) delay(2000);
|
||||
tft.endWrite();
|
||||
//delay(5);
|
||||
#ifdef USE_DMA
|
||||
if (pCount) tft.pushPixelsDMA(&renderbuf[bufIdx][0], pCount); // Push line to screen
|
||||
#else
|
||||
if (pCount) tft.pushPixels(&renderbuf[bufIdx][0], pCount);
|
||||
#endif
|
||||
|
||||
// Show approximate frame rate
|
||||
if(!(++frame & 255)) { // Every 256 frames...
|
||||
uint32_t elapsed = (millis() - startTime) / 1000; // Seconds
|
||||
|
|
|
|||
Loading…
Reference in New Issue