Attempts to merge SPI_TFT2 & SPI_TFT_ILI9341

Dependencies:   SPI_TFTx2 TFT_fonts TOUCH_TFTx2 mbed

Fork of CANary by Tick Tock

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers displayModes.cpp Source File

displayModes.cpp

00001 //displayModes.cpp
00002 #include "displayModes.h"
00003 
00004 char sTemp1[40];
00005 char sTemp2[16];
00006 
00007 void mainDisplay (bool force, bool showButtons){
00008     unsigned short gids, SOC_x10, packV_x2, tireP;
00009     float dte,total_kW;
00010     unsigned char aTemp;
00011     static unsigned short lgids=0, lSOC=0, lpackV_x2=0, ltireP=0;
00012     static unsigned char laTemp=0;
00013     static float lmaxTemp=0, lkW=0, laccV=0, lmpkWh=0, useable_kWh=0;
00014 
00015     CANMessage msg;
00016 
00017     msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
00018     gids = (msg.data[0]<<2)+(msg.data[1]>>6);
00019     msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC
00020     SOC_x10 = (msg.data[0]<<2)+(msg.data[1]>>6);
00021     msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts
00022     packV_x2 = (msg.data[2]<<2)+(msg.data[3]>>6);
00023     msg = lastMsg[indexLastMsg[0x54c]]; //Get ambient
00024     aTemp = msg.data[6]-56;
00025     msg = lastMsg[indexLastMsg[0x385]]; //Get tire pressure
00026     tireP = msg.data[2]+msg.data[3]+msg.data[4]+msg.data[5];
00027 
00028     tt.background(Navy);
00029     tt.set_font((unsigned char*) Arial28x28);
00030     if(force) tt.cls();
00031     if(skin==ttSkin){
00032         if(force||gids!=lgids){
00033             tt.locate(10,4);
00034             tt.foreground(White);
00035             printf("%dgids \n",gids);
00036             useable_kWh = (float)(gids-5)*kWperGid;
00037             if (useable_kWh<0){
00038                 useable_kWh=0;
00039             }
00040             if(debugMode){
00041                 tt.locate(165,4);
00042                 if (useable_kWh<9.95){
00043                     printf("%3.2f %3.2f\n",useable_kWh,(wh[gids]-400)/1000); //LAJ temp
00044                 } else {
00045                     printf("%3.1f %3.1f\n",useable_kWh,(wh[gids]-400)/1000); //LAJ temp
00046                 }
00047             }else{
00048                 tt.locate(181,4);
00049                 if (useable_kWh<9.95){
00050                     printf("%3.2fkWh\n",useable_kWh);
00051                 } else {
00052                     printf("%3.1fkWh\n",useable_kWh);
00053                 }
00054             }
00055         }
00056         if(force||SOC_x10!=lSOC){
00057             tt.locate(10,34);//216,10
00058             tt.foreground(LightGrey);
00059             printf("%2.1f%s\n",(float)SOC_x10/10,"%");
00060             lSOC=SOC_x10;
00061         }
00062         total_kW=kW[0]+CCkW;
00063         if(force||total_kW!=lkW){
00064             tt.foreground(Yellow);
00065             if(total_kW<=-9.95){ //Right justify
00066                 tt.locate(186,34);
00067                 printf("%3.1fkW\n",total_kW);
00068             } else if (total_kW<0){
00069                 tt.locate(186,34);
00070                 printf("%3.2fkW\n",total_kW);
00071             } else if (total_kW<9.95){
00072                 tt.locate(180,34);
00073                 printf(" %3.2fkW\n",total_kW);
00074             } else {
00075                 tt.locate(180,34);
00076                 printf(" %3.1fkW\n",total_kW);
00077             }
00078             lkW=total_kW;
00079             if(CCon){
00080                 tt.set_font((unsigned char*) Arial12x12);
00081                 tt.locate(228,64);
00082                 tt.foreground(GreenYellow);
00083                 printf("  -%3.2fkW\n",CCkW);
00084                 tt.set_font((unsigned char*) Arial28x28);
00085             }
00086         }
00087         if(force||gids!=lgids||mpkWh[dtePeriod]!=lmpkWh){
00088             // Display DTE
00089             // worst-case DTE
00090             // Compute DTE based on worst saved trip efficiency (without climate control) and adding the impact 
00091             // of the current climate control power relative to the last 10 minutes of driving
00092             if(maxTripEff>0){// Skip if no data available
00093                 dte=convertDistance((minTripEff-mpkWh_noCC+mpkWh[dtePeriod])*useable_kWh); //LM - add metric conversion
00094                 tt.foreground(Green);
00095                 tt.locate(10,84);            
00096                 if(dte>=9.5){
00097                     printf("%2.0f \n",dte);
00098                 }else{
00099                     printf("%2.1f \n",dte);
00100                 }
00101             }
00102             // 10-minute DTE
00103             tt.set_font((unsigned char*) SCProSB31x55);
00104             tt.foreground(Yellow);
00105             dte=convertDistance(mpkWh[dtePeriod]*useable_kWh); //LM - add metric conversion
00106             if(dte>199){
00107                 dte=199;
00108             }
00109             // " "=0x10, "."=0x15, #=0x1D
00110             if(dte>=99.5){
00111                 tt.locate(70,85);
00112                 printf(" %3.0f\n",dte); 
00113             }else if(dte>=9.5){
00114                 tt.locate(84,85);
00115                 printf("  %2.0f\n",dte);
00116             }else{
00117                 tt.locate(79,85);
00118                 printf(" %2.1f\n",dte);
00119             }
00120             tt.set_font((unsigned char*) Arial28x28);
00121             tt.locate(185,106);
00122             printf("%s\n",distanceUnit());
00123 
00124             // No Climate Control DTE
00125             tt.set_font((unsigned char*) Arial24x23);
00126             if(CCon) {
00127                 dte=convertDistance((mpkWh_noCC-mpkWh[dtePeriod])*useable_kWh); //LM - add metric conversion
00128                 if(dte>199){
00129                     dte=199;
00130                 }
00131                 tt.foreground(GreenYellow);
00132                 if(dte>=9.5){
00133                     tt.locate(130,134);
00134                     printf("+%2.0f \n",dte);
00135                 }else{
00136                     tt.locate(130,134);
00137                     printf("+%2.1f \n",dte);
00138                 }
00139                 
00140                 lmaxTemp=0; //force battery termperature refresh (sometimes overlaps)
00141             }
00142             // best-case DTE
00143             tt.set_font((unsigned char*) Arial28x28);
00144             // Compute DTE based on best saved trip efficiency (without climate control) and adding the impact 
00145             // of the current climate control power relative to the last 10 minutes of driving
00146             if(maxTripEff>0){// Skip if no data available
00147                 dte=convertDistance((maxTripEff-mpkWh_noCC+mpkWh[dtePeriod])*useable_kWh); //LM - add metric conversion
00148                 tt.foreground(Orange);
00149                 if(dte>=99.5){
00150                     tt.locate(255,84);            
00151                     printf("%3.0f \n",dte);          
00152                 }else if(dte>=9.5){
00153                     tt.locate(270,84);            
00154                     printf("%2.0f \n",dte);
00155                 }else{
00156                     tt.locate(265,84);            
00157                     printf("%2.1f \n",dte);
00158                 }
00159             }
00160             lmpkWh=mpkWh[dtePeriod];
00161         } //!(force||gids!=lgids||mpkWh[dtePeriod]!=lmpkWh)
00162         lgids=gids;
00163         if(force||packV_x2!=lpackV_x2){
00164             tt.locate(210,176);
00165             tt.foreground(Yellow);
00166             printf("%4.1fV\n",(float)packV_x2/2);
00167             lpackV_x2=packV_x2;
00168             ltireP=0;//Force tire pressure redraw, too
00169         }
00170         if(force||aTemp!=laTemp){
00171             tt.foreground(Cyan);
00172             tt.locate(10,146);
00173             printf("%2.0f%s\n",convertF(aTemp),temperatureUnit());
00174             laTemp=aTemp;
00175         }
00176         if(force||maxTemp!=lmaxTemp){
00177             tt.foreground(Cyan);
00178             tt.locate(210,146);
00179             if (convertC(maxTemp)<99.5){
00180                 printf(" %3.1f%s\n",convertC(maxTemp),temperatureUnit());
00181             }else{
00182                 printf("%4.1f%s\n",convertC(maxTemp),temperatureUnit());
00183             }
00184             lmaxTemp=maxTemp;
00185         }
00186         if(force||accV!=laccV){
00187             tt.locate(10,176);
00188             tt.foreground(Yellow);
00189             printf("%3.1fV  \n",accV);
00190             laccV=accV;
00191         }
00192         if(force||tireP!=ltireP){
00193             if(msg.data[2]<minTirePressure){
00194                 tt.foreground(Orange); // Hi-light if any are low (<35psi)
00195             }else{
00196                 tt.foreground(LightGrey);
00197             }
00198             if(msg.data[6]&0x80){
00199                 if(msg.data[2]<minTirePressure){
00200                     tt.foreground(Orange); // Hi-light if any are low (<35psi)
00201                 }else{
00202                     tt.foreground(LightGrey);
00203                 }
00204                 tt.locate(10,206);
00205                 printf("%3.1f\n",(float)msg.data[2]/4);
00206             }
00207             if(msg.data[6]&0x40){
00208                 if(msg.data[3]<minTirePressure){
00209                     tt.foreground(Orange); // Hi-light if any are low (<35psi)
00210                 }else{
00211                     tt.foreground(LightGrey);
00212                 }
00213                 tt.locate(90,206);
00214                 printf("%3.1f\n",(float)msg.data[3]/4);
00215             }
00216             if(msg.data[6]&0x20){
00217                 if(msg.data[4]<minTirePressure){
00218                     tt.foreground(Orange); // Hi-light if any are low (<35psi)
00219                 }else{
00220                     tt.foreground(LightGrey);
00221                 }
00222                 tt.locate(170,206);
00223                 printf("%3.1f\n",(float)msg.data[4]/4);
00224             }
00225             if(msg.data[6]&0x10){
00226                 if(msg.data[5]<minTirePressure){
00227                     tt.foreground(Orange); // Hi-light if any are low (<35psi)
00228                 }else{
00229                     tt.foreground(LightGrey);
00230                 }
00231                 tt.locate(250,206);
00232                 printf("%3.1f\n",(float)msg.data[5]/4);
00233             }
00234             ltireP=tireP;
00235         }
00236     }else {//if(skin==ggSkin){
00237         if(force||gids!=lgids){
00238             tt.locate(10,10);
00239             printf("%4d GIDs \n",gids);
00240             
00241             tt.locate(40,40); // gg - add GIDs Percent of 281
00242             printf("%4.1f%s \n", (float)gids*0.355872, "% ") ;
00243             tt.locate(20,70);
00244             printf("%4.1f kwh  \n",(float)gids*kWperGid); // gg - closer to usable
00245             
00246             tt.set_font((unsigned char*) SCProSB31x55);
00247             tt.foreground(Green);
00248             //tt.locate(60,96);
00249             tt.locate(60,116); // gg - move down a little
00250             printf("%4.1f %s  \n",convertDistance((float)(gids-5)*0.31),distanceUnit()); // Approx for now - LM added metric
00251             lgids=gids;
00252             tt.foreground(Yellow);
00253             tt.set_font((unsigned char*) Arial28x28);
00254         }
00255         
00256         if(force||SOC_x10!=lSOC){
00257             tt.locate(200,10);
00258             printf("%4.1f%s\n",(float)SOC_x10/10,"% ");
00259             lSOC=SOC_x10;
00260         }
00261         if(force||packV_x2!=lpackV_x2){
00262             tt.locate(200,200);
00263             printf("%4.1fV \n",(float)packV_x2/2);
00264             lpackV_x2=packV_x2;
00265         }
00266         if(force||accV!=laccV){
00267             tt.locate(20,200);
00268             printf("%3.1fV  \n",accV);
00269             laccV=accV;
00270         }
00271         total_kW=kW[0]+CCkW;
00272         if(force||total_kW!=lkW){
00273             tt.locate(160,40); // gg - move left to keep from wrap
00274             printf("%3.2fkw \n",total_kW); // use small w to save space
00275             lkW=total_kW;
00276         }
00277     }
00278     if(led4){
00279         tt.fillcircle(310,10,6,Red);
00280     }else{
00281         tt.fillcircle(310,10,6,Navy);
00282     }
00283 }
00284 
00285 void printLast (bool force, bool showButtons){
00286     CANMessage msg;
00287     tt.locate(0,6);
00288     tt.foreground(Red);
00289     tt.background(Yellow);
00290     if(force) tt.cls(); // Just clear screen if forced - always update display
00291     tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00292     for(int i=0; i<19; i++){
00293         msg = lastMsg[i+indexOffset];
00294         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]);
00295     }
00296     if(showButtons){
00297         showButton(0,0," <up>","",4,4);
00298         showButton(2,0,"<down>","",4,4);
00299     }
00300 }
00301 
00302 void printChanged (bool force, bool showButtons){
00303     CANMessage msg;
00304     unsigned char i,j;
00305     tt.locate(0,6);
00306     tt.foreground(Red);
00307     tt.background(Yellow);
00308     if(force) tt.cls(); // Just clear screen if forced - always update display
00309     tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00310     i=0;
00311     j=indexOffset;
00312     do{
00313         j=j<99?j+1:j;
00314         if(msgChanged[j]>0){
00315             msg = lastMsg[j];
00316             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]);
00317             i++;
00318         }// if changed
00319     }while(i<19&&j<99);
00320     if(showButtons){
00321         showButton(0,0,"  <up>","",4,4);
00322         showButton(2,0," <down>","",4,4);
00323         showButton(1,0," Reset","Baseline",4,4);
00324     }
00325 }
00326 
00327 void printLog (bool force, bool showButtons){
00328     static unsigned char lastldl = 0;
00329     unsigned char ldl=displayLoc;
00330     if(force||ldl!=lastldl){ //only update if changed
00331         tt.foreground(Amber);
00332         tt.background(Black);
00333         tt.cls();
00334         tt.locate(0,6);
00335         tt.set_font((unsigned char*) Arial12x12);
00336         for(int i=0; i<19; i++){
00337             printf("%s",displayLog[ldl]);
00338             ldl=ldl>17?0:ldl+1;
00339         }
00340     }
00341     lastldl=ldl;
00342 }
00343 
00344 void tripDisplay (bool force, bool showButtons, bool inclCC){
00345     static int lkWh=0;
00346     float mpkWh_f, kWh_f;
00347     tt.background(White);
00348     if(force){
00349         tt.cls();
00350     }
00351     if(force||(lkWh!=(int)(kWh_trip[0]*100))){ //only update if changed
00352         tt.foreground(Navy);
00353         tt.set_font((unsigned char*) Arial28x28);
00354         tt.locate(6,210);
00355         printf("kWh : %s : Eff\n",distanceUnit());
00356         tt.set_font((unsigned char*) Arial12x12);
00357         tt.locate(260,220);
00358         if(inclCC){
00359             printf(" (+CC)\n");
00360         } else {
00361             printf("(noCC)\n");
00362         }
00363         tt.set_font((unsigned char*) Arial28x28);
00364         for(int i=0; i<3; i++){
00365             kWh_f = kWh_trip[i];
00366             if(inclCC){
00367                 kWh_f += CCkWh_trip[i];
00368             }
00369             if(kWh_f>0.01){
00370                 mpkWh_f = convertDistance(miles_trip[i])/kWh_f;
00371             } else {
00372                 mpkWh_f = 0;
00373             }
00374             tt.locate(6,20+i*60);
00375             printf("%3.2f : %3.1f : %2.1f  \n",kWh_f,convertDistance(miles_trip[i]),mpkWh_f);
00376         }
00377         tt.foreground(Navy);
00378         tt.set_font((unsigned char*) Arial12x12);
00379         tt.locate(274,18);
00380         printf("per\n");
00381         tt.locate(274,33);
00382         printf("trip\n");
00383         tt.locate(274,78);
00384         printf("per\n");
00385         tt.locate(265,93);
00386         printf("charge\n");
00387         tt.locate(265,145);
00388         printf("custom\n");
00389         lkWh=(int)(kWh_trip[0]*100);
00390     }
00391     if(showButtons){
00392         showButton(3,1," Cancel","  Day",4,4);
00393         showButton(3,2," Reset","Custom",4,4);
00394     }
00395 }
00396 
00397 void healthDisplay (bool force, bool showButtons){
00398     unsigned short gids, SOC_x10, SOH_x2;
00399     static unsigned short lgids=0, lSOC=0, lSOH=0;
00400     static float lmaxTemp=0, lresr=0, lunlV=0;
00401     static unsigned long lAh=0;
00402     CANMessage msg;
00403 
00404     msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
00405     gids = (msg.data[0]<<2)+(msg.data[1]>>6);
00406     msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC
00407     SOC_x10 = (msg.data[0]<<2)+(msg.data[1]>>6);
00408     msg = lastMsg[indexLastMsg[0x5b3]]; //Get SOH
00409     SOH_x2 = msg.data[1];
00410 
00411     tt.background(Blue);
00412     tt.foreground(Yellow);
00413     tt.set_font((unsigned char*) Arial28x28);
00414     if(force) tt.cls();
00415 
00416     /*if(force||tock){ // for esr debug
00417         tt.locate(10,10);
00418         printf("%d %d amps\n",Imax,Imin);
00419         tt.locate(10,40);
00420         printf(" %4.1f %4.1f\n",incRmax/2,incRmin/2);
00421         tt.locate(10,70);
00422         printf(" %4.1f %4.1f\n",redRmax/2,redRmin/2);
00423         tt.locate(10,100);
00424         printf(" %4.1f %4.1f\n",curRmax/2,curRmin/2);
00425         //tt.locate(10,130);
00426         curRmin=1000;
00427         curRmax=0;
00428         incRmin=1000;
00429         incRmax=0;
00430         redRmin=1000;
00431         redRmax=0;
00432         Imax=-1000;
00433         Imin=1000;
00434     }*/
00435     if(force||gids!=lgids){
00436         tt.locate(10,10);
00437         if(dailyGids>5){ // Wh/gid, too
00438             printf("%d gids (%0.0f)\n",gids,1000*(kWh_trip[3]+CCkWh_trip[3])/dailyGids);
00439         }else{
00440             printf("%d gids \n",gids);
00441         }
00442         lgids=gids;
00443     }
00444     if(force||SOC_x10!=lSOC){
00445         tt.locate(10,40);
00446         printf("%4.1f%s SOC \n",(float)SOC_x10/10,"%");
00447         lSOC=SOC_x10;
00448     }
00449     if(force||SOH2_x100!=lSOH){
00450         tt.locate(10,70);
00451         printf("%d%s SOH, %3.1f Hx \n",SOH_x2/2,"%",(float)SOH2_x100/100);
00452         lSOH=SOH2_x100;
00453     }
00454     if(force||Ah_x10000!=lAh){
00455         tt.locate(10,100);
00456         printf("%4.2f Ah cap \n",(float)Ah_x10000/10000);
00457         lAh=Ah_x10000;
00458     }
00459     if(force||maxTemp!=lmaxTemp){
00460         tt.locate(10,130);
00461         printf("%4.1f %s (max) \n",convertC(maxTemp),temperatureUnit());
00462         lmaxTemp=maxTemp;
00463     }
00464     if(force||unloadedV_x2!=lunlV){
00465         tt.locate(10,160);
00466         printf("%4.1f V \n",unloadedV_x2/2);
00467         lunlV=unloadedV_x2;
00468     }
00469     if(force||Resr!=lresr){
00470         tt.locate(10,190);
00471         printf("%3.0f mOhms \n",Resr*1000);
00472         lresr=Resr;
00473     }
00474 }
00475 
00476 void braking (bool force, bool showButtons, bool prdata=false){
00477     unsigned long targetBraking, regenBraking;
00478     //static unsigned long maxTarget = 1000, maxRegen = 1000, tardivreg_x1000 = 1000;
00479     static unsigned long maxRegen = 1000, tardivreg_x1000 = 1000;
00480     unsigned long temp;
00481     static unsigned char lastPressure[4] = {200,200,200,200};
00482     unsigned char i,r,t;
00483     static unsigned char lr=0, lt=0;
00484     signed short steering;
00485     unsigned short s;
00486     static unsigned short ls;
00487     unsigned char throttle;
00488     static unsigned char lthrottle;
00489     short steerOutBounds = 0 ;
00490     CANMessage msg;
00491 
00492     //---------------
00493     msg = lastMsg[indexLastMsg[0x180]]; //Get Throttle position
00494     throttle = msg.data[5];
00495     
00496     // ---- steering ----
00497     msg = lastMsg[indexLastMsg[0x002]]; //Get Steering angle
00498     steering = (msg.data[1]<<8)+msg.data[0];
00499     
00500     if(skin==ttSkin){
00501         s= (unsigned short) ((steering/10)+155)%310; // this modulo wraps display
00502     }else{// if(skin==ggSkin){    
00503         // do not go off screen left or right. gg - steering
00504         short ss = (short) ((steering/15)+160); // less gain 10 -> 15
00505         if(ss<0) { ss=0; steerOutBounds = 1; }
00506         if(ss>310) { ss=310; steerOutBounds = 1; }
00507         s = (unsigned short) ss;
00508     }
00509     
00510     //--------------
00511     msg = lastMsg[indexLastMsg[0x1ca]]; //Get brake pressure
00512     tt.background(Navy);
00513     if (force) {
00514         tt.cls();
00515         tt.rect(0,111,170,239,White);
00516         tt.line(0,207,170,207,White);
00517         tt.line(0,175,170,175,White);
00518         tt.line(0,143,170,143,White);
00519         lastPressure[0] = 200;
00520         lastPressure[1] = 200;
00521         lastPressure[2] = 200;
00522         lastPressure[3] = 200;
00523     }
00524     
00525     // display the steering position small square
00526     if (s!=ls){
00527         // steering position has moved
00528         //tt.fillrect(ls,5,ls+9,14, Navy);    // blank old position    
00529         
00530         //---- gg - steering red
00531         // box is blanked by top of Braking bar, so move up 5
00532         tt.fillrect(ls,0,ls+9,9, Navy);    // blank old position    
00533         if( steerOutBounds != 0 ) // draw out-of-bounds as a red box 
00534             tt.fillrect(s,0,s+9,9, Red);     // draw out-of-bounds position 
00535         else
00536             tt.fillrect(s,0,s+9,9, White);   // draw new in-bounds position 
00537             
00538         //----
00539         //tt.foreground(Yellow);
00540         //tt.set_font((unsigned char*) Arial28x28);
00541         //tt.locate(10,40);
00542         //printf("%d %d    \n",s,ls);
00543         ls=s;
00544     }
00545     
00546     if (throttle!=lthrottle){
00547         if (throttle>239) throttle=239;
00548         if(throttle<lthrottle){
00549             tt.fillrect(280,239-lthrottle,310,239-throttle,Navy);
00550         }else{
00551             tt.fillrect(280,239-throttle,310,239,Yellow);
00552         }
00553         lthrottle=throttle;
00554     }
00555 
00556     // plot bar graph for each wheel pressure
00557     for (i=0; i<4; i++){
00558         if (msg.data[i]<239) {
00559             if (msg.data[i]>lastPressure[i]){
00560                 tt.fillrect(10+40*i,239-msg.data[i],40+40*i,239,Red);
00561             } else if (msg.data[i]<lastPressure[i]) {
00562                 tt.fillrect(10+40*i,238-lastPressure[i],40+40*i,238-msg.data[i],Navy);
00563             }
00564             lastPressure[i]=msg.data[i];
00565         }
00566     }
00567 
00568     msg = lastMsg[indexLastMsg[0x1cb]];
00569     targetBraking = (msg.data[2]<<3)+(msg.data[3]>>5); //Get target total braking force
00570     //regenBraking = (msg.data[0]<<3)+(msg.data[1]>>5); //Get target regen portion
00571     msg = lastMsg[indexLastMsg[0x1d5]]; //Get regen portion - seems to be actual regen versus target regen
00572     regenBraking = (msg.data[0]<<3)+(msg.data[1]>>5);
00573 
00574     if (targetBraking<2045){
00575         if ((targetBraking>50)&&(regenBraking>50)){
00576             temp = targetBraking;
00577             temp *= 1000;
00578             temp /= regenBraking;
00579             if (temp<tardivreg_x1000) tardivreg_x1000=temp;
00580         }
00581         if (targetBraking>maxTarget) maxTarget=targetBraking;
00582         if (regenBraking>maxRegen) maxRegen=regenBraking;
00583         temp = targetBraking;
00584         temp *=200;
00585         temp /= maxTarget;
00586         t = (char) temp;
00587         if (t>200) t=200;
00588         temp = regenBraking;
00589         temp *= tardivreg_x1000;
00590         temp /= maxTarget;
00591         temp /= 5; // 1000/200=5
00592         r = (char) temp;
00593         if (r>200) r=200;
00594         if(lr!=r&&prdata){
00595             tt.foreground(Yellow);
00596             tt.set_font((unsigned char*) Arial28x28);
00597             tt.locate(100,40);
00598             printf("%d %d    \n",regenBraking,maxRegen);
00599             tt.locate(100,70);
00600             printf("%3.1f (%3.1f%s)    \n",(float)tardivreg_x1000/10,(float)regenBraking*tardivreg_x1000/targetBraking/10,"%");
00601         }    
00602         if(lt!=t&&prdata){
00603             tt.foreground(Yellow);
00604             tt.set_font((unsigned char*) Arial28x28);
00605             tt.locate(100,10);
00606             printf("%d %d    \n",targetBraking,maxTarget);
00607         }
00608         if (r>t) t=r;  //Should never happen
00609         if((lr!=r||lt!=t)&&!prdata){
00610             tt.fillrect(190,10,260,239-t,Navy);
00611             tt.fillrect(190,239-t,260,239-r,Red);
00612             tt.fillrect(190,239-r,260,239,Green);
00613         }
00614         lt=t;
00615         lr=r;
00616     }
00617 }
00618 
00619 void cpData(bool force, bool showButtons){
00620     short unsigned max, min, jv, i, bd;
00621     unsigned avg;
00622     static char step=0; // counter to allow incremental update
00623     if(force){
00624         tt.foreground(White);
00625         tt.background(Navy);
00626         tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00627         max=0;
00628         min=9999;
00629         avg=0;
00630         for(i=0; i<96; i++){
00631            bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4];
00632            avg+=bd;
00633             if(bd>max) max=bd;
00634             if(bd<min) min=bd;
00635         }
00636         avg /= 96;
00637         if(min<3713) {
00638             jv=avg-(max-avg)*1.5;
00639         } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement
00640             jv=0;
00641         }
00642 
00643         char* sTemperatureUnit = temperatureUnit();
00644         switch(step){
00645             case 0:
00646                 tt.cls();
00647                 showCP=true;
00648                 break;
00649             case 1:
00650                 tt.locate(0,6);
00651                 printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %2.0f%s %2.0f%s %2.0f%s %2.0f%s\n\n",
00652                     max,min,avg,jv, convertC(battData[BatDataBaseG4*7+5]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+8]),sTemperatureUnit,
00653                     convertC(battData[BatDataBaseG4*7+11]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+14]),sTemperatureUnit);
00654                 tt.rect(8+0*41,16,40+0*41,28,Green);
00655                 tt.rect(8+1*41,16,40+1*41,28,Yellow);
00656                 //tt.rect(8+2*41,16,40+2*41,28,White);
00657                 tt.rect(8+3*41,16,40+3*41,28,Red);
00658                 break;
00659             default:
00660                 tt.locate(0,36+(step-2)*48);
00661                 for(i=(step-2)*4; i<(step-1)*4; i++){
00662                     printf("%02d-%02d : %04d %04d %04d %04d %04d %04d\n",
00663                         i*6+1,i*6+6,
00664                         (battData[BatDataBaseG2*7+i*12+3]<<8)+battData[BatDataBaseG2*7+i*12+4],(battData[BatDataBaseG2*7+i*12+5]<<8)+battData[BatDataBaseG2*7+i*12+6],
00665                         (battData[BatDataBaseG2*7+i*12+7]<<8)+battData[BatDataBaseG2*7+i*12+8],(battData[BatDataBaseG2*7+i*12+9]<<8)+battData[BatDataBaseG2*7+i*12+10],
00666                         (battData[BatDataBaseG2*7+i*12+11]<<8)+battData[BatDataBaseG2*7+i*12+12],(battData[BatDataBaseG2*7+i*12+13]<<8)+battData[BatDataBaseG2*7+i*12+14]);
00667                 }
00668                 for(i=(step-2)*24; i<(step-1)*24; i++){
00669                     bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4];
00670                     if(bd>0){
00671                         if(bd==max) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Green);
00672                         //if(bd==avg) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,White);
00673                         if(bd==min) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Yellow);
00674                         if(bd<jv) tt.rect(58+(i%6)*41,34+(int)(i/6)*12,90+(i%6)*41,46+(int)(i/6)*12,Red);
00675                     }
00676                 }
00677         }
00678         step=step<5?step+1:0;
00679         if(step==0){
00680             showCP=false;
00681         }
00682     }
00683     if(showButtons){
00684         showButton(1,0,"Request","CP Data",4,4);               
00685     }
00686 }
00687 
00688 //----------------
00689 // gg - index
00690 void showIndex(bool force, bool showButtons){ 
00691 
00692     if(force){
00693         tt.foreground(White);
00694         tt.background(Navy);
00695         //tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00696        
00697         tt.cls();
00698         
00699         // add the buttons to GoTo to other screens
00700 
00701         // top row
00702         showButton(0,0," GoTo"," Main",4,4);               
00703         showButton(1,0," GoTo"," Brake",4,4);               
00704         showButton(2,0," GoTo"," EFF",4,4);               
00705         showButton(3,0," GoTo","Health",4,4);     
00706         // middle row
00707         showButton(0,1," GoTo","CP Data",4,4);               
00708         showButton(1,1," GoTo","CP Hist",4,4);               
00709         showButton(2,1," GoTo","CP Bars",4,4);     
00710         showButton(3,1," GoTo"," Config",4,4);               
00711         // bottom (not Nav) row        
00712         showButton(0,2," GoTo","Playback",4,4);
00713         //showButton(1,2," GoTo","Set Time",4,4);             
00714         showButton(2,2," GoTo"," Log",4,4);     
00715         showButton(3,2," GoTo"," Trip",4,4);     
00716     
00717         showCP=false;
00718     }
00719     
00720     if(sMode==1&&showButtons){
00721         tt.foreground(Yellow);
00722         tt.background(DarkCyan);
00723         tt.set_font((unsigned char*) Arial12x12);
00724         
00725         // do nothing here?
00726     }
00727 }
00728 
00729 //----------------
00730 // gg - cpbars
00731 void cpBarPlot(bool force, bool showButtons){ 
00732     short unsigned max, min, jv, i, bd;
00733     unsigned avg;
00734     short unsigned nBar[96] ; // bar height over min
00735 
00736     if(force){
00737         tt.foreground(White);
00738         tt.background(Navy);
00739         tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00740         max=0;
00741         min=9999;
00742         avg=0;
00743        
00744         // calc each cell-pair voltage, find max and min
00745         for(i=0; i<96; i++){
00746            bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4];
00747            nBar[i] = bd; // init to bar height
00748            avg+=bd;
00749             if(bd>max) max=bd;
00750             if(bd<min) min=bd;
00751         }
00752         avg /= 96;
00753         
00754         if(min<3713) {
00755             jv=avg-(max-avg)*1.5;
00756         } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement
00757             jv=0;
00758         }
00759         
00760         //------------------
00761         tt.cls();
00762             
00763         // show as vertical bar plot
00764         int xWinMin = 26;
00765         int xWinMax = 316;
00766         int yWinMin = 50;
00767         int yWinMax = 150;
00768         // draw the Bar Graph Frame, 2 pixels wide
00769         tt.rect( xWinMin-1,yWinMin-1, xWinMax+1,yWinMax+1,Red);
00770         tt.rect( xWinMin-2,yWinMin-2, xWinMax+2,yWinMax+2,Green);
00771         
00772         // bar heights
00773         int height = yWinMax - yWinMin ;
00774         int iBarValMax = max - min ; // zero to N
00775         
00776         //----------------
00777         if( iBarValMax == 0 ) {
00778             // for testing
00779             min = 3501 ; 
00780             //max = min + 95*2 ; // for tall values
00781             max = min + 95/4 ; // for small values
00782             avg = ( max + min ) / 2;
00783             iBarValMax = max - min ; // zero to N
00784             for(int i=0; i<96; i++) {
00785               //nBar[i] = i*2 + min ; // test tall values
00786               nBar[i] = i/4 + min ; // test small values
00787             }
00788         }
00789         //---------------
00790         float nBarScale = float(height) / iBarValMax ;
00791         if( nBarScale < 0.1 ) nBarScale = 0.1 ;
00792     
00793         // do the Bar-height scaling
00794         for(int i=0; i<96; i++){
00795           nBar[i] -= min ; // now, 0 to N = iBinValMax
00796           nBar[i] *= nBarScale ; // scale, as needed
00797         }
00798         
00799         // label the Y axis
00800         tt.locate( 2, yWinMin-14 ); printf("%04d = (%d) mv range.\n", max , max - min );
00801         tt.locate( 2, yWinMax+5); printf("%04d\n", min );
00802 
00803         // BatDataBaseG4 * 7 = 280
00804         tt.locate( 0, yWinMax+40 );
00805         char* sTemperatureUnit = temperatureUnit();
00806         printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %2.0f%s %2.0f%s %2.0f%s %2.0f%s\n",
00807             max,min,avg,jv, convertC(battData[BatDataBaseG4*7+5]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+8]),sTemperatureUnit,
00808             convertC(battData[BatDataBaseG4*7+11]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+14]),sTemperatureUnit);
00809         //printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %02dC %02dC %02dC %02dC\n\n",
00810         //        max,min,avg,jv,  battData[BatDataBaseG4*7+5],battData[BatDataBaseG4*7+8],  battData[BatDataBaseG4*7+11],battData[BatDataBaseG4*7+14]);
00811         
00812                
00813         //---------------
00814         // show the bars
00815         int nBarWidth = 2 ;
00816         int nBarSpace = 1 ; // 1 for testing
00817         
00818         int xPos = xWinMin + 2 ; // start one from the left
00819          
00820         for( int i=0; i<96; i++) {
00821             height = nBar[i] ;
00822             if( height > 100 ) height = 100 ; // clip tops
00823             
00824             // draw the bar, is always inside x-window
00825             if (shunt[i]){
00826                 tt.fillrect( xPos,yWinMax-height, xPos+nBarWidth-1,yWinMax, Red);  
00827             } else {
00828                 tt.fillrect( xPos,yWinMax-height, xPos+nBarWidth-1,yWinMax, Green);  
00829             }
00830             // tic mark the y axis each 5
00831             if(i%5 == 4){
00832                tt.line( xPos,yWinMax+2, xPos,yWinMax+5, White);  // a white tick mark
00833                tt.line( xPos+1,yWinMax+2, xPos+1,yWinMax+5, White);  // a white tick mark, to widen
00834                //tt.rect( xPos,yWinMax+2, xPos+1,yWinMax+5, White);  // a white 2-wide tick mark is SLOW
00835             }
00836             // label the y axis each 10
00837             if(i%10 == 9){
00838                tt.locate( xPos-6, yWinMax+8 );
00839                printf("%02d\n", i+1 );
00840             }
00841             
00842             // step to the next bar position
00843             xPos += nBarWidth + nBarSpace ; 
00844         }
00845         
00846         showCP=false;
00847     }
00848     
00849     // handle the button
00850     if(sMode==1&&showButtons){
00851         showButton(1,0,"Request","CP Data",4,4);               
00852     }
00853 }
00854 
00855 //----------------
00856 // gg - hist
00857 void cpHistogram(bool force, bool showButtons){ 
00858     short unsigned max, min, jv, i, bd;
00859     unsigned avg;
00860     if(force){
00861         tt.foreground(White);
00862         tt.background(Navy);
00863         tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
00864         max=0;
00865         min=9999;
00866         avg=0;
00867         for(i=0; i<96; i++){
00868            bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4];
00869            avg+=bd;
00870             if(bd>max) max=bd;
00871             if(bd<min) min=bd;
00872         }
00873         avg /= 96;
00874         if(min<3713) {
00875             jv=avg-(max-avg)*1.5;
00876         } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement
00877             jv=0;
00878         }
00879         //------------------
00880         tt.cls();
00881             
00882         // show as histogram
00883         int xWinMin = 20;
00884         int xWinMax = 300;
00885         int yWinMin = 50;
00886         int yWinMax = 150;
00887 
00888         // binning
00889         short nBin[301] ; // bins to count Min values in nBin[0], etc.
00890         int height;
00891         int iBinValMax = max - min ; // zero to N
00892         int iBinIndxMax = (xWinMax-xWinMin)/2; // Maximum number of bars
00893         if( iBinValMax > iBinIndxMax ) iBinValMax = iBinIndxMax ;
00894     
00895         // clean the bins
00896         for(int i=0; i<=iBinIndxMax; i++) {
00897           nBin[i] = 0;
00898         }
00899         
00900         // do the bin counting
00901         for(int i=0; i<96; i++){
00902           bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4] - min ;
00903           if( bd > iBinValMax ) bd = iBinValMax ;
00904           nBin[bd]++ ;
00905         }
00906  
00907         //----------------
00908         if( iBinValMax == 0 ) { // dummy data if no real data
00909             min = 10 ; 
00910             max = 50 ;
00911             avg = ( max + min ) / 2;
00912             iBinValMax = max - min ;
00913             for(int i=0; i<=(iBinValMax/2); i++) {
00914               nBin[i] = i ;
00915               nBin[iBinValMax-i] = i ;
00916             }
00917         }
00918 
00919         // label the Y axis
00920         tt.locate( 0, yWinMin ); printf("25\n");
00921         tt.locate( 0, yWinMax-6 ); printf("0\n");  
00922         tt.locate( xWinMin-12, yWinMax+6 ); printf("%04d\n", min);
00923         tt.locate( xWinMax-18, yWinMax+6 ); printf("%04d\n", max);
00924         // draw the Histogram Frame, 2 pixels wide
00925         tt.rect( xWinMin-1,yWinMin-1, xWinMax+0,yWinMax+0,Red);
00926         tt.rect( xWinMin-2,yWinMin-2, xWinMax+1,yWinMax+1,Green);
00927         tt.locate( 0, yWinMax+40 );
00928         char* sTemperatureUnit = temperatureUnit();
00929         printf(" MAX  MIN  AVG CVLI T1  T2  T3  T4\n %04d %04d %04d %04d %2.0f%s %2.0f%s %2.0f%s %2.0f%s\n\n",
00930             max,min,avg,jv, convertC(battData[BatDataBaseG4*7+5]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+8]),sTemperatureUnit,
00931             convertC(battData[BatDataBaseG4*7+11]),sTemperatureUnit,convertC(battData[BatDataBaseG4*7+14]),sTemperatureUnit);
00932         
00933         //---------------
00934         // show the bars
00935         int nBarWidth = (xWinMax-xWinMin)/(iBinValMax+1)-1;
00936         if (nBarWidth < 1) nBarWidth = 1;
00937         int nBarSpace = 1 ;
00938         
00939         int xPos = (xWinMin + xWinMax)/2; 
00940         xPos -= ((iBinValMax+1)*(nBarWidth+nBarSpace))/2 ;
00941 
00942         for( int i=0; i<=iBinValMax; i++) {
00943             height = 4 * nBin[i] ;
00944             if( height > 100 ) height = 100 ; // clip tops
00945             
00946             // if inside the window, draw the bar
00947             if( ( xPos + nBarWidth < xWinMax ) && ( xPos > xWinMin ) )
00948               tt.fillrect( xPos,yWinMax-height, xPos+nBarWidth-1,yWinMax, Green);  
00949               
00950             // step to the next bar position
00951             xPos += nBarWidth + nBarSpace ; 
00952         }
00953         
00954         showCP=false;
00955     }
00956     
00957     // handle the button
00958     if(sMode==1&&showButtons){
00959         showButton(1,0,"Request","CP Data",4,4);               
00960     }
00961 }
00962 
00963 //---------------
00964 void config(bool force, bool showButtons){
00965     if (force) {
00966         tt.background(Black);
00967         tt.cls();
00968     }
00969     //-------- top row --------
00970     showButton(1,0," Reset","CANary",4,4);
00971     showButton(2,0,"  Save"," Config",4,4);
00972                
00973     //------- second row -----
00974     if (logEn&&usbEn) {
00975         sprintf(sTemp1,"Disable");
00976     } else {
00977         sprintf(sTemp1,"Enable");
00978     }
00979     showButton(0,1,sTemp1,"Logging",4,4);
00980     
00981     if (repeatPoll) {
00982         sprintf(sTemp1,"Disable");
00983     } else {
00984         sprintf(sTemp1,"Enable");
00985     }
00986     showButton(1,1,sTemp1,"Auto CP",4,4);
00987     
00988     // add Enable/Disable Batt Log gg - yesBattLog
00989     if (yesBattLog) {
00990         sprintf(sTemp1,"Disable");
00991     } else {
00992         sprintf(sTemp1,"Enable");
00993     }
00994     showButton(2,1,sTemp1,"Batt Log",4,4);
00995 
00996     //------- third row -----
00997     if(brakeMon)
00998         showButton(0,2,"Disable","BrkMon",4,4);
00999     else
01000         showButton(0,2," Enable"," BrkMon",4,4);
01001 
01002     if(regenMon)
01003         showButton(1,2,"Disable","RegMon",4,4);
01004     else
01005         showButton(1,2," Enable"," RegMon",4,4);
01006 
01007     if(heaterMon)
01008         showButton(2,2,"Disable","HeatMon",4,4);
01009     else
01010         showButton(2,2," Enable","HeatMon",4,4);
01011 
01012 }
01013 
01014 void config2(bool force, bool showButtons){
01015     if (force) {
01016         tt.background(Black);
01017         tt.cls();
01018     }
01019     //-------- top row --------
01020     showButton(0,0,"Calibrate"," Touch",4,4); // gg - 4x4
01021     showButton(1,0," Reset","Max/Min",4,4);
01022      if (showHealth) {
01023         sprintf(sTemp1," Hide");
01024     } else {
01025         sprintf(sTemp1," Show");
01026     }
01027     showButton(2,0,sTemp1," Health",4,4);
01028          
01029     // a button to step to the next skin
01030     unsigned int nextSkin = skin + 1 ;
01031     if( nextSkin > maxSkin ) nextSkin = 0 ;
01032     
01033     if( nextSkin == ttSkin ) sprintf(sTemp1,"Skin TT");
01034     else if( nextSkin == ggSkin ) sprintf(sTemp1,"Skin GG");
01035     else sprintf(sTemp1,"Skin %d",nextSkin);
01036 
01037     showButton(3,0,"  Use",sTemp1,4,4);
01038     
01039     //------- second row -----
01040     // add Enable/Disable Debug - debugMode
01041     if (debugMode) {
01042         sprintf(sTemp1," Disable");
01043     } else {
01044         sprintf(sTemp1," Enable");
01045     }
01046     showButton(3,1,sTemp1," Debug",4,4);    
01047 
01048     //------- third row -----
01049     if (autoSync) {
01050         sprintf(sTemp1," Disable");
01051     } else {
01052         sprintf(sTemp1," Enable");
01053     }
01054     showButton(0,2,sTemp1," tSync",4,4);    
01055     showButton(1,2,"  Set"," Time",4,4);
01056     showButton(2,2," Update"," Config",4,4);
01057     showButton(3,2," Update","Firmware",4,4);
01058 }
01059 
01060 void pbScreen(bool force, bool showButtons){
01061     if (force) {
01062         tt.background(Black);
01063         tt.cls();
01064     }
01065     if(playbackOpen){
01066         showButton(0,0,"Slower"," <--",4,4);
01067         
01068         if(playbackEn){
01069             sprintf(sTemp1,"Pause");
01070         }else{
01071             sprintf(sTemp1," Run");
01072         }
01073         sprintf(sTemp2,"%4.3f ",playbackInt);
01074         showButton(1,0,sTemp1,sTemp2,4,4);
01075         
01076         showButton(2,0,"Faster","   -->",4,4);
01077     }
01078     if(playbackOpen){
01079         sprintf(sTemp1," Stop");
01080     }else{
01081         sprintf(sTemp1,"Start");
01082     }
01083     showButton(1,1,sTemp1,"Playback",4,4);
01084 }
01085 
01086 void showDateTime(bool force, bool showButtons){
01087     CANMessage msg;
01088     struct tm t; // pointer to a static tm structure
01089     time_t seconds ;
01090     tt.foreground(Yellow);
01091     tt.background(Black);
01092     if (force||tock) {
01093         tt.cls();
01094         tt.locate(10,10);
01095         tt.set_font((unsigned char*) Arial12x12);
01096         if(accOn){
01097             seconds = time(NULL);
01098             t = *localtime(&seconds);
01099             
01100             if(modelYear<2013){
01101                 msg = lastMsg[indexLastMsg[0x5fa]];
01102                 t.tm_mon = (msg.data[5]>>4)-1;
01103                 t.tm_mday = msg.data[2]>>3;
01104                 // Have not figured out where the year is on MY2011
01105                 msg = lastMsg[indexLastMsg[0x5fc]];
01106                 t.tm_hour = msg.data[0]>>3;
01107                 t.tm_min = (msg.data[1]<<4&0x30)+(msg.data[2]>>4);
01108                 t.tm_sec = msg.data[1]>>2;
01109             }else{
01110                 // Have not figured out where Year, Month, or Day is for MY2013
01111                 msg = lastMsg[indexLastMsg[0x5f9]];
01112                 t.tm_hour = msg.data[5]>>3;
01113                 t.tm_min = msg.data[4];
01114                 msg = lastMsg[indexLastMsg[0x509]];
01115                 t.tm_sec = msg.data[2]>>2;
01116             }
01117 
01118             strftime(sTemp1, 32, "%a %m/%d/%Y %X  \n", &t);
01119             printf("Leaf: %s",sTemp1);
01120         }
01121         seconds = time(NULL);
01122         t = *localtime(&seconds);        
01123         strftime(sTemp1, 32, "%a %m/%d/%Y %X  \n", &t);
01124         tt.locate(10,24);
01125         printf("CANary: %s",sTemp1);
01126         if(showButtons){
01127             switch(dtMode){
01128                 case 0:
01129                     sprintf(sTemp1,"Year");
01130                     break;
01131                 case 1:
01132                     sprintf(sTemp1,"Month");
01133                     break;
01134                 case 2:
01135                     sprintf(sTemp1,"Day");
01136                     break;
01137                 case 3:
01138                     sprintf(sTemp1,"Hour");
01139                     break;
01140                 case 4:
01141                     sprintf(sTemp1,"Minute");
01142                     break;
01143                 case 5:
01144                     sprintf(sTemp1,"Second");
01145                     break;
01146                 default:
01147                     break;
01148             }
01149             showButton(0,1,sTemp1,"",4,4);                          
01150             showButton(1,1,"  Up","",4,4);               
01151             showButton(2,1," Down","",4,4);               
01152             if(accOn){
01153                 showButton(3,1," Sync","w/ car",4,4);               
01154             }
01155             if(autoSync){
01156                 showButton(3,2,"disable"," auto",4,4);               
01157             }else{
01158                 showButton(3,2,"enable"," auto",4,4);               
01159             }
01160         }
01161     }
01162 }
01163 
01164 void dteDisplay(bool force, bool showButtons, bool showMiles){
01165     unsigned short i,x,y,lx,ly,gids,radius,color,r,t;
01166     unsigned char toVal,availableRegen=0;
01167     static unsigned short lgids=0;
01168     static unsigned char leff[39]={0};
01169     CANMessage msg;
01170     unsigned long targetBraking, regenBraking, motorSpeed, motorAmps, frictionBraking;
01171     static unsigned char lr=0, lt=0, lar=0;
01172 
01173     msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids
01174     gids = (msg.data[0]<<2)+(msg.data[1]>>6);
01175     if(gids==0){
01176         gids=281; // Display new, fully charged capacity until real data obtained
01177     }
01178 
01179     tt.background(Navy);
01180     tt.foreground(Yellow);
01181     if(force){
01182         tt.set_font((unsigned char*) Arial12x12);   
01183         tt.cls();
01184         x=50+0*6;
01185         tt.locate(x-10,226);
01186         printf("sec\n");  
01187         tt.line(x,10,x,220,DarkGrey);     
01188         x=50+9*6;
01189         tt.locate(x-10,226);
01190         printf("min\n");  
01191         tt.line(x,10,x,220,DarkGrey);     
01192         x=50+18*6;
01193         tt.locate(x-10,226);
01194         printf("hour\n");  
01195         tt.line(x,10,x,220,DarkGrey);
01196         x=50+25*6;
01197         tt.locate(x-10,226);
01198         printf("day\n");  
01199         tt.line(x,10,x,220,DarkGrey);     
01200         x=50+32*6;
01201         tt.locate(x-10,226);
01202         printf("mon\n");  
01203         tt.line(x,10,x,220,DarkGrey);     
01204         x=50+38*6;
01205         lar=0;
01206     }
01207     toVal=33;
01208     if(force||lgids!=gids){ // update Y axis when kWh changes
01209         tt.set_font((unsigned char*) Arial24x23);
01210         for(i=2;i<7;i++){
01211             y=200-(i-2)*40;
01212             tt.locate(0,y-8);
01213             if (showMiles){
01214                 printf("%3.0f\n",convertDistance(i*((float)(gids-5)*.075))); // LM - Added metric support
01215             }else{
01216                 printf("%d.0\n",i);
01217             }
01218             tt.line(48,y,toVal*6+56,y,DarkGrey);
01219         }
01220         lgids=gids;    
01221     }
01222     if(tock||force){
01223         for(i=2;i<7;i++){
01224             y=200-(i-2)*40;
01225             tt.line(40,y,158,y,DarkGrey);
01226         }
01227 
01228         x=50+0*6; 
01229         tt.line(x,10,x,220,DarkGrey);     
01230         x=50+9*6;
01231         tt.line(x,10,x,220,DarkGrey);     
01232         x=50+18*6;
01233         tt.line(x,10,x,220,DarkGrey);     
01234         //x=50+25*6;
01235         //tt.line(x,60,x,220,DarkGrey);     
01236         //x=50+32*6;
01237         //tt.line(x,60,x,220,DarkGrey);     
01238         //x=50+38*6;
01239         //tt.line(x,60,x,220,DarkGrey);     
01240         tt.set_font((unsigned char*) SCProSB31x55);
01241         tt.foreground(Yellow);
01242         if (showMiles){
01243             float miles = mpkWh[dtePeriod]*((float)(gids-5)*.075);
01244             miles = convertDistance(miles); // LM - Metric support
01245             // Right justify
01246             if (miles>99.9){ //space=18; num=31; . = 23
01247                 tt.locate(161,1);
01248                 printf("%4.1f\n",miles);
01249             } else if (miles>9.9){
01250                 tt.locate(156,1);
01251                 printf("  %3.1f\n",miles);
01252             } else {
01253                 tt.locate(151,1);
01254                 printf("    %2.1f\n",miles);
01255             }
01256             if(CCon) {
01257                 tt.foreground(GreenYellow);
01258                 tt.set_font((unsigned char*) Arial24x23);
01259                 miles = (mpkWh_noCC-mpkWh[dtePeriod])*((float)(gids-5)*.075);
01260                 miles = convertDistance(miles); // LM - Metric support
01261                 // Right justify
01262                 if (miles>9.9){
01263                     tt.locate(190,52);
01264                     printf(" +%3.1f \n",miles);
01265                 } else {
01266                     tt.locate(182,52);
01267                     printf("   +%2.1f \n",miles);
01268                 }
01269             }
01270         } else {
01271             tt.locate(200,1);
01272             printf("%3.1f \n",mpkWh[dtePeriod]);
01273             if(CCon) {
01274                 tt.foreground(GreenYellow);
01275                 tt.set_font((unsigned char*) Arial24x23);
01276                 tt.locate(190,52);
01277                 printf(" +%2.1f \n",(mpkWh_noCC-mpkWh[dtePeriod]));
01278             }
01279         }
01280         lx=50;
01281         ly=mpkWh[0]*40;
01282         if(dtePeriod==0){
01283             radius=6;
01284             color=Yellow;
01285         }else{
01286             radius=2;
01287             color=Green;
01288         }
01289         if(ly<60){
01290             ly=220;
01291             color=Red;
01292         }else if(ly<280) {
01293             ly=280-ly;
01294         }else{
01295             ly=0;
01296         }
01297         tt.fillcircle(lx,leff[0],radius,Navy);
01298         tt.fillcircle(lx,ly,radius,color);
01299 
01300         for(i=1;i<toVal;i++){
01301             x=50+i*6;
01302             y=mpkWh[i]*40;
01303             if(i==dtePeriod){
01304                 radius=6;
01305                 color=Yellow;
01306             }else{
01307                 radius=2;
01308                 color=Green;
01309             }
01310             if(y<60){
01311                 y=220;
01312                 color=Red;
01313             }else if(y<280) {
01314                 y=280-y;
01315             }else{
01316                 y=0;
01317             }
01318             tt.fillcircle(x,leff[i],radius,Navy);
01319             tt.line(x-6,leff[i-1],x,leff[i],Navy);
01320             leff[i-1]=ly;
01321             if(y>0){
01322                 tt.fillcircle(x,y,radius,color);
01323             }
01324             tt.line(lx,ly,x,y,White);
01325             lx=x;
01326             ly=y;
01327         }
01328         leff[i-1]=y;
01329     }
01330 
01331     // Plot Braking friction/regen bar graph
01332     msg = lastMsg[indexLastMsg[0x176]]; //Get RPMs
01333     motorSpeed = (msg.data[2]<<8)+msg.data[3];
01334     msg = lastMsg[indexLastMsg[0x260]]; //Get available regen
01335     availableRegen = msg.data[1]*4;
01336     msg = lastMsg[indexLastMsg[0x1cb]]; //Get target total braking
01337     targetBraking = (msg.data[2]<<3)+(msg.data[3]>>5);
01338     msg = lastMsg[indexLastMsg[0x292]]; //Get friction braking
01339     frictionBraking = msg.data[6];
01340     msg = lastMsg[indexLastMsg[0x180]]; //Get motor amps
01341     motorAmps = (msg.data[2]<<4)+(msg.data[3]>>4);
01342     if(motorAmps>0x7ff){ // invert and chop positive current
01343         motorAmps=0x1000-motorAmps;
01344     }else{
01345         motorAmps=0;
01346     }
01347 
01348     targetBraking *= motorSpeed;
01349     targetBraking /= tbScalar;  //0.0000345 * 4
01350     regenBraking = motorAmps;
01351     regenBraking *= motorSpeed;
01352     regenBraking /= rbScalar;  //0.00002875 * 4
01353     frictionBraking *= motorSpeed;
01354     frictionBraking /= fbScalar;  //0.0019 * 4
01355 
01356     // Plot available regen brackets
01357     if(availableRegen>lar){
01358         tt.fillrect(273,238-availableRegen,275,239-lar,White);
01359         tt.fillrect(317,238-availableRegen,319,239-lar,White);
01360         if(availableRegen>0){
01361             for(i=0;i<=availableRegen;i+=24){
01362                 tt.fillrect(270,238-i,272,239-i,White);
01363             }
01364         }
01365         lar=availableRegen;
01366     }else if(availableRegen<lar){
01367         tt.fillrect(270,238-lar,275,239-availableRegen,Navy);
01368         tt.fillrect(317,238-lar,319,239-availableRegen,Navy);
01369         lar=availableRegen;
01370     }
01371 
01372     t = (unsigned char) regenBraking+frictionBraking;
01373     if (t>160) t=160;
01374     r = (unsigned char) regenBraking;
01375     if (r>160) r=160;
01376     if (r>t) t=r;  //Should never happen
01377     if(lr!=r||lt!=t){
01378         if (t<160) tt.fillrect(277,239-160,315,238-t,Navy);
01379         if (r<t) tt.fillrect(277,239-t,315,238-r,Red);
01380         if (0<r) tt.fillrect(277,239-r,315,238,Green);
01381     }
01382     lt=t;
01383     lr=r;
01384 }
01385 
01386 void testDisplay (bool force, bool showButtons){
01387     static unsigned short maxPS=0, oldData[8]={0};
01388     unsigned char i, uData[8];//, year, month, day, hour, minute, second;
01389     CANMessage msg;
01390 
01391     tt.set_font((unsigned char*) Arial24x23);
01392     tt.foreground(Yellow);
01393     tt.background(Navy);
01394     if(force){
01395         tt.cls();
01396     }
01397     if(logEn){
01398         if(pointerSep>maxPS){maxPS=pointerSep;}
01399         tt.locate(10,10);
01400         printf("%3d sep %3d max\n",pointerSep,maxPS);
01401     }else{
01402         tt.locate(10,10);
01403         printf("%d maxT\n",maxTarget);
01404     }
01405 
01406     for (i=0; i<8; i++){
01407         msg = lastMsg[indexLastMsg[(uMsgId[i]>>4)]];
01408         uData[i] = msg.data[(uMsgId[i]&0x000f)];
01409         if(i%2==0){
01410             tt.locate(10,90+(i/2)*30);
01411         }else{
01412             tt.locate(170,90+(i/2)*30);
01413         }
01414         if(clearTest){
01415             maxPS=0;
01416             oldData[i]=uData[i];
01417             tt.foreground(Yellow);
01418             tt.background(Navy);
01419             printf("%4x:%2x\n",uMsgId[i],uData[i]);
01420         }else if(uData[i]!=oldData[i]){
01421             tt.foreground(Navy);
01422             tt.background(Yellow);
01423             printf("%4x:%2x\n",uMsgId[i],uData[i]);
01424             oldData[i]=uData[i];
01425         }else if(force){
01426             tt.foreground(Yellow);
01427             tt.background(Navy);
01428             printf("%4x:%2x\n",uMsgId[i],uData[i]);
01429         }
01430     }
01431     clearTest=false;    
01432     showButton(3,0,"Reset","flags",4,4);               
01433 }
01434 
01435 void whpgDisplay(bool force, bool showButtons, bool showWh){ 
01436     unsigned short maxGid, minGid, i, y, maxWg;
01437     static unsigned short lmg;
01438 
01439     tt.foreground(White);
01440     tt.background(Navy);
01441     tt.set_font((unsigned char*) Arial12x12_prop);  // select the font
01442 
01443     maxGid=0;
01444     minGid=9999;
01445 
01446     if(force){
01447         lmg=281;
01448     }
01449 
01450     // find max/min/maxWg
01451     if(showWh){
01452         for(i=0; i<300; i++){
01453             if(wh[i]>0){
01454                 if(i>maxGid) maxGid=i;
01455                 if(i<minGid) minGid=i;
01456             }
01457         }
01458         maxWg = wh[maxGid];
01459     }else{
01460         for(i=0; i<300; i++){
01461             if(whpg[i]>0){
01462                 if(i>maxGid) maxGid=i;
01463                 if(i<minGid) minGid=i;
01464             }
01465         }
01466         maxWg = whpg[minGid];
01467     }
01468 
01469     if (force||(minGid<lmg)){ //update if new data
01470         lmg = minGid;
01471         //------------------
01472         tt.cls();
01473 
01474         // show as vertical bar plot
01475         int xWinMin = 26;
01476         int xWinMax = 316;
01477         int yWinMin = 20;
01478         int yWinMax = 200;
01479         // draw the Frame, 2 pixels wide
01480         tt.rect( xWinMin-1,yWinMin-1, xWinMax+1,yWinMax+1, Red);
01481         tt.rect( xWinMin-2,yWinMin-2, xWinMax+2,yWinMax+2, Green);
01482         // draw grid
01483         for( i=0; i<yWinMax-yWinMin; i+=20){
01484             tt.line(xWinMin,yWinMax-i,xWinMax,yWinMax-i,DarkGrey);
01485             if(i%40 == 0){
01486                 // label the y axis each 40
01487                 tt.line( xWinMin-8,yWinMax-i, xWinMin-2,yWinMax-i, White );  // a white tick mark
01488                 tt.locate( 0, yWinMax-i-4 );
01489                 printf("%d\n", i );
01490             }
01491         }
01492         for( i=0; i<xWinMax-xWinMin; i+=10){
01493             // tic mark the x axis each 10
01494             tt.line( i+xWinMin,yWinMax+2, i+xWinMin,yWinMax+4, White );  // a white tick mark
01495             if(i%40 == 0){
01496                 // label the x axis each 40
01497                 tt.line( i+xWinMin,yWinMax+2, i+xWinMin,yWinMax+8, White );  // a white tick mark
01498                 if(i<100){
01499                     tt.locate( i+xWinMin-7, yWinMax+8 );
01500                 }else{
01501                     tt.locate( i+xWinMin-15, yWinMax+8 );
01502                 }
01503                 printf("%d\n", i );
01504             }
01505             if(i%20 == 0){
01506                 tt.line(xWinMin+i,yWinMin,xWinMin+i,yWinMax,DarkGrey);
01507             }
01508         }
01509         
01510         // plot
01511         if( maxGid >= minGid ) {
01512             tt.locate( xWinMin+4, yWinMin+4);
01513             printf("%3.1f avg\n", (float) maxWg/(maxGid-minGid+1) );
01514             if(debugMode){
01515                 tt.locate( xWinMin+4, yWinMin+20);
01516                 printf("minGids=%d; maxGids=%d\n", minGid,maxGid);
01517                 tt.locate( xWinMin+4, yWinMin+36);
01518                 if(showWh){
01519                     printf("minwh=%3.1f; maxwh=%3.1f\n", wh[minGid],wh[maxGid]);
01520                 }else{
01521                     printf("minwhpg=%d; maxwhpg=%d\n", whpg[minGid],whpg[maxGid]);
01522                 }
01523             }
01524 
01525             for( i=3; i<=287; i++) {
01526                 if(showWh){
01527                     y =  wh[i]-wh[i-1];
01528                     tt.fillcircle(i+xWinMin,yWinMax-y,2,Green);
01529                 }else{
01530                     if((whpg[i-3]>0)&&(whpg[i+3]>0)){
01531                         y = (whpg[i-3]-whpg[i+3])/6;
01532                     }else{
01533                         y = 0;
01534                     }
01535                     if((y>0) && (y<180)){
01536                         tt.fillcircle(i+xWinMin,yWinMax-y,2,Yellow);
01537                     }
01538                 }
01539             }
01540         }
01541     }
01542 }
01543 
01544 void updateDisplay(char display){
01545     bool changed,showButtons;
01546     changed = (dMode[display]!=lastDMode[display]);
01547     showButtons = (display==whichTouched)&&(sMode==1);
01548     tt.set_display(display);
01549     switch (dMode[display]) {
01550         case logScreen:
01551             printLog(changed,showButtons);
01552             break;
01553         case mainScreen:
01554             mainDisplay(changed,showButtons);
01555             break;
01556         case brakeScreen:
01557             braking(changed,showButtons);
01558             break;
01559         case dteScreen:
01560             dteDisplay(changed,showButtons,true);
01561             break;
01562          case effScreen:
01563             dteDisplay(changed,showButtons,false);
01564             break;
01565        case monitorScreen:
01566             printLast(changed,showButtons);
01567             break;
01568         case changedScreen:
01569             printChanged(changed,showButtons);
01570             break;
01571         case cpScreen:
01572             cpData(changed||showCP,showButtons);
01573             break;
01574         case configScreen:
01575             config(changed,showButtons);
01576             break;
01577         case config2Screen:
01578             config2(changed,showButtons);
01579             break;
01580         case playbackScreen:
01581             pbScreen(changed,showButtons);
01582             break;
01583         case dateScreen:
01584             showDateTime(changed,showButtons);
01585             break;
01586         case cpHistScreen: // gg - hist
01587             cpHistogram(changed||showCP,showButtons);
01588             break;
01589         case cpBarScreen: // gg - cpbars
01590             cpBarPlot(changed||showCP,showButtons);
01591             break;
01592         case indexScreen:
01593             showIndex(changed,showButtons);
01594             break;
01595         case tripScreen:
01596             tripDisplay(changed,showButtons,false);
01597             break;
01598         case ccTripScreen:
01599             tripDisplay(changed,showButtons,true);
01600             break;
01601         case healthScreen:
01602             healthDisplay(changed,showButtons);
01603             break;
01604         case testScreen:
01605             testDisplay(changed,showButtons);
01606             break;
01607         case whpgScreen:
01608             whpgDisplay(changed,showButtons,false);
01609             break;        
01610         case whScreen:
01611             whpgDisplay(changed,showButtons,true);
01612             break;        
01613         default:
01614             if (changed){
01615                 tt.background(Black);
01616                 tt.cls();
01617             }
01618             break;
01619     }
01620     lastDMode[display]=dMode[display];
01621 
01622     if(display==whichTouched){
01623         switch (sMode) {
01624             case 1: // Select screens
01625                 showButton(0,tNavRow," <-Prev","",4,4); // gg - 4x4
01626                 // col 1 see below
01627                 showButton(2,tNavRow," Go To"," Index",4,4); // gg - index
01628                 showButton(3,tNavRow," Next->","",4,4); // gg - move next
01629                  if (enableSound) {
01630                     sprintf(sTemp1," Mute");
01631                 } else {
01632                     sprintf(sTemp1,"Un-Mute");
01633                 }               
01634                 // col 1 in Nav row                              
01635                 switch (dMode[display]) {
01636                     case offScreen:
01637                         showButton(3,0,sTemp1,"",4,4);
01638                         sprintf(sTemp2,"  Off");
01639                         break;
01640                     case logScreen:
01641                         showButton(3,0,sTemp1,"",4,4);
01642                         sprintf(sTemp2,"  Log");
01643                         break;
01644                     case mainScreen:
01645                         showButton(3,0,sTemp1,"",4,4);
01646                         sprintf(sTemp2,"  Main");
01647                         break;
01648                     case brakeScreen:
01649                         showButton(3,0,sTemp1,"",4,4);
01650                         sprintf(sTemp2,"Braking");
01651                         break;
01652                     case dteScreen:
01653                         showButton(3,0,sTemp1,"",4,4);
01654                         sprintf(sTemp2,"  DTE");
01655                         break;
01656                     case effScreen:
01657                         showButton(3,0,sTemp1,"",4,4);
01658                         sprintf(sTemp2,"  Eff");
01659                         break;
01660                     case monitorScreen:
01661                         showButton(3,0,sTemp1,"",4,4);
01662                         sprintf(sTemp2," Monitor");
01663                         break;
01664                     case changedScreen:
01665                         showButton(3,0,sTemp1,"",4,4);
01666                         sprintf(sTemp2,"DeltaMon");
01667                         break;
01668                     case cpScreen:
01669                         showButton(3,0,sTemp1,"",4,4);
01670                         sprintf(sTemp2,"CP Data");
01671                         break;
01672                     case configScreen:
01673                         sprintf(sTemp2," Config");
01674                         break;          
01675                     case config2Screen:
01676                         sprintf(sTemp2,"Config2");
01677                         break;          
01678                     case playbackScreen:
01679                         showButton(3,0,sTemp1,"",4,4);
01680                         sprintf(sTemp2,"Playback");
01681                         break;
01682                     case dateScreen:
01683                         showButton(3,0,sTemp1,"",4,4);
01684                         sprintf(sTemp2,"Set Time");
01685                         break;
01686                     case cpHistScreen: // gg - hist
01687                         showButton(3,0,sTemp1,"",4,4);
01688                         sprintf(sTemp2,"CP Hist");
01689                         break;
01690                     case cpBarScreen: // gg - cpbars
01691                         showButton(3,0,sTemp1,"",4,4);
01692                         sprintf(sTemp2,"CP Bars");
01693                         break;
01694                     case tripScreen:
01695                         showButton(3,0,sTemp1,"",4,4);
01696                         sprintf(sTemp2," Trip");
01697                         break;
01698                     case healthScreen:
01699                         showButton(3,0,sTemp1,"",4,4);
01700                         sprintf(sTemp2,"Health");
01701                         break;
01702                     case testScreen:
01703                         sprintf(sTemp2," Test");
01704                         break;
01705                     case indexScreen: // gg - index
01706                         sprintf(sTemp2," Index");
01707                         break;
01708                     case whpgScreen: // gg - index
01709                         sprintf(sTemp2," WHPG");
01710                         break;
01711                     case whScreen: // gg - index
01712                         sprintf(sTemp2,"  WH");
01713                         break;
01714                 }
01715                 showButton(1,tNavRow," Select",sTemp2,4,4);
01716                 
01717                 wait_ms(100); //  pause a moment to reduce flicker
01718                 break;
01719                 
01720             case 2: // numpad
01721                 showButton(0,0," 1","",4,4);
01722                 showButton(1,0," 2","",4,4);
01723                 showButton(2,0," 3","",4,4);
01724                 showButton(0,1," 4","",4,4);
01725                 showButton(1,1," 5","",4,4);
01726                 showButton(2,1," 6","",4,4);
01727                 showButton(0,2," 7","",4,4);
01728                 showButton(1,2," 8","",4,4);
01729                 showButton(2,2," 9","",4,4);
01730                 showButton(1,3," 0","",4,4);
01731                 
01732                 showButton(0,3,"<--","",4,4);
01733                 showButton(2,3,"-->","",4,4);
01734                 showButton(3,3,"return","",4,4);
01735             case 3:
01736                 break;
01737             default:
01738                 break;
01739         }
01740     }
01741     tock=false;
01742 } // updateDisplay
01743 
01744 //---------------------
01745 // gg - highlight
01746 void highlightButton(unsigned char column, unsigned char row, unsigned char tScn, unsigned char columns, unsigned char rows){
01747 
01748     unsigned short x1,x2,y1,y2;
01749     
01750     x1=column*(320/columns)+btnGap/2;
01751     x2=(column+1)*(320/columns)-btnGap/2;
01752     y1=row*(240/rows)+btnGap/2;
01753     y2=(row+1)*(240/rows)-btnGap/2;
01754     
01755     tt.set_display(tScn);
01756 
01757     if( skin == ggSkin ){
01758         // paint the whole button box, for a better visual effect
01759         //  especially on a screen with a yellow background
01760         if( tScn == 0 )
01761             tt.fillrect(x1,y1,x2,y2,White); // DarkCyan);
01762         else
01763             tt.fillrect(x1,y1,x2,y2,Green); // DarkCyan);
01764     } else {
01765         tt.fillrect(x1,y1,x2,y2,Green); // DarkCyan);
01766     }
01767 
01768     // paint the outer pixel as a yellow frame
01769     tt.rect(x1,y1,x2,y2,Yellow) ; // DarkCyan);
01770 }
01771 
01772 //---------------------
01773 void showButton(unsigned char column, unsigned char row, char * text1, char * text2, unsigned char columns, unsigned char rows){
01774     unsigned short x1,x2,y1,y2;
01775     
01776     x1=column*(320/columns)+btnGap/2;
01777     x2=(column+1)*(320/columns)-btnGap/2;
01778     y1=row*(240/rows)+btnGap/2;
01779     y2=(row+1)*(240/rows)-btnGap/2;
01780     tt.fillrect(x1,y1,x2,y2,DarkCyan);
01781 
01782     tt.foreground(Yellow);
01783     tt.background(DarkCyan);
01784     tt.set_font((unsigned char*) Arial12x12);
01785     
01786     // adapt formatting of text to the smaller 4x4 box
01787     tt.locate(x1+btnGap/2,y1+btnGap); // gg - 4x4
01788     printf("%s\n",text1);
01789     
01790     tt.locate(x1+btnGap/2,y1+btnGap+20);
01791     printf("%s\n",text2);
01792 }
01793 
01794 
01795 //The temps are stored as metric, distances as imperial... I'm assuming the input based on that - LM
01796 float convertC(float input) 
01797 {
01798     if (!metric) {
01799         //convert!
01800         float output = input *1.8f;
01801         output += 32.0f;
01802         return output;   
01803     }
01804     return input;
01805 }
01806 
01807 float convertF(float input) 
01808 {
01809     if (metric) {
01810         //convert!
01811         float output = input -32.0f;
01812         output /= 1.8f;
01813         return output;   
01814     }
01815     return input;
01816 }
01817 float convertDistance(float input)
01818 {
01819     if (metric) {
01820         return input / 0.62137f;
01821     }
01822     return input;
01823 }
01824 char* distanceUnit()
01825 {
01826     if(metric)
01827         return "km";
01828     return "mi";
01829 }
01830 char* temperatureUnit()
01831 {
01832     if(metric)
01833         return "C";
01834     return "F";
01835 }