Works

Dependencies:   BMP180 BNO055_fusion Fonts GPSISR HTU21D SDFileSystem UniGraphic mbed uGUI

Fork of Bicycl_Computer_NUCLEO-F411RE by Darren Ulrich

main.cpp

Committer:
trevieze
Date:
16 months ago
Revision:
16:e81bd672196b
Parent:
15:b174ec6e3ca0

File content as of revision 16:e81bd672196b:

/* 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"
//#include "TFT.h"
// Graphics GUI Library
#include    "ugui.h"

#include "SeeedStudioTFTv2.h"
#include "BNO055.h"
#include "HTU21D.h"
#include "BMP180.h"
#include "SDFileSystem.h"
#include "GPSISR.h"
#include "nav.h"


#include "ArialR16x17.h"
#include "Arial24x23i.h"
#include "Arial28x28.h"
#include "Neu44x36.h"
#include "SCProSB31x55.h"
#include "Arial12x12.h"
#include "ArialR20x20.h"

//#define PIN_CS_TSC      PA_9 
//#define PIN_TSC_INTR    PA_8
#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 1 MOSI
#define PIN_MISO_SPI3   PB_14 //SPI 1 MISO
#define PIN_SCLK_SPI3   PB_13 //SPI 1 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

#define PI                  3.14159265358979f
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;

#define DEVICE_NAME     "F411RE"

#ifndef TARGET_NECLEO_F411RE
#define TARGET_NECLEO_F411RE 
#endif

//DigitalOut backlight(PB_3) ;
// DigitalOut tsc_cs(PA_9, 1) ;
// DigitalOut tft_cs(PB_6, 1) ;

/** 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 TOUCH(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);

// SD Card Reader On Adafruit GPS Shield
SDFileSystem sd(PIN_MOSI_SPI3, PIN_MISO_SPI3, PIN_SCLK_SPI3, PIN_CS_SPI3, "sd"); // the pinout on the mbed Cool Components workshop board

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

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

void Draw_Compass_Rose(void);
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);

const int centreX = 120;
const int centreY = 150;
const int radius  = 40; 
float last_dx;
float last_dy;

int pageid = 1;
bool pageinit = 0;
#define PAGE1       1
#define PAGE2       2
#define PAGE3       3

UG_GUI   gui;

//Ticker to1;

int main()
{
        //to1.attach(&cb1, 2.0);
    TFT.BusEnable(true) ;
    TFT.FastWindow(true) ;
    wait(0.1);
    TFT.cls();
    wait(0.1);
        
        UG_Init(&gui,ili9341_pset,ILI9341_DEFAULT_HEIGHT,ILI9341_DEFAULT_WIDTH);
    
    Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info?
    const int refresh_Time = 2000; //refresh time in ms
    refresh_Timer.start();  //starts the clock on the timer
    //backlight = 0 ;
    wait(0.1);
     
  // Draw_Compass_Rose(); 
    /* 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" );
    
        /* Finally , show the window */
    //UG_WindowShow(&window_1) ;
    //UG_WindowHide(&window_2);
    //UG_WindowHide(&window_3);
    
    //UG_Update();

    while (1) { 
            
            cb1();
             
                TFT.set_font((unsigned char*) ArialR20x20);
                TFT.foreground(White);
                TFT.background(UG_WindowGetBackColor(&window_1));
                //check if we recieved a new message from GPS, if so, attempt to parse it,
        if (refresh_Timer.read_ms() >= refresh_Time) {
            refresh_Timer.reset();
            
                        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.locate(10, 50) ;
                                        TFT.printf("%.1fF", ((temp* 9.0) / 5.0 + 32));
                                }
                                int ftemp = humid.sample_ftemp();
                                int humidity = humid.sample_humid();
                                TFT.locate(10, 72) ;
                                TFT.printf("%d%%RH",humidity);
                                if (MyGPS.dataready()) {
                                    MyGPS.read();
                                    TFT.locate(10, 26) ;
                                    TFT.foreground(UG_WindowGetBackColor(&window_1));
                                    TFT.printf("No GPS Data");
                                    TFT.foreground(White);
                                    TFT.locate(10, 26) ;
                                    TFT.printf("%d:%d:%d", MyGPS.buffer.hours, MyGPS.buffer.minutes, MyGPS.buffer.seconds);
                                    TFT.locate(100, 26) ;
                                    TFT.printf("%d-%d-%d", MyGPS.buffer.month, MyGPS.buffer.day, MyGPS.buffer.year);
                                    TFT.set_font((unsigned char*) SCProSB31x55);    
                                    TFT.locate(130, 180) ;
                                    TFT.printf("%.1f", MyGPS.buffer.speed);
                                    TFT.locate(10, 180) ;
                                    TFT.printf("%.1f", MyGPS.buffer.speed); //Cadence
                                    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, 26) ;
                                    TFT.printf("No GPS Data");
                                    //pc.printf("NMEA has no valid data");
                                } 
                                break;
                            }
                            case PAGE2: 
                                {
                                    if (!pageinit) {
                                        UG_WindowHide(&window_1);
                                        UG_WindowHide(&window_3);
                                        UG_WindowShow(&window_2);
                                        UG_Update();
                                    }
                                    pageinit = 1;
                                    break;
                                }
                                case PAGE3: 
                                {
                                    if (!pageinit) {
                                        UG_WindowHide(&window_1);
                                        UG_WindowHide(&window_2);
                                        UG_WindowShow(&window_3);
                                        UG_Update();
                                    }
                                    pageinit = 1;
                                    break;
                                }   
                        }   
                }       
                            /*
                                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");
                            }
                        }
                    
                         float angle = euler_angles.h; // Convert radians to degrees for more a more usual result
                         // 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,White);      // Erase last arrow      
             arrow(dx,dy, centreX, centreY, 2, 2,Blue);               // Draw arrow in new position
             last_dx = dx; 
             last_dy = dy;
                                                
            
        }
        */              
    }  
}

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.line(x1, y1, x2, y2, colour);
  TFT.line(x1, y1, dx, dy, colour);
  TFT.line(x3, y3, x4, y4, colour);
  TFT.line(x3, y3, x2, y2, colour);
  TFT.line(x2, y2, x4, y4, colour);
    TFT.set_font((unsigned char*) Arial12x12);
  TFT.foreground(Blue);
  TFT.background(White);
    TFT.locate((centreX-2),(centreY-24));
  TFT.printf("N");
  TFT.locate((centreX-2),(centreY+17));
  TFT.printf("S");
  TFT.locate((centreX+19),(centreY-3));
  TFT.printf("E");
  TFT.locate((centreX-23),(centreY-3));
  TFT.printf("W");
    TFT.set_font((unsigned char*) ArialR20x20);
} 

void Draw_Compass_Rose(void) {
  int dxo, dyo, dxi, dyi;
  TFT.circle(centreX,centreY,radius,Blue);  // Draw compass circle
  for (float i = 0; i <360; i = i + 22.5) {
    dxo = radius * cos(i*3.14/180);
    dyo = radius * sin(i*3.14/180);
    dxi = dxo * 0.95;
    dyi = dyo * 0.95;
    TFT.line(dxi+centreX,dyi+centreY,dxo+centreX,dyo+centreY,Blue);   
  }
    TFT.set_font((unsigned char*) Arial12x12);
  TFT.foreground(Blue);
  TFT.background(White);
    TFT.locate((centreX-2),(centreY-24));
  TFT.printf("N");
  TFT.locate((centreX-2),(centreY+17));
  TFT.printf("S");
  TFT.locate((centreX+19),(centreY-3));
  TFT.printf("E");
  TFT.locate((centreX-23),(centreY-3));
  TFT.printf("W");
}

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;
    TOUCH.getTouch(p);
        if (p.z > __PRESURE)
        {
            UG_TouchUpdate ( p.x, p.y, TOUCH_STATE_PRESSED ) ;
        }
        else
        {
            UG_TouchUpdate (-1, -1, TOUCH_STATE_RELEASED ) ;
        }
    UG_Update();
}