TouchScreen

This library reads the XY position from a 4 wire resistive touch screen. It includes functions to determine if the pen is down and a utility function to determine if the detected XY position is within a bounding rectangle.

The touchscreen is connected directly to the analogue channels AN0 to AN3 of the PIC. Pull-down resistors are required on each of these pins (e.g. 10K resistors). There are a number of #options - these are documented at the start of the library.

It is the users responsibility to set up the analogue port correctly. The two sample codes below with give an example of how to do this.

Many thanks to juliovmd of the MikroElektronika forum for providing some ideas for this code.

Steven Wright

Vidoes

Here are some YouTube videos of the touchscreen in action!

TouchScreen Module

{
*****************************************************************************
*  Name    : TouchScreen.BAS                                                *
*  Author  : S Wright                                                       *
*  Notice  : Copyright (c) 2007 S Wright                                    *
*          : All Rights Reserved                                            *
*  Date    : 27/07/2007                                                     *
*  Version : 1.0                                                            *
*  Notes   : This library is hard coded to use ADC channels AN0 - AN3.      *
*          : These must be connected To the following connections of the    *
*          : touchscreen:                                                   *
*          : ADC Channel 0 (AN0) - connect To X1                            *
*          : ADC Channel 1 (AN1) - connect To X2                            *
*          : ADC Channel 2 (AN2) - connect To Y1                            *
*          : ADC Channel 3 (AN3) - connect To Y2                            *
*          : The user should ensure that these analogue channels are        *
*          : assigned to the correct pins for the PIC in use, using the     *
*          : #option statements (default to PORTA.0 - PORTA.3).             *
*          : In addition, it is down to the user to ensure that these       *
*          : channels are set as analogue using ADC.SetConfig in the main   *
*          : code and that the ADC is set up appropriately using            *
*          : ADC.SetAcqTime And ADC.SetConvTime.                            *
*          : The library also assumes that:                    X2           *
*          : X1 is the bottom plate of touchscreen         ----------       *
*          : X2 is the top plate of touchscreen           |          |      *
*          : Y1 is the left plate of touchscreen      Y1 -|          |- Y2  *
*          : Y2 is the right plate of touchscreen         |          |      *
*          :                                               ----------       *
*          :                                                   X1           *
*          : If this is not the case, then connect as if this was true,     *
*          : i.e. connect AN0 to bottom plate, AN1 to top plate etc...      *
*          : Please note that pull-down resistors are also required on all  *
*          : four analogue pins.                                            *
*          : In GetXY, the TL values are as if read from top-left and the   *
*          : BR values as if read from bottom-right.                        *
*          : When setting the calibration values, the TL values should be   *
*          : those found reading from top-left and the BR values those      *
*          : found reading from the bottom-right, i.e. using                *
*          : GetXY(X_TL, X_BR, Y_TL, Y_BR) for the top-left corner,         *
*          : X_TL is then X_Min_TL, whilst X_BR is X_Max_BR (furthest from  *
*          : bottom-right corner), etc...                                   *
*****************************************************************************
}
Module TouchScreen

Include "ADC.bas"
Include "Utils.bas"

// Default module options - user options can override these values...
#option TS_AN0 = PORTA.0              // ADC Channel 0 - connect to X1
#option TS_AN1 = PORTA.1              // ADC Channel 1 - connect to X2
#option TS_AN2 = PORTA.2              // ADC Channel 2 - connect to Y1
#option TS_AN3 = PORTA.3              // ADC Channel 3 - connect to Y2
#option TS_GLCD_Width = 320           // width of GLCD in pixels
#option TS_GLCD_Height = 240          // height of GLCD in pixels
#option TS_Pen_Down_DelayUS = 100     // delay before ADC for pen down (US)
#option TS_Read_XY_DelayMS = 1        // delay before ADC X & Y positions (MS)
#option TS_Pen_Down_Threshold = 175   // threshold value for pen down (0 - 255)
#option TS_X_Min_TL = 80              // min ADC reading of X value - reading from TL
#option TS_X_Max_TL = 740             // max ADC reading of X value
#option TS_Y_Min_TL = 90              // min ADC reading of Y value
#option TS_Y_Max_TL = 695             // max ADC reading of Y value
#option TS_X_Min_BR = 80              // min ADC reading of X value - reading from BR
#option TS_X_Max_BR = 740             // max ADC reading of X value
#option TS_Y_Min_BR = 90              // min ADC reading of Y value
#option TS_Y_Max_BR = 695             // max ADC reading of Y value

// Validate AN0 pin...
#if IsOption(TS_AN0) And Not IsValidPortPin(TS_AN0) 
   #error TS_AN0, "Invalid option. AN0 must be a valid port pin."
#endif

// Validate AN1 pin...
#if IsOption(TS_AN1) And Not IsValidPortPin(TS_AN1) 
   #error TS_AN1, "Invalid option. AN1 must be a valid port pin."
#endif

// Validate AN2 pin...
#if IsOption(TS_AN2) And Not IsValidPortPin(TS_AN2) 
   #error TS_AN2, "Invalid option. AN2 must be a valid port pin."
#endif

// Validate AN3 pin...
#if IsOption(TS_AN3) And Not IsValidPortPin(TS_AN3) 
   #error TS_AN3, "Invalid option. AN3 must be a valid port pin."
#endif

Dim
    TS_X1 As [email protected],
    TS_X2 As [email protected],
    TS_Y1 As [email protected],
    TS_Y2 As [email protected]

Const
    Pen_Down_DelayUS = TS_Pen_Down_DelayUS,   
    Read_XY_DelayMS = TS_Read_XY_DelayMS

Const
    X_Min_TL_Init = TS_X_Min_TL,
    X_Max_TL_Init = TS_X_Max_TL,
    Y_Min_TL_Init = TS_Y_Min_TL,
    Y_Max_TL_Init = TS_Y_Max_TL,
    X_Min_BR_Init = TS_X_Min_BR,
    X_Max_BR_Init = TS_X_Max_BR,
    Y_Min_BR_Init = TS_Y_Min_BR,
    Y_Max_BR_Init = TS_Y_Max_BR,
    X_Max_Pos = TS_GLCD_Width - 1,
    Y_Max_Pos = TS_GLCD_Height - 1,
    Pen_Down_Threshold_Init = TS_Pen_Down_Threshold

Structure TCalibration
    X_Min_TL As Word,
    X_Max_TL As Word,
    Y_Min_TL As Word,
    Y_Max_TL As Word,   
    X_Min_BR As Word,
    X_Max_BR As Word,
    Y_Min_BR As Word,
    Y_Max_BR As Word   
End Structure

Public Dim
    Calibration As TCalibration,
    Pen_Down_Threshold As Byte

{
********************************************************************************
* Name    : PenPressure (PUBLIC)                                               *
* Purpose : Returns a value between 0-255 indicating pen pressure.             *
*         : Testing this value will allow a sensible value for                 *
*         : Pen_Down_Threshold to be calculated.                               *
********************************************************************************
}
Public Function PenPressure() As Byte
    Input(TS_X1)                                 // X1 is input 
    Input(TS_X2)                                 // X2 is input 
    Output(TS_Y1)                                // Y1 is output 
    Output(TS_Y2)                                // Y2 is output 
    TS_Y1 = 1                                    // Both Y plates high
    TS_Y2 = 1                               
    DelayUS(Pen_Down_DelayUS)
    PenPressure = ADC.Read(AN1) >> 2             // Read ADC  
    Input(TS_Y1)                                 // Y1 is input - power save 
    Input(TS_Y2)                                 // Y2 is input - power save
End Function    
{
********************************************************************************
* Name    : PenIsDown (PUBLIC)                                                 *
* Purpose : Returns a boolean to indicate if pen is down.                      *
********************************************************************************
}
Public Function PenIsDown() As Boolean
    If PenPressure > Pen_Down_Threshold Then     // Pen is down
        Result = True
    Else
        Result = False
    EndIf   
End Function    
{
********************************************************************************
* Name    : ReadX (PRIVATE)                                                    *
* Purpose :                                                                    *
********************************************************************************
}
Function ReadX() As Word
    DelayMS(Read_XY_DelayMS)                     // Stabilise
    Result = Max(ADC.Read(AN0), ADC.Read(AN1))   // Read X co-ordinate
End Function     
{
********************************************************************************
* Name    : ReadY (PRIVATE)                                                    *
* Purpose :                                                                    *
********************************************************************************
}
Function ReadY() As Word
    DelayMS(Read_XY_DelayMS)                     // Stabilise
    Result = Max(ADC.Read(AN2), ADC.Read(AN3))   // Read Y co-ordinate
End Function     
{
********************************************************************************
* Name    : GetXY (PUBLIC)                                                     *
* Purpose : Gets raw values for pen position, used for setting Calibration     *
*         : values. pX_TL is the X-position, read from the top-left corner,    *
*         : pX_BR is the X-position, read from the bottom-right corner, etc... *
********************************************************************************
}     
Public Sub GetXY(ByRef pX_TL As Word, ByRef pX_BR As Word, ByRef pY_TL As Word, ByRef pY_BR As Word)
    // Get X co-ordinate          
    Input(TS_X1)                                 // X1 is input 
    Input(TS_X2)                                 // X2 is input 
    Output(TS_Y1)                                // Y1 is output 
    Output(TS_Y2)                                // Y2 is output 
    TS_Y1 = 0                                    // Y1 low
    TS_Y2 = 1                                    // Y2 high
    pX_TL = ReadX                                // Read X co-ordinate
    TS_Y1 = 1                                    // Reverse Y plates
    TS_Y2 = 0                           
    pX_BR = ReadX                                // Read X co-ordinate
    // Get Y co-ordinate   
    Input(TS_Y1)                                 // Y1 is input 
    Input(TS_Y2)                                 // Y2 is input 
    Output(TS_X1)                                // X1 is output 
    Output(TS_X2)                                // X2 is output 
    TS_X1 = 1                                    // X1 high
    TS_X2 = 0                                    // X2 low
    pY_TL = ReadY                                // Read Y co-ordinate
    TS_X1 = 0                                    // Reverse X plates
    TS_X2 = 1                           
    pY_BR = ReadY                                // Read Y co-ordinate
    Input(TS_X1)                                 // X1 is input - power save
    Input(TS_X2)                                 // X2 is input - power save
End Sub
{
********************************************************************************
* Name    : FindPosition (PRIVATE)                                             *
* Purpose :                                                                    *
********************************************************************************
}
Function FindPosition(pXY As Word, p1 As Word, p2 As Word, pMax_Pos As Word) As Word
Dim XY_Temp As LongWord
    If pXY < p1 Then
        Result = 0
    Else
        XY_Temp = Word(pXY - p1) * pMax_Pos
        Result = XY_Temp / Word(p2 - p1)
        If Result > pMax_Pos Then
            Result = pMax_Pos
        EndIf
    EndIf
End Function     
{
********************************************************************************
* Name    : GetPenPosition (PUBLIC)                                            *
* Purpose : Gets pen position (from the top-left corner), in pixels.           *
********************************************************************************
}     
Public Sub GetPenPosition(ByRef pX As Word, ByRef pY As Word)
Dim X_Read_TL, X_Read_BR, Y_Read_TL, Y_Read_BR, X_TL, X_BR, Y_TL, Y_BR As Word
    GetXY(X_Read_TL, X_Read_BR, Y_Read_TL, Y_Read_BR) 
    // Calculate X co-ordinate
    X_TL = FindPosition(X_Read_TL, Calibration.X_Min_TL, Calibration.X_Max_TL, X_Max_Pos)
    X_BR = X_Max_Pos - FindPosition(X_Read_BR, Calibration.X_Min_BR, Calibration.X_Max_BR, X_Max_Pos)
    pX = Word(X_TL + X_BR) / 2             // Average readings
    // Calculate Y co-ordinate
    Y_TL = FindPosition(Y_Read_TL, Calibration.Y_Min_TL, Calibration.Y_Max_TL, Y_Max_Pos)
    Y_BR = Y_Max_Pos - FindPosition(Y_Read_BR, Calibration.Y_Min_BR, Calibration.Y_Max_BR, Y_Max_Pos)
    pY = Word(Y_TL + Y_BR) / 2             // Average readings
End Sub
{
********************************************************************************
* Name    : IsInRectangle (PUBLIC)                                             *
* Purpose : Determines if position (pX, pY) is in the rectangle                *
*         : (px1, py1) - (px2, py2). Returns a boolean.                        *
********************************************************************************
}     
Public Function IsInRectangle(pX, pY, px1, py1, px2, py2 As Word) As Boolean
    If pX >= px1 And pX <= px2 And pY >= py1 And pY <= py2 Then
        Result = True
    Else
        Result = False
    EndIf
End Function   


// module initialisation...
Calibration.X_Min_TL = X_Min_TL_Init
Calibration.X_Max_TL = X_Max_TL_Init
Calibration.Y_Min_TL = Y_Min_TL_Init
Calibration.Y_Max_TL = Y_Max_TL_Init
Calibration.X_Min_BR = X_Min_BR_Init
Calibration.X_Max_BR = X_Max_BR_Init
Calibration.Y_Min_BR = Y_Min_BR_Init
Calibration.Y_Max_BR = Y_Max_BR_Init
Pen_Down_Threshold = Pen_Down_Threshold_Init

Sample Code 1 - Simple Drawing Application

{
********************************************************************************
*  Name    : Drawing.BAS                                                       *
*  Author  : S Wright                                                          *
*  Notice  : Copyright (c) 2007 S Wright                                       *
*          : All Rights Reserved                                               *
*  Date    : 27/01/2007                                                        *
*  Version : 1.0                                                               *
*  Notes   :                                                                   *
*          :                                                                   *
********************************************************************************
}

Device = 18F4620
Clock = 20

#option GLCD_MODEL = S1D13700
#option GLCD_MODE = 6800         // GLCD interface mode
#option GLCD_TCR = $29

Include "ADC.bas"
Include "GLCD.bas"
Include "Graphics.bas"
Include "Tahoma.bas"
Include "TouchScreen.bas"

Dim X_Pos, Y_Pos As Word
Dim PenDown As Boolean
{
********************************************************************************
* Name    : InitializeADC (PRIVATE)                                            *
* Purpose :                                                                    *
********************************************************************************
}     
Sub InitializeADC()
    ADC.SetConfig(%001011)    // Set A0-A3 as analogue 
    ADC.SetAcqTime(20)
    ADC.SetConvTime(FOSC_64)
End Sub
{
********************************************************************************
* Name    : InitializeGLCD (PRIVATE)                                           *
* Purpose :                                                                    *
********************************************************************************
}     
Sub InitializeGLCD()
    GLCD.SetFont(Tahoma)
    GLCD.Brush.Style = bsSolid
    GLCD.Font.Style = fsNormal
    GLCD.TextAlign = GLCD.taCenter
End Sub
{
********************************************************************************
* Name    : RectangleR (PRIVATE)                                               *
* Purpose :                                                                    *
********************************************************************************
}     
Sub RectangleR(px1, py1, pWidth, pHeight As Word)
   Dim px2, py2 As Word
   px2 = px1 + pWidth - 1
   py2 = py1 + pHeight - 1
   GLCD.Line(px1 + 1, py1, px2 - 1, py1)
   GLCD.Line(px2, py1 + 1, px2, py2 - 1)
   GLCD.Line(px1 + 1, py2, px2 - 1, py2)
   GLCD.Line(px1, py1 + 1, px1, py2 - 1)
End Sub
{
********************************************************************************
* Name    : SetUpScreen (PRIVATE)                                              *
* Purpose :                                                                    *
********************************************************************************
}     
Sub SetUpScreen()
    GLCD.Cls(1)
    GLCD.Rectangle(0, 0, 319, 239)
    RectangleR(5, 5, 24, 24)
    RectangleR(291, 5, 24, 24)
    GLCD.WriteAt(294, 12, "CLS")
End Sub
{
********************************************************************************
* Name    : Calibrate (PRIVATE)                                                *
* Purpose :                                                                    *
********************************************************************************
}     
Sub Calibrate()
Dim XMIN_TL, XMAX_TL, YMIN_TL, YMAX_TL, XMIN_BR, XMAX_BR, YMIN_BR, YMAX_BR As Word
    GLCD.Cls(1)
    GLCD.Rectangle(0, 0, 319, 239)
    GLCD.WriteStr(159, 110, "TOUCH TOP LEFT")
    Repeat     
    Until TouchScreen.PenIsDown
    DelayMS(30)
    TouchScreen.GetXY(XMIN_TL, XMAX_BR, YMIN_TL, YMAX_BR)
    Repeat     
    Until Not TouchScreen.PenIsDown
    GLCD.WriteStr(159, 110, "TOUCH BOTTOM RIGHT")
    Repeat     
    Until TouchScreen.PenIsDown
    DelayMS(30)
    TouchScreen.GetXY(XMAX_TL, XMIN_BR, YMAX_TL, YMIN_BR)
    Repeat     
    Until Not TouchScreen.PenIsDown
    TouchScreen.Calibration.X_Min_TL = XMIN_TL    
    TouchScreen.Calibration.X_Max_TL = XMAX_TL    
    TouchScreen.Calibration.Y_Min_TL = YMIN_TL    
    TouchScreen.Calibration.Y_Max_TL = YMAX_TL    
    TouchScreen.Calibration.X_Min_BR = XMIN_BR    
    TouchScreen.Calibration.X_Max_BR = XMAX_BR    
    TouchScreen.Calibration.Y_Min_BR = YMIN_BR    
    TouchScreen.Calibration.Y_Max_BR = YMAX_BR    
End Sub
{
********************************************************************************
* Main Program                                                                 *
********************************************************************************
}     
InitializeADC()
InitializeGLCD()
Calibrate()
SetUpScreen()
PenDown = False

Repeat   
    If TouchScreen.PenIsDown Then
        DelayMS(5)
        If TouchScreen.PenIsDown Then
            TouchScreen.GetPenPosition(X_Pos, Y_Pos)
            DelayMS(5)
            If TouchScreen.PenIsDown Then
                If Not PenDown Then
                    PenDown = True
                    GLCD.Brush.Color = 1
                    GLCD.Fill(6, 6, 27, 27)
                    GLCD.Brush.Color = 0
                EndIf
                GLCD.SetPixel(X_Pos, Y_Pos)
                GLCD.Circle(X_Pos, Y_Pos, 1)
                If TouchScreen.IsInRectangle(X_Pos, Y_Pos, 290, 5, 314, 28) Then
                    SetUpScreen()
                EndIf
            EndIf
        EndIf
    Else
        If PenDown Then
            PenDown = False
            GLCD.Fill(6, 6, 27, 27)
        EndIf
    EndIf
Until False

End

Sample Code 2 - Touchscreen Keyboard

{
********************************************************************************
*  Name    : Keyboard.BAS                                                      *
*  Author  : S Wright                                                          *
*  Notice  : Copyright (c) 2007 S Wright                                       *
*          : All Rights Reserved                                               *
*  Date    : 27/01/2007                                                        *
*  Version : 1.0                                                               *
*  Notes   :                                                                   *
*          :                                                                   *
********************************************************************************
}

Device = 18F4620
Clock = 20

#option GLCD_MODEL = S1D13700
#option GLCD_MODE = 6800         // GLCD interface mode
#option GLCD_TCR = $29

Include "ADC.bas"
Include "GLCD.bas"
Include "Graphics.bas"
Include "FontLarge.bas"
Include "TouchScreen.bas"
Include "Convert.bas"
Include "String.bas"

Dim TextString As String(40)
Dim GetLetter As Byte

{
********************************************************************************
* Name    : Images                                                             *
* Purpose :                                                                    *
********************************************************************************
}     
// Image with X - Direction Bytes
Public Const ImgDelete(58) As Byte =
      ($01,19,18,0,
      $00,$00,$00,$01,$03,$07,$0F,$1F,$3F,$7F,$FF,$7F,$3F,$1F,$0F,$07,$03,$01,
      $00,$00,$00,$00,$00,$00,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,
      $00,$00,$00,$00,$00,$00,$C0,$E0,$E0,$E0,$E0,$E0,$E0,$E0,$C0,$00,$00,$00)
{
********************************************************************************
* Name    : InitializeADC (PRIVATE)                                            *
* Purpose :                                                                    *
********************************************************************************
}     
Sub InitializeADC()
    ADC.SetConfig(%001011)    // Set A0-A3 as analogue 
    ADC.SetAcqTime(20)
    ADC.SetConvTime(FOSC_64)
End Sub
{
********************************************************************************
* Name    : InitializeGLCD (PRIVATE)                                           *
* Purpose :                                                                    *
********************************************************************************
}     
Sub InitializeGLCD()
    GLCD.SetFont(FontLarge)
    GLCD.Brush.Style = bsSolid
    GLCD.Font.Style = fsNormal
    GLCD.TextAlign = GLCD.taCenter
End Sub
{
********************************************************************************
* Name    : RectangleR (PRIVATE)                                               *
* Purpose :                                                                    *
********************************************************************************
}     
Sub RectangleR(px1, py1, pWidth, pHeight As TXY)
    Dim px2, py2 As TXY
    px2 = px1 + pWidth - 1
    py2 = py1 + pHeight - 1
    Line(px1 + 2, py1, px2 - 2, py1)
    Line(px2, py1 + 2, px2, py2 - 2)
    Line(px1 + 2, py2, px2 - 2, py2)
    Line(px1, py1 + 2, px1, py2 - 2)
    SetPixel(px1 + 1, py1 + 1)
    SetPixel(px2 - 1, py1 + 1)
    SetPixel(px1 + 1, py2 - 1)
    SetPixel(px2 - 1, py2 - 1)
End Sub
{
********************************************************************************
* Name    : Button (PRIVATE)                                                   *
* Purpose :                                                                    *
********************************************************************************
}     
Sub Button(px1 As Word, py1 As Byte, pWidth As Byte)
    Dim px2, py2 As TXY
    px2 = px1 + pWidth - 1
    py2 = py1 + 32 - 1
    RectangleR(px1, py1, pWidth, 32)
    Line(px1 + 4, py2 - 2, px2 - 4, py2 - 2)
    Line(px2 - 2, py1 + 4, px2 - 2, py2 - 4)
End Sub

Sub ButtonPrelim()
    SetFont(FontLarge)
    TextAlign = taCenter
End Sub

Sub Button(px1 As Word, py1 As Byte, pWidth As Byte, pChar As Char)
    ButtonPrelim
    Button(px1, py1, pWidth)
    WriteStr((px1 + (pWidth / 2) - 1), py1 + 6, pChar)
End Sub

Sub Button(px1 As Word, py1 As Byte, pWidth As Byte, pStr As String)
    ButtonPrelim
    Button(px1, py1, pWidth)
    WriteStr((px1 + (pWidth / 2) - 1), py1 + 6, pStr)
End Sub

Sub Button(px1 As Word, py1 As Byte, pWidth As Byte, ByRefConst pImage() As Byte)
    Dim Width As Byte
    Button(px1, py1, pWidth)
    Width = pImage(1)
    SetImage((px1 + (pWidth / 2) - (Width / 2) - 1), py1 + 4, pImage)
End Sub
{
********************************************************************************
* Name    : SetUpScreen (PRIVATE)                                              *
* Purpose :                                                                    *
********************************************************************************
}     
Sub SetUpScreen()
Dim x, y As Byte
Dim Letter As Byte
'   ShowLayer(1, False)
    GLCD.Cls(1)
    RectangleR(0, 0, 320, 57)
    RectangleR(0, 60, 320, 145)
    For y = 0 To 3
        For x = 0 To 6
            Letter = 65 + (x + (7 * y))
            If Letter < 92 Then
                If Letter = 91 Then              // Replace with '-'
                    Letter = 45
                EndIf
                Button(4 + (45 * x), 64 + (35 * y), 42, Letter)
            Else
                Button(274, 169, 42, ImgDelete)  // Replace with Del image
            EndIf                
        Next
    Next
    Button(0, 208, 91, "SHIFT")
    Button(94, 208, 132)
    Button(229, 208, 91, "ENTER")
'   ShowLayer(1, True)
End Sub
{
********************************************************************************
* Name    : Calibrate (PRIVATE)                                                *
* Purpose :                                                                    *
********************************************************************************
}     
Sub Calibrate()
Dim XMIN_TL, XMAX_TL, YMIN_TL, YMAX_TL, XMIN_BR, XMAX_BR, YMIN_BR, YMAX_BR As Word
    GLCD.Cls(1)
    GLCD.Rectangle(0, 0, 319, 239)
    GLCD.WriteStr(159, 110, "TOUCH TOP LEFT")
    Repeat     
    Until TouchScreen.PenIsDown
    DelayMS(30)
    TouchScreen.GetXY(XMIN_TL, XMAX_BR, YMIN_TL, YMAX_BR)
    Repeat     
    Until Not TouchScreen.PenIsDown
    GLCD.WriteStr(159, 110, "TOUCH BOTTOM RIGHT")
    Repeat     
    Until TouchScreen.PenIsDown
    DelayMS(30)
    TouchScreen.GetXY(XMAX_TL, XMIN_BR, YMAX_TL, YMIN_BR)
    Repeat     
    Until Not TouchScreen.PenIsDown
    TouchScreen.Calibration.X_Min_TL = XMIN_TL    
    TouchScreen.Calibration.X_Max_TL = XMAX_TL    
    TouchScreen.Calibration.Y_Min_TL = YMIN_TL    
    TouchScreen.Calibration.Y_Max_TL = YMAX_TL    
    TouchScreen.Calibration.X_Min_BR = XMIN_BR    
    TouchScreen.Calibration.X_Max_BR = XMAX_BR    
    TouchScreen.Calibration.Y_Min_BR = YMIN_BR    
    TouchScreen.Calibration.Y_Max_BR = YMAX_BR    
End Sub
{
********************************************************************************
* Name    : GetKey (PRIVATE)                                                   *
* Purpose : Returns ASCII code for letter, or 1 for Del, 2 for Shift and       *
*         : 3 For Enter                                                        *
********************************************************************************
}     
Function GetKey() As Byte
Dim KeyPressed As Boolean
Dim X_Pos, Y_Pos As Word
    KeyPressed = False
    Repeat
    Until Not TouchScreen.PenIsDown                   // Wait until key not pressed
    DelayMS(50)
    Repeat
        If TouchScreen.PenIsDown Then
            DelayMS(50)                               // Wait to debounce
            If TouchScreen.PenIsDown Then
                TouchScreen.GetPenPosition(X_Pos, Y_Pos)
                If TouchScreen.IsInRectangle(X_Pos, Y_Pos, 2, 62, 317, 202) Then        // Letter key
                    Result = 65 + ((X_Pos - 2) / 45) + (7 * ((Y_Pos - 62) / 35))
                    If Result = 91 Then                                                 // '-' key
                        Result = 45
                    ElseIf Result = 92 Then                                             // Del key
                        Result = 1
                    EndIf
                ElseIf TouchScreen.IsInRectangle(X_Pos, Y_Pos, 0, 208, 90, 239) Then    // Shift key
                    Result = 2
                ElseIf TouchScreen.IsInRectangle(X_Pos, Y_Pos, 94, 208, 225, 239) Then  // Space key
                    Result = " "
                ElseIf TouchScreen.IsInRectangle(X_Pos, Y_Pos, 229, 208, 319, 239) Then // Enter key
                    Result = 3              
                Else
                    Result = Null                                                       // No valid key
                EndIf
                KeyPressed = True
            EndIf
        EndIf   
    Until KeyPressed
End Function
{
********************************************************************************
* Main Program                                                                 *
********************************************************************************
}     
InitializeADC()
InitializeGLCD()
Calibrate()
SetUpScreen()

TextString = Null

Repeat   
    GetLetter = GetKey()
    If GetLetter > 3 Then                                 // Not a control character
        TextString = TextString + Char(GetLetter )
    ElseIf GetLetter = 1 Then                             // Del key pressed
        TextString = Str.Left(TextString, Str.Length(TextString) - 1)
        GLCD.Fill(1, 15, 318, 35)
    EndIf
    GLCD.WriteAt(5, 15, TextString, "_")
Until False

End

N.B. Replace the font include 'FontLarge.bas' and the GLCD.SetFont(FontLarge) to your own font.