Dual CANbus monitor and instrumentation cluster supporting ILI9341 display controller

Dependencies:   SPI_TFTx2_ILI9341 TOUCH_TFTx2_ILI9341 TFT_fonts mbed

Fork of CANary by Tick Tock

main.cpp

Committer:
TickTock
Date:
2013-03-04
Revision:
17:e32324a2678d
Parent:
16:2a6ca248e1cb
Child:
18:999401f359a5

File content as of revision 17:e32324a2678d:

// main.cpp

//To Do:
// * USB device detect
// * user programmable message decode
// * brake trainer
// * write and read the Mode Data
// * Date entry config screen (keypad)
// * auto-poll option for cellpair data
// * cellpair histogram
// * config screen (with ts cal, data, time, autopoll, enable/disable logging

#include "mbed.h"
#include "CAN.h"
#include "beep.h"
#include "MSCFileSystem.h"
#include "PowerControl.h"
#include "EthernetPowerControl.h"
#include "utility.h"
#include "displayModes.h"

LocalFileSystem local("local");

// to write to USB Flash Drives, or equivalent (SD card in Reader/Writer)
MSCFileSystem fs("fs"); // to write to a USB Flash Drive

time_t seconds ;
Beep spkr(p21);

Ticker ticker;
Timer timer;

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

PwmOut dled(p24);

InterruptIn touchpad(p17);
CAN can1(p9, p10);      // CAN1 (EV) uses pins 9 and 10 (rx, tx) and pin 8 (rs)
DigitalOut can1SleepMode(p8);     // Use pin 8 to control the sleep mode of can2
CAN can2(p30, p29);     // CAN2 (CAR) uses pins 30 and 29 (rx, tx) and pin 28 (rs)
DigitalOut can2SleepMode(p28);     // Use pin 28 to control the sleep mode of can1

TOUCH_TFTx2 tt(p16, p17, p19, p20, p11, p12, p13, p6, p7, p5, "TFT"); // x+,x-,y+,y-,mosi, miso, sclk, cs0, cs1, reset

bool logEn = true,logOpen = false;
FILE *cfile;
FILE *file;
char fileName[35] = "" ;
char writeBuffer[maxBufLen][13]; // buffer for USB write
char indexLastMsg[0x800]={0}; // index table for last message
CANMessage lastMsg[100]; // table to store last message of eachtype
unsigned char battData[256]={0};
unsigned char msgChanged[100]; // inidcates which bytes changed
char c;
volatile int writePointer = 0;
volatile int secsNoMsg = 0, secsNoTouch = 0;
volatile bool canIdle = false, userIdle = false;
bool touched=0; //flag to read touchscreen
char counter = 0;
unsigned char dMode[2] = {1,2}; //display mode
unsigned char sMode = 0; // setup mode
unsigned char lastDMode[2] = {0,0}; //last screen mode
char displayLog[20][40];
unsigned char displayLoc = 0;
unsigned char indexOffset = 1;
bool showCP = false;
bool pollCP = false;

int main() {
    int readPointer=0;
    char sTemp[40];
    unsigned long secs;
    char i,j,display=0;
    point lastTouch;    

    can1.monitor(true); // set to snoop mode
    can2.monitor(true); // set to snoop mode
    can1.frequency(500000);
    can2.frequency(500000);
    can1SleepMode = 1;         // Turn on Monitor_only Mode
    can2SleepMode = 1;         // Turn on Monitor_only Mode
    can1.attach(&recieve1);
    can2.attach(&recieve2);
    
    tt.set_orientation(1);
    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
    tt.set_display(2);     // select right display
    tt.background(Black);
    tt.cls();
    tt.set_display(0);       // select left display
    //if(true){ // bypass calibration
    //    tt.setcal(5570, 34030, 80, 108, 33700, 5780, 82, 108, 32500);
    //} else {  // calibrate the touch
    //    tt.calibrate();   
    //}
    tt.claim(stdout);        // send stdout to the TFT display
    touchpad.rise(&touch_ISR);
    tt.wfi();               // enable interrupt on touch
    dled = 0.8; // turn on display LED 80%
    timer.start() ;
    RTC_Init(); // start the RTC Interrupts that sync the timer
    struct tm t; // pointer to a static tm structure
    //NVIC_SetPriority(TIMER3_IRQn, 1); //set ticker priority
    //NVIC_SetPriority(CAN_IRQn, 2); //higher than can (so RTC sync works)
    seconds = time(NULL);
    t = *localtime(&seconds) ;
    strftime(sTemp, 32, "%a %m/%d/%Y %X", &t);
    //tt.locate(0,0);
    //printf("\nCurrent time : %s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS

    // is it a date before 2012 ?
    if ((t.tm_year + 1900) < 2012 ) {
        // before 2012, so the RTC probably lost power
        // So, set a near-recent date in 2012

        // enter people-values here
        t.tm_year = 2013 ; // 28 May 2012
        t.tm_mon = 3 ; // 1 to 12
        t.tm_mday = 5;
        t.tm_hour = 12; // 12:59:56 PM (after noon)
        t.tm_min = 59;
        t.tm_sec = 56;

        // adjust for tm structure required values
        t.tm_year = t.tm_year - 1900;
        t.tm_mon = t.tm_mon - 1;

        // set the RTC
        set_time(mktime(&t));
        seconds = time(NULL);

        //    printf("Set RTC to:\n" );
        //    strftime(sTemp, 32, "%a %m/%d/%Y %X", localtime(&seconds));
        //    printf("%s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS
    }

    // Look for new binary 
    // Can't make this work right now since USB doesn't attach the right timestamp (so new binary isn't loaded)
    cfile = fopen("/fs/CANary.bin", "rb");
    if (cfile!=NULL){ //found a new binary on the thumbdrive so copy it over
        sprintf(sTemp,"New binary found.\n");
        logMsg(sTemp);
        file = fopen("/local/CANary.bin", "wb");
        if (file==NULL){ //failed to open destination
            sprintf(sTemp,"Unable to open destination file.\n");
            logMsg(sTemp);
        } else {
            while ( int size = fread( writeBuffer, sizeof(char), maxBufLen*13, cfile )){
                fwrite( writeBuffer, sizeof(char), size, file );
            }
        fclose(cfile);
        fclose(file);
        remove("/fs/CANary.bin"); // delete original
        mbed_reset(); //restart
        }
    } else {
        sprintf(sTemp,"No binary found.\n");
        logMsg(sTemp);
    }

    // Look for config file
    cfile = fopen("/local/config.txt", "r");
    if (cfile==NULL){ // if doesn't exist --> create
        sprintf(sTemp,"No config file found.\n");
        logMsg(sTemp);
        sprintf(sTemp,"Calibrating touch screen.\n");
        logMsg(sTemp);
        tt.calibrate();
        cfile = fopen("/local/config.txt", "w");
        fprintf(cfile,"x0_off %d\r\n",tt.x0_off);
        fprintf(cfile,"y0_off %d\r\n",tt.y0_off);
        fprintf(cfile,"x0_pp %d\r\n",tt.x0_pp);
        fprintf(cfile,"y0_pp %d\r\n",tt.y0_pp);
        fprintf(cfile,"x1_off %d\r\n",tt.x1_off);
        fprintf(cfile,"y1_off %d\r\n",tt.y1_off);
        fprintf(cfile,"x1_pp %d\r\n",tt.x1_pp);
        fprintf(cfile,"y1_pp %d\r\n",tt.y1_pp);
        fprintf(cfile,"x_mid %d\r\n",tt.x_mid);
    } else { // read params
       sprintf(sTemp,"Reading config file.\n");
       logMsg(sTemp);
       fscanf(cfile, "x0_off %d\r\n", &tt.x0_off ) ;
       fscanf(cfile, "y0_off %d\r\n", &tt.y0_off ) ;
       fscanf(cfile, "x0_pp %d\r\n", &tt.x0_pp ) ;
       fscanf(cfile, "y0_pp %d\r\n", &tt.y0_pp ) ;
       fscanf(cfile, "x1_off %d\r\n", &tt.x1_off ) ;
       fscanf(cfile, "y1_off %d\r\n", &tt.y1_off ) ;
       fscanf(cfile, "x1_pp %d\r\n", &tt.x1_pp ) ;
       fscanf(cfile, "y1_pp %d\r\n", &tt.y1_pp ) ;
       fscanf(cfile, "x_mid %d\r\n", &tt.x_mid ) ;
    }
    fclose(cfile);    

    //ticker.attach(&tickerISR, 60);  //poll cellpair data every minute
    while (true) {
        if (!logOpen) { // Open new file if one is not already open
            if(logEn){ //logging enable
                seconds = time(NULL);
                t = *localtime(&seconds) ;
                strftime(fileName, 32, "/fs/%m%d%H%M.alc", &t); //mmddhhmm.alc
                //sprintf(sTemp,"Using file %s\n",fileName);
                //logMsg(sTemp);
                file = fopen(fileName, "ab");
                
                if(file==NULL){
                    sprintf(sTemp,"\nUnable to open %s\n\n\n\n",fileName);
                    logMsg(sTemp);
                    logEn=false;
                    spkr.beep(1000,0.2);
                } else {
                    logOpen = true;
                    readPointer=writePointer;
                    sprintf(sTemp,"Starting Can Log %s\n",fileName);
                    logMsg(sTemp);
                    logTS();
                    spkr.beep(2000,0.2);
                }
            }//logging enabled
        } else { // if (logOpen)
            if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/16)||canIdle) {
                // Dump buffer if > 1/16 full or canbus has stopped
                if (file == NULL) {
                    logOpen = false;
                    sprintf(sTemp,"Failed to append log file.\n\n");
                    spkr.beep(1000,0.2);
                    logMsg(sTemp);
                    logEn=false;
                } else {
                    while (readPointer != writePointer) {
                        for (j = 0; j<13; j++){
                            fprintf(file,"%c",writeBuffer[readPointer][j]);
                        }
                        if(++readPointer >= maxBufLen)
                            readPointer=0;
                    }
                    led4 = !led4;
                }
            } // if > 1/16 full, canbus has stopped, or PB1 pressed
        } // if logOpen
        if (canIdle&&userIdle) { // canbus idle --> sleep to save power
            if (logOpen){
                fclose(file);
            } // if (logOpen)*/
            sprintf(sTemp,"Putting uC to sleep.\n");
            logMsg(sTemp);
            //LPC_RTC->CIIR=0x00; // block RTC interrupts
            led1=0;
            led2=0;
            led3=0;
            led4=0;
            dled=0; // turn off display
            secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
            while (secsNoMsg>canTimeout && secsNoTouch>userTimeout) {
                //DeepPowerDown();
                tt.wfi(); //enable touch interrupt
                __wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
                //Sleep();
                //DeepPowerDown();
            }
            canIdle=secsNoMsg>canTimeout;
            userIdle=userIdle>userTimeout;
            dled=0.8; // turn on display LED
            sprintf(sTemp,"Waking uC.\n");
            logMsg(sTemp);
            if (time(NULL)>(secs+1800)) {
                logOpen = false; // Start new file if asleep for more than 30 minutes
                if (secsNoTouch>100) secsNoTouch = 100; // also mostly reset user Idle counter
            } else if (false){ // insert timestamp on each wake if logging enabled (disabled for now)
                file = fopen(fileName, "ab");
                logTS();
            }
        } // if idle
        
        if(touched){ // call touchscreen procedure if touch interrupt detected
            lastTouch = tt.get_touch();       
            lastTouch = tt.to_pixel(lastTouch);          // convert to pixel pos
            touched = false; // clear interrupt flag
        }

        if (!userIdle) {
            if (secsNoTouch<2) {// Recently touched
                secsNoTouch +=2; // increment to prevent double touch
                if (lastTouch.x>320){
                    i=1;
                    lastTouch.x-=320;
                } else {
                    i=0;
                }
                if (lastTouch.y>btn11y1 && lastTouch.y<btn11y2) {
                    if(sMode==1){
                        if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
                            dMode[i]=dMode[i]>0?dMode[i]-1:maxScreens;
                        } else if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2) {
                            secsNoTouch = userTimeout; // immediately exit config mode
                        } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
                            dMode[i]=dMode[i]<maxScreens?dMode[i]+1:0;
                        }
                    } else sMode=1;
                } else {
                    if (dMode[i]==monitorScreen||dMode[i]==changedScreen) {
                        if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
                            indexOffset=indexOffset>4?indexOffset-4:1;
                        } else if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2) {
                            for(j=0;j<100;j++) msgChanged[j]=0; // clear changed data
                            lastDMode[i]=99;//force refresh
                        } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
                            indexOffset=indexOffset<77?indexOffset+4:80;
                        }
                    } else if (dMode[i]==cpScreen) {
                        if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2){
                            pollCP=true;
                        }
                    }
                } //top of screen
            }
        } else { // userIdle
            if(sMode==1){
                sMode=0;
                lastDMode[0]=99;
                lastDMode[1]=99;
            }
        }

        if(pollCP){ // We do this inside main loop instead of ticker so CAN RX will not be blocked
            sendCPreq(); // send cellpair data request.
            wait_ms(16);
            sendTreq(); //send temperature request
            wait_ms(16);
            pollCP=false;
            showCP=true;
        }

        display=display<1?display+1:0; // toggle display
        updateDisplay(display);
    } //while (true)
}