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-02-17
Revision:
4:8d7759f4fe7a
Parent:
3:3e879b043bc5
Child:
5:ebf6fa994b78

File content as of revision 4:8d7759f4fe7a:

//To Do:
// USB device detec
#include "CANary.h"
// write and read the Mode Data
LocalFileSystem local("local"); // test the local file system to write files

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

extern "C" void mbed_reset();

time_t seconds ;
Beep buzzer(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 uses pins 9 and 10 (rx, tx) and pin 27 (rs)
DigitalOut can1_SleepMode(p8);     // Use pin 8 to control the sleep mode of can1
CAN can2(p30, p29);     // CAN2 uses pins 30 and 29 (rx, tx) and pin 28 (rs)
DigitalOut can2_SleepMode(p28);     // Use pin 28 to control the sleep mode of can2
bool logOpen = false;
FILE *rfile;
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
char ii = 0; // indexindex
char c;
volatile int writePointer = 0;
volatile int secsNoMsg = 0, secsNoTouch = 0;
volatile bool canIdle = false, userIdle = false;
point lastTouch;
char counter = 0;
int dMode[2] = {1,6}; //display mode
int sMode = 0; // setup mode
int lastDMode[2]; //last screen mode
int lastSMode = 0;
char displayLog[19][40];
int displayLoc = 0;

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

extern "C" void RTC_IRQHandler() {
    timer.reset(); // zero ms at the-seconds-tic
    canIdle=(++secsNoMsg>canTimeout);
    userIdle=(++secsNoTouch>userTimeout);
    LPC_RTC->ILR |= (1<<0); // clear interrupt to prepare for next
}

extern "C" void RTC_Init (void) {
    LPC_RTC->ILR=0x00; // set up the RTC interrupts
    LPC_RTC->CIIR=0x01; // interrupts each second
    LPC_RTC->CCR = 0x01;  // Clock enable
    //NVIC_SetPriority( RTC_IRQn, 10 );
    NVIC_EnableIRQ( RTC_IRQn );
}

unsigned short getTimeStamp() {
    int msec = timer.read_ms() ; // read ms from the timer
    unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
    int isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
    return ((isecs<<10)+msec) ; // return the two byte time stamp
}

void printLast (){
    int i;
    CANMessage msg;
    tt.locate(0,6);
    tt.foreground(Red);
    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
    for(i=0; i<19; i++){
        msg = lastMsg[i+1];
        printf("%03x : %02x %02x %02x %02x %02x %02x %02x %02x    \n",msg.id,msg.data[0],msg.data[1],msg.data[2],msg.data[3],msg.data[4],msg.data[5],msg.data[6],msg.data[7]);
    }
}

void printLog (){
    int i;
    tt.locate(0,6);
    tt.foreground(Amber);
    tt.cls();
    for(i=0; i<19; i++){
        printf("%s",displayLog[displayLoc]);
        displayLoc=displayLoc>17?0:displayLoc+1;
    }
}

void logMsg (char *msg) {
    strcpy(displayLog[displayLoc],msg);
    displayLoc=displayLoc>17?0:displayLoc+1;
}

void logCan (char mtype, CANMessage canRXmsg) {
    unsigned short ts = getTimeStamp();
    unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
    if(canRXmsg.id>0) {
        writeBuffer[writePointer][0]=mtype;
        writeBuffer[writePointer][1]=((secs%60)<<2)+((ts&0x300)>>8);
        writeBuffer[writePointer][2]=ts&0xff;
        writeBuffer[writePointer][3]=canRXmsg.id&0xff;
        writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4);
        for (int i = 5; i<13; i++){
            writeBuffer[writePointer][i]=canRXmsg.data[i-5];
        }
        if (++writePointer >= maxBufLen) {
            writePointer = 0;
            led4 = !led4;
        }
        if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
            indexLastMsg[canRXmsg.id]=++ii; //Create entry if first message
            if(ii>99) {
                ii=0;
            }
        }
        lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
    }
}

void logTS () {
    CANMessage tsMsg;
    unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
    tsMsg.id=0xfff;
    tsMsg.len=0xf;
    tsMsg.data[0]=secs&0xff;
    tsMsg.data[1]=(secs>>8)&0xff;
    tsMsg.data[2]=(secs>>16)&0xff;
    tsMsg.data[3]=secs>>24;
    tsMsg.data[4]=0xff;
    tsMsg.data[5]=0xff;
    tsMsg.data[6]=0xff;
    tsMsg.data[7]=0xff;
    logCan(0,tsMsg);
}

void send1() {
    static char counter = 0; // use for fake data

    can1.write(CANMessage(0x350, &counter, 1));
    counter++;
    // test sending 3 quickly
    //can1.write(CANMessage(0x351, &counter, 1));
    //can1.write(CANMessage(0x352, &counter, 1));
    printf("Sending message %d   \n",counter);

}


void recieve1() {
    CANMessage msg1;
    secsNoMsg=0; // reset deadman switch
    can1.read(msg1);
    //printf("Can1 rxd: %d\n", msg1.data[0]);
    if(logOpen)
        logCan(2, msg1);
    led1 = !led1;
}

void recieve2() {
    CANMessage msg2;
    secsNoMsg=0; // reset deadman switch
    can2.read(msg2);
    //printf("Can2 rxd: %d\n", msg2.data[0]);
    if(logOpen)
        logCan(1, msg2);
    led2 = !led2;
}

void touched(){
    LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
    lastTouch = tt.get_touch();       
    lastTouch = tt.to_pixel(lastTouch);          // convert to pixel pos
    //printf("X=%d Y=%d\n",lastTouch.x,lastTouch.y);
    /*if (lastTouch.x > tt.width()){
        tt.set_display(1);
        tt.fillcircle(lastTouch.x-tt.width(),lastTouch.y,10,Blue);
    }else{
        tt.set_display(0);
        tt.fillcircle(lastTouch.x,lastTouch.y,10,Blue);
    }*/
    secsNoTouch = 0;
}

void updateDisplay(){
    static int lastDisplayLoc = 0;
    for (int i=0; i<2; i++){
        tt.set_display(i);
        switch (dMode[i]) {
            case logMode:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)||(lastDisplayLoc!=displayLoc)){
                    printLog();
                    lastDisplayLoc=displayLoc;
                }
                break;
            case dteMode:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                tt.fillrect(10,10,300,50,Blue);
               break;
            case brakeMode:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                tt.fillcircle(100,100,15,Red);
                break;
            case powerMode:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                tt.fillrect(10,10,300,50,Green);
                break;
            case controlMode:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                tt.fillcircle(100,100,15,Orange);
                break;
            case monitorMode:
                tt.background(Yellow);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                printLast();
                break;
            default:
                tt.background(Black);
                if(dMode[i]!=lastDMode[i]||(lastSMode>0&&sMode==0)) tt.cls();
                break;
        }
        lastDMode[i]=dMode[i];
    } // for (i=0; i<1; i++)

    switch (sMode) {
        case 1:
            tt.set_display(2); // select both displays
            tt.foreground(Yellow);
            tt.background(DarkCyan);
            tt.set_font((unsigned char*) Arial12x12);
            tt.fillrect(btn31x1,btn11y1,btn31x2,btn11y2,DarkCyan);
            tt.locate(btn31x1+5,btn11y1+5);
            printf("<-Prev\n");
            tt.fillrect(btn32x1,btn11y1,btn32x2,btn11y2,DarkCyan);
            tt.fillrect(btn33x1,btn11y1,btn33x2,btn11y2,DarkCyan);
            tt.locate(btn33x2-50,btn11y1+5);
            printf("Next->\n");
            tt.set_display(0);
            tt.locate(btn32x1+15,btn11y1+5);
            printf("Select %d\n",dMode[0]);
            tt.set_display(1);
            tt.locate(btn32x1+15,btn11y1+5);
            printf("Select %d\n",dMode[1]);
            tt.background(Black);
            break;
        default:
            break;
    }
    lastSMode=sMode;
}

int main() {
    int readPointer=0;
    int fmon;
    int fday;
    int ftime;
    char sTemp[40];
    unsigned long secs;
    bool bit = false;
    int i,j;
    
    can1.frequency(500000);
    can2.frequency(500000);
    //can1_SleepMode = 0;         // Enable TX
    //can2_SleepMode = 0;         // Enable TX
    can1_SleepMode = 1;         // Turn on Monitor_only Mode
    can2_SleepMode = 1;         // Turn on Monitor_only Mode
    //ticker.attach(&send1, 0.5);
    ticker.attach(&updateDisplay, 0.25); // Display messages
    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
    tt.calibrate();           // calibrate the touch
    tt.claim(stdout);        // send stdout to the TFT display
    touchpad.rise(&touched);
    tt.wfi();               // enable interrupt on touch
    dled = 1; // 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

    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
    }
    while (true) {
        if (!logOpen) { // Open new file if one is not already open
            seconds = time(NULL);
            t = *localtime(&seconds) ;
            strftime(fileName, 32, "/fs/%m%d%H%M.alc", &t); //mmddhhmm.alc

            tt.set_display(0);     // select left display
            tt.locate(0,0);
            tt.foreground(Cyan);    // set chars to Cyan
            //printf("Using file %s\n",fileName);
            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);
            } else {
                logOpen = true;
                readPointer=writePointer;
                sprintf(sTemp,"Starting Can Log %s\n",fileName);
                logMsg(sTemp);
                logTS();
                fclose(file);
                file = fopen("/fs/loglog.txt", "a");
                fprintf(file,"%s\r\n",fileName);
                fclose(file);
            }
        } else { // if (!logOpen)
            if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/2)||canIdle) {
                // Dump buffer if > 1/2 full, canbus has stopped, or PB1 pressed
                if (logOpen) {
                    file = fopen(fileName, "ab");
                    if (file == NULL) {
                        logOpen = false;
                        sprintf(sTemp,"Failed to append log file.\n\n");
                        logMsg(sTemp);
                    } else {
                        while (readPointer != writePointer) {
                            for (j = 0; j<13; j++){
                                fprintf(file,"%c",writeBuffer[readPointer][j]);
                            }
                            if(++readPointer >= maxBufLen)
                                readPointer=0;
                        }
                        led3 = !led3;
                        fclose(file);
                    }
                } // if (logOpen)
            } // if > 1/2 full, canbus has stopped, or PB1 pressed
        } // if logOpen
        if (canIdle&&userIdle) { // canbus idle --> sleep to save power
            if (logOpen){
                // First take advantage of the idle time to clear some room
                bit = false;
                rfile = fopen("/fs/loglog.txt", "r");
                file = fopen("/fs/loglog.new", "w");
                while (!feof(rfile)) {
                    fscanf(rfile,"/fs/%2d%2d%4d.alc\r\n",&fmon,&fday,&ftime);
                    //if ((fmon<t.tm_mon)&&(fday<=t.tm_mday)){ // Delete all files more than 1 month old
                    if ((fmon < 12) || (t.tm_mon > 1)){
                        fday = fday + fmon*31; //crude - february will store 3 extra days of data
                    }
                    if ((fday+14)<(t.tm_mday+t.tm_mon*31)){ // Delete all files more than ~14 days old
                        bit=true;
                        sprintf(sTemp,"/fs/%02d%02d%04d.alc",fmon,fday,ftime);
                        if ((remove(sTemp)==NULL)) {
                            sprintf(sTemp,"Removed file %s\n",sTemp);
                            logMsg(sTemp);
                        }
                    }else{
                        fprintf(file,"/fs/%02d%02d%04d.alc\r\n",fmon,fday,ftime);
                    }
                }
                fclose (file);
                fclose (rfile);
                if (bit) {
                    remove ("/fs/loglog.txt");
                    //rename not working so do it the hard way
                    //rename ("/fs/loglog.new","/fs/loglog.txt");
                    rfile = fopen("/fs/loglog.new", "r");
                    file = fopen("/fs/loglog.txt", "w");
                    while (!feof(rfile)) {
                        fscanf(rfile,"%s\r\n",&sTemp);
                        fprintf(file,"%s\r\n",sTemp);
                    }
                    fclose (file);
                    fclose (rfile);
                }
                remove ("/fs/loglog.new");                    
                wait(5); // wait a few seconds to ensure fsRAM is done
            } // 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 touchpad input
                //__wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
                Sleep();
                //DeepPowerDown();
            }
            canIdle=secsNoMsg>canTimeout;
            userIdle=userIdle>userTimeout;
            dled=1; // 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 { // insert timestamp on each wake
                logTS();
            }
            //LPC_RTC->CIIR=0x01; // re-enable RTC interrupts
        } // if idle
        
        if (!userIdle) {
            if (secsNoTouch<2) {// Recently touched
                secsNoTouch +=2; // increment to prevent double touch
                sMode=1;
                if (lastTouch.x>320){
                    i=1;
                    lastTouch.x-=320;
                } else {
                    i=0;
                }
                if (lastTouch.y>btn11y1 && lastTouch.y<btn11y2){
                    if (lastTouch.x>btn31x1 && lastTouch.x<btn31x2) {
                        dMode[i]=dMode[i]>0?dMode[i]-1:maxModes;
                    } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
                        dMode[i]=dMode[i]<maxModes?dMode[i]+1:0;
                    }
                } else {
                    sprintf(sTemp,"missed button\n");
                    logMsg(sTemp);
                }
            }
        } else { // userIdle
            sMode=0;
        }
        
        wait(0.1); // We get >2K messages per second
    } //while (true)
}