456 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			456 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
 | 
						|
        //////////////////////////////////////////////////////
 | 
						|
        // TFT_eSPI driver functions for ESP8266 processors //
 | 
						|
        //////////////////////////////////////////////////////
 | 
						|
 | 
						|
// Select the SPI port to use
 | 
						|
// ESP8266 default (FLASH port also available via overlap mode)
 | 
						|
  SPIClass& spi = SPI;
 | 
						|
 | 
						|
#ifdef TOUCH_CS
 | 
						|
  #if defined (SPI2_for_TOUCH_PORT)
 | 
						|
    #error ESP8266 has only one SPI
 | 
						|
  #else
 | 
						|
	SPIClass& spi_touch = SPI;
 | 
						|
  #endif
 | 
						|
#endif
 | 
						|
 | 
						|
// Buffer for SPI transmit byte padding and byte order manipulation
 | 
						|
uint8_t   spiBuffer[8] = {0,0,0,0,0,0,0,0};
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           tft_Read_8
 | 
						|
** Description:             ESP8266 software SPI to read bidirectional SDA line
 | 
						|
***************************************************************************************/
 | 
						|
uint8_t TFT_eSPI::tft_Read_8(void)
 | 
						|
{
 | 
						|
  uint8_t  ret = 0;
 | 
						|
  uint32_t reg = 0;
 | 
						|
 | 
						|
  for (uint8_t i = 0; i < 8; i++) {  // read results
 | 
						|
    ret <<= 1;
 | 
						|
    SCLK_L;
 | 
						|
    if (digitalRead(TFT_MOSI)) ret |= 1;
 | 
						|
    SCLK_H;
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           beginSDA
 | 
						|
** Description:             Detach SPI from pin to permit software SPI
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::begin_SDA_Read(void)
 | 
						|
{
 | 
						|
  #ifdef TFT_SPI_OVERLAP
 | 
						|
    // Reads in overlap mode not supported
 | 
						|
  #else
 | 
						|
    spi.end();
 | 
						|
  #endif
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           endSDA
 | 
						|
** Description:             Attach SPI pins after software SPI
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::end_SDA_Read(void)
 | 
						|
{
 | 
						|
  #ifdef TFT_SPI_OVERLAP
 | 
						|
    spi.pins(6, 7, 8, 0);
 | 
						|
  #else
 | 
						|
    spi.begin();
 | 
						|
  #endif
 | 
						|
}
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#endif // #if defined (TFT_SDA_READ)
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           read byte  - supports class functions
 | 
						|
** Description:             Parallel bus only - dummy function - not used
 | 
						|
***************************************************************************************/
 | 
						|
uint8_t TFT_eSPI::readByte(void)
 | 
						|
{
 | 
						|
  uint8_t b = 0xAA;
 | 
						|
  return b;
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#if defined (RPI_WRITE_STROBE)
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushBlock - for ESP32 or ESP8266 RPi TFT
 | 
						|
** Description:             Write a block of pixels of the same colour
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
 | 
						|
{
 | 
						|
  uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color };
 | 
						|
  if(len) spi.writePattern(&colorBin[0], 2, 1); len--;
 | 
						|
  while(len--) {WR_L; WR_H;}
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushPixels - for ESP32 or ESP8266 RPi TFT
 | 
						|
** Description:             Write a sequence of pixels
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
 | 
						|
 | 
						|
  uint8_t *data = (uint8_t*)data_in;
 | 
						|
  while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; }
 | 
						|
  if (len) spi.writePattern(data, len, 1);
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushSwapBytePixels - for ESP32 or ESP8266 RPi TFT
 | 
						|
** Description:             Write a sequence of pixels with swapped bytes
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
 | 
						|
  uint16_t *data = (uint16_t*)data_in;
 | 
						|
  while ( len-- ) {tft_Write_16(*data); data++;}
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#elif defined (ILI9488_DRIVER)
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushBlock - for ESP8266 and 3 byte RGB display
 | 
						|
** Description:             Write a block of pixels of the same colour
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
 | 
						|
{
 | 
						|
  // Split out the colours
 | 
						|
  uint8_t r = (color & 0xF800)>>8;
 | 
						|
  uint8_t g = (color & 0x07E0)>>3;
 | 
						|
  uint8_t b = (color & 0x001F)<<3;
 | 
						|
  // Concatenate 4 pixels into three 32 bit blocks
 | 
						|
  uint32_t r0 = r<<24 | b<<16 | g<<8 | r;
 | 
						|
  uint32_t r1 = g<<24 | r<<16 | b<<8 | g;
 | 
						|
  uint32_t r2 = b<<24 | g<<16 | r<<8 | b;
 | 
						|
 | 
						|
  SPI1W0 = r0;
 | 
						|
  SPI1W1 = r1;
 | 
						|
  SPI1W2 = r2;
 | 
						|
 | 
						|
  if (len > 4)
 | 
						|
  {
 | 
						|
    SPI1W3 = r0;
 | 
						|
    SPI1W4 = r1;
 | 
						|
    SPI1W5 = r2;
 | 
						|
  }
 | 
						|
  if (len > 8)
 | 
						|
  {
 | 
						|
    SPI1W6 = r0;
 | 
						|
    SPI1W7 = r1;
 | 
						|
    SPI1W8 = r2;
 | 
						|
  }
 | 
						|
  if (len > 12)
 | 
						|
  {
 | 
						|
    SPI1W9  = r0;
 | 
						|
    SPI1W10 = r1;
 | 
						|
    SPI1W11 = r2;
 | 
						|
    SPI1W12 = r0;
 | 
						|
    SPI1W13 = r1;
 | 
						|
    SPI1W14 = r2;
 | 
						|
    SPI1W15 = r0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (len > 20)
 | 
						|
  {
 | 
						|
    SPI1U1 = (503 << SPILMOSI);
 | 
						|
    while(len>20)
 | 
						|
    {
 | 
						|
      while(SPI1CMD & SPIBUSY) {}
 | 
						|
      SPI1CMD |= SPIBUSY;
 | 
						|
      len -= 21;
 | 
						|
    }
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
  }
 | 
						|
 | 
						|
  if (len)
 | 
						|
  {
 | 
						|
    len = (len * 24) - 1;
 | 
						|
    SPI1U1 = (len << SPILMOSI);
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushPixels - for ESP8266 and 3 byte RGB display
 | 
						|
** Description:             Write a sequence of pixels
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
 | 
						|
 | 
						|
  uint16_t *data = (uint16_t*)data_in;
 | 
						|
 | 
						|
  // Send groups of 4 concatenated pixels
 | 
						|
  if (len > 3) {
 | 
						|
    SPI1U1 = ((4 * 24 - 1) << SPILMOSI);
 | 
						|
    while (len > 3) {
 | 
						|
 | 
						|
      uint8_t  r[4];
 | 
						|
      uint8_t  g[4];
 | 
						|
      uint8_t  b[4];
 | 
						|
 | 
						|
      if (!_swapBytes) {
 | 
						|
        // Split out the colours
 | 
						|
        for (uint16_t i = 0; i < 4; i++) {
 | 
						|
          uint16_t col = *data++;
 | 
						|
          r[i] = (col & 0xF8);
 | 
						|
          g[i] = (col & 0xE000)>>11 | (col & 0x07)<<5;
 | 
						|
          b[i] = (col & 0x1F00)>>5;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        for (uint16_t i = 0; i < 4; i++) {
 | 
						|
          uint16_t col = *data++;
 | 
						|
          r[i] = (col & 0xF800)>>8;
 | 
						|
          g[i] = (col & 0x07E0)>>3;
 | 
						|
          b[i] = (col & 0x001F)<<3;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      uint32_t r0 = r[1]<<24 | b[0]<<16 | g[0]<<8 | r[0];
 | 
						|
      uint32_t r1 = g[2]<<24 | r[2]<<16 | b[1]<<8 | g[1];
 | 
						|
      uint32_t r2 = b[3]<<24 | g[3]<<16 | r[3]<<8 | b[2];
 | 
						|
 | 
						|
      while(SPI1CMD & SPIBUSY) {}
 | 
						|
      SPI1W0 = r0;
 | 
						|
      SPI1W1 = r1;
 | 
						|
      SPI1W2 = r2;
 | 
						|
 | 
						|
      SPI1CMD |= SPIBUSY;
 | 
						|
      len -= 4;
 | 
						|
    }
 | 
						|
    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++;}
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushSwapBytePixels - for ESP8266 and 3 byte RGB display
 | 
						|
** Description:             Write a sequence of pixels with swapped bytes
 | 
						|
***************************************************************************************/
 | 
						|
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++;}
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#else
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushBlock - for ESP8266
 | 
						|
** Description:             Write a block of pixels of the same colour
 | 
						|
***************************************************************************************/
 | 
						|
//Clear screen test 76.8ms theoretical. 81.5ms TFT_eSPI, 967ms Adafruit_ILI9341
 | 
						|
//Performance 26.15Mbps@26.66MHz, 39.04Mbps@40MHz, 75.4Mbps@80MHz SPI clock
 | 
						|
//Efficiency:
 | 
						|
//       TFT_eSPI       98.06%              97.59%          94.24%
 | 
						|
//       Adafruit_GFX   19.62%              14.31%           7.94%
 | 
						|
//
 | 
						|
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;
 | 
						|
//*/
 | 
						|
 | 
						|
  SPI1W0 = color32;
 | 
						|
  SPI1W1 = color32;
 | 
						|
  SPI1W2 = color32;
 | 
						|
  SPI1W3 = color32;
 | 
						|
  if (len > 8)
 | 
						|
  {
 | 
						|
    SPI1W4 = color32;
 | 
						|
    SPI1W5 = color32;
 | 
						|
    SPI1W6 = color32;
 | 
						|
    SPI1W7 = color32;
 | 
						|
  }
 | 
						|
  if (len > 16)
 | 
						|
  {
 | 
						|
    SPI1W8 = color32;
 | 
						|
    SPI1W9 = color32;
 | 
						|
    SPI1W10 = color32;
 | 
						|
    SPI1W11 = color32;
 | 
						|
  }
 | 
						|
  if (len > 24)
 | 
						|
  {
 | 
						|
    SPI1W12 = color32;
 | 
						|
    SPI1W13 = color32;
 | 
						|
    SPI1W14 = color32;
 | 
						|
    SPI1W15 = color32;
 | 
						|
  }
 | 
						|
  if (len > 31)
 | 
						|
  {
 | 
						|
    SPI1U1 = (511 << SPILMOSI);
 | 
						|
    while(len>31)
 | 
						|
    {
 | 
						|
#if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000)
 | 
						|
      if(SPI1CMD & SPIBUSY) // added to sync with flag change
 | 
						|
#endif
 | 
						|
      while(SPI1CMD & SPIBUSY) {}
 | 
						|
      SPI1CMD |= SPIBUSY;
 | 
						|
      len -= 32;
 | 
						|
    }
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
  }
 | 
						|
 | 
						|
  if (len)
 | 
						|
  {
 | 
						|
    len = (len << 4) - 1;
 | 
						|
    SPI1U1 = (len << SPILMOSI);
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
  }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushPixels - for ESP8266
 | 
						|
** Description:             Write a sequence of pixels
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
 | 
						|
 | 
						|
  if(_swapBytes) {
 | 
						|
    pushSwapBytePixels(data_in, len);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  uint16_t *data = (uint16_t*) data_in;
 | 
						|
 | 
						|
  uint32_t color[8];
 | 
						|
 | 
						|
  SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO);
 | 
						|
 | 
						|
 | 
						|
  while(len>15)
 | 
						|
  {
 | 
						|
    memcpy(color,data,32);
 | 
						|
    data+=16;
 | 
						|
 | 
						|
    len -= 16;
 | 
						|
 | 
						|
    // ESP8266 wait time here at 40MHz SPI is ~5.45us
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
    SPI1W0 = color[0];
 | 
						|
    SPI1W1 = color[1];
 | 
						|
    SPI1W2 = color[2];
 | 
						|
    SPI1W3 = color[3];
 | 
						|
    SPI1W4 = color[4];
 | 
						|
    SPI1W5 = color[5];
 | 
						|
    SPI1W6 = color[6];
 | 
						|
    SPI1W7 = color[7];
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
  }
 | 
						|
 | 
						|
  if(len)
 | 
						|
  {
 | 
						|
    uint32_t bits = (len*16-1); // bits left to shift - 1
 | 
						|
 | 
						|
    memcpy(color,data,len<<1);
 | 
						|
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
    SPI1U1 = (bits << SPILMOSI) | (bits << SPILMISO);
 | 
						|
    SPI1W0 = color[0];
 | 
						|
    SPI1W1 = color[1];
 | 
						|
    SPI1W2 = color[2];
 | 
						|
    SPI1W3 = color[3];
 | 
						|
    SPI1W4 = color[4];
 | 
						|
    SPI1W5 = color[5];
 | 
						|
    SPI1W6 = color[6];
 | 
						|
    SPI1W7 = color[7];
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
  }
 | 
						|
 | 
						|
  while(SPI1CMD & SPIBUSY) {}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************************
 | 
						|
** Function name:           pushSwapBytePixels - for ESP8266
 | 
						|
** Description:             Write a sequence of pixels with swapped bytes
 | 
						|
***************************************************************************************/
 | 
						|
void TFT_eSPI::pushSwapBytePixels(const void* data_in, uint32_t len){
 | 
						|
 | 
						|
  uint8_t* data = (uint8_t*)data_in;
 | 
						|
  //uint16_t* data = (uint16_t*)data_in;
 | 
						|
 | 
						|
  uint32_t color[8];
 | 
						|
 | 
						|
  SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO);
 | 
						|
 | 
						|
  while(len>15)
 | 
						|
  {
 | 
						|
    uint32_t i = 0;
 | 
						|
    while(i<8) { color[i++] = DAT8TO32(data); data+=4; }
 | 
						|
 | 
						|
    len -= 16;
 | 
						|
 | 
						|
    // ESP8266 wait time here at 40MHz SPI is ~5.45us
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
    SPI1W0 = color[0];
 | 
						|
    SPI1W1 = color[1];
 | 
						|
    SPI1W2 = color[2];
 | 
						|
    SPI1W3 = color[3];
 | 
						|
    SPI1W4 = color[4];
 | 
						|
    SPI1W5 = color[5];
 | 
						|
    SPI1W6 = color[6];
 | 
						|
    SPI1W7 = color[7];
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
  }
 | 
						|
 | 
						|
  if(len)
 | 
						|
  {
 | 
						|
    uint32_t i = 0;
 | 
						|
    uint32_t bits = (len*16-1); // bits left to shift - 1
 | 
						|
    len = (len+1)>>1;
 | 
						|
    while(len--) { color[i++] = DAT8TO32(data); data+=4; }
 | 
						|
 | 
						|
    while(SPI1CMD & SPIBUSY) {}
 | 
						|
    SPI1U1 = (bits << SPILMOSI) | (bits << SPILMISO);
 | 
						|
    SPI1W0 = color[0];
 | 
						|
    SPI1W1 = color[1];
 | 
						|
    SPI1W2 = color[2];
 | 
						|
    SPI1W3 = color[3];
 | 
						|
    SPI1W4 = color[4];
 | 
						|
    SPI1W5 = color[5];
 | 
						|
    SPI1W6 = color[6];
 | 
						|
    SPI1W7 = color[7];
 | 
						|
    SPI1CMD |= SPIBUSY;
 | 
						|
  }
 | 
						|
 | 
						|
  while(SPI1CMD & SPIBUSY) {}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 | 
						|
#endif
 | 
						|
////////////////////////////////////////////////////////////////////////////////////////
 |