B4R Question ESP8266 2.8 TFT 240x320 Working Code Example

KiloBravo

Active Member
Licensed User
Longtime User
I was working on another project and decided to add a TFT Display. I had a 240x320 TFT laying around so decided to wire it up and Test it on a esp8266.
Code below is ONLY for the Display. Touch is not working. I ran out of Pins on the ESP8266 for the Touch to work. I used Erel's Lib Wrap of the ILI9341, STMPE610, and GFX.
I modified Erel's Lib to Add a RESET Pin to the Init/Constructor. I did this because I read in a post somewhere that Adafruit's docs say you don't need the RESET pin.
However they use it in their code and if you don't have it defined and use a knockoff board it can cause the board to crash. YMMV :)

My board does not have a STMPE610 Touch Chip. It uses an XPT2046 Touch Chip. So ignore the warning about STMPE610 not used from the compiler.

I am incorporating the display and touch into my current project with an ESP32. I ran out of pins to do it on the ESP8266.
I am working on wrapping the LCDWIKI_Touch Library to use in B4R. I will post that Lib when/if I get it working. :cool:

Besides the RESET pin, I think another gotcha for folks may have been that most code I saw says to use D8 (GPIO15) for CS (Chip Select). CS is ACTIVE LOW, PIN D8 has PULLDOWN Resistor tied to it. IMHO that won't work. Use another Pin for CS. This CODE uses the SPI Hardware defined pins. (D5 SCLock GPIO14, D6 MISO GPIO12, D7 MOSI GPIO13).

Another gotcha is I read posts where it says you don't need to have the MISO pin connected. But, you DO if you are using this Library.
SPI usually indicates a 4 wire interface CS, MISO, MOSI, Sclk, this is NOT the same as IIC/I2C which is a two wire interface SCL, and SDA. I read numerous posts on other sites where people use the terms interchangeably and incorrectly, which is why most of THEIR code does not work. YMMV.

Finally the Touch Chip on some TFT boards use STMPE610 or a clone which can be interfaced with SPI or I2C like the above mentioned Lib.

My TFT board uses the Touch Chip XPT2046. This has a completely different interface. It requires a four wire SPI interface and an ADDITIONAL Interrupt Pin. This is why I am wrapping the LCDWIKI_TOUCH Library so I can interface with the XPT2046 and use the Touch Screen.

I am going to post my Working code in the next post. Comments at the end list websites and resources I used to get it working. I will also attached my Lib with my changes to Erel's Wrap.

A long post but I hope some folks find the information provided useful in there projects. Any mistakes I made or critiques of what I said are welcome.



Live Long and Prosper!
 
Last edited:
My working code for the TFT Display.

[CODE lang="b4x" title="Esp8266 TFT 240x320"]#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 300
#End Region

Sub Process_Globals
Public Serial1 As Serial
Private ILI As AdafruitILI93411
Private Timer1 As Timer
End Sub

Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
Delay(100)
''
Log("ILI9341 Init")
ILI.Initialize(16,4,0)
' LED Pin Always ON, tied to 3.3V protoboard powersupply, power for TFT not driven by ESP8266
' Remember to tie the Grounds together :-)
Delay(120) ''''''' Only INIT the TFT Once and the 120 ms delay IS needed or it fails ****
Log("ILI9341 Init Done")
'
Timer1.Initialize("TickSub_1",1000)
Timer1.Enabled = True

End Sub

Sub TickSub_1 '''''''''' Works Up To Here
Log("Red")
ILI.FillScreen(ILI.COLOR_RED)
Delay(500)
Log("White")
ILI.FillScreen(ILI.COLOR_WHITE)
Delay(500)
Log("Blue")
ILI.FillScreen(ILI.COLOR_BLUE)
Delay(500)
Log("Done")
ILI.FillScreen(ILI.COLOR_WHITE)
Delay(500)
Log("Draw Text")
Delay(500)
ILI.GFX.ConfigureText(2, ILI.COLOR_BLACK, True)
ILI.GFX.SetCursor(2, 2)
ILI.GFX.DrawText("This is a test")
Log("Draw Text Done")
Log("Height: ", ILI.GFX.Height)
Log("Width: ", ILI.GFX.Width)
Delay(500)
'''''''''''''''''''''''''''''''
ILI.GFX.DrawCircle(120, 160, 100, ILI.COLOR_RED,True)
Delay(5000)

End Sub

'''''''''' Notes '''''''''''
' B4R v3.90
' Arduino v1.8.12
' Board Lolin D1 Mini Pro
' https://www.wemos.cc/en/latest/d1/d1_mini_pro.html#

' I2C Bus Esp8266
' D1 is GPI05 SCL ''' Check This But Not Used In This Project
' D2 is GPI04 SDA ''' Check This But Not Used In This Project
'
' SPI Bus
' D5 GPI014 SCK ''' Standard on Lolin D1 Mini Pro
' D6 GPI012 MISO ''' Standard on Lolin D1 Mini Pro
' D7 GPI013 MOSI ''' Standard on Lolin D1 Mini Pro
' D0 GPI016 Chp Select SS/CS ''' Changed See Below ''' KB :-)

'// Constructor when using hardware SPI. Faster, but must use SPI pins
'Adafruit_ILI9341::Adafruit_ILI9341(int8_t cs, int8_t dc, int8_t rst) : Adafruit_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) {
' // _cs = cs;
' // _dc = dc;
' // _rst = rst;
' // hwSPI = true;
' // _mosi = _sclk = 0;
' Modified Erel's Wrap to INCLUDE the RST in the CONSTRUCTOR ********
' _cs = 16; // D0 I0 **** Can't use "D8" Has A pull Down Resistor CS is Active Low which means Chip will alsways be selected ****
' _rst = 0; // D3 IO, 10k Pull-up
' _dc = 4; // D2 IO, SDA
' _mosi = 13; // D7
' _sclk = 14; // D5
' _Led = Backlight Hardwired to +3.3V
' _miso = 12; // D6
' hwSPI = True;
'}

'Lolin D1 Mini Pro Pinout '' https://www.wemos.cc/en/latest/d1/d1_mini_pro.html#pin
'
'Pin Function ESP-8266 Pin
'TX TXD TXD
'RX RXD RXD
'A0 Analog A0 input Max 3.2V
'D0 IO GPIO16
'D1 IO, SCL GPIO5
'D2 IO, SDA GPIO4
'D3 IO, GPIO0 10k Pull-up
'D4 IO, GPIO2 10k Pull-up BUILTIN_LED
'D5 IO, SCK GPIO14
'D6 IO, MISO GPIO12
'D7 IO, MOSI GPIO13
'D8 IO, 10k GPIO15 10K Pull-down,
'G Ground GND
'5V 5V -
'3V3 3.3V 3.3V
'RST Reset RST

'2.8 TFT SPI 240x320 V1.2 '' http://www.lcdwiki.com/2.8inch_SPI_Module_ILI9341_SKU:MSP2807
' TFT/Display Chip Unknown but works with ILI93411
' Touch Chip XPT2046 NOT --- STMPE610
'' Below Not Used in this Project
'' https://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf
'' Datasheet lists http://http://xptek.com.cn/ As the Chip Maker
'' https://github.com/spapadim/XPT2046 Driver Code[/CODE]
 

Attachments

Upvote 0
Just wanted to add on my module the Display chip is in/or under the Display board and can not be identified by sight.
There is an SPI command in the Library to determine the Display Chip. But I did not use it.
Try my code and if it works it is compatible with the ILI9341.

The Touch Chip is visible on the back of the board and wired to the T_ pin outs. You can just look at that one and see what it is.

Enjoy!
 
Upvote 0
This is the working code for the ESP32 uses the same Libs as above.

[CODE lang="b4x" title="Lolin32 V1.0.0 ESP32 TFT - No Touch yet"]
#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 600
#End Region

Sub Process_Globals
Public Serial1 As Serial
Private ILI As AdafruitILI93411
Private Timer1 As Timer
End Sub

Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
Delay(100)
''
Log("ILI9341 Init")
'
' TFT_MISO 19
' TFT_MOSI 23
' TFT_SCLK 18
' TFT_CS 5 // Chip Select control pin
' TFT_DC 16 // Data Command control pin
' TFT_RST 17 // Reset pin (could connect To RST pin)
'
ILI.Initialize(5,16,17)
' LED Pin Always ON, tied to 3.3V protoboard powersupply, power for TFT not driven by ESP32
' Remember to tie the Grounds together :-)
Delay(120) ''''''' Only INIT the TFT Once and the 120 ms delay IS needed or it fails ****
Log("ILI9341 Init Done")
'
Timer1.Initialize("TickSub_1",1000)
Timer1.Enabled = True

End Sub

Sub TickSub_1
Log("Red")
ILI.FillScreen(ILI.COLOR_RED)
Delay(500)
Log("White")
ILI.FillScreen(ILI.COLOR_WHITE)
Delay(500)
Log("Blue")
ILI.FillScreen(ILI.COLOR_BLUE)
Delay(500)
Log("Done")
ILI.FillScreen(ILI.COLOR_WHITE)
Delay(500)
Log("Draw Text")
Delay(500)
ILI.GFX.ConfigureText(2, ILI.COLOR_BLACK, True)
ILI.GFX.SetCursor(2, 2)
ILI.GFX.DrawText("This is a test")
Log("Draw Text Done")
Log("Height: ", ILI.GFX.Height)
Log("Width: ", ILI.GFX.Width)
Delay(500)
'''''''''''''''''''''''''''''''
ILI.GFX.DrawCircle(120, 160, 100, ILI.COLOR_RED,True)
Delay(5000)

End Sub[/CODE]
 
Upvote 0
I spent a little time on writing some code to read the XPT2046. I followed this example ...
https://www.ccsinfo.com/forum/viewtopic.php?t=58912 for A PIC Chip. He also mentions ...
"This is a functional driver you can use on the XPT2046 or the TI TSC2046, it MAY also work with the ADS7843"

I can read the Data (x,y,z). My XY rotation seems to be off from the ILI9341. Could be my bit manipulation or the Select Case.
I did not calibrate anything. I just wanted to see if I could pull the point location off of the screen which it seems to do. But not in the right orientation.
I did not use an interupt. I am just polling the tirq pin with a timer.

Thanks to whoever ported the rSPI32 Library it worked great ! ?

I will post the code but it is very raw and not a driver just some quick and dirty code to read the point on the touch screen.
Probably lots of Code Smells in there as well! ?
"If" I clean it up I will update the code on this thread. Enjoy!

[CODE lang="b4x" title="Use At Your Own Risk ! XPT2046 read code :-)"]
#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 600
#End Region

Sub Process_Globals
Public Serial1 As Serial
Private ILI As AdafruitILI93411
Private Timer1 As Timer

Public tirqPin As Pin
Public X_COMMAND_BYTE As Byte = 0xD0 ' get X values
Public Y_COMMAND_BYTE As Byte = 0x90 ' get Y values
Public Z1_COMMAND_BYTE As Byte = 0xB1 ' get Z1 value
Public Z2_COMMAND_BYTE As Byte = 0xC1 ' get Z2 value
Public MSB_BIT_MASK As Byte = 0x7F ' Bit mask For MSB byte
Public Z_THRESHOLD As Byte = 400
Public Z_THRESHOLD_INT As Int = 75
Public X_Val, Y_Val As UInt
Public Z_Val, Z1, Z2 As Int
Public xraw, yraw As Int
Public ScreenRotation As Byte = 3 'screen rotation
Public TOUCH_FLAG As Boolean = False
End Sub
' Followed the example below from "cbarberis" Written for a PIC Chip.
'https://www.ccsinfo.com/forum/viewtopic.php?t=58912
'//For resolution 240x320,the calibration parameter is 663,-13,894,-30
' XFAC 663
' XOFFSET (-13)
' YFAC 894
' YOFFSET (-30)

Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
Delay(100)
''
Log("ILI9341 Init")
ILI.Initialize(5,16,17)
ILI.SetRotation(1)

' LED Pin Always ON, tied to 3.3V protoboard powersupply, power for TFT not driven by ESP8266
' Remember to tie the Grounds together :-)
Delay(120) ''''''' Only INIT the TFT Once and the 120 ms delay IS needed or it fails ****
Log("ILI9341 Init Done")
Delay(120) ''''''' Only INIT the TFT Once and the 120 ms delay IS needed or it fails ****
'
ScreenSet
'
SPI.CheckIfThisBoardIsSupported
'CHANGE HERE THE PIN NUMBERS (SCK, MISO, MOSI, CS)
'SS/CS =15 MISO=12 MOSI=13 SCK =14 T_IRQ = 0
SPI.ESP32_SPI_Set_Pins(14,12,13,15)
SPI.CSPinDeActivate(SPI.CS__SPI)
'
tirqPin.Initialize(0,tirqPin.MODE_INPUT)

Timer1.Initialize("TickSub_1",100)
Timer1.Enabled = True

End Sub

Sub TickSub_1
If tirqPin.digitalread = True Then
ReadTouch_XYZData
If Z_Val > Z_THRESHOLD_INT Then
Log("XRaw value: ",xraw)
Log("YRaw value: ",yraw)
Log("X value: ",X_Val)
Log("Y value: ",Y_Val)
Log("Z value: ",Z_Val)
Log("Done XYZ Data")
End If
End If
End Sub

Sub ReadTouch_XYZData ' read 12 Bit data from SPI bus after sending a command byte For X,Y,Z1&Z2 measurements

Dim MSB, LSB As Byte = 0 ' was Uin_8t
' output_low(PIN_B8);
' delay_us(2);
' /////////////////////Gather Z pressure readings////////////////////////////////////
SPI.Begin_Transaction(2000000, SPI.MSBFIRST, SPI.SPI_MODE0)
SPI.CSPinActivate(SPI.CS__SPI)

SPI.Transfer_Byte(Z1_COMMAND_BYTE) ' send command byte
MSB = SPI.Transfer_Byte(0)
LSB = SPI.Transfer_Byte(0)
' Z1 = (((MSB & MSB_BIT_MASK) << 8)+ LSB) >> 3;
Z1 = Bit.ShiftLeft(Bit.And(MSB,MSB_BIT_MASK),8)
Z1 = Z1 + LSB
Z1 = Bit.ShiftRight(Z1,3)
'
SPI.Transfer_Byte(Z2_COMMAND_BYTE) ' send command byte
MSB = SPI.Transfer_Byte(0)
LSB = SPI.Transfer_Byte(0)
' Z2 = (((MSB & MSB_BIT_MASK) << 8)+ LSB) >> 3;
Z2 = Bit.ShiftLeft(Bit.And(MSB,MSB_BIT_MASK),8)
Z2 = Z2 + LSB
Z2 = Bit.ShiftRight(Z2,3)
'
Z_Val = Z1 + 4095
Z_Val = Z_Val - Z2
'
If(Z_Val >= Z_THRESHOLD) Then ' If we have more than the pressure threshold Then read X&Y data
SPI.Transfer_Byte(X_COMMAND_BYTE) ' send command byte
MSB = SPI.Transfer_Byte(0)
LSB = SPI.Transfer_Byte(0)
xraw = Bit.ShiftLeft(Bit.And(MSB,MSB_BIT_MASK),8)
xraw = xraw + LSB
xraw = Bit.ShiftRight(xraw,3)

SPI.Transfer_Byte(Y_COMMAND_BYTE) ' send command byte
MSB = SPI.Transfer_Byte(0)
LSB = SPI.Transfer_Byte(0)
yraw = Bit.ShiftLeft(Bit.And(MSB,MSB_BIT_MASK),8)
yraw = yraw + LSB
yraw = Bit.ShiftRight(yraw,3)
End If

'output_high(PIN_B8); // in Case Z_Val did Not qualify lets bring CS high
SPI.CSPinDeActivate(SPI.CS__SPI)
SPI.End_Transaction
' We need To know the display rotation To compensate For X,Y locations
Select Case True ' We need To know the display rotation To compensate For X,Y locations

Case ScreenRotation = 1
X_Val = 4095 - yraw
Y_Val = 4095 - xraw

Case ScreenRotation = 2
X_Val = xraw
Y_Val = yraw

Case ScreenRotation = 3
X_Val = yraw
Y_Val = 4095 - xraw

Case ScreenRotation = 4
X_Val = 4095 - xraw
Y_Val = 4095 - yraw

End Select
End Sub

Sub ScreenSet
Log("Blue")
ILI.FillScreen(ILI.COLOR_BLUE)
Delay(500)
Log("Done")
ILI.FillScreen(ILI.COLOR_WHITE)
Delay(500)
Log("Draw Text")
Delay(500)
ILI.GFX.ConfigureText(2, ILI.COLOR_BLACK, True)
ILI.GFX.SetCursor(2, 2)
ILI.GFX.DrawText("This is a test")
Log("Draw Text Done")
Log("Height: ", ILI.GFX.Height-10)
Log("Width: ", ILI.GFX.Width)
End Sub

'//For resolution 240x320,the calibration parameter is 663,-13,894,-30
'//For resolution 320x480,the calibration parameter is 852,-14,1284,-30
'
'#define XFAC 663 //852
'#define XOFFSET (-13) //(-14)
'#define YFAC 894 //1284
'#define YOFFSET (-30)
''[/CODE]
 
Upvote 0
Back
Top