Attempts to merge SPI_TFT2 & SPI_TFT_ILI9341

Dependencies:   SPI_TFTx2 TFT_fonts TOUCH_TFTx2 mbed

Fork of CANary by Tick Tock

Files at this revision

API Documentation at this revision

Comitter:
TickTock
Date:
Sat Mar 23 04:43:45 2013 +0000
Parent:
35:5acbd8a64a89
Child:
37:fea2c1d52c5f
Commit message:
Added playback option

Changed in this revision

common.h Show annotated file Show diff for this revision Revisions of this file
displayModes.cpp 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.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/common.h	Thu Mar 21 12:05:22 2013 +0000
+++ b/common.h	Sat Mar 23 04:43:45 2013 +0000
@@ -8,9 +8,10 @@
 #define cpScreen 7
 #define config1Screen 8
 #define config2Screen 9
-#define maxScreens 9
+#define dateScreen 10
+#define maxScreens 10
 #define btnGap 10
 
-#define maxBufLen 768
+#define maxBufLen 512
 #define canTimeout 5
 #define userTimeout 15
--- a/displayModes.cpp	Thu Mar 21 12:05:22 2013 +0000
+++ b/displayModes.cpp	Sat Mar 23 04:43:45 2013 +0000
@@ -196,6 +196,286 @@
     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;
+    }
+    if(sMode==1){
+        tt.foreground(Yellow);
+        tt.background(DarkCyan);
+        tt.set_font((unsigned char*) Arial12x12);
+        sprintf(sTemp1,"Request");
+        sprintf(sTemp2,"CP data");
+        showButton(1,0,sTemp1,sTemp2,3,3);               
+    }
+}
+
+void config1(bool force){
+    if (force) {
+        tt.background(Black);
+        tt.cls();
+    }
+    tt.foreground(Yellow);
+    tt.background(DarkCyan);
+    tt.set_font((unsigned char*) Arial12x12);
+    sprintf(sTemp1," Calibrate");
+    sprintf(sTemp2,"  Touch");
+    showButton(0,0,sTemp1,sTemp2,3,3);
+    sprintf(sTemp1,"  Reset");
+    sprintf(sTemp2,"");
+    showButton(1,0,sTemp1,sTemp2,3,3);
+    sprintf(sTemp1,"  Save");
+    sprintf(sTemp2,"  Config");
+    showButton(2,0,sTemp1,sTemp2,3,3);
+    if (logEn) {
+        sprintf(sTemp1," Disable");
+    } else {
+        sprintf(sTemp1," Enable");
+    }
+    sprintf(sTemp2," Logging");
+    showButton(0,1,sTemp1,sTemp2,3,3);
+    if (repeatPoll) {
+        sprintf(sTemp1," Disable");
+    } else {
+        sprintf(sTemp1," Enable");
+    }
+    sprintf(sTemp2," Auto CP");
+    showButton(1,1,sTemp1,sTemp2,3,3);
+    sprintf(sTemp1," Start");
+    sprintf(sTemp2,"Playback");
+    showButton(2,1,sTemp1,sTemp2,3,3);
+}
+
+void config2(bool force){
+    if (force) {
+        tt.background(Black);
+        tt.cls();
+    }
+    tt.foreground(Yellow);
+    tt.background(DarkCyan);
+    tt.set_font((unsigned char*) Arial12x12);
+    if(playbackOpen){
+        sprintf(sTemp1,"Slower");
+        sprintf(sTemp2," <--");
+        showButton(0,0,sTemp1,sTemp2,3,3);
+        if(playbackEn){
+            sprintf(sTemp1," Pause");
+        }else{
+            sprintf(sTemp1,"  Run");
+        }
+        sprintf(sTemp2," %4.3f ",playbackInt);
+        showButton(1,0,sTemp1,sTemp2,3,3);
+        sprintf(sTemp1,"Faster");
+        sprintf(sTemp2,"     -->");
+        showButton(2,0,sTemp1,sTemp2,3,3);
+    }
+    if(playbackOpen){
+        sprintf(sTemp1," Stop");
+    }else{
+        sprintf(sTemp1," Start");
+    }
+    sprintf(sTemp2,"Playback");
+    showButton(1,1,sTemp1,sTemp2,3,3);
+}
+
+void showDateTime(bool force){
+    struct tm t; // pointer to a static tm structure
+    time_t seconds ;
+    tt.foreground(Yellow);
+    tt.background(Navy);
+    if (force) {
+        tt.cls();
+        seconds = time(NULL);
+        t = *localtime(&seconds) ;
+        
+        tt.locate(10,10);
+        strftime(sTemp1, 32, "%a %m/%d/%Y %X  \n", &t);
+        printf("%s",sTemp1);
+        if(sMode==1){
+            tt.foreground(Yellow);
+            tt.background(DarkCyan);
+            tt.set_font((unsigned char*) Arial12x12);
+            sprintf(sTemp2,"");
+            switch(dtMode){
+                case 0:
+                    sprintf(sTemp1,"Year");
+                    break;
+                case 1:
+                    sprintf(sTemp1,"Month");
+                    break;
+                case 2:
+                    sprintf(sTemp1,"Day");
+                    break;
+                case 3:
+                    sprintf(sTemp1,"Hour");
+                    break;
+                case 4:
+                    sprintf(sTemp1,"Minute");
+                    break;
+                case 5:
+                    sprintf(sTemp1,"Second");
+                    break;
+                case 6:
+                    sprintf(sTemp1,"Select");
+                    break;
+                default:
+                    break;
+            }
+            showButton(0,1,sTemp1,sTemp2,3,3);               
+            sprintf(sTemp1,"   UP");
+            showButton(1,1,sTemp1,sTemp2,3,3);               
+            sprintf(sTemp1,"  DOWN");
+            showButton(2,1,sTemp1,sTemp2,3,3);               
+        }
+    }
+}
+
+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);
+            break;
+        case powerScreen:
+            //braking(changed, true);
+            //break;
+        case monitorScreen:
+            printLast(changed);
+            break;
+        case changedScreen:
+            printChanged(changed);
+            break;
+        case cpScreen:
+            cpData(changed||showCP);
+            break;
+        case config1Screen:
+            config1(changed);
+            break;
+        case config2Screen:
+            config2(changed);
+            break;
+        case dateScreen:
+            showDateTime(changed);
+            break;
+        default:
+            tt.background(Black);
+            tt.cls();
+            break;
+    }
+    lastDMode[display]=dMode[display];
+
+    switch (sMode) {
+        case 1: // Select screens
+            tt.foreground(Yellow);
+            tt.background(DarkCyan);
+            tt.set_font((unsigned char*) Arial12x12);
+            sprintf(sTemp1,"<-Prev");
+            sprintf(sTemp2,"");
+            showButton(0,2,sTemp1,sTemp2,3,3);
+            sprintf(sTemp1," Select %d",dMode[display]);
+            showButton(1,2,sTemp1,sTemp2,3,3);
+            sprintf(sTemp1,"   Next->");
+            showButton(2,2,sTemp1,sTemp2,3,3);
+            break;
+        case 2: // numpad
+            sprintf(sTemp2,"");
+            tt.foreground(Yellow);
+            tt.background(DarkCyan);
+            tt.set_font((unsigned char*) Arial24x23);
+            sprintf(sTemp1," 1");
+            showButton(0,0,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 2");
+            showButton(1,0,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 3");
+            showButton(2,0,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 4");
+            showButton(0,1,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 5");
+            showButton(1,1,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 6");
+            showButton(2,1,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 7");
+            showButton(0,2,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 8");
+            showButton(1,2,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 9");
+            showButton(2,2,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1," 0");
+            showButton(1,3,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1,"<--");
+            showButton(0,3,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1,"-->");
+            showButton(2,3,sTemp1,sTemp2,4,4);
+            sprintf(sTemp1,"return");
+            showButton(3,3,sTemp1,sTemp2,4,4);
+        case 3:
+            break;
+        default:
+            break;
+    }
+}
+
+void showButton(unsigned char column, unsigned char row, char * text1, char * text2, unsigned char columns, unsigned char rows){
+    unsigned short x1,x2,y1,y2;
+    x1=column*(320/columns)+btnGap/2;
+    x2=(column+1)*(320/columns)-btnGap/2;
+    y1=row*(240/rows)+btnGap/2;
+    y2=(row+1)*(240/rows)-btnGap/2;
+    tt.fillrect(x1,y1,x2,y2,DarkCyan);
+    tt.locate(x1+btnGap,y1+btnGap);
+    printf("%s\n",text1);
+    tt.locate(x1+btnGap,y1+btnGap+30);
+    printf("%s\n",text2);
+}
+
 /*void braking (bool force, bool prdata=false){
     unsigned long targetBraking, regenBraking, speed;
     static unsigned long maxTarget = 20000, maxRegen = 20000, tarDivReg = 1000;
@@ -286,247 +566,4 @@
     }
     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;
-    }
-    if(sMode==1){
-        tt.foreground(Yellow);
-        tt.background(DarkCyan);
-        tt.set_font((unsigned char*) Arial12x12);
-        sprintf(sTemp1,"Request");
-        sprintf(sTemp2,"CP data");
-        showButton(1,0,sTemp1,sTemp2,3,3);               
-    }
-}
-
-void config1(bool force){
-    if (force) {
-        tt.background(Black);
-        tt.cls();
-    }
-    tt.foreground(Yellow);
-    tt.background(DarkCyan);
-    tt.set_font((unsigned char*) Arial12x12);
-    sprintf(sTemp1," Calibrate");
-    sprintf(sTemp2,"  Touch");
-    showButton(0,0,sTemp1,sTemp2,3,3);
-    sprintf(sTemp1,"  Reset");
-    sprintf(sTemp2,"");
-    showButton(1,0,sTemp1,sTemp2,3,3);
-    sprintf(sTemp1,"  Save");
-    sprintf(sTemp2,"  Config");
-    showButton(2,0,sTemp1,sTemp2,3,3);
-    if (logEn) {
-        sprintf(sTemp1," Disable");
-    } else {
-        sprintf(sTemp1," Enable");
-    }
-    sprintf(sTemp2," Logging");
-    showButton(0,1,sTemp1,sTemp2,3,3);
-    if (repeatPoll) {
-        sprintf(sTemp1," Disable");
-    } else {
-        sprintf(sTemp1," Enable");
-    }
-    sprintf(sTemp2," Auto CP");
-    showButton(1,1,sTemp1,sTemp2,3,3);
-}
-
-void showDateTime(bool force){
-    struct tm t; // pointer to a static tm structure
-    time_t seconds ;
-    tt.foreground(Yellow);
-    tt.background(Navy);
-    if (force) {
-        tt.cls();
-        seconds = time(NULL);
-        t = *localtime(&seconds) ;
-        
-        tt.locate(10,10);
-        strftime(sTemp1, 32, "%a %m/%d/%Y %X  \n", &t);
-        printf("%s",sTemp1);
-        if(sMode==1){
-            tt.foreground(Yellow);
-            tt.background(DarkCyan);
-            tt.set_font((unsigned char*) Arial12x12);
-            sprintf(sTemp2,"");
-            switch(dtMode){
-                case 0:
-                    sprintf(sTemp1,"Year");
-                    break;
-                case 1:
-                    sprintf(sTemp1,"Month");
-                    break;
-                case 2:
-                    sprintf(sTemp1,"Day");
-                    break;
-                case 3:
-                    sprintf(sTemp1,"Hour");
-                    break;
-                case 4:
-                    sprintf(sTemp1,"Minute");
-                    break;
-                case 5:
-                    sprintf(sTemp1,"Second");
-                    break;
-                case 6:
-                    sprintf(sTemp1,"Select");
-                    break;
-                default:
-                    break;
-            }
-            showButton(0,1,sTemp1,sTemp2,3,3);               
-            sprintf(sTemp1,"   UP");
-            showButton(1,1,sTemp1,sTemp2,3,3);               
-            sprintf(sTemp1,"  DOWN");
-            showButton(2,1,sTemp1,sTemp2,3,3);               
-        }
-    }
-}
-
-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);
-            break;
-        case powerScreen:
-            //braking(changed, true);
-            //break;
-        case monitorScreen:
-            printLast(changed);
-            break;
-        case changedScreen:
-            printChanged(changed);
-            break;
-        case cpScreen:
-            cpData(changed||showCP);
-            break;
-        case config1Screen:
-            config1(changed);
-            break;
-        case config2Screen:
-            showDateTime(changed);
-            break;
-        default:
-            tt.background(Black);
-            tt.cls();
-            break;
-    }
-    lastDMode[display]=dMode[display];
-
-    switch (sMode) {
-        case 1: // Select screens
-            tt.foreground(Yellow);
-            tt.background(DarkCyan);
-            tt.set_font((unsigned char*) Arial12x12);
-            sprintf(sTemp1,"<-Prev");
-            sprintf(sTemp2,"");
-            showButton(0,2,sTemp1,sTemp2,3,3);
-            sprintf(sTemp1," Select %d",dMode[display]);
-            showButton(1,2,sTemp1,sTemp2,3,3);
-            sprintf(sTemp1,"   Next->");
-            showButton(2,2,sTemp1,sTemp2,3,3);
-            break;
-        case 2: // numpad
-            sprintf(sTemp2,"");
-            tt.foreground(Yellow);
-            tt.background(DarkCyan);
-            tt.set_font((unsigned char*) Arial24x23);
-            sprintf(sTemp1," 1");
-            showButton(0,0,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 2");
-            showButton(1,0,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 3");
-            showButton(2,0,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 4");
-            showButton(0,1,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 5");
-            showButton(1,1,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 6");
-            showButton(2,1,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 7");
-            showButton(0,2,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 8");
-            showButton(1,2,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 9");
-            showButton(2,2,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1," 0");
-            showButton(1,3,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1,"<--");
-            showButton(0,3,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1,"-->");
-            showButton(2,3,sTemp1,sTemp2,4,4);
-            sprintf(sTemp1,"return");
-            showButton(3,3,sTemp1,sTemp2,4,4);
-        case 3:
-            break;
-        default:
-            break;
-    }
-}
-
-void showButton(unsigned char column, unsigned char row, char * text1, char * text2, unsigned char columns, unsigned char rows){
-    unsigned short x1,x2,y1,y2;
-    x1=column*(320/columns)+btnGap/2;
-    x2=(column+1)*(320/columns)-btnGap/2;
-    y1=row*(240/rows)+btnGap/2;
-    y2=(row+1)*(240/rows)-btnGap/2;
-    tt.fillrect(x1,y1,x2,y2,DarkCyan);
-    tt.locate(x1+btnGap,y1+btnGap);
-    printf("%s\n",text1);
-    tt.locate(x1+btnGap,y1+btnGap+30);
-    printf("%s\n",text2);
-}
-
+}*/
\ No newline at end of file
--- a/displayModes.h	Thu Mar 21 12:05:22 2013 +0000
+++ b/displayModes.h	Sat Mar 23 04:43:45 2013 +0000
@@ -26,6 +26,9 @@
 extern unsigned char dtMode;
 extern float accV;
 extern bool tick;
+extern bool playbackEn;
+extern bool playbackOpen;
+extern float playbackInt;
 
 extern "C" {
     void printLast (bool force);
--- a/main.cpp	Thu Mar 21 12:05:22 2013 +0000
+++ b/main.cpp	Sat Mar 23 04:43:45 2013 +0000
@@ -32,7 +32,8 @@
 
 time_t seconds ;
 
-Ticker ticker;
+Ticker autoPoll;
+Ticker playback;
 Timer timer;
 
 DigitalOut led1(LED1);
@@ -84,13 +85,21 @@
 unsigned short pollInt = 300; // polling interval=5 minutes (until config file read)
 bool accOn = false; // Accessories on
 float scale12V = 16.2; // R1:R2 ratio
+signed long kWh = 0;
+unsigned long miles = 0;
+float mpkWh = 0;
 float accV = 0;
+bool playbackEn = false;
+bool playbackOpen = false;
+float playbackInt = 1; //read one message every 64 ms
+bool step = false;
+char data[8];
 
 int main() {
     int readPointer=0;
     char sTemp[40];
     unsigned long secs;
-    char i,j,display=0;
+    unsigned char i,j,display=0;
     point lastTouch;
 
     can1.monitor(true); // set to snoop mode
@@ -223,7 +232,7 @@
                 logOpen=false;
             }
         } // if logOpen
-        if (canIdle&&userIdle) { // canbus idle --> sleep to save power
+        if (canIdle&&userIdle&&!playbackEn) { // canbus idle --> sleep to save power
             if (logOpen){
                 fclose(file);
             } // if (logOpen)*/
@@ -296,6 +305,12 @@
                                 } else if (dMode[i]==config1Screen) {
                                     wait_ms(500);
                                     tt.calibrate();
+                                } else if (dMode[i]==config2Screen) { // slower
+                                        playbackInt *=2;
+                                    if(playbackEn){
+                                        playback.detach();
+                                        playback.attach(&playbackISR,playbackInt);
+                                    }
                                 }
                                 break;
                             case 10:
@@ -307,6 +322,13 @@
                                     pollCP=true;
                                 } else if (dMode[i]==config1Screen) {
                                     mbed_reset();
+                                } else if (dMode[i]==config2Screen) { // pause/unpause
+                                    playbackEn=!playbackEn;
+                                    if(playbackEn){
+                                        playback.attach(&playbackISR,playbackInt);
+                                    }else{
+                                        playback.detach();
+                                    }
                                 }
                                 break;
                             case 20:
@@ -318,6 +340,14 @@
                                     logMsg(sTemp);
                                     saveConfig();
                                     spkr.beep(2000,0.25);
+                                } else if (dMode[i]==config2Screen) { // faster
+                                    if(playbackInt>.002){
+                                        playbackInt/=2;
+                                        if(playbackEn){
+                                            playback.detach();
+                                            playback.attach(&playbackISR,playbackInt);
+                                        }
+                                    }
                                 }
                                 break;
                             case 01:
@@ -325,28 +355,58 @@
                                 if (dMode[i]==config1Screen) {
                                     logEn = !logEn;
                                     if (!logEn) repeatPoll=false;
-                                } else if (dMode[i]==config2Screen){
+                                } else if (dMode[i]==dateScreen){
                                     dtMode=(dtMode<6)?dtMode+1:0;
                                     lastDMode[i]=99;
                                 }
                                 break;
                             case 11:
                             case 41:
-                                if (dMode[i]==config1Screen) {
+                                if (dMode[i]==config1Screen){
                                     repeatPoll = !repeatPoll&&logEn;
                                     if (repeatPoll) {
-                                        ticker.attach(&tickerISR,pollInt);
+                                        autoPoll.attach(&autoPollISR,pollInt);
                                     } else {
-                                        ticker.detach();
+                                        autoPoll.detach();
                                     }
-                                } else if (dMode[i]==config2Screen){
+                                } else if (dMode[i]==config2Screen) {
+                                    // Start/stop playback
+                                    if(!playbackOpen){
+                                        if(!logOpen){
+                                            file = fopen("/usb/playback.alc", "rb");                                          
+                                            if(file==NULL){
+                                                sprintf(sTemp,"Unable to open /usb/playback.alc\n");
+                                                logMsg(sTemp);
+                                                spkr.beep(1000,0.25);
+                                            } else {
+                                                playbackOpen = true;
+                                                sprintf(sTemp,"Starting playback\n");
+                                                logMsg(sTemp);
+                                                spkr.beep(2000,0.25);
+                                                can1.attach(&doNothing);// Stop recieving CAN data
+                                                can2.attach(&doNothing);
+                                            }
+                                        } else {
+                                            sprintf(sTemp,"Must stop logging first\n");
+                                            logMsg(sTemp);
+                                        }
+                                    } else {
+                                        playback.detach();
+                                        fclose(file);
+                                        playbackOpen=false;
+                                        can1.attach(&recieve1);// Restore CAN data recieve
+                                        can2.attach(&recieve2);
+                                        lastDMode[i]=99;
+                                    }
+                                    playbackEn=false;
+                                } else if (dMode[i]==dateScreen){
                                     upDate(dtMode,true);
                                     lastDMode[i]=99;
                                 }
                                 break;
                             case 21:
                             case 51:
-                                if (dMode[i]==config2Screen){
+                                if (dMode[i]==dateScreen){
                                     upDate(dtMode,false);
                                     lastDMode[i]=99;
                                 }
@@ -398,14 +458,42 @@
         if(tick){ // Executes once a second
             accV=mon12V*scale12V;
             accOn=(accV>5)?true:false;
-            if(!accOn&&!logEn&&userIdle){
+            if(!accOn&&!logEn&&userIdle&&!playbackEn){
                 dled = 0; // turn off display if car off and logging disabled and no user activity
             }else if(!headlights){
                 dled = ledHi;
             }else{
                 dled = ledLo;
             }
+            if(kWh>0){
+                mpkWh=miles/kWh;
+            }else{
+                mpkWh=99;
+            }
+            miles=0;
+            kWh=0;
             tick=false;
         }
+
+        if(step){ // playback
+            if(playbackOpen&&playbackEn){
+                //sprintf(sTemp,"step\n");
+                //logMsg(sTemp);
+                for(i=0;i<200;i++){
+                    if(!feof(file)){
+                        //for (j = 0; j<5; j++){
+                            fscanf(file,"%5c",&writeBuffer[0][0]);
+                        //}
+                        fscanf(file,"%8c",&data[0]);
+                        logCan(writeBuffer[0][0],CANMessage(0x7ff&((writeBuffer[0][4]<<8)+writeBuffer[0][3]), data, 8));
+                    }else{
+                        fclose(file); // restart
+                        file = fopen("/usb/playback.alc", "rb");                                          
+                        spkr.beep(2000,0.25);
+                    }
+                }
+            }
+            step=false;
+        }
     } //while (true)
 }
\ No newline at end of file
--- a/utility.cpp	Thu Mar 21 12:05:22 2013 +0000
+++ b/utility.cpp	Sat Mar 23 04:43:45 2013 +0000
@@ -44,6 +44,7 @@
     static unsigned char ii = 0, lasti = 0; // indexindex
     unsigned char changed,i;
     static unsigned char bdi;
+    secsNoMsg=0; // reset deadman switch
     if(logOpen){
         if(canRXmsg.id>0) {
             writeBuffer[writePointer][0]=mType;
@@ -160,13 +161,19 @@
     can1.monitor(true); // set to snoop mode
 }
 
-void tickerISR() {  //This is the ticker ISR for auto-polling
+void autoPollISR() {  //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 playbackISR() { //Used for autoplayback
+    step=true;
+}
+
+void doNothing(){ //CAN deattach work-around
+}
+
 void recieve1() {
     CANMessage msg1;
-    secsNoMsg=0; // reset deadman switch
     can1.read(msg1);
     logCan(1, msg1); //EVcan
     led1 = !led1;
@@ -174,7 +181,6 @@
 
 void recieve2() {
     CANMessage msg2;
-    secsNoMsg=0; // reset deadman switch
     can2.read(msg2);
     logCan(2, msg2); //CARcan
     led2 = !led2;
--- a/utility.h	Thu Mar 21 12:05:22 2013 +0000
+++ b/utility.h	Sat Mar 23 04:43:45 2013 +0000
@@ -32,6 +32,10 @@
 extern float ledLo;
 extern unsigned short pollInt;
 extern float scale12V;
+extern bool playbackEn;
+extern bool playbackOpen;
+extern bool step;
+extern float playbackInt;
 
 extern "C" {
     void mbed_reset();
@@ -44,9 +48,11 @@
     void logTS ();    
     void sendCPreq();    
     void sendTreq();    
-    void tickerISR();
+    void autoPollISR();
+    void playbackISR();
     void recieve1();
     void recieve2();
+    void doNothing();
     unsigned char buttonX(unsigned short X, unsigned char columns);
     unsigned char buttonY(unsigned short Y,unsigned char rows);
     void saveConfig();