This is a fork of a functional ILI9341 display with a functional Seeed touch screen library.

Dependencies:   BMP180 UniGraphic mbed BNO055_fusionI_fixed HTU21D GPSISR Compass Fonts uGUI

Fork of TFT_test_NUCLEO-F411RE by Motoo Tanaka

/media/uploads/trevieze/win_20170427_21_31_20_pro.jpg

Had to move sensors to a remote board because of interference. Added spi burst mode to supported displays.

To do.... ugui buttons are slow. will need to add rtos to project. Finish other way points screen. Will have to rewrite portions of the touch screen class. Sense touch, delay, read values and then average, touch released, is the sequence. Add cadence input and logic to program for computer screen.

main.cpp

Committer:
trevieze
Date:
2018-05-18
Revision:
22:39a8e5c47f3c
Parent:
21:39ef2fd5c4bf

File content as of revision 22:39a8e5c47f3c:

/* mbed main.cpp to test adafruit 2.8" TFT LCD shiled w Touchscreen
 * Copyright (c) 2014, 2015 Motoo Tanaka @ Design Methodology Lab
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/*
 * Note: This program is derived from the SeeeStudioTFTv2 program.
 * Although both program share same ILI9341 TFT driver,
 * the touch sensor was not same with the Display I purchased from Akizuki.
 * http://akizukidenshi.com/catalog/g/gM-07747/
 * The touch sensor on the display is STMPE610,
 * so I hacked the minimum spi driver for it (polling mode only).
 */

#include "mbed.h"
#include <math.h>
#include "ILI9341.h"
// Graphics GUI Library
#include    "ugui.h"
// Include all devices on sensor board. 
#include "SeeedStudioTFTv2.h"
#include "BNO055.h"
#include "HTU21D.h"
#include "BMP180.h"
#include "GPSISR.h"
#include "nav.h"
// Include all fonts used on display.
#include "ArialR16x17.h"
#include "Arial24x23i.h"
#include "Arial28x28.h"
#include "Neu44x36.h"
#include "SCProSB31x55.h"
#include "Arial12x12.h"
#include "ArialR20x20.h"
#include "compass.h"

// Define screen SPI and memory card SPI hardware pins.
#define PIN_RESET_TFT   PC_13 /* place holder */
//ILI9341 SPI PINS
#define PIN_XP          A3
#define PIN_XM          A1
#define PIN_YP          A2
#define PIN_YM          A0
#define PIN_MOSI_SPI1   D11 //SPI 1 MOSI
#define PIN_MISO_SPI1   D12 //SPI 1 MISO
#define PIN_SCLK_SPI1   D13 //SPI 1 SLCK
#define PIN_CS_SPI1     D5 // SPI CS D10 Was D5
#define PIN_DC_TFT      D6
#define PIN_CS_SD       D4
#define PIN_RESET       D7
// SD Card on GPS shield PINS
#define PIN_MOSI_SPI3   PB_15 //SPI 3 MOSI
#define PIN_MISO_SPI3   PB_14 //SPI 3 MISO
#define PIN_SCLK_SPI3   PB_13 //SPI 3 SLCK
#define PIN_CS_SPI3     D2 // SPI CS
#define PIN_RX_GPS      PA_12 //GPS Shield RX pin
#define PIN_TX_GPS      PA_11 //GPS Shield TX pin
//PI
#define PI                  3.14159265358979f
//BN055 compass module classes definitions.
BNO055_ID_INF_TypeDef       bno055_id_inf;
BNO055_EULER_TypeDef        euler_angles;
BNO055_QUATERNION_TypeDef   quaternion;
BNO055_LIN_ACC_TypeDef      linear_acc;
BNO055_GRAVITY_TypeDef      gravity;
BNO055_TEMPERATURE_TypeDef  chip_temp;
// Compiler processor name.
#define DEVICE_NAME     "F411RE"

#ifndef TARGET_NECLEO_F411RE
#define TARGET_NECLEO_F411RE
#endif

//DigitalOut backlight(PB_3) ;

/** Height of display using default orientation */
#define ILI9341_DEFAULT_HEIGHT   240

/** Width of display using default orientation */
#define ILI9341_DEFAULT_WIDTH    320

/** Height of display using swapped X/Y orientation */
#define ILI9341_SWITCH_XY_HEIGHT 320

/** Width of display using swapped X/Y orientation */
#define ILI9341_SWITCH_XY_WIDTH  240

Serial pc(USBTX, USBRX);

// Display
ILI9341 TFT(SPI_8, 20000000,
            PIN_MOSI_SPI1, PIN_MISO_SPI1,  PIN_SCLK_SPI1,
            PIN_CS_SPI1, PIN_RESET_TFT, PIN_DC_TFT, "Adafruit2.8") ;

// TouchScreen
TouchScreen TSC(PIN_XP, PIN_XM, PIN_YP, PIN_YM);

// 3 Axis IMU
BNO055 imu(I2C_SDA, I2C_SCL, PIN_RESET);  // Reset =D7, addr = BNO055_G_CHIP_ADDR, mode = MODE_NDOF <- as default
// Humidity and Temperature
HTU21D humid(I2C_SDA, I2C_SCL);

// Pressure
BMP180 bmp180(I2C_SDA, I2C_SCL);

// Set up serial interrupe service handler for gps characters.
GPS MyGPS(PIN_TX_GPS,PIN_RX_GPS, 9600);

//Navigation Class. Perry Michigan coordinates.
NAV nav;
double plat = 42.826420;
double plon = -84.219413;

// Graphics library declarations. 
void arrow(int x2, int y2, int x1, int y1, int alength, int awidth, int colour);
void ili9341_pset(UG_S16 ul_x,UG_S16 ul_y, UG_COLOR ul_color);
void window_1_callback( UG_MESSAGE* msg );
void window_2_callback( UG_MESSAGE* msg );
void window_3_callback( UG_MESSAGE* msg );
void cb1(void);

// Compass graphic screen placement.
const int centreX = 120; // e compass indicator
const int centreY = 136;
const int radius  = 104;
float last_dx;
float last_dy;

// Bike computer page setup.
int pageid = 1;
bool pageinit = false;

// Touch screen point structer.
struct pt {
    int x;
    int y;
    bool z;
};
pt ptouch;

// Page constants.
#define PAGE1       1
#define PAGE2       2
#define PAGE3       3

// Instance of GUI.
UG_GUI   gui;

// Main routine.
int main()
{
    // Initialize touch screen.    
    TFT.BusEnable(true) ;
    TFT.FastWindow(true) ;
    wait(0.1);
    TFT.cls();
    wait(0.1);
    // Initialize graphics library.
    UG_Init(&gui,ili9341_pset,ILI9341_DEFAULT_HEIGHT,ILI9341_DEFAULT_WIDTH);

    // Sets up a timer for use in loop; how often do we print GPS info?
    // How often screen is updated.
    Timer refresh_Timer;
    const int refresh_Time = 2000; //refresh time in ms
    refresh_Timer.start();  //starts the clock on the timer
    wait(0.1);
   
    /* Window 1 Bike Computer */
    #define MAX_OBJECTS 10
    UG_WINDOW window_1 ; /* Window */
    UG_BUTTON button_1; /* Button container */
    UG_BUTTON button_2; /* Button container */
    UG_OBJECT obj_buff_wnd_1 [MAX_OBJECTS] ; /* Object buffer */
    UG_WindowCreate ( &window_1 , obj_buff_wnd_1 , MAX_OBJECTS, window_1_callback);
    UG_WindowSetTitleTextFont ( &window_1 , &FONT_8X8 ) ;
    UG_WindowSetTitleText ( &window_1 , "Bike Computer" ) ;
    UG_WindowSetBackColor( &window_1 , C_GRAY ) ;
    UG_ButtonCreate (&window_1, &button_1, BTN_ID_0, 10 , 230 , 115 , 290 );
    UG_ButtonCreate (&window_1, &button_2, BTN_ID_1, 125 , 230 , 225 , 290 );
    UG_ButtonSetBackColor (&window_1 ,BTN_ID_0 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_1 ,BTN_ID_0 , C_WHITE ) ;
    UG_ButtonSetBackColor (&window_1 ,BTN_ID_1 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_1 ,BTN_ID_1 , C_WHITE ) ;
    UG_ButtonSetFont (&window_1 , BTN_ID_0 , &FONT_8X8) ;
    UG_ButtonSetFont (&window_1 , BTN_ID_1 , &FONT_8X8) ;
    UG_ButtonSetText (&window_1 , BTN_ID_0 , "Prev" );
    UG_ButtonSetText (&window_1 , BTN_ID_1 , "Next" );

    /* Window 2 e-Compass */
    UG_WINDOW window_2 ; /* Window */
    UG_BUTTON button_3; /* Button container */
    UG_BUTTON button_4; /* Button container */
    UG_OBJECT obj_buff_wnd_2 [MAX_OBJECTS] ; /* Object buffer */
    UG_WindowCreate ( &window_2 , obj_buff_wnd_2 , MAX_OBJECTS, window_2_callback);
    UG_WindowSetTitleTextFont ( &window_2 , &FONT_8X8 ) ;
    UG_WindowSetTitleText ( &window_2 , "e-Compass" ) ;
    UG_WindowSetBackColor( &window_2 , C_GRAY ) ;
    UG_ButtonCreate (&window_2, &button_3, BTN_ID_2, 10 , 230 , 115 , 290 );
    UG_ButtonCreate (&window_2, &button_4, BTN_ID_3, 125 , 230 , 225 , 290 );
    UG_ButtonSetBackColor (&window_2 ,BTN_ID_2 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_2 ,BTN_ID_2 , C_WHITE ) ;
    UG_ButtonSetBackColor (&window_2 ,BTN_ID_3 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_2 ,BTN_ID_3 , C_WHITE ) ;
    UG_ButtonSetFont (&window_2 , BTN_ID_2 , &FONT_8X8) ;
    UG_ButtonSetFont (&window_2 , BTN_ID_3 , &FONT_8X8) ;
    UG_ButtonSetText (&window_2 , BTN_ID_2 , "Prev" );
    UG_ButtonSetText (&window_2 , BTN_ID_3 , "Next" );
    
    /* Window 3 GSP */
    UG_WINDOW window_3 ; /* Window */
    UG_BUTTON button_5; /* Button container */
    UG_BUTTON button_6; /* Button container */
    UG_OBJECT obj_buff_wnd_3 [MAX_OBJECTS] ; /* Object buffer */
    UG_WindowCreate ( &window_3 , obj_buff_wnd_3 , MAX_OBJECTS, window_3_callback);
    UG_WindowSetTitleTextFont ( &window_3 , &FONT_8X8 ) ;
    UG_WindowSetTitleText ( &window_3 , "GPS Waypoints" ) ;
    UG_WindowSetBackColor( &window_3 , C_GRAY ) ;
    UG_ButtonCreate (&window_3, &button_5, BTN_ID_4, 10 , 230 , 115 , 290 );
    UG_ButtonCreate (&window_3, &button_6, BTN_ID_5, 125 , 230 , 225 , 290 );
    UG_ButtonSetBackColor (&window_3 ,BTN_ID_4 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_3 ,BTN_ID_4 , C_WHITE ) ;
    UG_ButtonSetBackColor (&window_3 ,BTN_ID_5 , C_BLUE ) ;
    UG_ButtonSetForeColor (&window_3 ,BTN_ID_5 , C_WHITE ) ;
    UG_ButtonSetFont (&window_3 , BTN_ID_4 , &FONT_8X8) ;
    UG_ButtonSetFont (&window_3 , BTN_ID_5 , &FONT_8X8) ;
    UG_ButtonSetText (&window_3 , BTN_ID_4 , "Prev" );
    UG_ButtonSetText (&window_3 , BTN_ID_5 , "Next" );

    while (1) {
        //Read touch screen every 0.2 seconds and pass it to uGUI
        cb1();

        TFT.set_font((unsigned char*) ArialR20x20);
        TFT.foreground(White);
        TFT.background(UG_WindowGetBackColor(&window_1));
        // Sets up a timer for use in loop; how often do we print GPS info?
        if (refresh_Timer.read_ms() >= refresh_Time) {
            refresh_Timer.reset();
            //This is screen one of bike computer. It is executed every 2 seconds. Ie...refresh_Time
            switch ( pageid ) {
                case PAGE1: {
                    if (!pageinit) {
                        UG_WindowHide(&window_2);
                        UG_WindowHide(&window_3);
                        UG_WindowShow(&window_1);
                        UG_Update();
                    }
                    pageinit = 1;
                    if (bmp180.init() != 0) {
                    //pc.printf("Error communicating with BMP180\n");
                    } else {
                        //pc.printf("Initialized BMP180\n");
                        bmp180.startTemperature();
                        wait(0.1);     // Wait for conversion to complete
                        float temp;
                        if(bmp180.getTemperature(&temp) != 0) {
                            //pc.printf("Error getting temperature\n");
                        }
                        TFT.set_font((unsigned char*) Arial12x12);
                        TFT.locate(10, 65) ;
                        TFT.printf("Temperature");
                        TFT.set_font((unsigned char*) ArialR20x20);
                        TFT.locate(10, 80);
                        TFT.printf("%.1f*", ((temp* 9.0) / 5.0 + 32));
                    }
                    int ftemp = humid.sample_ftemp();
                    int humidity = humid.sample_humid();
                    TFT.set_font((unsigned char*) Arial12x12);
                    TFT.locate(150, 65) ;
                    TFT.printf("Humidity");
                    TFT.set_font((unsigned char*) ArialR20x20);
                    TFT.locate(150, 80) ;
                    TFT.printf("%d%%",humidity);
                    if (MyGPS.dataready()) {
                        MyGPS.read();
                        TFT.locate(10, 40) ;
                        TFT.foreground(UG_WindowGetBackColor(&window_1));
                        TFT.printf("No GPS Data");
                        TFT.foreground(White);
                        TFT.set_font((unsigned char*) Arial12x12);
                        TFT.locate(12, 25) ;
                        TFT.printf("Time");
                        TFT.locate(150, 25) ;
                        TFT.printf("Date");
                        TFT.set_font((unsigned char*) ArialR20x20);
                        TFT.locate(10, 40) ;
                        TFT.printf("%d:%d:%d", MyGPS.buffer.hours, MyGPS.buffer.minutes, MyGPS.buffer.seconds);
                        TFT.set_font((unsigned char*) ArialR20x20);
                        TFT.locate(150, 40) ;
                        TFT.printf("%d-%d-%d", MyGPS.buffer.month, MyGPS.buffer.day, MyGPS.buffer.year);
                        TFT.set_font((unsigned char*) SCProSB31x55);
                        TFT.locate(125, 180) ;
                        TFT.printf("%.1f", MyGPS.buffer.speed);
                        TFT.locate(10, 180);
                        TFT.printf("%d", 6); //Cadence
                        TFT.set_font((unsigned char*) Arial12x12);
                        TFT.locate(45, 212) ;
                        TFT.printf("rpm");
                        TFT.locate(10, 170) ;
                        TFT.printf("Cadence");
                        TFT.locate(207, 212) ;
                        TFT.printf("mph");
                        TFT.locate(125, 170) ;
                        TFT.printf("Speed");
                        TFT.set_font((unsigned char*) ArialR20x20);
                        //TFT.locate(10, 50) ;
                        //double waypoint = nav.CalculateDistance(MyGPS.buffer.latitude,MyGPS.buffer.longitude,plat,plon)/double(1609.344);
                        //TFT.printf("%.1fMI From Perry", waypoint);
                    } else {
                        TFT.locate(10, 40) ;
                        TFT.printf("No GPS Data     ");
                        //pc.printf("NMEA has no valid data");
                    }
                    break;
                }
                //This is screen two of bike computer. It is executed every 2 seconds. Ie...refresh_Time
                case PAGE2: {
                    if (!pageinit) {
                        UG_WindowHide(&window_1);
                        UG_WindowHide(&window_3);
                        UG_WindowShow(&window_2);
                        UG_Update();
                        TFT.drawXBitmap(20,35,compass,compass_width,compass_height,C_WHITE);
                    }
                    pageinit = 1;
                    // Need to fix this. Documentation states that this is bitwise status. 
                    if (imu.read_calib_status() > 0x0) {
                        imu.get_Euler_Angles(&euler_angles);
                        float angle = euler_angles.h; // Convert radians to degrees for more a more usual result

                        TFT.set_font((unsigned char*) ArialR20x20);
                        TFT.foreground(White);
                        TFT.background(UG_WindowGetBackColor(&window_1));
                        TFT.locate(10, 224) ;
                        TFT.printf("%.1f*", euler_angles.h);

                        // For the screen -X = up and +X = down and -Y = left and +Y = right, so does not follow coordinate conventions
                        float dx = (radius * cos((angle-90)*PI/180)) + centreX;  // calculate X position for the screen coordinates - can be confusing!
                        float dy = (radius * sin((angle-90)*PI/180)) + centreY;  // calculate Y position for the screen coordinates - can be confusing!
                        arrow(last_dx,last_dy, centreX, centreY, 2,2,UG_WindowGetBackColor(&window_2));      // Erase last arrow
                        arrow(dx,dy, centreX, centreY, 2, 2,C_WHITE);               // Draw arrow in new position
                        last_dx = dx;
                        last_dy = dy;
                    }


                    break;
                }
                 //This is screen three of bike computer. It is executed every 2 seconds. Ie...refresh_Time
                case PAGE3: {
                    if (!pageinit) {
                        UG_WindowHide(&window_1);
                        UG_WindowHide(&window_2);
                        UG_WindowShow(&window_3);
                        UG_Update();
                    }
                    pageinit = 1;
                    break;
                }
            }
        }
    
        /*  Add Nav back onto screen 3
            TFT.locate(140, 260) ;
        TFT.printf("%.1fft", MyGPS.buffer.altitude/0.3048);
            TFT.locate(4, 280) ;
            int degree;
            int minutes;
            int seconds;
            degree = (int)abs(MyGPS.buffer.longitude);
        minutes = (int) ( (abs(MyGPS.buffer.longitude) - (double)degree) * 60.0);
        seconds = (int) ( (abs(MyGPS.buffer.longitude) - (double)degree - (double)minutes / 60.0) * 60.0 * 60.0 );
        TFT.printf("%d %d' %d\" %c lon", degree, minutes,seconds, MyGPS.buffer.lonc);
            TFT.locate(4, 300) ;
            TFT.locate(4, 300) ;
        degree = (int)abs(MyGPS.buffer.latitude);
        minutes = (int) ( (abs(MyGPS.buffer.latitude) - (double)degree) * 60.0);
        seconds = (int) ( (abs(MyGPS.buffer.latitude) - (double)degree - (double)minutes / 60.0) * 60.0 * 60.0 );
        TFT.printf("%d %d' %d\" %c lat", degree, minutes,seconds, MyGPS.buffer.latc);



            //pc.printf("Dist to Perry %.4f ", nav.CalculateDistance(MyGPS.buffer.latitude,MyGPS.buffer.longitude,plat,plon));


        }


        if (imu.chip_ready() == 0){
        pc.printf("Bosch BNO055 is NOT avirable!!\r\n");
        } else {

        if (imu.read_calib_status() > 0x0){
            TFT.foreground(White);
            TFT.locate(4, 260) ;
            TFT.printf("No Data");
            TFT.foreground(Blue);
            imu.get_Euler_Angles(&euler_angles);
            TFT.locate(4, 260) ;
            TFT.printf("%.1f @ %.1f",euler_angles.h, euler_angles.p);
            //pc.printf("H %d",(int)euler_angles.h);
            //pc.printf("R %.1f",euler_angles.r);
            //pc.printf("P %.1f",euler_angles.p);

        } else {
                TFT.locate(4, 260) ;
                TFT.printf("No Data");
        }
        }




        }
        */
    }
}

void arrow(int x2, int y2, int x1, int y1, int alength, int awidth, int colour)
{
    float distance;
    int dx, dy, x2o, y2o, x3, y3, x4, y4, k;
    distance = sqrt(pow((double)(x1 - x2),2) + pow((double)(y1 - y2), 2));
    dx = x2 + (x1 - x2) * alength / distance;
    dy = y2 + (y1 - y2) * alength / distance;
    k = awidth / alength;
    x2o = x2 - dx;
    y2o = dy - y2;
    x3 = y2o * k + dx;
    y3 = x2o * k + dy;
    x4 = dx - y2o * k;
    y4 = dy - x2o * k;
    TFT.fillcircle(x3,y3,2,colour);
    TFT.set_font((unsigned char*) ArialR20x20);
}

void ili9341_pset(UG_S16 ul_x,UG_S16 ul_y, UG_COLOR ul_color)
{
    TFT.pixel(ul_x, ul_y, ul_color);
}

void window_1_callback( UG_MESSAGE* msg )
{
    if ( msg->type == MSG_TYPE_OBJECT ) {
        if ( msg->id == OBJ_TYPE_BUTTON ) {
            switch ( msg->sub_id ) {
                case BTN_ID_0: {
                    pageid--;
                    if (pageid < 1) {
                        pageid = 3;
                    }
                    pageinit = 0;
                    break;
                }
                case BTN_ID_1: {
                    pageid++;
                    if (pageid > 3) {
                        pageid = 1;
                    }
                    pageinit = 0;
                    break;
                }
            }
        }
    }
}

void window_2_callback( UG_MESSAGE* msg )
{
    if ( msg->type == MSG_TYPE_OBJECT ) {
        if ( msg->id == OBJ_TYPE_BUTTON ) {
            switch ( msg->sub_id ) {
                case BTN_ID_2: {
                    pageid--;
                    if (pageid < 1) {
                        pageid = 3;
                    }
                    pageinit = 0;
                    break;
                }
                case BTN_ID_3: {
                    pageid++;
                    if (pageid > 3) {
                        pageid = 1;
                    }
                    pageinit = 0;
                    break;
                }
            }
        }
    }
}

void window_3_callback( UG_MESSAGE* msg )
{
    if ( msg->type == MSG_TYPE_OBJECT ) {
        if ( msg->id == OBJ_TYPE_BUTTON ) {
            switch ( msg->sub_id ) {
                case BTN_ID_4: {
                    pageid--;
                    if (pageid < 1) {
                        pageid = 3;
                    }
                    pageinit = 0;
                    break;
                }
                case BTN_ID_5: {
                    pageid++;
                    if (pageid > 3) {
                        pageid = 1;
                    }
                    pageinit = 0;
                    break;
                }
            }
        }
    }
}

void cb1(void)
{
    point p;
    TSC.getTouch(p);
    // Only update uGui when screen has been released
    if (p.z >= __PRESURE) {
        ptouch.x = p.x;
        ptouch.y = p.y;
        ptouch.z = true;
    }    
    if (p.z < __NOPRESURE and ptouch.z) { 
        UG_TouchUpdate ( ptouch.x, ptouch.y, TOUCH_STATE_PRESSED ) ;
        ptouch.z = false;
    } else {
        UG_TouchUpdate (-1, -1, TOUCH_STATE_RELEASED ) ;
    }
    UG_Update();
}