Dual CANbus monitor and instrumentation cluster

Dependencies:   SPI_TFTx2 TFT_fonts TOUCH_TFTx2 beep mbed

Fork of CANary by Tick Tock

Files at this revision

API Documentation at this revision

Comitter:
TickTock
Date:
Sun Mar 03 15:50:54 2013 +0000
Parent:
11:e9d155aad4e2
Child:
13:62e0f7f39ff5
Commit message:
Repartitioned display and utility functions

Changed in this revision

CANary.h Show diff for this revision Revisions of this file
TFT_fonts.lib Show annotated file Show diff for this revision Revisions of this file
TOUCH_TFTx2.lib Show annotated file Show diff for this revision Revisions of this file
displayModes.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
utility.h Show annotated file Show diff for this revision Revisions of this file
--- a/CANary.h	Wed Feb 27 03:47:06 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-//CANary
-
-#include "mbed.h"
-#include "CAN.h"
-#include "beep.h"
-#include "MSCFileSystem.h"
-#include "SPI_TFTx2.h"
-#include "Arial12x12.h"
-#include "Arial12x12_prop.h"
-#include "Arial28x28.h"
-#include "Neu42x35.h"
-#include "SCProSB31x55.h"
-#include "TOUCH_TFTx2.h"
-#include "PowerControl.h"
-#include "EthernetPowerControl.h"
-#define upLine "\033[1A"
-#define maxBufLen 768
-#define canTimeout 500
-#define userTimeout 10
-#define maxModes 7
-#define offMode 0
-#define logMode 1
-#define dteMode 2
-#define brakeMode 3
-#define powerMode 4
-#define monitorMode 5
-#define changedMode 6
-#define cpMode 7
-#define btn31x1 12
-#define btn31x2 101
-#define btn32x1 115
-#define btn32x2 204
-#define btn33x1 218
-#define btn33x2 307
-#define btn11y1 180
-#define btn11y2 229
-
-//LEAF OBD
-//1:
-//2:
-//3:    AVCAN-L     White/Blue
-//4:    VSS-Shield
-//5:    VSS         Brown,White/Brown
-//6:    CARCAN-H    Green
-//7:
-//8:    12V-SW      Orange,White/Orange
-//9:
-//10:
-//11:   AVCAN-H     Blue
-//12:   EVCAN-L     White/Grey
-//13:   EVCAN-H     Grey
-//14:   CARCAN-L    White/Green
-//15:
-//16:   12V-AON     Red/Blue,Blue/Red
-
-//VP230
-//1:D   
-//2:GND 
-//3:VCC 
-//4:R   
-//5:Vref
-//6:CANL
-//7:CANH
-//8:RS
-
-//LPC1768
-//1:    VSS
-//2:        NC:VIN  (4.5-9V supply)
-//3:        NC:VB
-//4:        NC:nR
-//5:    SPI:CS0
-//6:    SPI:CS1
-//7:    SPI:Reset
-//8:    CAN1:Sleep -->  8:CAN1:RS
-//9:    CAN1:RX    -->  4:CAN1:R
-//10:   CAN1:TX    -->  1:CAN1:D
-//11:   SPI:MOSI
-//12:   SPI:MISO
-//13:   SPI:SCLK
-//14:       NC:Ain
-//15:   MON12V     -->  4K to 12V, 1K to VSS  (To be implemented)
-//16:   TOUCH_X+
-//17:   TOUCH_X-
-//18:       NC:Aout
-//19:   TOUCH_Y+
-//20:   TOUCH_Y-
-//21:   Spkr+
-//22:   Spkr-           (optional complimentary output for more volume)
-//23:       NC:pwm
-//24:       LED
-//25:       NC:pwm
-//26:       NC:pwm
-//27:       NC
-//28:   CAN2:Sleep -->  8:CAN2:RS
-//29:   CAN2:TX    -->  1:CAN2:D
-//30:   CAN2:RX    -->  4:CAN2:R
-//31:   USB_D+
-//32:   USB_D-
-//33:       NC:Eth_TD+
-//34:       NC:Eth_TD-
-//35:       NC:Eth_RD+
-//36:       NC:Eth_RD-
-//37:       NC:IF+
-//38:       NC:IF-
-//39:       NC:5Vout (only available when connected as USB device)
-//40:   VCC3.3
-/*
-cellpair
-02 21 02
-30 01 00 page request
-
-temp
-79b 02 21 04
-    +2 more pages
-7bb
-020314
-020713
-020c13
-020d13
-
-+1300fffffff
-
-saw 30 01 04 ???
-*/
\ No newline at end of file
--- a/TFT_fonts.lib	Wed Feb 27 03:47:06 2013 +0000
+++ b/TFT_fonts.lib	Sun Mar 03 15:50:54 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/TickTock/code/TFT_fonts/#dd46e436f435
+http://mbed.org/users/TickTock/code/TFT_fonts/#49b5ef080441
--- a/TOUCH_TFTx2.lib	Wed Feb 27 03:47:06 2013 +0000
+++ b/TOUCH_TFTx2.lib	Sun Mar 03 15:50:54 2013 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/TickTock/code/TOUCH_TFTx2/#fd0abf6a7f59
+http://mbed.org/users/TickTock/code/TOUCH_TFTx2/#fd7ae99850a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/displayModes.h	Sun Mar 03 15:50:54 2013 +0000
@@ -0,0 +1,295 @@
+// This contains all the display subroutines
+
+#include "TOUCH_TFTx2.h"
+#include "SPI_TFTx2.h"
+#include "Arial12x12.h"
+#include "Arial12x12_prop.h"
+#include "Arial28x28.h"
+#include "Neu42x35.h"
+#include "SCProSB31x55.h"
+
+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 printLast (bool force){
+        CANMessage msg;
+        tt.locate(0,6);
+        tt.foreground(Red);
+        tt.background(Yellow);
+        if(force) tt.cls(); // Just clear screen if forced - always update display
+        tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
+        for(int i=0; i<19; i++){
+            msg = lastMsg[i+indexOffset];
+            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 printChanged (bool force){
+        CANMessage msg;
+        unsigned char i,j;
+        tt.locate(0,6);
+        tt.foreground(Red);
+        tt.background(Yellow);
+        if(force) tt.cls(); // Just clear screen if forced - always update display
+        tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
+        i=0;
+        j=indexOffset;
+        do{
+            j=j<99?j+1:j;
+            if(msgChanged[j]>0){
+                msg = lastMsg[j];
+                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]);
+                i++;
+            }// if changed
+        }while(i<19&&j<99);
+    }
+    
+    void printLog (bool force){
+        static unsigned char lastDisplayLoc = 0;
+        if(force||displayLoc!=lastDisplayLoc){ //only update if changed
+            tt.foreground(Amber);
+            tt.background(Black);
+            tt.cls();
+            tt.locate(0,6);
+            tt.set_font((unsigned char*) Arial12x12);
+            for(int i=0; i<19; i++){
+                printf("%s",displayLog[displayLoc]);
+                displayLoc=displayLoc>17?0:displayLoc+1;
+            }
+        }
+        lastDisplayLoc=displayLoc;
+    }
+    
+    void printDTE (bool force){
+        unsigned short gids, SOC, packV;
+        static unsigned short lgids=0, lSOC=0, lpackV=0;
+        CANMessage msg;
+    
+        msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
+        gids = (msg.data[0]<<2)+(msg.data[1]>>6);
+        msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC
+        SOC = (msg.data[0]<<2)+(msg.data[1]>>6);
+        msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts
+        packV = (msg.data[2]<<2)+(msg.data[3]>>6);
+    
+        tt.background(Navy);
+        if(force) tt.cls();
+        if(force||gids!=lgids){
+            tt.foreground(Amber);
+            tt.set_font((unsigned char*) Arial28x28);
+            tt.locate(10,10);
+            printf("%4d gids\n",gids);
+            tt.locate(10,200);
+            printf("%4.1f kWh\n",(float)gids*0.08);
+            tt.set_font((unsigned char*) SCProSB31x55);
+            //tt.set_font((unsigned char*) Neu42x35);
+            tt.foreground(Green);
+            tt.locate(60,96);
+            printf("%4.1f mi  \n",(float)(gids-5)*0.33); // Approx for now
+            lgids=gids;
+        }
+        if(force||SOC!=lSOC){
+            tt.foreground(Amber);
+            tt.set_font((unsigned char*) Arial28x28);
+            tt.locate(200,10);
+            printf("%4.1f%s\n",(float)SOC/10,"%");
+            lSOC=SOC;
+        }
+        if(force||packV!=lpackV){
+            tt.foreground(Amber);
+            tt.set_font((unsigned char*) Arial28x28);
+            tt.locate(200,200);
+            printf("%4.1fV\n",(float)packV/2);
+            lpackV=packV;
+        }
+    }
+    
+    void braking (bool force, bool prdata){
+        unsigned short targetBraking, regenBraking, speed;
+        static unsigned short maxTarget = 0, maxRegen = 0, tarDivReg = 0;
+        short rpm;
+        unsigned long temp;
+        static unsigned char lastPressure[4] = {200,200,200,200};
+        unsigned char i,r,t;
+        static unsigned char lr, lt;
+        CANMessage msg;
+    
+        msg = lastMsg[indexLastMsg[0x1cb]]; //Get Target and Regen
+        regenBraking = (msg.data[0]<<3)+(msg.data[1]>>5);
+        targetBraking = (msg.data[2]<<3)+(msg.data[3]>>5);
+        if (targetBraking>maxTarget) maxTarget=targetBraking;
+        if (regenBraking>maxRegen) maxRegen=regenBraking;
+        if (regenBraking>50) {
+            temp = 1000*targetBraking;
+            temp /= regenBraking;
+            if (temp>tarDivReg) tarDivReg=temp;
+        }
+        msg = lastMsg[indexLastMsg[0x176]]; //Get rpms - not sure what this is but scales to mph with .0725
+        rpm = ((short)msg.data[0]<<8)+msg.data[1];
+        speed =rpm>0?rpm>>3:-rpm>>3; //Take absolute to get speed; div8
+        msg = lastMsg[indexLastMsg[0x1ca]]; //Get brake pressure
+    
+        tt.background(Navy);
+        if (force) {
+            tt.cls();
+            tt.rect(0,111,170,239,White);
+            tt.line(0,207,170,207,White);
+            tt.line(0,175,170,175,White);
+            tt.line(0,143,170,143,White);
+            lastPressure[0] = 200;
+            lastPressure[1] = 200;
+            lastPressure[2] = 200;
+            lastPressure[3] = 200;
+        }
+        // plot bar graph for each wheel pressure
+        for (i=0; i<4; i++){
+            if (msg.data[i]<239) {
+                if (msg.data[i]>lastPressure[i]){
+                    tt.fillrect(10+40*i,239-msg.data[i],40+40*i,239,Red);
+                } else if (msg.data[i]<lastPressure[i]) {
+                    tt.fillrect(10+40*i,238-lastPressure[i],40+40*i,238-msg.data[i],Navy);
+                }
+                lastPressure[i]=msg.data[i];
+            }
+        }
+    
+        if(targetBraking>50){
+            targetBraking *= speed;
+            regenBraking *= speed;
+            temp = 200*targetBraking/maxTarget;
+            t = (char) temp;
+            temp = 200*regenBraking*tarDivReg/maxTarget;
+            r = (char) temp;
+            if(lr!=r&&prdata){
+                tt.foreground(Amber);
+                tt.set_font((unsigned char*) Arial28x28);
+                tt.locate(100,50);
+                printf("%d %d    \n",regenBraking,maxRegen);
+                tt.locate(100,90);
+                printf("%3.1f (%3.1f%s)    \n",(float)tarDivReg/1000,(float)regenBraking*tarDivReg/targetBraking/1000,"%");
+            }    
+            if(lt!=t&&prdata){
+                tt.foreground(Amber);
+                tt.set_font((unsigned char*) Arial28x28);
+                tt.locate(100,10);
+                printf("%d %d    \n",targetBraking,maxTarget);
+            }
+            if((lr!=r||lt!=t)&&!prdata){
+                if(r<lr)
+                    tt.fillrect(200,239-lr,300,239-r,Red);
+                else
+                    tt.fillrect(200,239-r,300,239,Green);
+                if(t<lt)
+                    tt.fillrect(200,239-lt,300,239-t,Navy);
+                else
+                    tt.fillrect(200,239-t,300,238-r,Red);
+                lt=t;
+                lr=r;
+            }
+        }
+    }
+    
+    void cpData(bool force){
+        short unsigned max, min, jv, i, bd;
+        unsigned avg;
+        if(force){
+            tt.foreground(White);
+            tt.background(Navy);
+            tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
+            max=0;
+            min=9999;
+            avg=0;
+            for(i=0; i<96; i++){
+               bd=(battData[i*2+3]<<8)+battData[i*2+4];
+               avg+=bd;
+                if(bd>max) max=bd;
+                if(bd<min) min=bd;
+            }
+            avg /= 96;
+            if(min<3713) {
+                jv=avg-(max-avg)*1.5;
+            } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement
+                jv=0;
+            }
+            tt.cls();
+            tt.locate(0,6);
+            printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %02dC %02dC %02dC %02dC\n\n",max,min,avg,jv,battData[224+5],battData[224+8],battData[224+11],battData[224+14]);
+            tt.locate(0,36);
+            for(i=0; i<16; i++){
+                printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",i*6+1,i*6+6,(battData[i*12+3]<<8)+battData[i*12+4],(battData[i*12+5]<<8)+battData[i*12+6],(battData[i*12+7]<<8)+battData[i*12+8],(battData[i*12+9]<<8)+battData[i*12+10],(battData[i*12+11]<<8)+battData[i*12+12],(battData[i*12+13]<<8)+battData[i*12+14]);
+            }
+            tt.rect(8+0*41,16,40+0*41,28,Green);
+            tt.rect(8+1*41,16,40+1*41,28,Yellow);
+            //tt.rect(8+2*41,16,40+2*41,28,White);
+            tt.rect(8+3*41,16,40+3*41,28,Red);
+            for(i=0; i<96; i++){
+                bd=(battData[i*2+3]<<8)+battData[i*2+4];
+                if(bd>0){
+                    if(bd==max) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Green);
+                    //if(bd==avg) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,White);
+                    if(bd==min) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Yellow);
+                    if(bd<jv) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Red);
+                }
+            }
+            showCP=false;
+        }
+    }
+    
+    void updateDisplay(char display){
+        bool changed;
+        changed = dMode[display]!=lastDMode[display];
+        tt.set_display(display);
+        switch (dMode[display]) {
+            case logScreen:
+                printLog(changed);
+                break;
+            case dteScreen:
+                printDTE(changed);
+                break;
+            case brakeScreen:
+                braking(changed,true);
+                break;
+            case powerScreen:
+                braking(changed,false);
+                break;
+            case monitorScreen:
+                printLast(changed);
+                break;
+            case changedScreen:
+                printChanged(changed);
+                break;
+            case cpScreen:
+                cpData(changed||showCP);
+                break;
+            default:
+                tt.background(Black);
+                tt.cls();
+                break;
+        }
+        lastDMode[display]=dMode[display];
+    
+        switch (sMode) {
+            case 1:
+                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;
+        }
+    }
+}
\ No newline at end of file
--- a/main.cpp	Wed Feb 27 03:47:06 2013 +0000
+++ b/main.cpp	Sun Mar 03 15:50:54 2013 +0000
@@ -1,504 +1,23 @@
-#include "CANary.h"
+//#include "utility.h"
+//#include "displayModes.h"
 //To Do:
-// USB device detect
-// config file on local fs
-// user programmable message decode
-// brake trainer
-// write and read the Mode Data
-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
-
-extern "C" void mbed_reset();
-
-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);      // CAN2 uses pins 9 and 10 (rx, tx) and pin 27 (rs)
-DigitalOut can1SleepMode(p8);     // Use pin 8 to control the sleep mode of can2
-CAN can2(p30, p29);     // CAN1 uses pins 30 and 29 (rx, tx) and pin 28 (rs)
-DigitalOut can2SleepMode(p28);     // Use pin 28 to control the sleep mode of can1
-
-bool logEn = true,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
-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 getXY=0; //flag to read touchscreen
-char counter = 0;
-unsigned char dMode[2] = {7,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;
-
-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 );
-}
-
-void logMsg (char *msg) {
-    strcpy(displayLog[displayLoc],msg);
-    displayLoc=displayLoc>17?0:displayLoc+1;
-}
-
-void touched(){
-    LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
-    secsNoTouch = 0;
-    getXY=true;
-}
-
-unsigned short getTimeStamp() {
-    unsigned short msec = timer.read_ms() ; // read ms from the timer
-    unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
-    unsigned short isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
-    return ((isecs<<10)+msec) ; // return the two byte time stamp
-}
-
-void logCan (char mType, CANMessage canRXmsg) {
-    char sTemp[40];
-    unsigned short ts = getTimeStamp();
-    unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
-    static unsigned char ii = 0, lasti = 0; // indexindex
-    unsigned char changed,i;
-    static unsigned char bdi;
-    if(logOpen){
-        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(i=5;i<13;i++){
-                writeBuffer[writePointer][i]=canRXmsg.data[i-5];
-            }
-            if (++writePointer >= maxBufLen) {
-                writePointer = 0;
-                led3 = !led3;
-            }
-        }
-    }//if logOpen
-    if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
-        ii=ii<99?ii+1:0;
-        indexLastMsg[canRXmsg.id]=ii; //Create entry if first message
-    }
-    if(dMode[0]==changedMode||dMode[1]==changedMode){
-        changed=msgChanged[indexLastMsg[canRXmsg.id]];
-        for(i=0;i<8;i++){
-            if(lastMsg[indexLastMsg[canRXmsg.id]].data[i]!=canRXmsg.data[i]){
-                changed |= 1<<i;
-            }
-        }
-        msgChanged[indexLastMsg[canRXmsg.id]]=changed;
-    }
-    lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
-    if(mType==1&&canRXmsg.id==0x7bb){ // is battery data?  Need to store all responses
-        if(canRXmsg.data[0]<0x20){
-            if(canRXmsg.data[3]==2){//cellpair data
-                bdi=0;
-                sprintf(sTemp,"Getting cell pair data\n");
-                logMsg(sTemp);
-           }else if(canRXmsg.data[3]==4){//temperature data
-                bdi=0x20;
-                sprintf(sTemp,"Getting temperature data\n");
-                logMsg(sTemp);
-            }else bdi=0;
-            lasti=0;
-        }
-        i=canRXmsg.data[0]&0x0f; //lower nibble of D0 is index
-        if(lasti>i){ //detect rolloever and offset index appropriately
-            bdi=0x10;
-        }
-        lasti=i; //remember the msb to detect rollover next time around
-        i+=bdi;
-        i*=7;
-        if(i<0xfa){
-            battData[i+0]=canRXmsg.data[1];
-            battData[i+1]=canRXmsg.data[2];
-            battData[i+2]=canRXmsg.data[3];
-            battData[i+3]=canRXmsg.data[4];
-            battData[i+4]=canRXmsg.data[5];
-            battData[i+5]=canRXmsg.data[6];
-            battData[i+6]=canRXmsg.data[7];
-        }
-    }//if 0x7bb
-}
-
-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 sendCPreq() {
-    char i;
-    char data[8] = {0x02, 0x21, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff};
-    can1.monitor(false); // set to active mode
-    can1SleepMode = 0; // enable TX
-    can1.write(CANMessage(0x79b, data, 8));
-    data[0]=0x30; //change to request next line message
-    data[1]=0x01;
-    data[2]=0x00;
-    for(i=0;i<64;i++){
-        wait_ms(16); //wait 16ms
-        can1.write(CANMessage(0x79b, data, 8));
-    }
-    can1SleepMode = 1; // disable TX
-    can1.monitor(true); // set to snoop mode
-}
-
-void sendTreq() {
-    char i;
-    char data[8] = {0x02, 0x21, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff};
-    can1.monitor(false); // set to active mode
-    can1SleepMode = 0; // enable TX
-    can1.write(CANMessage(0x79b, data, 8));
-    data[0]=0x30; //change to request next line message
-    data[1]=0x01;
-    data[2]=0x00;
-    for(i=0;i<8;i++){
-        wait_ms(16); //wait 16ms
-        can1.write(CANMessage(0x79b, data, 8));
-    }
-    can1SleepMode = 1; // disable TX
-    can1.monitor(true); // set to snoop mode
-}
-
-void recieve1() {
-    CANMessage msg1;
-    secsNoMsg=0; // reset deadman switch
-    can1.read(msg1);
-    logCan(1, msg1);
-    led1 = !led1;
-}
-
-void recieve2() {
-    CANMessage msg2;
-    secsNoMsg=0; // reset deadman switch
-    can2.read(msg2);
-    logCan(2, msg2);
-    led2 = !led2;
-}
-
-void printLast (bool force){
-    CANMessage msg;
-    tt.locate(0,6);
-    tt.foreground(Red);
-    tt.background(Yellow);
-    if(force) tt.cls(); // Just clear screen if forced - always update display
-    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
-    for(int i=0; i<19; i++){
-        msg = lastMsg[i+indexOffset];
-        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 printChanged (bool force){
-    CANMessage msg;
-    unsigned char i,j;
-    tt.locate(0,6);
-    tt.foreground(Red);
-    tt.background(Yellow);
-    if(force) tt.cls(); // Just clear screen if forced - always update display
-    tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
-    i=0;
-    j=indexOffset;
-    do{
-        j=j<99?j+1:j;
-        if(msgChanged[j]>0){
-            msg = lastMsg[j];
-            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]);
-            i++;
-        }// if changed
-    }while(i<19&&j<99);
-}
-
-void printLog (bool force){
-    static unsigned char lastDisplayLoc = 0;
-    if(force||displayLoc!=lastDisplayLoc){ //only update if changed
-        tt.foreground(Amber);
-        tt.background(Black);
-        tt.cls();
-        tt.locate(0,6);
-        tt.set_font((unsigned char*) Arial12x12);
-        for(int i=0; i<19; i++){
-            printf("%s",displayLog[displayLoc]);
-            displayLoc=displayLoc>17?0:displayLoc+1;
-        }
-    }
-    lastDisplayLoc=displayLoc;
-}
-
-void printDTE (bool force){
-    unsigned short gids, SOC, packV;
-    static unsigned short lgids=0, lSOC=0, lpackV=0;
-    CANMessage msg;
-
-    msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
-    gids = (msg.data[0]<<2)+(msg.data[1]>>6);
-    msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC
-    SOC = (msg.data[0]<<2)+(msg.data[1]>>6);
-    msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts
-    packV = (msg.data[2]<<2)+(msg.data[3]>>6);
-
-    tt.background(Navy);
-    if(force) tt.cls();
-    if(force||gids!=lgids){
-        tt.foreground(Amber);
-        tt.set_font((unsigned char*) Arial28x28);
-        tt.locate(10,10);
-        printf("%4d gids\n",gids);
-        tt.locate(10,200);
-        printf("%4.1f kWh\n",(float)gids*0.08);
-        tt.set_font((unsigned char*) SCProSB31x55);
-        //tt.set_font((unsigned char*) Neu42x35);
-        tt.foreground(Green);
-        tt.locate(60,96);
-        printf("%4.1f mi\n",(float)gids*0.33); // Approx for now
-        lgids=gids;
-    }
-    if(force||SOC!=lSOC){
-        tt.foreground(Amber);
-        tt.set_font((unsigned char*) Arial28x28);
-        tt.locate(200,10);
-        printf("%4.1f%s\n",(float)SOC/10,"%");
-        lSOC=SOC;
-    }
-    if(force||packV!=lpackV){
-        tt.foreground(Amber);
-        tt.set_font((unsigned char*) Arial28x28);
-        tt.locate(200,200);
-        printf("%4.1fV\n",(float)packV/2);
-        lpackV=packV;
-    }
-}
-
-void braking (bool force, bool prdata){
-    unsigned short targetBraking, regenBraking, speed;
-    static unsigned short maxTarget = 0, maxRegen = 0, tarDivReg = 0;
-    short rpm;
-    unsigned long temp;
-    static unsigned char lastPressure[4] = {200,200,200,200};
-    unsigned char i,r,t;
-    static unsigned char lr, lt;
-    CANMessage msg;
-
-    msg = lastMsg[indexLastMsg[0x1cb]]; //Get Target and Regen
-    regenBraking = (msg.data[0]<<3)+(msg.data[1]>>5);
-    targetBraking = (msg.data[2]<<3)+(msg.data[3]>>5);
-    if (targetBraking>maxTarget) maxTarget=targetBraking;
-    if (regenBraking>maxRegen) maxRegen=regenBraking;
-    if (regenBraking>50) {
-        temp = 1000*targetBraking;
-        temp /= regenBraking;
-        if (temp>tarDivReg) tarDivReg=temp;
-    }
-    msg = lastMsg[indexLastMsg[0x176]]; //Get rpms - not sure what this is but scales to mph with .0725
-    rpm = ((short)msg.data[0]<<8)+msg.data[1];
-    speed =rpm>0?rpm>>3:-rpm>>3; //Take absolute to get speed; div8
-    msg = lastMsg[indexLastMsg[0x1ca]]; //Get brake pressure
-
-    tt.background(Navy);
-    if (force) {
-        tt.cls();
-        tt.rect(0,111,170,239,White);
-        tt.line(0,207,170,207,White);
-        tt.line(0,175,170,175,White);
-        tt.line(0,143,170,143,White);
-        lastPressure[0] = 200;
-        lastPressure[1] = 200;
-        lastPressure[2] = 200;
-        lastPressure[3] = 200;
-    }
-    // plot bar graph for each wheel pressure
-    for (i=0; i<4; i++){
-        if (msg.data[i]<239) {
-            if (msg.data[i]>lastPressure[i]){
-                tt.fillrect(10+40*i,239-msg.data[i],40+40*i,239,Red);
-            } else if (msg.data[i]<lastPressure[i]) {
-                tt.fillrect(10+40*i,238-lastPressure[i],40+40*i,238-msg.data[i],Navy);
-            }
-            lastPressure[i]=msg.data[i];
-        }
-    }
-
-    if(targetBraking>50){
-        targetBraking *= speed;
-        regenBraking *= speed;
-        temp = 200*targetBraking/maxTarget;
-        t = (char) temp;
-        temp = 200*regenBraking*tarDivReg/maxTarget;
-        r = (char) temp;
-        if(lr!=r&&prdata){
-            tt.foreground(Amber);
-            tt.set_font((unsigned char*) Arial28x28);
-            tt.locate(100,50);
-            printf("%d %d    \n",regenBraking,maxRegen);
-            tt.locate(100,90);
-            printf("%3.1f (%3.1f%s)    \n",(float)tarDivReg/1000,(float)regenBraking*tarDivReg/targetBraking/1000,"%");
-        }    
-        if(lt!=t&&prdata){
-            tt.foreground(Amber);
-            tt.set_font((unsigned char*) Arial28x28);
-            tt.locate(100,10);
-            printf("%d %d    \n",targetBraking,maxTarget);
-        }
-        if((lr!=r||lt!=t)&&!prdata){
-            if(r<lr)
-                tt.fillrect(200,239-lr,300,239-r,Red);
-            else
-                tt.fillrect(200,239-r,300,239,Green);
-            if(t<lt)
-                tt.fillrect(200,239-lt,300,239-t,Navy);
-            else
-                tt.fillrect(200,239-t,300,238-r,Red);
-            lt=t;
-            lr=r;
-        }
-    }
-}
-
-void cpData(bool force){
-    short unsigned max, min, jv, i, bd;
-    unsigned avg;
-    if(force){
-        tt.foreground(White);
-        tt.background(Navy);
-        tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
-        max=0;
-        min=9999;
-        avg=0;
-        for(i=0; i<96; i++){
-           bd=(battData[i*2+3]<<8)+battData[i*2+4];
-           avg+=bd;
-            if(bd>max) max=bd;
-            if(bd<min) min=bd;
-        }
-        avg /= 96;
-        jv=avg-(max-avg)*2.5;
-        tt.cls();
-        tt.locate(0,6);
-        printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %02dC %02dC %02dC %02dC\n\n",max,min,avg,jv,battData[224+5],battData[224+8],battData[224+11],battData[224+14]);
-        tt.locate(0,36);
-        for(i=0; i<16; i++){
-            printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",i*6+1,i*6+6,(battData[i*12+3]<<8)+battData[i*12+4],(battData[i*12+5]<<8)+battData[i*12+6],(battData[i*12+7]<<8)+battData[i*12+8],(battData[i*12+9]<<8)+battData[i*12+10],(battData[i*12+11]<<8)+battData[i*12+12],(battData[i*12+13]<<8)+battData[i*12+14]);
-        }
-        tt.rect(8+0*41,16,40+0*41,28,Green);
-        tt.rect(8+1*41,16,40+1*41,28,Yellow);
-        //tt.rect(8+2*41,16,40+2*41,28,White);
-        tt.rect(8+3*41,16,40+3*41,28,Red);
-        for(i=0; i<96; i++){
-            bd=(battData[i*2+3]<<8)+battData[i*2+4];
-            if(bd>0){
-                if(bd==max) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Green);
-                //if(bd==avg) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,White);
-                if(bd==min) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Yellow);
-                if(bd<jv) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Red);
-            }
-        }
-        showCP=false;
-    }
-}
-
-void updateDisplay(char display){
-    bool changed;
-    changed = dMode[display]!=lastDMode[display];
-    tt.set_display(display);
-    switch (dMode[display]) {
-        case logMode:
-            printLog(changed);
-            break;
-        case dteMode:
-            printDTE(changed);
-            break;
-        case brakeMode:
-            braking(changed,true);
-            break;
-        case powerMode:
-            braking(changed,false);
-            break;
-        case monitorMode:
-            printLast(changed);
-            break;
-        case changedMode:
-            printChanged(changed);
-            break;
-        case cpMode:
-            cpData(changed||showCP);
-            break;
-        default:
-            tt.background(Black);
-            tt.cls();
-            break;
-    }
-    lastDMode[display]=dMode[display];
-
-    switch (sMode) {
-        case 1:
-            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;
-    }
-}
+// * USB device detect
+// * config file on local fs with touchscreen calibration
+// * 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
+// * 
+#include "mbed.h"
+#include "CAN.h"
+#include "beep.h"
+#include "MSCFileSystem.h"
+#include "PowerControl.h"
+#include "EthernetPowerControl.h"
+#include "utility.h"
+#include "displayModes.h"
 
 int main() {
     int readPointer=0;
@@ -522,9 +41,13 @@
     tt.background(Black);
     tt.cls();
     tt.set_display(0);       // select left display
-    tt.calibrate();           // calibrate the touch
+    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(&touched);
+    touchpad.rise(&touch_ISR);
     tt.wfi();               // enable interrupt on touch
     dled = 0.8; // turn on display LED 80%
     timer.start() ;
@@ -563,6 +86,7 @@
         //    strftime(sTemp, 32, "%a %m/%d/%Y %X", localtime(&seconds));
         //    printf("%s\n", sTemp); // DAY MM/DD/YYYY HH:MM:SS
     }
+    //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
@@ -623,7 +147,7 @@
             secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
             while (secsNoMsg>canTimeout && secsNoTouch>userTimeout) {
                 //DeepPowerDown();
-                tt.wfi(); //enable touchpad input
+                tt.wfi(); //enable touch interrupt
                 __wfi(); // freeze CPU and wait for interrupt (from canbus or touch)
                 //Sleep();
                 //DeepPowerDown();
@@ -642,10 +166,10 @@
             }
         } // if idle
         
-        if(getXY){
+        if(touched){
             lastTouch = tt.get_touch();       
             lastTouch = tt.to_pixel(lastTouch);          // convert to pixel pos
-            getXY = false; // clear interrupt flag
+            touched = false; // clear interrupt flag
         }
         if (!userIdle) {
             if (secsNoTouch<2) {// Recently touched
@@ -659,15 +183,15 @@
                 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:maxModes;
+                            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]<maxModes?dMode[i]+1:0;
+                            dMode[i]=dMode[i]<maxScreens?dMode[i]+1:0;
                         }
                     } else sMode=1;
                 } else {
-                    if (dMode[i]==monitorMode||dMode[i]==changedMode) {
+                    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) {
@@ -676,13 +200,9 @@
                         } else if (lastTouch.x>btn33x1 && lastTouch.x<btn33x2) {
                             indexOffset=indexOffset<77?indexOffset+4:80;
                         }
-                    } else if (dMode[i]==cpMode) {
+                    } else if (dMode[i]==cpScreen) {
                         if (lastTouch.x>btn32x1 && lastTouch.x<btn32x2){
-                            sendCPreq(); // send cellpair data request.
-                            wait_ms(16);
-                            sendTreq(); //send temperature request
-                            wait_ms(16);
-                            showCP=true;
+                            pollCP=true;
                         }
                     }
                 } //top of screen
@@ -694,6 +214,14 @@
                 lastDMode[1]=99;
             }
         }
+        if(pollCP){
+            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);
         //wait(0.1); // We get >2K messages per second
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utility.h	Sun Mar 03 15:50:54 2013 +0000
@@ -0,0 +1,319 @@
+// utility.cpp
+#include "mbed.h"
+#include "CAN.h"
+#include "beep.h"
+#include "MSCFileSystem.h"
+#include "PowerControl.h"
+#include "EthernetPowerControl.h"
+
+#define upLine "\033[1A"
+#define maxBufLen 768
+#define canTimeout 500
+#define userTimeout 10
+#define btn31x1 12
+#define btn31x2 101
+#define btn32x1 115
+#define btn32x2 204
+#define btn33x1 218
+#define btn33x2 307
+#define btn11y1 180
+#define btn11y2 229
+#define maxScreens 7
+#define offScreen 0
+#define logScreen 1
+#define dteScreen 2
+#define brakeScreen 3
+#define powerScreen 4
+#define monitorScreen 5
+#define changedScreen 6
+#define cpScreen 7
+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
+
+bool logEn = true,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
+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] = {7,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;
+
+extern "C" {
+    void mbed_reset();
+    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 );
+    }
+    
+    void logMsg (char *msg) {
+        strcpy(displayLog[displayLoc],msg);
+        displayLoc=displayLoc>17?0:displayLoc+1;
+    }
+    
+    void touch_ISR(){
+        LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
+        secsNoTouch = 0;
+        touched=true;
+    }
+    
+    unsigned short getTimeStamp() {
+        unsigned short msec = timer.read_ms() ; // read ms from the timer
+        unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
+        unsigned short isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC
+        return ((isecs<<10)+msec) ; // return the two byte time stamp
+    }
+    
+    void logCan (char mType, CANMessage canRXmsg) {
+        char sTemp[40];
+        unsigned short ts = getTimeStamp();
+        unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
+        static unsigned char ii = 0, lasti = 0; // indexindex
+        unsigned char changed,i;
+        static unsigned char bdi;
+        if(logOpen){
+            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(i=5;i<13;i++){
+                    writeBuffer[writePointer][i]=canRXmsg.data[i-5];
+                }
+                if (++writePointer >= maxBufLen) {
+                    writePointer = 0;
+                    led3 = !led3;
+                }
+            }
+        }//if logOpen
+        if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
+            ii=ii<99?ii+1:0;
+            indexLastMsg[canRXmsg.id]=ii; //Create entry if first message
+        }
+        if(dMode[0]==changedScreen||dMode[1]==changedScreen){
+            changed=msgChanged[indexLastMsg[canRXmsg.id]];
+            for(i=0;i<8;i++){
+                if(lastMsg[indexLastMsg[canRXmsg.id]].data[i]!=canRXmsg.data[i]){
+                    changed |= 1<<i;
+                }
+            }
+            msgChanged[indexLastMsg[canRXmsg.id]]=changed;
+        }
+        lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
+        if(mType==1&&canRXmsg.id==0x7bb){ // is battery data?  Need to store all responses
+            if(canRXmsg.data[0]<0x20){
+                if(canRXmsg.data[3]==2){//cellpair data
+                    bdi=0;
+                    sprintf(sTemp,"Getting cell pair data\n");
+                    logMsg(sTemp);
+               }else if(canRXmsg.data[3]==4){//temperature data
+                    bdi=0x20;
+                    sprintf(sTemp,"Getting temperature data\n");
+                    logMsg(sTemp);
+                }else bdi=0;
+                lasti=0;
+            }
+            i=canRXmsg.data[0]&0x0f; //lower nibble of D0 is index
+            if(lasti>i){ //detect rolloever and offset index appropriately
+                bdi=0x10;
+            }
+            lasti=i; //remember the msb to detect rollover next time around
+            i+=bdi;
+            i*=7;
+            if(i<0xfa){
+                battData[i+0]=canRXmsg.data[1];
+                battData[i+1]=canRXmsg.data[2];
+                battData[i+2]=canRXmsg.data[3];
+                battData[i+3]=canRXmsg.data[4];
+                battData[i+4]=canRXmsg.data[5];
+                battData[i+5]=canRXmsg.data[6];
+                battData[i+6]=canRXmsg.data[7];
+            }
+        }//if 0x7bb
+    }
+    
+    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 sendCPreq() {
+        char i;
+        char data[8] = {0x02, 0x21, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff};
+        can1.monitor(false); // set to active mode
+        can1SleepMode = 0; // enable TX
+        can1.write(CANMessage(0x79b, data, 8));
+        data[0]=0x30; //change to request next line message
+        data[1]=0x01;
+        data[2]=0x00;
+        for(i=0;i<27;i++){
+            wait_ms(16); //wait 16ms
+            can1.write(CANMessage(0x79b, data, 8));
+        }
+        can1SleepMode = 1; // disable TX
+        can1.monitor(true); // set to snoop mode
+    }
+    
+    void sendTreq() {
+        char i;
+        char data[8] = {0x02, 0x21, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff};
+        can1.monitor(false); // set to active mode
+        can1SleepMode = 0; // enable TX
+        can1.write(CANMessage(0x79b, data, 8));
+        data[0]=0x30; //change to request next line message
+        data[1]=0x01;
+        data[2]=0x00;
+        for(i=0;i<2;i++){
+            wait_ms(16); //wait 16ms
+            can1.write(CANMessage(0x79b, data, 8));
+        }
+        can1SleepMode = 1; // disable TX
+        can1.monitor(true); // set to snoop mode
+    }
+    
+    void tickerISR() {  //This is the ticker ISR for auto-polling
+        pollCP=true;    //Set a flag to do in main loop instead of here
+    }                   //since ticker blocks other interrupts
+    
+    void recieve1() {
+        CANMessage msg1;
+        secsNoMsg=0; // reset deadman switch
+        can1.read(msg1);
+        logCan(1, msg1);
+        led1 = !led1;
+    }
+    
+    void recieve2() {
+        CANMessage msg2;
+        secsNoMsg=0; // reset deadman switch
+        can2.read(msg2);
+        logCan(2, msg2);
+        led2 = !led2;
+    }
+}
+
+//LEAF OBD
+//1:
+//2:
+//3:    AVCAN-L     White/Blue
+//4:    VSS-Shield
+//5:    VSS         Brown,White/Brown
+//6:    CARCAN-H    Green
+//7:
+//8:    12V-SW      Orange,White/Orange
+//9:
+//10:
+//11:   AVCAN-H     Blue
+//12:   EVCAN-L     White/Grey
+//13:   EVCAN-H     Grey
+//14:   CARCAN-L    White/Green
+//15:
+//16:   12V-AON     Red/Blue,Blue/Red
+
+//VP230
+//1:D   
+//2:GND 
+//3:VCC 
+//4:R   
+//5:Vref
+//6:CANL
+//7:CANH
+//8:RS
+
+//LPC1768
+//1:    VSS
+//2:        NC:VIN  (4.5-9V supply)
+//3:        NC:VB
+//4:        NC:nR
+//5:    SPI:CS0
+//6:    SPI:CS1
+//7:    SPI:Reset
+//8:    CAN1:Sleep -->  8:CAN1:RS
+//9:    CAN1:RX    -->  4:CAN1:R
+//10:   CAN1:TX    -->  1:CAN1:D
+//11:   SPI:MOSI
+//12:   SPI:MISO
+//13:   SPI:SCLK
+//14:       NC:Ain
+//15:   MON12V     -->  4K to 12V, 1K to VSS  (To be implemented)
+//16:   TOUCH_X+
+//17:   TOUCH_X-
+//18:       NC:Aout
+//19:   TOUCH_Y+
+//20:   TOUCH_Y-
+//21:   Spkr+
+//22:   Spkr-           (optional complimentary output for more volume)
+//23:       NC:pwm
+//24:       LED
+//25:       NC:pwm
+//26:       NC:pwm
+//27:       NC
+//28:   CAN2:Sleep -->  8:CAN2:RS
+//29:   CAN2:TX    -->  1:CAN2:D
+//30:   CAN2:RX    -->  4:CAN2:R
+//31:   USB_D+
+//32:   USB_D-
+//33:       NC:Eth_TD+
+//34:       NC:Eth_TD-
+//35:       NC:Eth_RD+
+//36:       NC:Eth_RD-
+//37:       NC:IF+
+//38:       NC:IF-
+//39:       NC:5Vout (only available when connected as USB device)
+//40:   VCC3.3
\ No newline at end of file