News:

Let's find out together what makes a PIC Tick!

Main Menu

TFT Touch Screen from Aliexpress and Proton PIC BASIC

Started by trastikata, Apr 04, 2024, 01:30 AM

Previous topic - Next topic

trastikata

Hi,

got a cheap TFT Touch screen from Aliexpress and had some free time to play with it. I had to write new libraries for the Touch screen calibration using matrix transformation from 3 points and rework some of my old TFT display routines but the cheap screen works much better than I expected.

Still have to optimize and clean the code, but it works very well. I am not good at writing Libraries and code optimization so if somebody wishes to help with creating the library and the code optimization it could be beneficial for everyone.

P.s. To run that screen smoothly at high refresh rates a high speed dsPIC with more RAM is recommended.

Cheers.


John Lawton

Nice.

Still using Proton, not Positron?

9/10

:)

I'm looking for my old Etch-a-Sketch.

John

pjdenyer

Hi,

Could you post the code, I'd like to have a look at it.

Paul

trastikata

This is clean handwriting done on a cheap TFT touch screen with Positron.

The code for the handwriting is a mess and I have to organize it, but I am posting the code for the calibration coefficients and the Touch coordinates transformation to Screen point coordinates. As mentioned I am not good at making libraries and I am used to my style of programming, but if you can optimize and clean the code and make a library, it would be beneficial for others.

P.s. @John Lawton I am still mixing Proton and Positron when I talk.


Device = 33EP128MC504   
Declare Xtal 16

'Display coordinates of the First point --> wDisplayX1 : wDisplayY1
Dim wDisplayX1 As Word
Dim wDisplayY1 As Word
'Coordinates returned from the First touch point --> wTouchX1 : wTouchY1
Dim wTouchX1 As Word
Dim wTouchY1 As Word
'Display coordinates of the Second point --> wDisplayX2 : wDisplayY2
Dim wDisplayX2 As Word
Dim wDisplayY2 As Word
'Coordinates returned from the Second touch point --> wTouchX2 : wTouchY2 
Dim wTouchX2 As Word
Dim wTouchY2 As Word
'Display coordinates of the Third point --> wDisplayX3 : wDisplayY3
Dim wDisplayX3 As Word
Dim wDisplayY3 As Word
'Coordinates returned from the Third touch point --> wTouchX3 : wTouchY3
Dim wTouchX3 As Word
Dim wTouchY3 As Word

'Matrix coefficients to be used for point conversion
Dim sdwK As SDword
Dim fA As Float
Dim fB As Float
Dim fC As Float
Dim fD As Float
Dim fE As Float
Dim fF As Float

'Hold the touch screen X and Y coordinate
Dim wTouchX As Word
Dim wTouchY As Word

Main:
    'Some points based on display coordinates and received touch coordinates
    'Those are examples, you can use any 3 points as long as they are not
    'at the edges and they are relative far from eachother
    'Display coordinates of the First point
    wDisplayX1 = 230
    wDisplayY1 = 40
    'Coordinates returned from the First touch point
    wTouchX1 = 3202
    wTouchY1 = 1094
    'Display coordinates of the Second point
    wDisplayX2 = 290
    wDisplayY2 = 200
    'Coordinates returned from the Second touch point
    wTouchX2 = 845
    wTouchY2 = 480
    'Display coordinates of the Third point
    wDisplayX3 = 60
    wDisplayY3 = 120
    'Coordinates returned from the Third touch point
    wTouchX3 = 2057
    wTouchY3 = 3044

    'Call matrix solver to calculate coefficients
    CalibrationMatrix()

    'Get some touch coordinates to convert into screen coordinates

    'Convert touch coordinates to screen X coordinate and display
    Print "X=", Dec3 TouchToScreenX(wTouchX, wTouchY)
    'Convert touch coordinates to screen Y coordinate and display
    Print "Y=", Dec3 TouchToScreenY(wTouchX, wTouchY)
End

'Calculates calibration matrix coefficients
Proc CalibrationMatrix()
    'Temporary variables
    Dim swTemp1 As SWord
    Dim swTemp2 As SWord
    Dim swTemp3 As SWord
    Dim swTemp4 As SWord
    Dim sdwTemp1 As SDword
    Dim sdwTemp2 As SDword
    Dim sdwTemp3 As SDword
    Dim sdwTemp4 As SDword
    Dim sdwTemp5 As SDword
    Dim sdwTemp6 As SDword
   
    'Claculate sdwK
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wTouchX2 - wTouchX3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwK = sdwTemp1 - sdwTemp2
   
    'Calculate fA
    swTemp1 = wDisplayX1 - wDisplayX3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wDisplayX2 - wDisplayX3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fA = sdwTemp3 / sdwK

    'Calculate fB
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wDisplayX2 - wDisplayX3
    swTemp3 = wDisplayX1 - wDisplayX3
    swTemp4 = wTouchX2 - wTouchX3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fB = sdwTemp3 / sdwK
   
    'Calculate fC
    sdwTemp1 = wTouchX3 * wDisplayX2
    sdwTemp2 = wTouchX2 * wDisplayX3
    sdwTemp3 = wTouchY1 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX1 * wDisplayX3
    sdwTemp2 = wTouchX3 * wDisplayX1
    sdwTemp4 = wTouchY2 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX2 * wDisplayX1
    sdwTemp2 = wTouchX1 * wDisplayX2
    sdwTemp5 = wTouchY3 * (sdwTemp1 - sdwTemp2)
    sdwTemp6 = sdwTemp3 + sdwTemp4 + sdwTemp5
    fC = sdwTemp6 / sdwK
   
    'Calculate fD
    swTemp1 = wDisplayY1 - wDisplayY3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wDisplayY2 - wDisplayY3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fD = sdwTemp3 / sdwK

    'Calculate fE
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wDisplayY2 - wDisplayY3
    swTemp3 = wDisplayY1 - wDisplayY3
    swTemp4 = wTouchX2 - wTouchX3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fE = sdwTemp3 / sdwK
   
    'Calculate fF
    sdwTemp1 = wTouchX3 * wDisplayY2
    sdwTemp2 = wTouchX2 * wDisplayY3
    sdwTemp3 = wTouchY1 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX1 * wDisplayY3
    sdwTemp2 = wTouchX3 * wDisplayY1
    sdwTemp4 = wTouchY2 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX2 * wDisplayY1
    sdwTemp2 = wTouchX1 * wDisplayY2
    sdwTemp5 = wTouchY3 * (sdwTemp1 - sdwTemp2)
    sdwTemp6 = sdwTemp3 + sdwTemp4 + sdwTemp5
    fF = sdwTemp6 / sdwK
EndProc

'Calculates the actual screen coordinates on X-axis by
'using the matrix transformation coefficients
'and touch coordinates returned from the touch screen
Proc TouchToScreenX(wTouchX As Word, wTouchY As Word), Word
    'Temporary variables
    Dim fTemp1 As Float
    Dim fTemp2 As Float
    Dim fTemp3 As Float
   
    fTemp1 = fA * wTouchX
    fTemp2 = fB * wTouchY
    fTemp3 = fTemp1 + fTemp2
    Result = fTemp3 + fC
EndProc

'Calculates the actual screen coordinates on Y-axis by
'using the matrix transformation coefficients
'and touch coordinates returned from the touch screen
Proc TouchToScreenY(wTouchX As Word, wTouchY As Word), Word
    'Temporary variables
    Dim fTemp1 As Float
    Dim fTemp2 As Float
    Dim fTemp3 As Float
   
    fTemp1 = fD * wTouchX
    fTemp2 = fE * wTouchY
    fTemp3 = fTemp1 + fTemp2
    Result = fTemp3 + fF
EndProc

RGV250

Hi,
Is the display a standard controller or do you have a link for the one you use.

Bob

trastikata

Quote from: RGV250 on Apr 04, 2024, 10:14 AMIs the display a standard controller or do you have a link for the one you use.

Hi,

https://www.aliexpress.com/item/1005005266408030.html?spm=a2g0o.cart.0.0.611f38dawdFCmD&mp=1

The model I bought is 240x320 2.8" SPI TFT with ST7789V chip

trastikata

#6
Hi,

this is the entire program for a blackboard with asmall 320*240 Touch display, might be helpful to people.

Cheers.


Device = 33EP128MC504   
 
Config FICD = ICS_PGD1, JTAGEN_OFF
Config FPOR = ALTI2C1_OFF, ALTI2C2_OFF, WDTWIN_WIN25
Config FWDT = FWDTEN_OFF, PLLKEN_ON, WDTPOST_PS16384, WDTPRE_PR128, WINDIS_OFF
Config FOSC = FCKSM_CSECMD, IOL1WAY_OFF, OSCIOFNC_OFF, POSCMD_HS
Config FOSCSEL = FNOSC_PRIPLL, IESO_ON, PWMLOCK_OFF
Config FGS = GCP_OFF, GWRP_OFF

Declare Xtal = 140
Declare Watchdog = Off
Declare Warnings = OFF
Declare Reminders = Off
Declare Stack_Size = 256
Declare Stack_Expand = On
Declare Optimiser_Level = 3
Declare Access_Upper_64K = On

Main:
    SetCrystal()
    SetPins()
    SetInterrupt1()
    SetTimer3()
    TftSetUp()
    TftResetScreen()
   
StartTouchCalibration:
    'Print circles : at coordinates x,y (230,40) : radius size points (5)
    'color filled 1=Yes : Color : Border size = 1 point : no thick border direction
    wDisplayX1 = 230 : wDisplayY1 = 40
    TftCircle(wDisplayX1, wDisplayY1, 5, 1, WHITE, 1, 0)
    wDisplayX2 = 290 : wDisplayY2 = 200
    TftCircle(wDisplayX2, wDisplayY2, 5, 1, RED, 1, 0)
    wDisplayX3 = 60 : wDisplayY3 = 120
    TftCircle(wDisplayX3, wDisplayY3, 5, 1, GREEN, 1, 0)

    'Get touch coordinates for the first point and average 5 values
    TestTouchPoint1()
    'Get touch coordinates for the second point and average 5 values
    TestTouchPoint2()
    'Get touch coordinates for the third point and average 5 values
    TestTouchPoint3()

    'Call calibration matrix using circle center points and corresponding touch coordinates
    CalibrationMatrix()
   
    'Clear screen
    TftResetScreen()
   
    'Create a Screen WRITE button
    CreateWriteButton()
    'Create a Screen RESET button
    CreateResetButton()
    'Create a Screen ERASE button
    CreateEraseButton()
   
    TftSquare(0,207, 100,230, 0, OLIVE, 2, -1)
    pBoardMode = 0
    bBufferStatus = 0
    pBufferReset = 1

BlackBoard:     
    'Hand writing display
    While 1 = 1
        'Continual touch screen read
        TouchScreenReadValues()
        'Verify if pressure on screen is enough
        If wTouchZ > Z_Threshold Then
            'Convert touch screen points to screen points
            TouchToScreenX(wTouchX, wTouchY)
            TouchToScreenY(wTouchX, wTouchY)
            'Timer 3 is used to detect gaps in writing
            TMR3 = 0        'Clear Timer3
            T3CON.15 = 1    'TMR3 ON
               
            If bBufferStatus < 4 Then
                'Initialize smoothing filter
                If bBufferStatus = 0 Then
                    Clear waTempX
                    Clear waTempY
                EndIf
                waTempX[bBufferStatus] = TouchToScreenX_Result
                waTempY[bBufferStatus] = TouchToScreenY_Result
                Inc bBufferStatus
            Else
                'Smoothing filter filled and shift buffer
                For bTemp = 0 To 2
                    waTempX[bTemp] = waTempX[bTemp + 1] 
                    waTempY[bTemp] = waTempY[bTemp + 1] 
                Next
                waTempX[3] = TouchToScreenX_Result
                waTempY[3] = TouchToScreenY_Result
                   
                If pBufferReset = 1 Then
                    wNewX = waTempX[3] + waTempX[2] + waTempX[1] + waTempX[0]
                    wNewX = wNewX >> 2
                    wNewY = waTempY[3] + waTempY[2] + waTempY[1] + waTempY[0]
                    wNewY = wNewY >> 2
                    pBufferReset = 0
                EndIf
                   
                wOldX = wNewX
                wOldY = wNewY
                 
                'Average smoothing filter   
                wNewX = waTempX[3] + waTempX[2] + waTempX[1] + waTempX[0]
                wNewY = waTempY[3] + waTempY[2] + waTempY[1] + waTempY[0]
                   
                wNewX = wNewX >> 2
                wNewY = wNewY >> 2

                'Check for outlier points on X
                swTemp = wNewX - wOldX
                If swTemp > 3 Then
                    If wNewX > wOldX Then
                        wNewX = wOldX + 2
                        If wNewX > 319 Then wNewX = 319
                    Else
                        wNewX = wOldX - 2
                        If wNewX > 65531 Then wNewX = 0
                    EndIf
                EndIf     
               
                'Check for outlier points on y
                swTemp = wNewY - wOldY
                If swTemp > 3 Then
                    If wNewY > wOldY Then
                        wNewY = wOldY + 2
                        If wNewY > 239 Then wNewY = 239
                    Else
                        wNewY = wOldY - 2
                        If wNewY > 65531 Then wNewY = 0
                    EndIf
                EndIf
                   
                If wNewX > 110 And wNewX < 210 And wNewY > 208 And wNewY < 229 Then
                    'If RESET button is pressed
                    TftSquare(110,207, 210,230, 0, OLIVE, 2, -1)
                    DelayMS 200
                    TftResetScreen()
                    pBoardMode = 0
                    CreateWriteButton()
                    CreateResetButton()
                    CreateEraseButton()
                ElseIf wNewX > 0 And wNewX < 100 And wNewY > 200 And wNewY < 229 Then
                    'If WRITE button is pressed
                    CreateEraseButton()
                    CreateWriteButton()
                    TftSquare(0,207, 100,230, 0, OLIVE, 2, -1)
                    pBoardMode = 0
                    DelayMS 200 
                ElseIf wNewX > 220 And wNewX < 320 And wNewY > 200 And wNewY < 229 Then
                    'If ERASE button is pressed
                    CreateWriteButton()
                    CreateEraseButton()
                    TftSquare(220,207, 319,230, 0, OLIVE, 2, -1)
                    pBoardMode = 1
                    DelayMS 200   
                Else
                    'Print touch pixel according to erase/writemode
                    If pBoardMode = 0 Then
                        TftPixel(wNewX, wNewY, GREEN)
                    Else
                        For sbXExpand = -4 To 4 Step 1
                            For sbYExpand = -4 To 4 Step 1
                                TftPixel(wNewX + sbXExpand , wNewY + sbYExpand, BLACK)
                            Next
                        Next
                    EndIf   
                EndIf
            EndIf
        EndIf
    Wend
End



'=========================== Procedures ============================
Proc TestTouchPoint1()
    Dim bTemp As Byte
    pTftTouchInterrupt = 0
   
    TftPrintInteger(36, 210, BLACK, WHITE, 5, 1, 1, 0)
    For bTemp = 0 To 4
        While 1 = 1
            'Wait for touch screen interrupt
            If pTftTouchInterrupt = 1 Then
                TouchScreenReadValues()
                'Check pressure force if over threshold
                If wTouchZ > Z_Threshold Then
                    TftPrintInteger(36, 210, BLACK, WHITE, 4 - bTemp, 1, 1, 0)
                    Break
                Else
                    pTftTouchInterrupt = 0   
                EndIf
            EndIf
        Wend
       
        'Fill buffer with current values
        waTempX[bTemp] = wTouchX
        waTempY[bTemp] = wTouchY
        pTftTouchInterrupt = 0
        DelayMS 250
    Next
    wTouchX1 = waTempX[0] + waTempX[1] + waTempX[2] + waTempX[3] + waTempX[4] 
    wTouchY1 = waTempY[0] + waTempY[1] + waTempY[2] + waTempY[3] + waTempY[4]
    wTouchX1 = wTouchX1 / 5
    wTouchY1 = wTouchY1 / 5
    TftPrintInteger(12, 204, BLACK, WHITE, wTouchX1, 4, 1, 0)
    TftPrintInteger(24, 204, BLACK, WHITE, wTouchY1, 4, 1, 0)
EndProc

Proc TestTouchPoint2()
    Dim bTemp As Byte
    pTftTouchInterrupt = 0
   
    TftPrintInteger(196, 270, BLACK, RED, 5, 1, 1, 0)
    For bTemp = 0 To 4
        While 1 = 1
            'Wait for touch screen interrupt
            If pTftTouchInterrupt = 1 Then
                TouchScreenReadValues()
                'Check pressure force if over threshold
                If wTouchZ > Z_Threshold Then
                    TftPrintInteger(196, 270, BLACK, RED, 4 - bTemp, 1, 1, 0)
                    Break
                Else
                    pTftTouchInterrupt = 0   
                EndIf
            EndIf
        Wend
       
        'Fill buffer with current values
        waTempX[bTemp] = wTouchX
        waTempY[bTemp] = wTouchY
        pTftTouchInterrupt = 0
        DelayMS 250
    Next
    wTouchX2 = waTempX[0] + waTempX[1] + waTempX[2] + waTempX[3] + waTempX[4] 
    wTouchY2 = waTempY[0] + waTempY[1] + waTempY[2] + waTempY[3] + waTempY[4]
    wTouchX2 = wTouchX2 / 5
    wTouchY2 = wTouchY2 / 5
    TftPrintInteger(172, 264, BLACK, RED, wTouchX2, 4, 1, 0)
    TftPrintInteger(184, 264, BLACK, RED, wTouchY2, 4, 1, 0)
EndProc

Proc TestTouchPoint3() 
    Dim bTemp As Byte
    pTftTouchInterrupt = 0
   
    TftPrintInteger(116, 40, BLACK, GREEN, 5, 1, 1, 0)
    For bTemp = 0 To 4
        While 1 = 1
            'Wait for touch screen interrupt
            If pTftTouchInterrupt = 1 Then
                TouchScreenReadValues()
                'Check pressure force if over threshold
                If wTouchZ > Z_Threshold Then
                    TftPrintInteger(116, 40, BLACK, GREEN, 4 - bTemp, 1, 1, 0)
                    Break
                Else
                    pTftTouchInterrupt = 0   
                EndIf
            EndIf
        Wend
       
        'Fill buffer with current values
        waTempX[bTemp] = wTouchX
        waTempY[bTemp] = wTouchY
        pTftTouchInterrupt = 0
        DelayMS 250
    Next
    wTouchX3 = waTempX[0] + waTempX[1] + waTempX[2] + waTempX[3] + waTempX[4] 
    wTouchY3 = waTempY[0] + waTempY[1] + waTempY[2] + waTempY[3] + waTempY[4]
    wTouchX3 = wTouchX3 / 5
    wTouchY3 = wTouchY3 / 5
    TftPrintInteger(92, 34, BLACK, GREEN, wTouchX3, 4, 1, 0)
    TftPrintInteger(104, 34, BLACK, GREEN, wTouchY3, 4, 1, 0)
EndProc


'======================== = Touch Screen ===========================

'Calculates calibration matrix coefficients
Proc CalibrationMatrix()
    'Temporary variables
    Dim swTemp1 As SWord
    Dim swTemp2 As SWord
    Dim swTemp3 As SWord
    Dim swTemp4 As SWord
    Dim sdwTemp1 As SDword
    Dim sdwTemp2 As SDword
    Dim sdwTemp3 As SDword
    Dim sdwTemp4 As SDword
    Dim sdwTemp5 As SDword
    Dim sdwTemp6 As SDword
   
    'Claculate sdwK
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wTouchX2 - wTouchX3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwK = sdwTemp1 - sdwTemp2
   
    'Calculate fA
    swTemp1 = wDisplayX1 - wDisplayX3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wDisplayX2 - wDisplayX3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fA = sdwTemp3 / sdwK

    'Calculate fB
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wDisplayX2 - wDisplayX3
    swTemp3 = wDisplayX1 - wDisplayX3
    swTemp4 = wTouchX2 - wTouchX3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fB = sdwTemp3 / sdwK
   
    'Calculate fC
    sdwTemp1 = wTouchX3 * wDisplayX2
    sdwTemp2 = wTouchX2 * wDisplayX3
    sdwTemp3 = wTouchY1 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX1 * wDisplayX3
    sdwTemp2 = wTouchX3 * wDisplayX1
    sdwTemp4 = wTouchY2 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX2 * wDisplayX1
    sdwTemp2 = wTouchX1 * wDisplayX2
    sdwTemp5 = wTouchY3 * (sdwTemp1 - sdwTemp2)
    sdwTemp6 = sdwTemp3 + sdwTemp4 + sdwTemp5
    fC = sdwTemp6 / sdwK
   
    'Calculate fD
    swTemp1 = wDisplayY1 - wDisplayY3
    swTemp2 = wTouchY2 - wTouchY3
    swTemp3 = wDisplayY2 - wDisplayY3
    swTemp4 = wTouchY1 - wTouchY3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fD = sdwTemp3 / sdwK

    'Calculate fE
    swTemp1 = wTouchX1 - wTouchX3
    swTemp2 = wDisplayY2 - wDisplayY3
    swTemp3 = wDisplayY1 - wDisplayY3
    swTemp4 = wTouchX2 - wTouchX3
    sdwTemp1 = swTemp1 * swTemp2
    sdwTemp2 = swTemp3 * swTemp4
    sdwTemp3 = sdwTemp1 - sdwTemp2
    fE = sdwTemp3 / sdwK
   
    'Calculate fF
    sdwTemp1 = wTouchX3 * wDisplayY2
    sdwTemp2 = wTouchX2 * wDisplayY3
    sdwTemp3 = wTouchY1 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX1 * wDisplayY3
    sdwTemp2 = wTouchX3 * wDisplayY1
    sdwTemp4 = wTouchY2 * (sdwTemp1 - sdwTemp2)
    sdwTemp1 = wTouchX2 * wDisplayY1
    sdwTemp2 = wTouchX1 * wDisplayY2
    sdwTemp5 = wTouchY3 * (sdwTemp1 - sdwTemp2)
    sdwTemp6 = sdwTemp3 + sdwTemp4 + sdwTemp5
    fF = sdwTemp6 / sdwK
EndProc

'Calculates the actual screen coordinates on X-axis by
'using the matrix transformation coefficients
'and touch coordinates returned from the touch screen
Proc TouchToScreenX(wTouchX As Word, wTouchY As Word), Word
    'Temporary variables
    Dim fTemp1 As Float
    Dim fTemp2 As Float
    Dim fTemp3 As Float
   
    fTemp1 = fA * wTouchX
    fTemp2 = fB * wTouchY
    fTemp3 = fTemp1 + fTemp2
    Result = fTemp3 + fC
EndProc

'Calculates the actual screen coordinates on Y-axis by
'using the matrix transformation coefficients
'and touch coordinates returned from the touch screen
Proc TouchToScreenY(wTouchX As Word, wTouchY As Word), Word
    'Temporary variables
    Dim fTemp1 As Float
    Dim fTemp2 As Float
    Dim fTemp3 As Float
   
    fTemp1 = fD * wTouchX
    fTemp2 = fE * wTouchY
    fTemp3 = fTemp1 + fTemp2
    Result = fTemp3 + fF
EndProc

'Read Touch Screen coordinates
Proc TouchScreenReadValues()
    Dim wTemp1 As Word
    Dim wTemp2 As Word
   
    Low SCLK : Low T_CS
        DelayUS 1
        SpiSendMode0Ts(Z1_Command_Byte)
        Low MOSI
        wTemp1.Byte1 = SpiReceiveMode0Ts()
        wTemp1.Byte0 = SpiReceiveMode0Ts()
        SpiSendMode0Ts(Z2_Command_Byte)
        Low MOSI
        wTemp2.Byte1 = SpiReceiveMode0Ts()
        wTemp2.Byte0 = SpiReceiveMode0Ts()
        SpiSendMode0Ts(X_Command_Byte)
        Low MOSI
        wTouchX.Byte1 = SpiReceiveMode0Ts()
        wTouchX.Byte0 = SpiReceiveMode0Ts()
        SpiSendMode0Ts(Y_Command_Byte)
        Low MOSI
        wTouchY.Byte1 = SpiReceiveMode0Ts()
        wTouchY.Byte0 = SpiReceiveMode0Ts()
    High T_CS
   
    wTemp1 = wTemp1 >> 3
    wTemp2 = wTemp2 >> 3
    wTouchX = wTouchX >> 3
    wTouchY = wTouchY >> 3
    wTouchZ = wTemp1 + 4095 - wTemp2
EndProc

'Touch screen software SPI send
Proc SpiSendMode0Ts(bSpiByte As Byte)
    Dim bTemp As Byte
   
    For bTemp = 7 DownTo 0 Step -1
        MOSI = GetBit bSpiByte, bTemp
        DelayCS 10 : High SCLK : DelayCS 10 : Low SCLK : DelayCS 10   
    Next
EndProc

'Touch screen software SPI receive
Proc SpiReceiveMode0Ts(), Byte
    Dim bTemp As Byte

    For bTemp = 7 DownTo 0 Step -1
        High SCLK : DelayCS 5
        LoadBit Result, bTemp, MISO
        DelayCS 5 : Low SCLK : DelayCS 5
    Next
EndProc

'========================== TFT Screen ===========================
'Intial TFT screen setup
Proc TftSetUp()
    'HW TFT Reset
    Low TFT_RESET : DelayMS 150 : High TFT_RESET : DelayMS 150
    'Sleep Out
    TftWriteCommand(0x11)
    DelayMS 150
    'Normal Display Mode On
    TftWriteCommand(0x13)
    'Display OFF
    TftWriteCommand(0x28)
    DelayMS 100
    'Pixel Format Set - RGB Interface Format/16 bits / pixel - MCU Interface Format/16 bits / pixel
    TftTwoByteCommand(0x3A, %01010101)
    'Write Display Brightness - 00h value means the lowest brightness and FFh value means the highest brightness
    TftTwoByteCommand(0x51, 160)
    'Interface Control - EPF = 01 / RM = 1 / RIM = 0
    TftFourByteCommand(0xF6, %00000001, %00010000, %00000000)
    'Memory Access Control -  MY = 1 / MV = 1
    TftTwoByteCommand(0x36, %10100000)
EndProc

'Reset TFT screen to all black
Proc TftResetScreen()
    Dim dwTemp As Dword
   
    TftSetColumnAddress(0, 320)
    TftSetPageAddress(0, 240)

    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(0x2C)
    High TFT_DC
    For dwTemp = 0 To 76799
        SpiSendMode0Tft($00)
        SpiSendMode0Tft($00)
    Next
    High TFT_CS

    'Display ON
    TftWriteCommand(0x29)
EndProc

'Set screen page address
Proc TftSetPageAddress(StartPage As Word, StopPage As Word)
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(0x2B)
    High TFT_DC
    SpiSendMode0Tft(StartPage.Byte1)
    SpiSendMode0Tft(StartPage.Byte0)
    SpiSendMode0Tft(StopPage.Byte1)
    SpiSendMode0Tft(StopPage.Byte0)
    High TFT_CS
EndProc

'Set screen column address
Proc TftSetColumnAddress(StartColumn As Word, StopColumn As Word)
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(0x2A)
    High TFT_DC
    SpiSendMode0Tft(StartColumn.Byte1)
    SpiSendMode0Tft(StartColumn.Byte0)
    SpiSendMode0Tft(StopColumn.Byte1)
    SpiSendMode0Tft(StopColumn.Byte0)
    High TFT_CS
EndProc

'Write 1-byte command to the TFT
Proc TftWriteCommand(Command As Byte)
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(Command)
    High TFT_CS
EndProc

'Write 2-byte command to the TFT
Proc TftTwoByteCommand(Command As Byte, Parameter As Byte)
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(Command)
    High TFT_DC
    SpiSendMode0Tft(Parameter)
    High TFT_CS
EndProc

'Write 4-byte command to the TFT
Proc TftFourByteCommand(Command As Byte, Parameter1 As Byte, Parameter2 As Byte, Parameter3 As Byte)
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(Command)
    High TFT_DC
    SpiSendMode0Tft(Parameter1)
    SpiSendMode0Tft(Parameter2)
    SpiSendMode0Tft(Parameter3)
    High TFT_CS
EndProc

'Start TFF DRAM change
Proc TftInitiateDataRam()
    Low SCLK : Low TFT_DC
    Low TFT_CS
    SpiSendMode0Tft(0x2C)
    High TFT_DC
EndProc

'Stop TFF DRAM change
Proc TftStopDataRam()
    High TFT_CS
EndProc

'TFT screen software SPI send
Proc SpiSendMode0Tft(bSpiByte As Byte)
    Dim bTemp As Byte
   
    For bTemp = 7 DownTo 0 Step -1
        MOSI = GetBit bSpiByte, bTemp
        High SCLK : Low SCLK   
    Next
EndProc

'Print TFT pixel
Proc TftPixel(X_Pixel As Word, Y_Pixel As Word, Color As Word)
    TftSetColumnAddress(X_Pixel, X_Pixel)
    TftSetPageAddress(Y_Pixel, Y_Pixel)
    TftInitiateDataRam()
    SpiSendMode0Tft(Color.Byte1)
    SpiSendMode0Tft(Color.Byte0)
    TftStopDataRam()
EndProc

'Print circle
Proc TftCircle(X_Cenetr As SWord, Y_Center As SWord, Radius As Byte, bFill As Bit, Color As Word, Width As Byte, Direction As SByte)
    Dim X As SWord
    Dim Y As SWord
    Dim swTemp As SWord
    Dim fTemp As Float
    Dim i As Byte


    For swTemp = 0 To 90

        fTemp = Cos(swTemp * 0.01744)
        fTemp = fTemp * Radius
        X = fRound(fTemp)
        fTemp = Sin(swTemp * 0.01744)
        fTemp = fTemp * Radius
        Y = fRound(fTemp)

        If Width = 0 Then
            If bFill = 0 Then
                TftPixel(X_Cenetr + X, Y_Center + Y, Color)
                TftPixel(X_Cenetr + X, Y_Center - Y, Color)
                TftPixel(X_Cenetr - X, Y_Center + Y, Color)
                TftPixel(X_Cenetr - X, Y_Center - Y, Color)
            Else
                TftLine(X_Cenetr - X, Y_Center + Y, X_Cenetr + X, Y_Center + Y, Color, 0, 0)
                TftLine(X_Cenetr - X, Y_Center - Y, X_Cenetr + X, Y_Center - Y, Color, 0, 0)
            EndIf
        Else
            If bFill = 0 Then
                For i = 0 To Width
                    Select Direction
                        Case -1
                            TftPixel(X_Cenetr + X - i, Y_Center + Y, Color)
                            TftPixel(X_Cenetr + X - i, Y_Center - Y, Color)
                            TftPixel(X_Cenetr - X + i, Y_Center + Y, Color)
                            TftPixel(X_Cenetr - X + i, Y_Center - Y, Color)
                            TftPixel(X_Cenetr + X, Y_Center + Y - i, Color)
                            TftPixel(X_Cenetr + X, Y_Center - Y + i, Color)
                            TftPixel(X_Cenetr - X, Y_Center + Y - i, Color)
                            TftPixel(X_Cenetr - X, Y_Center - Y + i, Color)
                        Case 1
                            TftPixel(X_Cenetr + X + i, Y_Center + Y, Color)
                            TftPixel(X_Cenetr + X + i, Y_Center - Y, Color)
                            TftPixel(X_Cenetr - X - i, Y_Center + Y, Color)
                            TftPixel(X_Cenetr - X - i, Y_Center - Y, Color)
                            TftPixel(X_Cenetr + X, Y_Center + Y + i, Color)
                            TftPixel(X_Cenetr + X, Y_Center - Y - i, Color)
                            TftPixel(X_Cenetr - X, Y_Center + Y + i, Color)
                            TftPixel(X_Cenetr - X, Y_Center - Y - i, Color)
                        Case Else
                            TftPixel(X_Cenetr + X, Y_Center + Y, Color)
                            TftPixel(X_Cenetr + X, Y_Center - Y, Color)
                            TftPixel(X_Cenetr - X, Y_Center + Y, Color)
                            TftPixel(X_Cenetr - X, Y_Center - Y, Color)
                    EndSelect
                Next
            Else
                For i = 0 To Width
                    Select Direction
                        Case 1
                            TftLine(X_Cenetr - X - i, Y_Center + Y, X_Cenetr + X + i, Y_Center + Y, Color, 0, 0)
                            TftLine(X_Cenetr - X - i, Y_Center - Y, X_Cenetr + X + i, Y_Center - Y, Color, 0, 0)
                            TftLine(X_Cenetr - X, Y_Center + Y + i, X_Cenetr + X, Y_Center + Y + i, Color, 0, 0)
                            TftLine(X_Cenetr - X, Y_Center - Y - i, X_Cenetr + X, Y_Center - Y - i, Color, 0, 0)
                        Case Else
                            TftLine(X_Cenetr - X, Y_Center + Y, X_Cenetr + X, Y_Center + Y, Color, 0, 0)
                            TftLine(X_Cenetr - X, Y_Center - Y, X_Cenetr + X, Y_Center - Y, Color, 0, 0)
                    EndSelect
                Next
            EndIf
        EndIf
    Next
EndProc

'TFT Square
Proc TftSquare(X_Start As SWord, Y_Start As SWord, X_Stop As SWord, Y_Stop As SWord, SqFill As Bit, Color As Word, Width As Byte, Direction As SByte)
    Dim sdTemp As SDword
    Dim X As SWord
    Dim Y As SWord
    Dim i As Byte

    If X_Start > X_Stop Then Swap X_Start, X_Stop
    If Y_Start > Y_Stop Then Swap Y_Start, Y_Stop

    If Width = 0 Then
        TftSetColumnAddress(X_Start, X_Stop)
        TftSetPageAddress(Y_Start, Y_Stop)

        If SqFill = 1 Then
            X = X_Stop - X_Start
            Y = (Y_Stop - Y_Start) + 2
            TftInitiateDataRam()
            For sdTemp = 0 To (X * Y)
                SpiSendMode0Tft(Color.Byte1)
                SpiSendMode0Tft(Color.Byte0)
            Next
            TftStopDataRam()
        Else
            TftLine(X_Start, Y_Start, X_Stop, Y_Start, Color, 0, 0)
            TftLine(X_Stop, Y_Start, X_Stop, Y_Stop, Color, 0, 0)
            TftLine(X_Start, Y_Start, X_Start, Y_Stop, Color, 0, 0)
            TftLine(X_Start, Y_Stop, X_Stop, Y_Stop, Color, 0, 0)
        EndIf
    Else
        Select Direction
            Case -1
                TftSetColumnAddress(X_Start + Width, X_Stop - Width)
                TftSetPageAddress(Y_Start + Width, Y_Stop - Width)

                If SqFill = 1 Then
                    X = X_Stop - X_Start - 2 * Width
                    Y = (Y_Stop - Y_Start) + 2 - 2 * Width
                    TftInitiateDataRam()
                    For sdTemp = 0 To (X * Y)
                        SpiSendMode0Tft(Color.Byte1)
                        SpiSendMode0Tft(Color.Byte0)
                    Next
                    TftStopDataRam()
                Else
                    For i = 0 To Width
                        TftLine(X_Start + i, Y_Start + i, X_Stop - i, Y_Start + i, Color, 0, 0)
                        TftLine(X_Stop - i, Y_Start + i, X_Stop - i, Y_Stop - i, Color, 0, 0)
                        TftLine(X_Start + i, Y_Start + i, X_Start + i, Y_Stop - i, Color, 0, 0)
                        TftLine(X_Start + i, Y_Stop - i, X_Stop - i, Y_Stop - i, Color, 0, 0)
                    Next
                EndIf
            Case 1
                TftSetColumnAddress(X_Start - Width, X_Stop + Width)
                TftSetPageAddress(Y_Start - Width, Y_Stop + Width)

                If SqFill = 1 Then
                    X = X_Stop - X_Start + 2 * Width
                    Y = (Y_Stop - Y_Start) + 2 + 2 * Width
                    TftInitiateDataRam()
                    For sdTemp = 0 To (X * Y)
                        SpiSendMode0Tft(Color.Byte1)
                        SpiSendMode0Tft(Color.Byte0)
                    Next
                    TftStopDataRam()
                Else
                    For i = 0 To Width
                        TftLine(X_Start - i, Y_Start - i, X_Stop + i, Y_Start - i, Color, 0, 0)
                        TftLine(X_Stop + i, Y_Start - i, X_Stop + i, Y_Stop + i, Color, 0, 0)
                        TftLine(X_Start - i, Y_Start - i, X_Start - i, Y_Stop + i, Color, 0, 0)
                        TftLine(X_Start - i, Y_Stop + i, X_Stop + i, Y_Stop + i, Color, 0, 0)
                    Next
                EndIf
            Case Else
                TftSetColumnAddress(X_Start, X_Stop)
                TftSetPageAddress(Y_Start, Y_Stop)

                If SqFill = 1 Then
                    X = X_Stop - X_Start
                    Y = (Y_Stop - Y_Start) + 2
                    TftInitiateDataRam()
                    For sdTemp = 0 To (X * Y)
                        SpiSendMode0Tft(Color.Byte1)
                        SpiSendMode0Tft(Color.Byte0)
                    Next
                    TftStopDataRam()
                Else
                    TftLine(X_Start, Y_Start, X_Stop, Y_Start, Color, 0, 0)
                    TftLine(X_Stop, Y_Start, X_Stop, Y_Stop, Color, 0, 0)
                    TftLine(X_Start, Y_Start, X_Start, Y_Stop, Color, 0, 0)
                    TftLine(X_Start, Y_Stop, X_Stop, Y_Stop, Color, 0, 0)
                EndIf
        EndSelect
    EndIf
EndProc

'Print TFT line
Proc TftLine(X_Start As SWord, Y_Start As SWord, X_Stop As SWord, Y_Stop As SWord, Color As Word, Width As Byte, Direction As SByte)
    Dim swTemp As SWord
    Dim X As SWord
    Dim Y As SWord
    Dim m As Float
    Dim c As Float
    Dim i As Byte
    Dim fTemp As Float

    If Y_Start = Y_Stop Then                    'Horizontal Line
        If X_Start > X_Stop Then Swap X_Start, X_Stop

        For i = 0 To Width
            Select Direction
                Case 1
                    TftSetColumnAddress(X_Start, X_Stop)
                    TftSetPageAddress(Y_Start - i, Y_Stop - i)
                Case -1
                    TftSetColumnAddress(X_Start, X_Stop)
                    TftSetPageAddress(Y_Start + i, Y_Stop + i)
                Case Else
                    TftSetColumnAddress(X_Start, X_Stop)
                    TftSetPageAddress(Y_Start, Y_Stop)
            EndSelect

            X = X_Stop - X_Start
            TftInitiateDataRam()
            For swTemp = 0 To X + 2
                SpiSendMode0Tft(Color.Byte1)
                SpiSendMode0Tft(Color.Byte0)
            Next
            TftStopDataRam()
        Next
    ElseIf X_Start = X_Stop Then                'Vertical Line
        If Y_Start > Y_Stop Then Swap Y_Start, Y_Stop

        For i = 0 To Width
            Select Direction
                Case 1
                    TftSetColumnAddress(X_Start + i, X_Stop + i)
                    TftSetPageAddress(Y_Start, Y_Stop)
                Case -1
                    TftSetColumnAddress(X_Start - i, X_Stop - i)
                    TftSetPageAddress(Y_Start, Y_Stop)
                Case Else
                    TftSetColumnAddress(X_Start, X_Stop)
                    TftSetPageAddress(Y_Start, Y_Stop)
            EndSelect

            Y = Y_Stop - Y_Start
            TftInitiateDataRam()
            For swTemp = 0 To Y + 2
                SpiSendMode0Tft(Color.Byte1)
                SpiSendMode0Tft(Color.Byte0)
            Next
            TftStopDataRam()
        Next
    Else                                        'Diagonal Line
        If Abs(X_Stop - X_Start) > Abs(Y_Stop - Y_Start) Then
            m = (Y_Stop - Y_Start) / (X_Stop - X_Start)
            c = Y_Start - m * X_Start

            If X_Start > X_Stop Then Swap X_Start, X_Stop
            X = X_Start

            Select Direction
                Case 1
                    For swTemp = X_Start To X_Stop
                        fTemp = (m * swTemp) + c
                        Y = fRound(fTemp)
                        X = swTemp
                        For i = 0 To Width
                            TftPixel(X, Y - i, Color)
                        Next
                    Next
                Case -1
                    For swTemp = X_Start To X_Stop
                        fTemp = (m * swTemp) + c
                        Y = fRound(fTemp)
                        X = swTemp
                        For i = 0 To Width
                            TftPixel(X, Y + i, Color)
                        Next
                    Next
                Case 0
                    For swTemp = X_Start To X_Stop
                        fTemp = (m * swTemp) + c
                        Y = fRound(fTemp)
                        X = swTemp
                        TftPixel(X, Y, Color)
                    Next
            EndSelect
        Else
            m = (X_Stop - X_Start) / (Y_Stop - Y_Start)
            c = X_Start - m * Y_Start

            If Y_Start > Y_Stop Then Swap Y_Start, Y_Stop
            Y = Y_Start

            Select Direction
                Case 1
                    For swTemp = Y_Start To Y_Stop
                        fTemp = (m * swTemp) + c
                        X = fRound(fTemp)
                        Y = swTemp
                        For i = 0 To Width
                            TftPixel(X + i, Y, Color)
                        Next
                    Next
                Case -1
                    For swTemp = Y_Start To Y_Stop
                        fTemp = (m * swTemp) + c
                        X = fRound(fTemp)
                        Y = swTemp
                        For i = 0 To Width
                            TftPixel(X - i, Y, Color)
                        Next
                    Next
                Case 0
                    For swTemp = Y_Start To Y_Stop
                        fTemp = (m * swTemp) + c
                        X = fRound(fTemp)
                        Y = swTemp
                        TftPixel(X, Y, Color)
                    Next
            EndSelect
        EndIf
    EndIf
EndProc

'TFT print integer
Proc TftPrintInteger(bRow As Word, bColumn As Word, BackColor As Word, ForeColor As Word, sdInteger As SDword, bDigits As Byte, bFontSize As Byte, pPosition As Bit)
    Dim sString As String * 12

    Select bDigits
        Case 1
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec1 sdInteger), bFontSize, pPosition)
        Case 2
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec2 sdInteger), bFontSize, pPosition)
        Case 3
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec3 sdInteger), bFontSize, pPosition)
        Case 4
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec4 sdInteger), bFontSize, pPosition)
        Case 5
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec5 sdInteger), bFontSize, pPosition)
        Case 6
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec6 sdInteger), bFontSize, pPosition)
        Case 7
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec7 sdInteger), bFontSize, pPosition)
        Case 8
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec8 sdInteger), bFontSize, pPosition)
        Case 9
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec9 sdInteger), bFontSize, pPosition)
        Case 10
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec10 sdInteger), bFontSize, pPosition)
        Case Else
            TftPrintString(bRow, bColumn, BackColor, ForeColor, Str$(SDec sdInteger), bFontSize, pPosition)
    EndSelect
EndProc

'Tft print string
Proc TftPrintString(bRow As Word, bColumn As Word, BackColor As Word, ForeColor As Word, sString As String * 32, bFontSize As Byte, pPosition As Bit)
    Dim bA As Byte

    If pPosition = 1 Then
        For bA = 0 To 31
            If sString[bA] <> 0 Then
                TftPrintChar(bRow, bColumn + ba, BackColor, ForeColor, sString[bA], bFontSize, pPosition)
            Else
                Break
            EndIf
        Next
    Else
        For bA = 0 To 31
            If sString[bA] <> 0 Then
                TftPrintChar(bRow, bColumn + ba * 10 * bFontSize, BackColor, ForeColor, sString[bA], bFontSize, pPosition)
            Else
                Break
            EndIf
        Next
    EndIf
EndProc

'TFT print character
Proc TftPrintChar(bRow As Word, bColumn As Word, BackColor As Word, ForeColor As Word, bChar As Byte, bFontSize As Byte, pPosition As Bit)
    Dim bA As Byte
    Dim bB As Byte
    Dim bE As Byte
    Dim bD As Byte
    Dim bF As Byte
    Dim wTemp As Word
    Dim bBit As Byte

    TftLookUpChar(bChar)

    If pPosition = 1 Then
        TftSetColumnAddress(bColumn * 10 * bFontSize, 10 * bFontSize - 1 + bColumn * 10 * bFontSize)
        TftSetPageAddress(bRow * 10 * bFontSize, 10 * bFontSize - 1 + bRow * 10 * bFontSize)
    Else
        TftSetColumnAddress(bColumn, 10 * bFontSize - 1 + bColumn)
        TftSetPageAddress(bRow, 10 * bFontSize - 1 + bRow)
    EndIf

    bF = 0

    TftInitiateDataRam()
    For bA = 0 To (10 * bFontSize - 1) Step bFontSize
        wTemp = waPrintArray[bF]
        Inc bF
        For bD = 1 To bFontSize
            For bB = 0 To 9
                bBit = GetBit wTemp, bB
                For bE = 1 To bFontSize
                    If bBit = 0 Then
                        SpiSendMode0Tft(BackColor.Byte1)
                        SpiSendMode0Tft(BackColor.Byte0)
                    Else
                        SpiSendMode0Tft(ForeColor.Byte1)
                        SpiSendMode0Tft(ForeColor.Byte0)
                    EndIf
                Next
            Next
        Next
    Next
    TftStopDataRam()
EndProc

'8x8 font
Proc TftLookUpChar(bChar As Byte)
    Select bChar
        Case "A"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $01CE, $01FE, $01FE, $01CE, $01CE, $0000
        Case "B"
            waPrintArray = $0000, $00FE, $01FE, $01CE, $00FE, $00FE, $01CE, $01FE, $00FE, $0000
        Case "C"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $000E, $000E, $01CE, $01FE, $00FC, $0000
        Case "D"
            waPrintArray = $0000, $00FE, $01FE, $01CE, $01CE, $01CE, $01CE, $01FE, $00FE, $0000
        Case "E"
            waPrintArray = $0000, $01FE, $01FE, $000E, $007E, $007E, $000E, $01FE, $01FE, $0000
        Case "F"
            waPrintArray = $0000, $01FE, $01FE, $000E, $007E, $007E, $000E, $000E, $000E, $0000
        Case "G"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $000E, $01EE, $01CE, $01FE, $00FC, $0000
        Case "H"
            waPrintArray = $0000, $01CE, $01CE, $01CE, $01FE, $01FE, $01CE, $01CE, $01CE, $0000
        Case "I"
            waPrintArray = $0000, $0038, $0038, $0038, $0038, $0038, $0038, $0038, $0038, $0000
        Case "J"
            waPrintArray = $0000, $0070, $0070, $0070, $0070, $0070, $0070, $007E, $003E, $0000
        Case "K"
            waPrintArray = $0000, $018E, $01CE, $00EE, $007E, $007E, $00EE, $01CE, $018E, $0000
        Case "L"
            waPrintArray = $0000, $000E, $000E, $000E, $000E, $000E, $000E, $01FE, $01FE, $0000
        Case "M"
            waPrintArray = $0000, $038E, $03DE, $03FE, $03FE, $038E, $038E, $038E, $038E, $0000
        Case "N"
            waPrintArray = $0000, $01CE, $01DE, $01DE, $01FE, $01FE, $01FE, $01EE, $01CE, $0000
        Case "O"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $01CE, $01CE, $01CE, $01FE, $00FC, $0000
        Case "P"
            waPrintArray = $0000, $00FE, $01FE, $01CE, $01FE, $00FE, $000E, $000E, $000E, $0000
        Case "Q"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $01CE, $018E, $016E, $00DE, $01BC, $0000
        Case "R"
            waPrintArray = $0000, $00FE, $01FE, $01CE, $01FE, $00FE, $01CE, $01CE, $01CE, $0000
        Case "S"
            waPrintArray = $0000, $00FC, $01FE, $000E, $00FE, $01FC, $01C0, $01FE, $00FC, $0000
        Case "T"
            waPrintArray = $0000, $00FE, $00FE, $0038, $0038, $0038, $0038, $0038, $0038, $0000
        Case "U"
            waPrintArray = $0000, $01CE, $01CE, $01CE, $01CE, $01CE, $01CE, $01FE, $00FC, $0000
        Case "V"
            waPrintArray = $0000, $01CE, $01CE, $01CE, $01CE, $01CE, $01CE, $00FC, $0078, $0000
        Case "W"
            waPrintArray = $0000, $038E, $038E, $03AE, $03AE, $03AE, $03FE, $01FC, $00A8, $0000
        Case "X"
            waPrintArray = $0000, $01CE, $01CE, $00FC, $0078, $0078, $00FC, $01CE, $01CE, $0000
        Case "Y"
            waPrintArray = $0000, $01CE, $01CE, $01CE, $00FC, $0078, $0030, $0030, $0030, $0000
        Case "Z"
            waPrintArray = $0000, $01FE, $01FE, $01E0, $00F0, $003C, $001E, $01FE, $01FE, $0000


        Case "0"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $01CE, $01CE, $01CE, $01FE, $00FC, $0000
        Case "1"
            waPrintArray = $0000, $0038, $003C, $003E, $0038, $0038, $0038, $0038, $0038, $0000
        Case "2"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $00E0, $0038, $000E, $01FE, $01FE, $0000
        Case "3"
            waPrintArray = $0000, $00FE, $01FE, $01C0, $00FE, $00FE, $01C0, $01FE, $00FE, $0000
        Case "4"
            waPrintArray = $0000, $00EE, $00EE, $00EE, $01FE, $01FE, $00E0, $00E0, $00E0, $0000
        Case "5"
            waPrintArray = $0000, $01FE, $01FE, $000E, $00FE, $01FE, $01C0, $01FE, $00FC, $0000
        Case "6"
            waPrintArray = $0000, $00FC, $01FE, $000E, $00FE, $01FE, $01CE, $01FE, $00FC, $0000
        Case "7"
            waPrintArray = $0000, $01FE, $01FE, $01C0, $00E0, $0070, $0038, $0038, $0038, $0000
        Case "8"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $00FC, $00FC, $01CE, $01FE, $00FC, $0000
        Case "9"
            waPrintArray = $0000, $00FC, $01FE, $01CE, $01FE, $01FC, $01C0, $01FE, $00FC, $0000

        Case " "
            waPrintArray = $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
        Case 0
            waPrintArray = $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
        Case ""
            waPrintArray = $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000
        Case "-"
            waPrintArray = $0000, $0000, $0000, $0000, $00FC, $00FC, $0000, $0000, $0000, $0000
        Case "%"
            waPrintArray = $0000, $00CE, $006A, $002E, $0010, $00E8, $00AC, $00E6, $0000, $0000
        Case "="
            waPrintArray = $0000, $0000, $00FC, $00FC, $0000, $00FC, $00FC, $0000, $0000, $0000
        Case "+"
            waPrintArray = $0000, $0000, $0030, $0030, $00FC, $00FC, $0030, $0030, $0000, $0000
        Case "."
            waPrintArray = $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0018, $0018, $0000
        Case ","
            waPrintArray = $0000, $0000, $0000, $0000, $0000, $0000, $0018, $0018, $0010, $0008
        Case ":"
            waPrintArray = $0000, $0000, $0018, $0018, $0000, $0000, $0000, $0018, $0018, $0000
        Case "/"
            waPrintArray = $0000, $0030, $0030, $0018, $0018, $000C, $000C, $0006, $0006, $0000
        Case "*"
            waPrintArray = $0000, $00A8, $0070, $00F8, $0070, $00A8, $0000, $0000, $0000, $0000
        Case "^"
            waPrintArray = $0000, $0038, $006C, $00C6, $0082, $0000, $0000, $0000, $0000, $0000
        Case "#"
            waPrintArray = $0000, $006C, $00FE, $00FE, $006C, $00FE, $00FE, $006C, $0000, $0000
        Case "("
            waPrintArray = $0000, $01C0, $0060, $0030, $0018, $0018, $0030, $0060, $01C0, $0000
        Case ")"
            waPrintArray = $0000, $000E, $0018, $0030, $0060, $0060, $0030, $0018, $000E, $0000

        Case Else

    EndSelect
EndProc

'Create a Screen RESET button
Proc CreateResetButton()
    TftSquare(110,207, 210,230, 0, OLIVE, 0, 0)
    TftSquare(111,208, 209,229, 0, MAROON, 1, -1)
    TftSquare(113,210, 207,227, 1, BROWN, 0, 0)
    TftPrintString(213, 136, BROWN, ORANGE, "RESET", 1, 0)
EndProc

'Create a Screen WRITE button
Proc CreateWriteButton()
    TftSquare(0,207, 100,230, 0, OLIVE, 0, 0)
    TftSquare(1,208, 99,229, 0, MAROON, 1, -1)
    TftSquare(3,210, 97,227, 1, BROWN, 0, 0)
    TftPrintString(213, 26, BROWN, ORANGE, "WRITE", 1, 0)
EndProc

'Create a Screen ERASE button
Proc CreateEraseButton()
    TftSquare(220,207, 319,230, 0, OLIVE, 0, 0)
    TftSquare(221,208, 318,229, 0, MAROON, 1, -1)
    TftSquare(223,210, 316,227, 1, BROWN, 0, 0)
    TftPrintString(213, 246, BROWN, ORANGE, "ERASE", 1, 0)   
EndProc

'========================== System Procs ===========================
Proc SetTimer3()
    INTCON2.15 = 1              'GIE = 1
    TMR3 = 0                    'Clear Timer3
    PR3 = 10937                 'Period = 10 ms
    T3CON = 0x0020              'PS:
    IFS0.8 = 0                  'TMR3IF clear
    IPC2.2 = 0                  'IP = 1
    IPC2.1 = 0
    IPC2.0 = 1
    IEC0.8 = 1                  'T3IE = 1
EndProc

Proc SetInterrupt1()
    INTCON2.1 = 1               'Interrupt on negative edge
    IFS1.4 = 0                  'INT1IF clear
    IPC5.2 = 0                  'IP = 1
    IPC5.1 = 0
    IPC5.0 = 1
    IEC1.4 = 1                  'INT1IE = 1
EndProc

Proc SetCrystal()
    'Crystal = 20 MHz --> PLLDIV = 40 for 140MHz
    CLKDIV = %0000000000000001  'PLLPRE = 1 ; PLLPOST = 0
    PLLFBD.Byte0 = 40 '--> 140MHz Fp
    'Wait for oscillator PLL lock
    While OSCCON.5 = 0 : Wend
    DelayMS 50
EndProc

Proc SetPins()
    'Set pins
    Clear : High T_CS : High TFT_CS : Low MOSI : Low SCLK : High TFT_SW
    DelayMS 50
    Low PORTC.7 : High PORTB.12 : High PORTB.0 : Low PORTB.8
    'INT1 - T_IRQ - to RPI24
    PPS_Unlock() : RPINR0 = %0001100000000000
EndProc

'========================== Interrupts ===========================
Isr INT1Interrupt
    IEC1.4 = 0                  'INT1IE = 0
    IFS1.4 = 0                  'INT1IF clear
    IEC1.4 = 1                  'INT1IE = 1
    pTftTouchInterrupt = 1
EndIsr

Isr T3Interrupt
    T3CON.15 = 0        'TMR3 off
    TMR3 = 0            'Clear Timer3
    IFS0.8 = 0          'TMR3IF clear
    bBufferStatus = 0   'Set point buffer counter to 0
    pBufferReset = 1    'Request Reset point buffer
EndIsr




'TFT pins
Symbol TFT_CS = PORTC.9
Output TFT_CS
Symbol TFT_DC = PORTC.1
Output TFT_DC
Symbol TFT_RESET = PORTC.2
Output TFT_RESET
Symbol TFT_SW = PORTB.5
Output TFT_SW
'Touch pins
Symbol T_IRQ = PORTA.8
Input T_IRQ
Symbol T_CS = PORTC.8
Output T_CS
'SPI pins
Symbol MISO = PORTC.3
Input MISO
Symbol MOSI = PORTC.4
Output MOSI
Symbol SCLK = PORTC.5
Output SCLK

'TFT screen color schemes
Symbol BLACK = 0x0000
Symbol NAVY = 0x000F
Symbol DARKGREEN = 0x03E0
Symbol DARKCYAN = 0x03EF
Symbol MAROON = 0x7800
Symbol PURPLE = 0x780F
Symbol OLIVE = 0x7BE0
Symbol LIGHTGREY = 0xC618
Symbol DARKGREY = 0x7BEF
Symbol BLUE = 0x001F
Symbol GREEN = 0x07E0
Symbol CYAN = 0x07FF
Symbol RED = 0xF800
Symbol MAGENTA = 0xF81F
Symbol YELLOW = 0xFFE0
Symbol WHITE = 0xFFFF
Symbol ORANGE = 0xFD20
Symbol GREENYELLOW = 0xAFE5
Symbol PINK = 0xF81F
Symbol VIOLET = 0xEC1D
Symbol BROWN = 0xA145

'TFT Screen Variables And Aliases
Dim waPrintArray[15] As Word

'Touch Screen Variables and Aliases
Symbol X_Command_Byte = 0xD0    'get X values
Symbol Y_Command_Byte = 0x90    'get Y values
Symbol Z1_Command_Byte = 0xB1   'get Z1 value
Symbol Z2_Command_Byte = 0xC1   'get Z2 value
Symbol Z_Threshold = 700
Dim swTemp As SWord

'Hold the touch screen X, Y and Z coordinate
Dim wTouchX As Word
Dim wTouchY As Word
Dim wTouchZ As Word

'Other touch screen variables
Dim bBufferStatus As Byte
Dim pBufferReset As Bit
Dim pTftTouchInterrupt As Bit
Dim waTempX[5] As Word
Dim waTempY[5] As Word

'Display coordinates of the First point --> wDisplayX1 : wDisplayY1
Dim wDisplayX1 As Word
Dim wDisplayY1 As Word
'Coordinates returned from the First touch point --> wTouchX1 : wTouchY1
Dim wTouchX1 As Word
Dim wTouchY1 As Word
'Display coordinates of the Second point --> wDisplayX2 : wDisplayY2
Dim wDisplayX2 As Word
Dim wDisplayY2 As Word
'Coordinates returned from the Second touch point --> wTouchX2 : wTouchY2 
Dim wTouchX2 As Word
Dim wTouchY2 As Word
'Display coordinates of the Third point --> wDisplayX3 : wDisplayY3
Dim wDisplayX3 As Word
Dim wDisplayY3 As Word
'Coordinates returned from the Third touch point --> wTouchX3 : wTouchY3
Dim wTouchX3 As Word
Dim wTouchY3 As Word

'Matrix coefficients to be used for point conversion
Dim sdwK As SDword
Dim fA As Float
Dim fB As Float
Dim fC As Float
Dim fD As Float
Dim fE As Float
Dim fF As Float

'Misc variables
Dim bTemp As Byte
Dim wOldX As Word
Dim wOldY As Word
Dim wNewX As Word
Dim wNewY As Word
Dim sbXExpand As SByte
Dim sbYExpand As SByte
Dim pBoardMode As Bit

John Drew

Trastikata, great job.
Would you be willing to put the code in the wiki?
There's a section for graphic LCD.
Cheers
John D

John Lawton

Hi Trastikata, great job indeed. I like the addition of the Erase function, I see it came in handy to remove your Proton Positron error.

:)

John