basic functional test of FT810 LCD via SPI

Dependencies:   FT810 mbed

main.cpp

Committer:
cpm219
Date:
2016-07-01
Revision:
16:19ade236df07
Parent:
15:25cbc8345067
Child:
17:f98333612db8

File content as of revision 16:19ade236df07:

/*
Title Block
**     Project     : data logger: lcd power levels
**     Engineers   : Curtis Mattull
**     Processor   : MK20
**     Version     : 1.0
**     Compiler    : mbed
**     Date/Time   : 7/1/2016
**     Abstract    : This program demonstrates the possible power saving modes using the LCD touch screen.
                     This program also serves as a learning experience with using touch screen LCDs.
                     
                     Power modes: (mcu never sleeps)
                        1. Screen off, touch off
                        2. Screen off, touch on.        wake from touch input
                        3. Screen dim, touch on.        touch to brighten screen
                        4. After time-out delay,
                            System can enter power modes 1,2, or 3.
                       
                     Take measurements of power consumed on 3.3V bus for each state.
                     
                    
                     bonus points:
                        1. sleep between data captures, then using interrupt, wake mcu with touch input.
                        2. 
                   
**
**     Notes       : The limitations of the VERTEX2II program forced us to create a bandage when trying to write images past pixel 511. The range of VERTEX2II is 0 to 511
**                   so in order to draw an image further away we had to use the translate command.
**
**     Todo        :    
*/
#include "mbed.h"                               // library #includes
#include "FT_Platform.h"
#include "FT_color.h"
#include "stdio.h"
#include "float.h"
#include "SDFileSystem.h"
#include "MCP4725.h"

#define K20                                     // used to simplify defining for different microcontroller platforms
//#define Program_Button                          // used add easy way to reprogram without using the phsyical button.
//#define Debug_Swipe                           // reads back touch data in real time on the screen

#ifdef K20
FT800 TFT(D11,D12,D13,D9,D8,D14);               // create object for the LCD, handles all of the data passing and slave select commands (SPI)
SDFileSystem sd(D11, D12, D13, D10, "sd");      // create object for the SD card, handles all of the data passing and slave select commands (SPI)
MCP4725 dac1(D18, D19, MCP4725::ADDRESS_2);     // create object for the first DAC board, handles all fo the data addressing (I2C)
MCP4725 dac2(D18, D19, MCP4725::ADDRESS_3);     // create object for the second DAC board, handles all fo the data addressing (I2C)

AnalogIn PSEpressure_raw(A9);                   // analog 9 pin connected to the PSE input
AnalogIn PFWflowrate_raw(A8);                   // analog 9 pin connected to the PFW input
AnalogIn ITVpressure1_feedback_raw(A3);         // analog 9 pin connected to the ITV1 input
AnalogIn ITVpressure2_feedback_raw(A2);         // analog 9 pin connected to the ITV2 input
DigitalIn card_present(D7);                     // analog 9 pin connected to the SD card detect pin input
#endif

// global variables
unsigned int CalVal0, CalVal1, CalVal2, CalVal3, CalVal4, curX, curY, pasX, pasY;                                   // touchscreen calibration data and swiping variables.
float PSEpressure, PFWflowrate = 0.0;                                                                               // variables to store data used in calculating flow and pressure
float ITVpressure1_feedback, ITVpressure2_feedback, ITVpressure1_user_input,  ITVpressure2_user_input = 0.0;        // variables to store data thats used in calculating the output and input pressure for the ITVs
float ITVpressure1_input_scaled, ITVpressure2_input_scaled = 0.0;
float ITV1_pre, ITV1_fcal, ITV2_pre, ITV2_fcal, PFW_pre, PFW_fcal, PSE_pre, PSE_fcal = 0.0;                         // moving average filter variables
static float avg1 = 0.15;                                                                                           // filter value for new samples
static float avg2 = 0.85;                                                                                           // filter value previous samples
uint16_t ITVpressure1_input_raw, ITVpressure2_input_raw = 0;                                                          // stores the raw 16 bit reads for the ITVs
int16_t velocity, distance, touched, location, paslocation;                                                         // variables to handle the swiping and multiple pages
char buffer[50];                                                                                                    // temporary buffer for writing characters to the LCD
uint8_t tcal[24];                                                                                                   // touch screen Calibration
char tstr[40];                                                                                                      // temp location for Touch Screen Calibration
ft_int16_t x_size, y_size;                                                                                          // stores size data for loaded jpegs, not currently used
unsigned int err[7] = {0,0,0,0,0,0,0};                                                                              // array to store returned values from Load_jpg function, possible future error handling
/****************************************************************************************/
/* The DeviceCal array stores the external hardware calibration data.                   */
/* The array format is as follows:                                                      */
/* DeviceCal[0] = 5V input from device 1,       DeviceCal[1] = 1V input from device 1   */
/* DeviceCal[2] = 20mA input from device 2,     DeviceCal[3] = 4mA input from device 2  */
/* DeviceCal[4] = 5V input from device 3,       DeviceCal[5] = 1V input from device 3   */
/* DeviceCal[6] = 20mA output from device 3,    DeviceCal[7] = 4mA output from device 3 */
/* DeviceCal[8] = 5V input from device 4,       DeviceCal[9] = 1V input from device 4   */
/* DeviceCal[10] = 20mA output from device 4,   DeviceCal[11] = 4mA output from device 4*/
/****************************************************************************************/
uint16_t DeviceCal[12];                     // array that stores calibraton data
unsigned char DeviceCal_buffer[50];         // buffer to store char data read back from SD card before it's converted into an integer

/****************************************************************************/
/* Serves as the bootup screen as the images are loaded from the SD card    */
/* A spinner shows the delay                                                */
/****************************************************************************/
ft_void_t Start_Screen(ft_char8_t *str)
{
    TFT.DLstart();                                             // start a new display command list
    TFT.DL(CLEAR_COLOR_RGB(255,255,255));                      // set the clear color to white
    TFT.DL(CLEAR(1,1,1));                                      // clear buffers -> color buffer,stencil buffer, tag buffer

    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                         // generate border in SMC blue, all functions are in 1/16 pixel format
    TFT.DL(BEGIN(LINES));
    TFT.DL(LINE_WIDTH(8 * 16));
    TFT.DL(VERTEX2F(0*16,0*16));
    TFT.DL(VERTEX2F(799*16,0*16));
    TFT.DL(VERTEX2F(799*16,0*16));
    TFT.DL(VERTEX2F(799*16,479*16));
    TFT.DL(VERTEX2F(799*16,479*16));
    TFT.DL(VERTEX2F(0*16,479*16));
    TFT.DL(VERTEX2F(0*16,479*16));
    TFT.DL(VERTEX2F(0*16,0*16));
    TFT.DL(END());

    TFT.Text((TFT.DispWidth/2), TFT.DispHeight/2, 31, OPT_CENTERX, str);        // draw Text with font 31
    TFT.Text((TFT.DispWidth/2), 350, 31, OPT_CENTERX, "Brew Panel");            // draw Text with font 31
    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                          // change current color
    TFT.Spinner((TFT.DispWidth/2),TFT.DispHeight/4, 0,0);                       // draw a animated spinner

    TFT.DL(DISPLAY());                   // Display the image
    TFT.Swap();                          // Swap the current display list
    TFT.Flush_Co_Buffer();               // Download the command list into fifo
    TFT.WaitCmdfifo_empty();             // Wait till coprocessor completes the operation
    TFT.Sleep(1000);                     // Wait 1s to show
}

/****************************************************************************/
/* Main screen function that writes the SD images and external hardware     */
/* data to the screen, also controls the ITV pressure                       */
/****************************************************************************/
void Main_Screen()
{
    TFT.DLstart();                                                      // start a new display command list
    TFT.DL(CLEAR_COLOR_RGB(255,255,255));                               // set the clear color to white
    TFT.DL(CLEAR(1,1,1));                                               // clear buffers -> color buffer,stencil buffer, tag buffer
#ifdef Program_Button
    TFT.DL(TAG(200));                                                   // assign TAG value 200
    TFT.Button(710, 10, 76, 22, 26, 0, "Reprogram");                    // generate reprogram button, only works for teensy
    TFT.DL(TAG(3));
#endif

    /***************************************************************************************************/
    /*Border Creation*/
    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                  // generate border in SMC blue, all functions are in 1/16 pixel format
    TFT.DL(BEGIN(LINES));
    TFT.DL(LINE_WIDTH(8 * 16));
    TFT.DL(VERTEX2F(0*16,0*16));
    TFT.DL(VERTEX2F(799*16,0*16));
    TFT.DL(VERTEX2F(799*16,0*16));
    TFT.DL(VERTEX2F(799*16,479*16));
    TFT.DL(VERTEX2F(799*16,479*16));
    TFT.DL(VERTEX2F(0*16,479*16));
    TFT.DL(VERTEX2F(0*16,479*16));
    TFT.DL(VERTEX2F(0*16,0*16));
    TFT.DL(END());
    /***************************************************************************************************/

    /***************************************************************************************************/
    /*ITV 1 Screen Display*/
    TFT.DL(COLOR_RGB(255,255,255));                                     // set background to white
    TFT.DL(VERTEX_TRANSLATE_X(location* 16));                           // page 1

    TFT.DL(BEGIN(BITMAPS));                                             // draw a bitmap that stores the first screens images
    TFT.DL(VERTEX2II(265,50,0,0));                                      // draw logo image with bit handle 0
    TFT.DL(VERTEX2II(75,50,1,0));                                       // draw ITV_1 image with bit handle 1
    TFT.DL(VERTEX_TRANSLATE_X((149+location)*16));                      // translate right 149 pixels for third image, location controls what page the screen is on
    TFT.DL(VERTEX2II(511,50,2,0));                                      // draw ITV_2 image with bit handle 2
    TFT.DL(VERTEX_TRANSLATE_X((0+location)*16));                        // translate back to prevent the remaining commands from also being translated
    TFT.DL(END());

    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                  // set color to SMC blue for the text
    TFT.Text(265, 200, 31, 0, "ITV 1 Pressure");                        // title block for screen
    TFT.DL(BEGIN(RECTS));                                               // draw rounded rectangle in SMC blue to act as background for where the feedback will be written
    TFT.DL(VERTEX2F(300*16,265*16));
    TFT.DL(VERTEX2F(505*16,330*16));
    TFT.DL(END());
    ITVpressure1_feedback = (ITVpressure1_feedback_raw.read_u16() - DeviceCal[5]) * (70.0) / (DeviceCal[4] - DeviceCal[5]) + 0;        // calibration and scaling math for the ITV feedback
    ITV1_fcal = ITVpressure1_feedback;                                  // moving average filter
    ITV1_fcal *= avg1;
    ITV1_fcal += ITV1_pre * avg2;
    ITV1_pre = ITV1_fcal;
    ITVpressure1_feedback = ITV1_fcal;                                  // store the filtered value in the feedback variable
    TFT.DL(COLOR_RGB(255,255,255));                                     // set color to white for the text
    sprintf(buffer, "%.1f", ITVpressure1_feedback);                     // write the feedback pressure to the screen
    TFT.Text(325,275,31,0,buffer);
    TFT.Text(415, 275, 31, 0, " PSI");                                  // write the units to the screen

    TFT.DL(COLOR_RGB(255,255,255));                                     // controls the color of the slider bar in RGB format
    TFT.FgColor(COLOR_RGB(0,124,196));                                  // foreground color set to SMC blue in RGB format
    TFT.BgColor(COLOR_RGB(0,124,196));                                  // background color set to SMC blue in RGB format
    TFT.DL(TAG(1));                                                     // assign TAG value 1
    TFT.Slider(225,375,350,30,0,ITVpressure1_user_input,2355);          // generate slider that controls the output pressure of ITV1
    TFT.DL(TAG(3));                                                     // general tag assignment to prevent any tag assigning errors
    /***************************************************************************************************/

    /***************************************************************************************************/
    /*ITV 2 and PF3W Screen Display*/
    TFT.DL(COLOR_RGB(255,255,255));                                     // set background color to white
    TFT.DL(VERTEX_TRANSLATE_X(location* 16)+12800);                     // translate screen writes by 12800 which is a 1/16th pixel format, this creates page 2 of the screen
    TFT.DL(BEGIN(BITMAPS));                                             // draw a bitmap that stores the second screens images
    TFT.DL(VERTEX2II(30,75,3,0));                                       // write PF3W_1 image to the LCD
    TFT.DL(VERTEX_TRANSLATE_X((149+location)*16)+12800);                // translate right 149 pixels for third image, location controls what page the screen is on
    TFT.DL(VERTEX2II(411,75,4,0));                                      // write PF3W_2 image to the LCD
    TFT.DL(VERTEX_TRANSLATE_X((0+location)*16)+12800);                  // translate back to 0 for remaining screen writes
    TFT.DL(END());

    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                  // set text color to SMC blue, RGB format
    TFT.Text(265, 200, 31, 0, "ITV 2 Pressure");                        // write title block to screen
    TFT.DL(BEGIN(RECTS));                                               // draw rounded rectangle in SMC blue to act as background for where the feedback will be written
    TFT.DL(VERTEX2F(300*16,265*16));
    TFT.DL(VERTEX2F(505*16,330*16));
    TFT.DL(END());

    ITVpressure2_feedback = (ITVpressure2_feedback_raw.read_u16()- DeviceCal[9]) * (70.0) / (DeviceCal[8] - DeviceCal[9]) + 0; // calibration and scaling math for the ITV feedback
    ITV2_fcal = ITVpressure2_feedback;                                  // moving average filter
    ITV2_fcal *= avg1;
    ITV2_fcal += ITV2_pre * avg2;
    ITV2_pre = ITV2_fcal;
    ITVpressure2_feedback = ITV2_fcal;                                  // store filtered value in feedback variable
    TFT.DL(COLOR_RGB(255,255,255));                                     // set color for text to white
    sprintf(buffer, "%.1f", ITVpressure2_feedback);                     // write feedback to screen in white
    TFT.Text(325,275,31,0,buffer);
    TFT.Text(415, 275, 31, 0, " PSI");                                  // write the units to the screen
    TFT.DL(COLOR_RGB(255,255,255));                                     // controls the color of the slider bar in RGB format
    TFT.FgColor(COLOR_RGB(0,124,196));                                  // foreground color set to SMC blue in RGB format
    TFT.BgColor(COLOR_RGB(0,124,196));                                  // background color set to SMC blue in RGB format
    TFT.DL(TAG(2));                                                     // assign tag 2 to slider for ITV2
    TFT.Slider(225,375,350,30,0,ITVpressure2_user_input,2387);          // generate slider that controls the output pressure of ITV2
    TFT.DL(TAG(3));                                                     // general tag assignment to prevent any tag assigning errors

    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                  // set color to SMC blue for text
    TFT.Text(250, 20, 31, 0, "PF3W Flow Rate");                         // write title block to screen
    TFT.DL(BEGIN(RECTS));                                               // draw rounded rectangle in SMC blue to act as background for where the feedback will be written
    TFT.DL(VERTEX2F(300*16,85*16));
    TFT.DL(VERTEX2F(505*16,150*16));
    PFWflowrate = (PFWflowrate_raw.read_u16() - DeviceCal[3]) * (40.0) / (DeviceCal[2] - DeviceCal[3]) + 0; // calibration and scaling math for the PFW feedback
    PFW_fcal = PFWflowrate;                                             // moving average filter
    PFW_fcal *= avg1;
    PFW_fcal += PFW_pre * avg2;
    PFW_pre = PFW_fcal;
    PFWflowrate = PFW_fcal;                                             // store filtered value in feedback variable
    TFT.DL(COLOR_RGB(255,255,255));                                     // set text feedback text color to white
    sprintf(buffer, "%.1f", PFWflowrate);                               // write feedback to LCD
    TFT.Text(305,95,31,0,buffer);
    TFT.Text(385, 95, 31, 0, " L/min");                                 // write units to LCD
    /***************************************************************************************************/

    /***************************************************************************************************/
    /*PSE Screen Display*/
    TFT.DL(COLOR_RGB(255,255,255));                                     // set the background for page 3 to white
    TFT.DL(VERTEX_TRANSLATE_X(location* 16)+25600);                     // translate screen writes by 25600 which is a 1/16th pixel format, this creates page 3 of the screen
    TFT.DL(BEGIN(BITMAPS));                                             // create bitmap to draw images on LCD
    TFT.DL(VERTEX2II(265,50,0,0));                                      // wrtie the SMC logo to the screen
    TFT.DL(VERTEX2II(75,50,5,0));                                       // write PSE_1 image to the screen
    TFT.DL(VERTEX_TRANSLATE_X((99+location)*16)+25600);                 // translate right by 99 pixels for the next image write
    TFT.DL(VERTEX2II(511,85,6,0));                                      // write PSE_2 image to the screen
    TFT.DL(VERTEX_TRANSLATE_X((0+location)*16)+25600);                  // translate back to pixel 0 for the remaining screen writes
    TFT.DL(END());

    TFT.DL(COLOR_RGB(0x00,0x7C,0xC4));                                  // set text color to SMC blue
    TFT.Text(280, 200, 31, 0, "PSE Pressure");                          // write title block to screen
    TFT.DL(BEGIN(RECTS));                                               // draw rounded rectangle in SMC blue to act as background for where the feedback will be written
    TFT.DL(VERTEX2F(295*16,265*16));
    TFT.DL(VERTEX2F(505*16,330*16));
    TFT.DL(END());
    PSEpressure = ((PSEpressure_raw.read_u16() - DeviceCal[1]) * (1.0) / (DeviceCal[0] - DeviceCal[1]) + 0)*145.0377; // calibration and scaling math for the PSE feedback
    PSE_fcal = PSEpressure;                                             // moving average filter
    PSE_fcal *= avg1;
    PSE_fcal += PSE_pre * avg2;
    PSE_pre = PSE_fcal;
    PSEpressure = PSE_fcal;                                             // store the filtered value in feedback variable
    TFT.DL(COLOR_RGB(255,255,255));                                     // set text color to white
    sprintf(buffer, "%.1f", PSEpressure);                               // write feedback to screen
    TFT.Text(300,275,31,0,buffer);
    TFT.Text(405, 275, 31, 0, " PSI");                                  // write units to LCD
    /***************************************************************************************************/

#ifdef Debug_Swipe                                   // writes touch data to screen
    TFT.DL(COLOR_RGB(0,0,0));                        // set text color to black
    TFT.Number(20, 450, 26, 0, distance);            // write distance value to screen
    TFT.Number(80, 450, 26, 0, velocity);            // write velocity to screen
#endif

#ifdef Debug_Touch_File                              // debug the touch up load
    TFT.DL(COLOR_RGB(0,0,0));                        // set text color to black
    int j;                                           // loop counter
    for (j = 0; j < 24; j++) {                       // write file data to screen
        TFT.Number(j*30+20, 450, 26, 0, tcal[j]);
    }
#endif

    TFT.DL(DISPLAY());                     // display the image
    TFT.Swap();                            // swap the current display list
    TFT.Flush_Co_Buffer();                 // download the command list into fifo
    TFT.WaitCmdfifo_empty();               // wait till coprocessor completes the operation
}

/****************************************************************************/
/* This function displays the error screen                                  */
/* the function causes the screen to flash yellow and writes text to the LCD*/
/****************************************************************************/
void error_screen(ft_char8_t *str1, ft_char8_t *str2)
{
    TFT.DLstart();                         // start a new display command list
    TFT.DL(CLEAR_COLOR_RGB(255,242,0));    // clear the screen and set the background to yellow
    TFT.DL(CLEAR(1,1,1));                  // clear buffers -> color buffer,stencil buffer, tag buffer
    TFT.DL(COLOR_RGB(0,0,0));
    TFT.Text((TFT.DispWidth/2), 170, 31, OPT_CENTERX, str1);                // draw Text with font 31
    TFT.Text((TFT.DispWidth/2), 215, 31, OPT_CENTERX, str2);                // draw Text with font 31
    TFT.DL(DISPLAY());                                                      // display the image
    TFT.Swap();                                                             // swap the current display list
    TFT.Flush_Co_Buffer();                                                  // download the command list into fifo
    TFT.WaitCmdfifo_empty();                                                // wait till coprocessor completes the operation
    TFT.Sleep(1000);

    TFT.DLstart();                                                          // start a new display command list
    TFT.DL(CLEAR_COLOR_RGB(255,255,255));                                   // set clear color to white
    TFT.DL(CLEAR(1,1,1));                                                   // clear buffers -> color buffer,stencil buffer, tag buffer;
    TFT.DL(COLOR_RGB(0,0,0));
    TFT.Text((TFT.DispWidth/2), 170, 31, OPT_CENTERX, str1);                // draw Text with font 31
    TFT.Text((TFT.DispWidth/2), 215, 31, OPT_CENTERX, str2);                // draw Text with font 31
    TFT.DL(DISPLAY());                                                      // display the image
    TFT.Swap();                                                             // swap the current display list
    TFT.Flush_Co_Buffer();                                                  // download the command list into fifo
    TFT.WaitCmdfifo_empty();                                                // wait till coprocessor completes the operation
    TFT.Sleep(1000);
}

/****************************************************************************/
/* Checks for an SD card and reads/writes the calibration data              */
/* from the SD card                                                         */
/****************************************************************************/
void read_Calibration()
{
    int i = 0;
    int k = -4;                                                 // loop counter
    while(card_present.read()) {                                // checks for SD card, if not present hold program until a SD card is inserted
        error_screen("Error!","Insert SD card!");               // write error screen to LCD
    }
    FILE *fp= fopen("/sd/TCal/TCalData.txt", "r");
    if(!fp) {                                                   // could not open file for read so generate data then store on SD card
        TFT.Calibrate();                                        // calibrate the touch screen
        TFT.read_calibrate(tcal);                               // read in cal data from screen
        mkdir("/sd/TCal", 0777);                                // open file for to save calibration data
        FILE *fp = fopen("/sd/TCal/TCalData.txt", "w");
        for (i = 0; i < 25; i++) {                              // save integers one at a time to the file
            fprintf(fp, "%c", tcal[i] );
        }
    } else {                                                    // file found, read in data
        fread(tstr,24,1,fp);
        for (i = 0; i < 24; i++) {                              // convert from int to char
            tcal[i] = tstr[i];
        }
        TFT.write_calibrate(tcal);                              // write cal data to screen
    }
    fclose(fp);                                                 // close SD card file
    
    FILE *fp2= fopen("/sd/DeviceCalData.txt", "r");             // read DeviceCalData.txt where the external hardware calibration data where is integer is stored in 4 sets of 4 bit chars.                             
    fread(DeviceCal_buffer,48,1,fp2);                           // read the data
    for (i = 0; i < 12; i++) {                                  // convert from int to char
        DeviceCal[i] = (uint16_t)((DeviceCal_buffer[4+k]<<12) | (DeviceCal_buffer[k+5]<<8) | (DeviceCal_buffer[6+k]<<4) | (DeviceCal_buffer[k+7]<<0));      // take 4 sets of 4 bit chars and rebuild it into 1 integer
        k=k+4;      // increment loop
    }
    fclose(fp2);    // close file
}

/****************************************************************************/
/* Loads all of the images from the SD card and assigns them bitmap handles */
/****************************************************************************/
void initialize_Images()
{
    while(card_present.read()) {                                // checks for SD card, if not present hold program until a SD card is inserted
        error_screen("Error!","Insert SD card!");               // write error screen to LCD
    }
    TFT.DLstart();                           // start a new display command list
    TFT.DL(CLEAR(1,1,1));                    // clear buffers -> color buffer,stencil buffer, tag buffer

    TFT.DL(BITMAP_HANDLE(0));                                               // assign bitmap handle 0 to logo.jpg
    err[0] = TFT.Load_jpg("/sd/Logo.jpg",& x_size,& y_size, 0);             // load the jpg and write it to address 0 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(1));                                               // assign bitmap handle 1 to ITV_1.jpg
    err[1] = TFT.Load_jpg("/sd/ITV_1.jpg",& x_size,& y_size, 45000);        // load the jpg and write it to address 45,000 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(2));                                               // assign bitmap handle 2 to ITV_2.jpg
    err[2] = TFT.Load_jpg("/sd/ITV_2.jpg",& x_size,& y_size, 60000);        // load the jpg and write it to address 60,000 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(3));                                               // assign bitmap handle 3 to PF3W_1.jpg
    err[3] = TFT.Load_jpg("/sd/PF3W_1.jpg",& x_size,& y_size, 85000);       // load the jpg and write it to address 85,000 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(4));                                               // assign bitmap handle 4 to PF3W_2.jpg
    err[4] = TFT.Load_jpg("/sd/PF3W_2.jpg",& x_size,& y_size, 150000);      // load the jpg and write it to address 150,000 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(5));                                               // assign bitmap handle 5 to PSE_1.jpg
    err[5] = TFT.Load_jpg("/sd/PSE_1.jpg",& x_size,& y_size, 230000);       // load the jpg and write it to address 230,000 in the FT810 RAM and store error result in array
    TFT.DL(BITMAP_HANDLE(6));                                               // assign bitmap handle 6 to PSE_2.jpg
    err[6] = TFT.Load_jpg("/sd/PSE_2.jpg",& x_size,& y_size, 260000);       // load the jpg and write it to address 260,000 in the FT810 RAM and store error result in array

    TFT.DL(DISPLAY());                     // display the image
    TFT.Swap();                            // swap the current display list
    TFT.Flush_Co_Buffer();                 // download the command list into fifo
    TFT.WaitCmdfifo_empty();
}

/****************************************************************************/
/* Function that checks for a inadequate supply pressure and displays       */
/* an error                                                                 */
/****************************************************************************/
void SupplyPressure_Check(float check1, float check2)
{
    while(((PSEpressure) < (check1 - 10)) || ((PSEpressure) < (check2 - 10))) {
        dac1.write_u12(0);                                                                  // turn off ITVs
        dac2.write_u12(0);
        error_screen("Supply pressure too low!", "");                                       // display error
        PSEpressure = ((PSEpressure_raw.read_u16() - DeviceCal[1]) * (1.0) / (DeviceCal[0] - DeviceCal[1]) + 0)*145.0377; // calibration and scaling math for the PSE feedback
    }
    dac1.write_u12(ITVpressure1_input_raw);                                                 // restore ITV pressure
    dac2.write_u12(ITVpressure2_input_raw);
}

/****************************************************************************/
/* Main function that tracks all of the touchscreen data and updates the    */
/* screen accordingly                                                       */
/****************************************************************************/
int main()
{
//    dac1.wakeup();                                                      // activate DAC boards
//    dac2.wakeup();
//    dac1.write_u12(0);                                                  // the natural DAC output value is 50% of its maximum value
//    dac2.write_u12(0);                                                  // the program has to immediately write a 0 to the DAC to turn off the outputs

    ft_uint32_t TrackRegisterVal = 0;                                   // touch track variable
//
    TFT.MemWrite(REG_ROTATE, 1);                                        // rotate screen
    TFT.Rotate(1);
//
//    //SupplyPressure_Check(0,0);                                          // check for any supply pressure
    read_Calibration();                                                 // load touchscreen calibration data
    initialize_Images();                                                // load and initialize images
    Start_Screen("Starting...");                                        // show start screen
//
    TFT.Track(200, 400, 375, 50, 1);                                    // track sliders
    TFT.Track(200, 400, 375, 50, 2);
    TFT.Flush_Co_Buffer();                                              // download the command list into fifo
    TFT.WaitCmdfifo_empty();                                            // wait till coprocessor completes the operation

    while(1) 
    {
        Main_Screen();                                                  // paint new screen
        curY = TFT.Rd32(REG_TOUCH_SCREEN_XY)& 0xffff;                   // get the current touch screen position
        curX = TFT.Rd32(REG_TOUCH_SCREEN_XY)>>16;                       // if not touch the results are 0x8000 for x and y
        ft_uint8_t tagval = 0;                                          // initialize return tag value
        TrackRegisterVal = TFT.Rd32(REG_TRACKER);                       // check if one of the two tracking fields is touched
        tagval = TrackRegisterVal & 0xff;                               // store return tag value
       
        // check what tag was touched
        if(1 == tagval) 
        {                                                                       // tag value for ITV1 slider touch
            ITVpressure1_user_input = (TrackRegisterVal>>20) * (2356.0/4095);                   // calculate new slider value so that the slider updates graphically
            ITVpressure1_input_raw = (TrackRegisterVal>>20) * (2356.0/4095) + 590;              // calculate raw 12 bit input number, includes calibration number to never go above 20mA
            dac1.write_u12(ITVpressure1_input_raw);                                             // write 12 bit number to DAC to fire the ITV
            ITVpressure1_input_scaled = (ITVpressure1_input_raw-590)*(70.0)/(4095)+0;
        }

        else if(2 == tagval) 
        {                                                                  // tag value for ITV2 slider touch
            ITVpressure2_user_input = (TrackRegisterVal>>20) * (2386.0/4095);                   // calculate new slider value so that the slider updates graphically
            ITVpressure2_input_raw = (TrackRegisterVal>>20) * (2386.0/4095) + 585;              // calculate raw 12 bit input number, includes calibration number to never go above 20mA
//            dac2.write_u12(ITVpressure2_input_raw);                                             // write 12 bit number to DAC to fire the ITV
            ITVpressure2_input_scaled = (ITVpressure2_input_raw-590)*(70.0)/(4095)+0;
        }

        else if (200 == tagval) 
        {                                                               // tag for the reprogram button that works by exiting the program which cases the teensy to load the bootloader
            break;
        } 
        
        else if(curX !=0x8000 && touched>0)                                                     // If the sceen is being touched and has been touched before and is not on a tag
        {                                                           
            touched++;                                                                          // touched is used to determine how long the screen has beed touched for and if it is currently being touched
            distance = curX - pasX;                                                             // find the swipe distance in pixels
            location = (int16_t)paslocation + distance;                                         // add the distance of the swipe to the location so the screen moves as you swipe
        } 
        
        else if(curX !=0x8000 && !touched)                                                   // If the screen is being touched but was not the pervious time through the loop then this is the starting point of the swipe
        {
            touched++;
            pasX = curX;
        } 
        
        else if(curX ==0x8000 && touched) 
        {                                                                                       // Not being touched currently but was touched last time through the loop
            velocity = distance/touched;                                                        // Now that the swipe is finished we can calculate the velocity from the distance and time touched
            paslocation = location;                                                             // Store Location data away
            touched=0;                                                                          // Reset for the next touch                                                                                     // If not being touched
        } 
        
        else 
        {   
            if (location < - 1500 && location > -1700)                                  //page 3 location
            {                                                                           // repeat for each page
                if (velocity)
                {
                    velocity = (location + 1600)/-5;
                    location += (int16_t) velocity;
                    paslocation = location;
                } 
                else
                {
                    location = -1600;
                }
            }
            else if (location < - 700 && location > -900)                               //page 2
            {
                if (velocity)
                {
                    velocity = (location + 800)/-5;
                    location += (int16_t) velocity;
                    paslocation = location;
                } 
                else 
                {
                    location = -800;
                }
            }
            else if (location > -100 && location < 100)                                  //page 1
            {
                if (velocity)
                {
                    velocity = location/-5;
                    location += (int16_t) velocity;
                    paslocation = location;
                }
                else 
                {
                    location = 0;
                }
            } 
            else if (location >60)                                          //no page 0  
            {                                                               // Do not allow the page screen to go to -1 page
                velocity = -10;                                             // Change the velocity to return
                location += (int16_t) velocity;
                paslocation = location;
            } 
            else if (location <-1700)                                       //no page 4
            {                                                               // Do not allow the page screen to go pass top page
                velocity = 10;                                              // Change the velocity to return
                location += (int16_t) velocity;
                paslocation = location;
            } 
            else if (velocity)                                              //between pages 
            {                                                               // if the page is not at edge but has velocity
                location += (int16_t) velocity;
                paslocation = location;
                if (velocity >0) 
                {                                                              // acceleration between pages so it does not take forever
                    velocity+= 2;                                                               // increase velocity
                }
                else 
                {
                    velocity-= 2;
                }
            }
        }
        //SupplyPressure_Check(ITVpressure1_input_scaled, ITVpressure2_input_scaled);     // check to see if theres enough supply pressure for the ITVs
        TFT.Sleep(10);                  // wait 10ms for next time to repaint the screen
    }                                   // end of display loop
}