From Firewing

FirewingUser: TFTTouch

TFT Touch Screen Module

This is a module that I have put together to work with the Firewing Color TFT Library, the module has only been tested with the 2.4" TFT Display Shield from IteadStudio, the same one that was used on the Firewing Color TFT Library, See here for more information: TFT Library article.

I have also put together a simple Calibration programme that you can use to set the calibration values into the Touch module to suit your display.

I will include download links at the bottom to make it easier to download.

Module Touch

' Touch Data In pin...
#option T_DIN = A0
#if IsOption(T_DIN) And Not IsValidPortPin(T_DIN) 
   #error T_DIN, "Invalid option. Touch T_DIN must be a valid pin."
#endif

' Touch Clock pin...
#option T_CLK = A1
#if IsOption(T_CLK) And Not IsValidPortPin(T_CLK) 
   #error T_CLK, "Invalid option. Touch T_CLK must be a valid pin."
#endif

' Touch Data Out pin...
#option T_DOUT = D8
#if IsOption(T_DOUT) And Not IsValidPortPin(T_DOUT) 
   #error T_DOUT, "Invalid option. Touch T_DOUT must be a valid pin."
#endif

' Touch Pen Interrupt pin...
#option T_IRQ = D9
#if IsOption(TFT_EN) And Not IsValidPortPin(T_IRQ) 
   #error T_IRQ, "Invalid option. Touch T_IRQ must be a valid pin."
#endif

' Bring pin options into the Module...
private _din As T_DIN.T_DIN@       ' Data In pin
private _clk As T_CLK.T_CLK@       ' Clock pin
private _dout As T_DOUT.T_DOUT@    ' Data Out pin
private _irq As T_IRQ.T_IRQ@       ' Touch Interrupt pin

' Calibration Structure...
private Structure TCalibration
    dim X_TopLeft As integer 
    dim X_BottomRight as integer 
    dim Y_TopLeft As integer 
    dim Y_BottomRight as integer 
End Structure

' Public variables...
public Calibrate As TCalibration
public dispX as ushort = 320
public dispY as ushort = 240 
public TPos_X as integer = 0
public TPos_Y as integer = 0

'******************************************************************************
'* Name    : SendCommand                                                      *
'* Purpose : Send command to touch (MSB first)                                *
'******************************************************************************
private sub SendCommand(byval data as byte)
   low(_clk)      
   delayus(1)
   for i as byte = 7 to 0 step -1
      if data.bits(i) = 1 then  
         high(_din)
      else
         Low(_din)
      end if
      low(_clk)                
      delayus(5)
      high(_clk) 
      delayus(5)            
   next
end sub

'******************************************************************************
'* Name    : ReadData                                                         *
'* Purpose : Reads the touch data                                             *
'******************************************************************************
private function ReadData() as ushort
   dim data as ushort = 0
   for count as byte = 12 to 0 step - 1  
      if _dout = 1 then
         data.bits(count) = 1
      else
         data.bits(count) = 0
      end if   
      high(_clk)               
      delayus(25)
      low(_clk)
      delayus(25)
   next
   return data
end function

'******************************************************************************
'* Name    : Read                                                             *
'* Purpose : Initialise a read sequence to get new touch data                 *
'******************************************************************************  
public sub Read()
   dim x as uinteger = 0
   dim y as uinteger = 0                               
   for i as byte = 1 to 9    
      SendCommand(&H90)                  
      high(_clk)           
      delayus(20)
      low(_clk) 
      delayus(20)            
      y += ReadData()
      delayus(20)          
      SendCommand(&HD0)      
      high(_clk) 
      delayus(20)
      low(_clk) 
      delayus(20)   
      x += ReadData() 
   next        
   TPos_X = x / 9 
   TPos_Y = y / 9 
end sub

'******************************************************************************
'* Name    : Available                                                        *
'* Purpose : Check to see if there is touch data                              *
'******************************************************************************
' Available Touch Data (Returns True/False)...
public function Available() as Boolean
  return (_irq = 0)
end function

'******************************************************************************
'* Name    : GetXPos                                                          *
'* Purpose : Get touch X position                                             *
'******************************************************************************
public function GetXPos() as ushort
   dim x as ushort = Cal(TPos_Y,Calibrate.X_TopLeft,Calibrate.X_BottomRight,0,dispX-1)
   if x >= (dispX-1) then
      x = (dispX-1)
   end if
   if x <= 0 then
      x = 0
   end if
   return x
end function

'******************************************************************************
'* Name    : GetYPos                                                          * 
'* Purpose : Get touch Y position                                             *
'******************************************************************************
public function GetYPos() as ushort
   dim y as ushort = Cal(TPos_X,Calibrate.Y_TopLeft,Calibrate.Y_BottomRight,0,dispY-1)
   if y >= (dispY-1) then
      y = (dispY-1)
   end if
   if y <= 0 then
      y = 0
   end if
	return y
end function

'******************************************************************************
'* Name    : Cal                                                              *
'* Purpose : Calculate touch calibration                                      *
'******************************************************************************
Private Function Cal(val as ushort, inMin as ushort, inMax as ushort, outMin as ushort, outMax as ushort) as ushort
  return (val - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
end function

'******************************************************************************
'* Name    : SetDefaultCal                                                    *
'* Purpose : Set default calibration values                                   *
'* Note    : Edit these values to suit your tft touch screen calibration,     *
'*         : Obtain calibration values by running the touch calibration prog  *
'******************************************************************************
private sub SetDefaultCal()
   Calibrate.X_TopLeft     = 406
   Calibrate.X_BottomRight = 3831
   Calibrate.Y_TopLeft     = 370
   Calibrate.Y_BottomRight = 3765
end sub

'******************************************************************************
'* Name    : Main                                                             *
'* Purpose : Configure the touch screen module before use                     *
'******************************************************************************
private Sub Main()
   input(_dout)
   input(_irq)
   high(_clk)
   high(_din) 
   SetDefaultCal()
End Sub

End Module

CalibrationProg

This is a simple calibration programme which you can use to obtain the calibration values for your tft display, you will then need to edit the Touch module to suit your display, see "SetDefaultCal" subroutine in the Touch module. The calibration procedure is pretty much self explanatory, just follow what it says on the tft display.

Note: you will also need to download the Font module which I have used with the Calibration programme, just put the font file and touch module into your User Library.

Example Prog Images



 

 

 

 

 

 


The image to the right shows a screen with cross hairs, this is the screen that you will see after the Calibration is complete, you can test your calibration values by holding a stylus in the centre of the cross hairs, the X/Y text will automatically update on the screen.

The values expected should be close to (X=50,Y=50), (X=100,Y=100) and (X=200,Y=200).

 

 

 

Calibration Prog Code

'*****************************************************************************
'*  Name    : CalibrateProg.bas                                              *
'*  Author  : Gavin Wiggett                                                  *
'*  Notice  : Copyright (c) 2013 Bitfogav                                    *
'*          : All Rights Reserved                                            *
'*  Date    : 17/07/2013                                                     *
'*  Version : 1.1 Changed PPS pins configuration see (Onstartup) sub.        *
'*  Version : 1.0                                                            *
'*  Notes   : Record the Calibration values and edit the values under,       *
'*          : SetDefaultCal() in the tft Touch module.                       *
'*****************************************************************************

' set high speed clock and import modules...
clock = 80
imports Tft
imports TftGraphic
imports ComicSansMS
imports TftTouch

' program entry point...
Sub Main()
   WriteInstr()  
   CalibrateScreen(1) ' Top Left
   CalibrateScreen(2) ' Bottom Right       
   DisplayCalValues() ' display cal values                   
   do ' wait for user to touch screen
   loop until Touch.Available()           
   DrawMarkers()    
   dim x,y as ushort
   while true  
      if Touch.Available() then 
         Tft.Clear                                          
         DrawMarkers()
         Touch.Read()
         x = Touch.GetXPos()
         y = Touch.GetYPos()
         Tft.WriteAt(150,20, "X="+str(x)+" Y="+str(y))        
         delayms(800)
      end if                              
   end while
End Sub

' Display Cal values...
sub DisplayCalValues()
   Tft.Clear
   Tft.WriteAt(15, 5,  "*Calibration Values*")          
   Tft.WriteAt(15, 20, "X_TopLeft..........= "+ str(Calibrate.X_TopLeft))
   Tft.WriteAt(15, 32, "X_BottomRight....= "+str(Calibrate.X_BottomRight))
   Tft.WriteAt(15, 44, "Y_TopLeft..........= "+str(Calibrate.Y_TopLeft))
   Tft.WriteAt(15, 56, "Y_BottomRight....= "+str(Calibrate.Y_BottomRight))
   Tft.WriteAt(15, 76, "Calibration is complete.")
   Tft.WriteAt(15, 88, "Record values and edit TftTouch Module.")  
   Tft.WriteAt(15, 108,"Tap screen to continue to test.")
end sub

' testmarkers...
sub DrawMarkers()
   CrossHair(50,50)
   CrossHair(100,100)
   CrossHair(200,200)
   CornerMarker(1,0,0)
   CornerMarker(2,dispX-1,dispY-1)
end sub

' Calibrate Touch Screen...
sub CalibrateScreen(n as byte)
   dim counter as ushort = 0
   Tft.Clear
   select case n
      case 1 : CornerMarker(1,0,0)
      case 2 : CornerMarker(2,dispX-1,dispY-1)
   end select
   Tft.WriteAt((dispX/2)-15,(dispY/2)-10, "PRESS")
   do ' wait for user to touch screen
   loop until Touch.Available()
   Tft.Clear
   select case n
      case 1 : CornerMarker(1,0,0)
      case 2 : CornerMarker(2,dispX-1,dispY-1)
   end select
   Tft.WriteAt((dispX/2)-10,(dispY/2)-10, "HOLD") 
   do            
   Touch.Read()      ' keep reading touch screen values
   counter += 1
   loop until counter = 60 
   select case n 
      case 1 : Calibrate.X_TopLeft = TPos_Y : Calibrate.Y_TopLeft = TPos_X
      case 2 : Calibrate.X_BottomRight = TPos_Y : Calibrate.Y_BottomRight = TPos_X
   end select        
   Tft.Clear
   select case n
      case 1 : CornerMarker(1,0,0)
      case 2 : CornerMarker(2,dispX-1,dispY-1)
   end select
   Tft.WriteAt((dispX/2)-20,(dispY/2)-10, "RELEASE")
   do ' wait for user to release
   loop until not Touch.Available()
   delayms(500) 
end sub

' Write Instructions on start screen...
sub WriteInstr()
   Tft.Clear
   Tft.Brush.Style = BrushStyle.IsClear
   Tft.SetFont(ComicSansMS)
   Tft.WriteAt(25,50,"Use a stylus or something similar to touch as close")
   Tft.WriteAt(25,65,"to the corner of the selected corner marker as possible.")
   Tft.WriteAt(25,85,"Keep as still as possible and keep holding")
   Tft.WriteAt(25,100,"until told to release!.")
   Tft.WriteAt(25,120,"Repeat for both Top/Bottom.")
   Tft.WriteAt(25,140,"Do NOT use your finger as a calibration.")
   Tft.WriteAt(25,160,"Tap screen to continue.") 
   Tft.WriteAt((dispX/2)-60,(dispY)-15,"*TFT Touch Calibration*")
   do ' wait for user to touch screen
   loop until Touch.Available() 
   do ' wait for user to release
   loop until not Touch.Available()
   delayms(500) 
end sub

' Cross Hairs...
sub CrossHair(x as ushort, y as ushort)
  Tft.Rect(x-10, y-10, x+10, y+10)
  Tft.Line(x-5, y, x+5, y)
  Tft.Line(x, y-5, x, y+5)
end sub

' Corner Markers...
sub CornerMarker(n as byte, x as ushort, y as ushort)
   select case n  
      case 1 ' Top
      Tft.Line(x, y, x+10, y+10)
      Tft.Line(x, y, x+10, y)
      Tft.Line(x, y, x, y+10)
      case 2 ' Bottom
      Tft.Line(x, y, x-10, y-10)
      Tft.Line(x, y, x-10, y)
      Tft.Line(x, y, x, y-10)
   end select
end sub

' disable UART1 on pins D0 and D1...
sub OnStartup() Handles PIC.OnStartup
   RPINR18 = RPINR18 or &H001F
   RPOR2 = RPOR2 and &HE0FF    
end sub

Download Files

*TftTouch.zip - TFT Touch Module.

*CalibrateProgV1_1.zip - Calibration Prog.

*ComicSansMS.zip - Font File.

Retrieved from http://www.firewing.info/pmwiki.php?n=FirewingUser.TFTTouch
Page last modified on July 18, 2013, at 06:23 PM