Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: SPI_TFTx2 SPI_TFTx2_ILI9341 TFT_fonts TOUCH_TFTx2 mbed
Fork of CANary_9341 by
utility.cpp
00001 // utility.cpp 00002 #include "utility.h" 00003 unsigned long brkMonRate = 378947; 00004 unsigned short brkMonThr = 1895; 00005 Timeout beepOff; 00006 unsigned char bCount = 2; 00007 float bFreq[2] = { 1000, 1000 }; 00008 float bTime[2] = { 0.1, 0.1 }; 00009 00010 void mbed_reset(); 00011 00012 void RTC_IRQHandler() { 00013 timer.reset(); // zero ms at the-seconds-tic 00014 carCanIdle=(++secsNoCarCanMsg>canTimeout)?true:false; 00015 evCanIdle=(++secsNoEvCanMsg>canTimeout)?true:false; 00016 userIdle=(++secsNoTouch>userTimeout)?true:false; 00017 LPC_RTC->ILR |= (1<<0); // clear interrupt to prepare for next 00018 tick=true; 00019 // will use this to generate a logTP() just before the next Message received. 00020 if( (time(NULL) % 60) == 0) ZeroSecTick = true; // gg - at 0-second of each minute 00021 } 00022 00023 void RTC_Init (void) { 00024 LPC_RTC->ILR=0x00; // set up the RTC interrupts 00025 LPC_RTC->CIIR=0x01; // interrupts each second 00026 LPC_RTC->CCR = 0x01; // Clock enable 00027 //NVIC_SetPriority( RTC_IRQn, 10 ); 00028 NVIC_EnableIRQ( RTC_IRQn ); 00029 } 00030 00031 void printMsg (char *msg) { 00032 strcpy(displayLog[displayLoc],msg); 00033 displayLoc=displayLoc>17?0:displayLoc+1; 00034 } 00035 00036 void touch_ISR(){ 00037 //LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF); // seems to work without so maybe not necessary (performed in InterruptIn handler?) 00038 touched=true; // just set flag - touch screen algorythm is long and we don't want to block other interrupts 00039 } 00040 00041 unsigned short getTimeStamp() { 00042 unsigned short msec = timer.read_ms() ; // read ms from the timer 00043 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00044 unsigned short isecs = secs%60 ; // modulo 60 for 0-59 seconds from RTC 00045 return ((isecs<<10)+msec) ; // return the two byte time stamp 00046 } 00047 00048 void logCan (char mType, CANMessage canRXmsg) { 00049 00050 static unsigned char ii = 0; 00051 static unsigned char lasti = 0; // indexindex 00052 static unsigned char bdi=0; 00053 static signed short imotorRPM = 0; 00054 static unsigned short nLost = 0; // gg - overrun 00055 00056 char sTemp[40]; 00057 unsigned char changed; 00058 unsigned short i,j,k; 00059 signed short packV_x2; 00060 signed short packA_x2; 00061 signed long imWs_x4; 00062 unsigned short ts; 00063 00064 if(debugMode||(skin==ggSkin)){ 00065 // code to insert actual number of dropped frames for overrun debug - skipped in normal mode to keep logcan short 00066 if(logOpen){ 00067 // check to see if buffer is already full (read - write) = 1 00068 // actually the last buffer location cannot be used because then 00069 // the buffer would look empty after writePointer++ 00070 00071 //if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/16)) // modulo is slow? 00072 00073 // pointers are 0 through maxBufLen-1 00074 if( (readPointer - writePointer) == 1 || (writePointer - readPointer) == (maxBufLen - 1)) { 00075 // the buffer is "full", so Lose this message 00076 00077 // point to the last-stored message 00078 int tempWritePointer = writePointer - 1 ; 00079 if( tempWritePointer < 0 ) tempWritePointer = maxBufLen - 1; 00080 char strLost[9] ; 00081 00082 if( nLost == 0 ) { 00083 // this is the first message lost 00084 // and we must overwrite the last message with an FFE comment message 00085 // So, there will be two messages lost as the comment message is laid in. 00086 nLost = 2; 00087 sprintf(strLost,"%s","Lost0002"); // indicate two messages lost 00088 00089 // overlay the last message with a "Lost0002" comment 00090 writeBuffer[tempWritePointer][0]=0; 00091 // leave the ts of the overlaid message 00092 //writeBuffer[tempWritePointer][1]=(ts&0xff00)>>8; // Time Stamp (2 bytes_ 00093 //writeBuffer[tempWritePointer][2]=(ts&0x00ff); 00094 // force the MsgID to an Event Message 00095 writeBuffer[tempWritePointer][3]=0xfe; // MsgID, low byte 00096 writeBuffer[tempWritePointer][4]=0xff; // Len nibble, and MsgID high nibble 00097 // lay in the "Lost0002" text 00098 for(i=5;i<13;i++){ 00099 writeBuffer[tempWritePointer][i]= strLost[i-5]; 00100 } 00101 } else { 00102 // at least one message was previously lost 00103 // increment the loat counter 00104 nLost += 1; 00105 00106 // lay the new count into the comment 00107 sprintf(strLost,"%04d",nLost); 00108 for(i=9;i<13;i++){ 00109 writeBuffer[tempWritePointer][i]= strLost[i-9]; 00110 } 00111 } 00112 } else { 00113 // there is room to insert the message 00114 // get it inserted quickly 00115 ts=getTimeStamp(); 00116 writeBuffer[writePointer][0]=mType; 00117 writeBuffer[writePointer][1]=(ts&0xff00)>>8; // Time Stamp (2 bytes_ 00118 writeBuffer[writePointer][2]=(ts&0x00ff); 00119 writeBuffer[writePointer][3]=canRXmsg.id&0xff; // MsgID, low byte 00120 char sLen = canRXmsg.len ; 00121 writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(sLen<<4); // Len nibble, and MsgID high nibble 00122 for(i=0;i<8;i++){ // Is there a better way to do this? (writeBuffer[writePointer][i]=canRXmsg.data?) 00123 if(i<sLen) 00124 writeBuffer[writePointer][i+5]=canRXmsg.data[i]; 00125 else // i>=sLen 00126 // force unused data bytes to FF for CAN-Do compatibility 00127 writeBuffer[writePointer][i+5]=0xFF; 00128 } 00129 00130 //-------------- 00131 // Note, this is not protected from the interrupt. 00132 // Due to the nLost code above, this no longer 00133 // overflows to writePointer = readPointer 00134 // which would make the buffer look empty 00135 if (++writePointer >= maxBufLen) { 00136 writePointer = 0; 00137 led3 = !led3; 00138 } 00139 //-------------- 00140 // log a local message if we had lost messages. gg - logcan 00141 if( nLost > 0 ) { 00142 // We previously lost messages that did not get into the buffer 00143 sprintf(sTemp,"-- Lost %d Messages.\n", nLost); 00144 printMsg(sTemp); // write buffer overrun 00145 beep(500,0.25); 00146 00147 nLost = 0 ; 00148 } 00149 //-------------- 00150 } 00151 } 00152 }else{ // not debugMode - keep code short 00153 if(logOpen){ 00154 NVIC_DisableIRQ(CAN_IRQn); // Block interrupts until write pointer assigned 00155 int localWritePointer = writePointer++; // create local copy to make logCan reentrant 00156 // note that the static variables do not prevent safe reentry 00157 // since they are only used for msgId<0x800 which will never interrupt 00158 // another msgId<0x800 (both CANbusses are same priority) 00159 if (writePointer >= maxBufLen) { 00160 writePointer = 0; 00161 led3 = !led3; 00162 } 00163 NVIC_EnableIRQ(CAN_IRQn); // Unblock interrupts once local pointer set and global pointer incremented 00164 ts=getTimeStamp(); 00165 writeBuffer[localWritePointer][0]=mType; 00166 writeBuffer[localWritePointer][1]=(ts&0xff00)>>8; 00167 writeBuffer[localWritePointer][2]=(ts&0x00ff); 00168 writeBuffer[localWritePointer][3]=canRXmsg.id&0xff; 00169 writeBuffer[localWritePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4); 00170 for(i=5;i<13;i++){ // Is there a better way to do this? 00171 writeBuffer[localWritePointer][i]=canRXmsg.data[i-5]; 00172 } 00173 if (writePointer==readPointer) { 00174 // Just caught up to read pointer 00175 printMsg("Write buffer overrun.\n"); // write buffer overrun 00176 //beep(500,0.25); 00177 } 00178 } 00179 } 00180 00181 if(canRXmsg.id<0x800){ // Block FFE and FFF messages 00182 if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry 00183 if(ii<99) { 00184 indexLastMsg[canRXmsg.id]=++ii; //Create entry for first MsgID occurance 00185 // ii max is 99 here 00186 } else { 00187 // the ii array is full, more than 100 MsgIDs found 00188 if(ii==99) { 00189 ii++; // step to 100 to log only one error 00190 printMsg("msgID buffer overrun.\n"); 00191 beep3(500,0.25,1000,0.5,500,0.25); //Alert driver to check log 00192 } 00193 } 00194 } 00195 lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store data in table at assigned index 00196 00197 //---------------- 00198 if(dMode[0]==changedScreen||dMode[1]==changedScreen){// Skip if not using (for execution speed) 00199 changed=msgChanged[indexLastMsg[canRXmsg.id]]; 00200 // This is cleared in the main loop when reset button is touched 00201 for(i=0;i<8;i++){ 00202 if(lastMsg[indexLastMsg[canRXmsg.id]].data[i]!=canRXmsg.data[i]){ 00203 changed |= 1<<i; 00204 } 00205 } 00206 msgChanged[indexLastMsg[canRXmsg.id]]=changed; 00207 } 00208 00209 //------------------- 00210 //Miscellaneous on-recieve operations below 00211 if((mType==1)&&(canRXmsg.id==0x7bb)){ // is battery data? Need to store all responses 00212 if(canRXmsg.data[0]<0x20){ 00213 if(canRXmsg.data[3]==1){//Group 1 data 00214 bdi=BatDataBaseG1; // index offset for Group 1 data 00215 if(debugMode){ 00216 printMsg(" Getting Group 1 data\n"); 00217 } 00218 00219 }else if(canRXmsg.data[3]==2){//Group 2 = cellpair data 00220 bdi=BatDataBaseG2; // index offset for CP data 00221 if(debugMode){ 00222 printMsg(" Getting cell pair data\n"); 00223 } 00224 00225 }else if(canRXmsg.data[3]==3){//Group 3 data 00226 bdi=BatDataBaseG3; // index offset for Group 3 data 00227 if(debugMode){ 00228 printMsg(" Getting Group 3 data\n"); 00229 } 00230 00231 }else if(canRXmsg.data[3]==4){//Group 4 = temperature data 00232 bdi=BatDataBaseG4; // index offset for Temperature data 00233 if(debugMode){ 00234 printMsg(" Getting temperature data\n"); 00235 } 00236 00237 }else if(canRXmsg.data[3]==5){//Group 5 data 00238 bdi=BatDataBaseG5; // index offset for Group 5 data 00239 if(debugMode){ 00240 printMsg(" Getting Group 5 data\n"); 00241 } 00242 00243 }else if(canRXmsg.data[3]==6){//Group 6 data = shunt data 00244 bdi=BatDataBaseG6; // index offset for Group 6 data 00245 if(debugMode){ 00246 printMsg(" Getting Group 6 data\n"); 00247 } 00248 00249 }else bdi=0xff; // ignore other messages (for now) 00250 lasti=0; 00251 } 00252 00253 if(bdi<0xff){ 00254 i=canRXmsg.data[0]&0x0f; //lower nibble of D0 is index 00255 if(lasti>i){ //detect rollover and offset index appropriately 00256 bdi += 0x10; // for CP data 00257 } 00258 lasti=i; //remember the msb to detect rollover next time around 00259 i+=bdi; 00260 //------- 00261 //------- 00262 i*=7; 00263 if(i+6 < BatDataBufMax) { 00264 battData[i+0]=canRXmsg.data[1]; 00265 battData[i+1]=canRXmsg.data[2]; 00266 battData[i+2]=canRXmsg.data[3]; 00267 battData[i+3]=canRXmsg.data[4]; 00268 battData[i+4]=canRXmsg.data[5]; 00269 battData[i+5]=canRXmsg.data[6]; 00270 battData[i+6]=canRXmsg.data[7]; 00271 } 00272 if(i==(BatDataBaseG6+3)*7){ // All data loaded 00273 logCP=yesBattLog; // Only log if logging enabled 00274 showCP=true; // Always show 00275 00276 // Find hottest temperature by finding smallest ADC value 00277 // 2013 models only have three sensors 00278 k=battData[(BatDataBaseG4*7)+3]*0x100+battData[(BatDataBaseG4*7)+4]; 00279 j=battData[(BatDataBaseG4*7)+6]*0x100+battData[(BatDataBaseG4*7)+7]; 00280 if(j<k)k=j; 00281 j=battData[(BatDataBaseG4*7)+9]*0x100+battData[(BatDataBaseG4*7)+10]; 00282 if(j<k)k=j; 00283 j=battData[(BatDataBaseG4*7)+12]*0x100+battData[(BatDataBaseG4*7)+13]; 00284 if(j<k)k=j; 00285 //interpolate from lookup table 00286 unsigned short temp_adc[10] = {1000,720,690,589,487,401,365,340,309,000}; 00287 float temp_C[10] = { -27, 0, 3, 13, 23, 32, 36, 39, 43, 76}; 00288 char ii=0; 00289 while(k<=temp_adc[++ii]) { } // Find section in table 00290 maxTemp=(float)(k-temp_adc[ii]); 00291 maxTemp/=(float)(temp_adc[ii-1]-temp_adc[ii]); 00292 maxTemp*=(temp_C[ii-1]-temp_C[ii]); 00293 maxTemp+=temp_C[ii]; 00294 00295 // Get state of health 00296 SOH2_x100=battData[(BatDataBaseG1*7)+29]*0x100+battData[(BatDataBaseG1*7)+30]; 00297 Ah_x10000=battData[(BatDataBaseG1*7)+36]*0x10000+battData[(BatDataBaseG1*7)+37]*0x100+battData[(BatDataBaseG1*7)+38]; 00298 SOC_x10000=battData[(BatDataBaseG1*7)+32]*0x10000+battData[(BatDataBaseG1*7)+33]*0x100+battData[(BatDataBaseG1*7)+34]; 00299 accV2=(float)battData[(BatDataBaseG1*7)+23]/4+(float)battData[(BatDataBaseG1*7)+24]/1024; 00300 00301 // Save shunt data 00302 for(j=0; j<24; j++){ 00303 shunt[j*4+0]=battData[BatDataBaseG6*7+j+3]&0x08; 00304 shunt[j*4+1]=battData[BatDataBaseG6*7+j+3]&0x04; 00305 shunt[j*4+2]=battData[BatDataBaseG6*7+j+3]&0x02; 00306 shunt[j*4+3]=battData[BatDataBaseG6*7+j+3]&0x01; 00307 } 00308 } 00309 } 00310 }else if((mType==1)&&(canRXmsg.id==0x1db)){ //Battery Volts and Amps 00311 packV_x2=((canRXmsg.data[2]<<2)|(canRXmsg.data[3]>>6)); // 1 LSB = 0.5V 00312 packA_x2=((canRXmsg.data[0]<<3)|(canRXmsg.data[1]>>5)); // 1 LSB = 0.5A 00313 if(packA_x2>0x03ff){ 00314 packA_x2|=0xf800;//extend sign; 00315 } 00316 packA_x2 -= 2; //Slight correction to value required (unique to my Leaf?) 00317 if (-packA_x2<Imin){ 00318 Imin=-packA_x2; 00319 } else if (-packA_x2>Imax){ 00320 Imax=-packA_x2; 00321 } 00322 imWs_x4 = packV_x2; // Volts*milliSeconds*2 00323 imWs_x4 *= -packA_x2; // milliWattseconds*4 00324 mWs_x4 += imWs_x4; // total mWs_x4 00325 float temp; 00326 temp = Resr; 00327 temp *= (float) -packA_x2; 00328 temp += (float) packV_x2; 00329 if(temp>curRmax){ 00330 curRmax=temp; 00331 } else if(temp<curRmin){ 00332 curRmin=temp; 00333 } 00334 temp = Resr-0.001; 00335 temp *= (float) -packA_x2; 00336 temp += (float) packV_x2; 00337 if(temp>redRmax){ 00338 redRmax=temp; 00339 } else if(temp<redRmin){ 00340 redRmin=temp; 00341 } 00342 temp = Resr+0.001; 00343 temp *= (float) -packA_x2; 00344 temp += (float) packV_x2; 00345 if(temp>incRmax){ 00346 incRmax=temp; 00347 } else if(temp<incRmin){ 00348 incRmin=temp; 00349 } 00350 numWsamples++; 00351 }else if((mType==2)&&(canRXmsg.id==0x176)){ //Motor Speed 00352 imotorRPM=((canRXmsg.data[2]<<8)|(canRXmsg.data[3])); 00353 motorRPM+=imotorRPM; 00354 numSsamples++; 00355 // }else if((mType==1)&&(canRXmsg.id==0x1da)){ //Motor Speed 00356 // imotorRPM_x2=((canRXmsg.data[4]<<8)|(canRXmsg.data[5])); 00357 // if(imotorRPM_x2<0){ // take absolute value 00358 // imotorRPM_x2=-imotorRPM_x2; 00359 // } 00360 // motorRPM_x2+=imotorRPM_x2; 00361 // numSsamples++; 00362 // }else if((mType==2)&&(canRXmsg.id==0x1ca)){ //Brake Pressure 00363 }else if((mType==2)&&(canRXmsg.id==0x292)){ //Brake Pressure 00364 if(brakeMon){ 00365 if(canRXmsg.data[0]<0xff){ 00366 if((canRXmsg.data[6]*imotorRPM)<brkMonThr){ // brkMonThr = 3.6/.0019 = 1895 --> squelch threshold 1Wh/sec 00367 chirpInt=0; 00368 }else{ // imotorRPM*data[6]*.0019=kW; 3.6/kW = seconds until 1Wh; 00369 chirpInt=brkMonRate/imotorRPM; // brkMonRate=3.6/.0019/.02=94736.8 --> 1 chirp per Wh 00370 chirpInt/=canRXmsg.data[6]; 00371 } 00372 } 00373 } 00374 } 00375 } 00376 } 00377 00378 //----------------------------- 00379 void logTS () { 00380 CANMessage tsMsg; 00381 unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900 00382 // NOTE: In Mbed, I believe that this is seconds past start of 1970, not 1900 00383 // but this is good, since seconds past 1970 is what CAN-Do expects. GG - Date Time 00384 tsMsg.id=0xfff; 00385 tsMsg.len=0xf; 00386 tsMsg.data[0]=secs&0xff; 00387 tsMsg.data[1]=(secs>>8)&0xff; 00388 tsMsg.data[2]=(secs>>16)&0xff; 00389 tsMsg.data[3]=(secs>>24)&0xff; 00390 tsMsg.data[4]=0; // 0xff; gg - Date Time 00391 tsMsg.data[5]=0; // 0xff; for CAN-Do 00392 tsMsg.data[6]=0; // 0xff; 00393 tsMsg.data[7]=0xff; 00394 logCan(0,tsMsg); // Date-Time 00395 } 00396 00397 void logEvent (char * errMsg) { 00398 // log CAN-Do 8-character Pseudo Message 00399 CANMessage tsMsg; 00400 tsMsg.id=0xffe; // pseudo Message to CAN-Do log 00401 tsMsg.len=0xf; 00402 int iMsgLen = strlen(errMsg); 00403 // 8 character message compatible with CAN-Do 00404 for(int i=0; i<8; i++){ 00405 tsMsg.data[i]=' '; 00406 if( i < iMsgLen ) tsMsg.data[i]=errMsg[i]; 00407 } 00408 logCan(0,tsMsg); // FFE Comment Message 00409 } 00410 00411 void sendReq() { 00412 static char data[8] = {0x02, 0x21, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff}; 00413 if(reqMsgCnt<99){ 00414 switch (reqMsgCnt){ 00415 case BatDataBaseG1: 00416 can2.monitor(false); // set to active mode 00417 can2SleepMode = 0; // enable TX 00418 data[0]=0x02; //change to request group 1 00419 data[1]=0x21; 00420 data[2]=0x01; 00421 break; 00422 case BatDataBaseG2: // group 1 has 6 frames 00423 data[0]=0x02; //change to request group 2 (cp data) 00424 data[1]=0x21; 00425 data[2]=0x02; 00426 break; 00427 case BatDataBaseG3: // group 2 has 29 frames 00428 data[0]=0x02; //change to request group 3 00429 data[1]=0x21; 00430 data[2]=0x03; 00431 break; 00432 case BatDataBaseG4: // group 3 has 5 frames 00433 data[0]=0x02; //change to request group 4 (temperature) 00434 data[1]=0x21; 00435 data[2]=0x04; 00436 break; 00437 case BatDataBaseG5: // group 4 has 3 frames 00438 data[0]=0x02; //change to request group 5 00439 data[1]=0x21; 00440 data[2]=0x05; 00441 break; 00442 case BatDataBaseG6: // group 4 has 3 frames 00443 data[0]=0x02; //change to request group 5 00444 data[1]=0x21; 00445 data[2]=0x06; 00446 break; 00447 case BatDataBaseG7: // group 5 has 11 frames 00448 reqMsgCnt = 99; 00449 can2SleepMode = VP230Sleep; // disable TX 00450 can2.monitor(true); // set to snoop mode 00451 msgReq.detach(); // stop ticker 00452 default: 00453 data[0]=0x30; //change to request next line message 00454 data[1]=0x01; 00455 data[2]=0x00; 00456 } 00457 can2.write(CANMessage(0x79b, data, 8)); 00458 reqMsgCnt++; 00459 } 00460 } 00461 00462 void sendTempReq(){ 00463 //Requests ambient and cabin temperature 00464 char data[8] = {0x03, 0x22, 0x11, 0x5d, 0xff, 0xff, 0xff, 0xff}; 00465 can2.monitor(false); // set to active mode 00466 can2SleepMode = 0; // enable TX 00467 can2.write(CANMessage(0x797, data, 8)); 00468 can2SleepMode = VP230Sleep; // disable TX 00469 } 00470 00471 void autoPollISR(){ 00472 //sendTempReq(); 00473 reqMsgCnt = 0; //reset message counter 00474 msgReq.attach(&sendReq,0.015); 00475 } 00476 00477 void playbackISR() { //Used for autoplayback 00478 step=true; 00479 } 00480 00481 void recieve1() { 00482 CANMessage msg1; 00483 can1.read(msg1); 00484 00485 secsNoEvCanMsg=0; // reset deadman switch 00486 if( ZeroSecTick ) { ZeroSecTick = false; logTS(); } // gg - 0-second EV bus 00487 if(msg1.id>0) { 00488 logCan(1, msg1); // EVcan Message Received 00489 led1 = !led1; 00490 } 00491 } 00492 00493 void recieve2() { 00494 CANMessage msg2; 00495 can2.read(msg2); 00496 00497 secsNoCarCanMsg=0; // reset deadman switch 00498 if( ZeroSecTick ) { ZeroSecTick = false; logTS(); } // gg - 0-second CAR bus 00499 if(msg2.id>0) { 00500 logCan(2, msg2); // CARcan Message Received 00501 led2 = !led2; 00502 } 00503 } 00504 00505 unsigned char buttonX(unsigned short X, unsigned char columns) { 00506 unsigned char val = X*columns/320; 00507 return val; 00508 } 00509 00510 unsigned char buttonY(unsigned short Y, unsigned char rows) { 00511 unsigned short val = Y*rows/240; 00512 return val; 00513 } 00514 00515 void saveConfig(){ 00516 FILE *cfile; 00517 FIL efile; // external usb file 00518 FRESULT sfr; // external file access flags 00519 unsigned int bytesRW; 00520 const int bufSize = 2048; 00521 char buffer[bufSize]; 00522 char sTemp[16]; 00523 00524 tt.set_font((unsigned char*) Arial12x12); 00525 tt.background(Blue); 00526 tt.foreground(Yellow); 00527 tt.locate(0,10); 00528 tt.cls(); 00529 00530 printMsg("Saving local config file.\n"); 00531 printf("Saving local config file.\n"); 00532 cfile = fopen("/local/config.txt", "w"); 00533 fprintf(cfile,"format 11\r\n"); 00534 fprintf(cfile,"x0_off %d\r\n",tt.x0_off); 00535 fprintf(cfile,"y0_off %d\r\n",tt.y0_off); 00536 fprintf(cfile,"x0_pp %d\r\n",tt.x0_pp); 00537 fprintf(cfile,"y0_pp %d\r\n",tt.y0_pp); 00538 fprintf(cfile,"x1_off %d\r\n",tt.x1_off); 00539 fprintf(cfile,"y1_off %d\r\n",tt.y1_off); 00540 fprintf(cfile,"x1_pp %d\r\n",tt.x1_pp); 00541 fprintf(cfile,"y1_pp %d\r\n",tt.y1_pp); 00542 fprintf(cfile,"x_mid %d\r\n",tt.x_mid); 00543 if ((dMode[0]==configScreen)||(dMode[0]==config2Screen)) 00544 fprintf(cfile,"dMode0 %d\r\n",mainScreen); 00545 else 00546 fprintf(cfile,"dMode0 %d\r\n",dMode[0]); 00547 if ((dMode[1]==configScreen)||(dMode[1]==config2Screen)) 00548 fprintf(cfile,"dMode1 %d\r\n",mainScreen); 00549 else 00550 fprintf(cfile,"dMode1 %d\r\n",dMode[1]); 00551 fprintf(cfile,"ledHi %4.3f\r\n",ledHi); 00552 fprintf(cfile,"ledLo %4.3f\r\n",ledLo); 00553 fprintf(cfile,"pollInt %d\r\n",pollInt); 00554 fprintf(cfile,"scale12V %4.2f\r\n",scale12V); 00555 fprintf(cfile,"skin %d\r\n",skin); 00556 fprintf(cfile,"dtePeriod %d\r\n",dtePeriod); 00557 fprintf(cfile,"DebugMode %d\r\n",(debugMode?1:0)); 00558 fprintf(cfile,"metric %d\r\n",(metric?1:0)); 00559 fprintf(cfile, "firmware %d\r\n", fwCount ); 00560 fprintf(cfile,"showHealth %d\r\n",(showHealth?1:0)); 00561 fprintf(cfile,"brakeMon %d\r\n",(heaterMon?4:0)+(brakeMon?2:0)+(regenMon?1:0)); 00562 fprintf(cfile,"brkMonRate %2.1f\r\n", (float) brkMonRate/94737 ); 00563 fprintf(cfile,"brkMonThr %2.1f\r\n", (float) brkMonThr/1895); 00564 for(char i=0;i<8;i++){ 00565 sprintf(sTemp,"usrMsgId %04x",uMsgId[i]); 00566 fprintf(cfile,"%s\r\n", sTemp ); 00567 } 00568 fprintf(cfile,"modelYear %d\r\n",modelYear); 00569 fprintf(cfile,"autoSync %d\r\n",(autoSync?1:0)); 00570 fprintf(cfile,"kWperGid %4.3f\r\n",kWperGid); 00571 fclose(cfile); 00572 00573 // Make copy of CONFIG.TXT 00574 printMsg("Saving CONFIG.BAK.\n"); 00575 cfile = fopen("/local/CONFIG.TXT", "r"); 00576 sfr = f_open(&efile,"CONFIG.BAK",FA_WRITE|FA_CREATE_NEW); 00577 if((cfile != NULL)&&(sfr == FR_OK)){ 00578 printf("Copy config file to USB\n"); 00579 while (!feof(cfile)) 00580 { 00581 bytesRW=fread(buffer, 1, bufSize, cfile); 00582 sfr=f_write(&efile,&buffer,bytesRW,&bytesRW); 00583 } 00584 fflush(cfile); 00585 fclose(cfile); 00586 f_close(&efile); 00587 } 00588 00589 // Make copy of ehist.cny 00590 printMsg("Saving ehist.bak.\n"); 00591 cfile = fopen("/local/ehist.cny", "r"); 00592 sfr = f_open(&efile,"ehist.bak",FA_WRITE|FA_CREATE_NEW); 00593 if((cfile != NULL)&&(sfr == FR_OK)){ 00594 printf("Copy ehist file to USB\n"); 00595 while (!feof(cfile)) 00596 { 00597 bytesRW=fread(buffer, 1, bufSize, cfile); 00598 sfr=f_write(&efile,&buffer,bytesRW,&bytesRW); 00599 } 00600 fflush(cfile); 00601 fclose(cfile); 00602 f_close(&efile); 00603 } 00604 wait(3); 00605 } 00606 00607 void readConfig(){ 00608 FILE *cfile; 00609 int ff,readHex,readBool; 00610 char sTemp[16]; 00611 float readFloat; 00612 00613 cfile = fopen("/local/config.txt", "r"); 00614 if (cfile==NULL){ // if doesn't exist --> create 00615 printMsg("No config file found.\n"); // no config file 00616 printMsg("Calibrating touch screen.\n"); // calibrating 00617 //tt.setcal(5570, 34030, 80, 108, 33700, 5780, 82, 108, 32500);// bypass calibration using my values 00618 tt.calibrate(); // run touchscreen calibration routine 00619 // NOTE: calibrates screen 1 first, then screen 0. 00620 saveConfig(); 00621 } else { 00622 ledHi = 0.8; 00623 ledLo = 0.3; 00624 pollInt = 60; 00625 scale12V = 16.2; 00626 kWperGid=0.080; 00627 skin = ttSkin; 00628 fscanf(cfile, "format %d\r\n", &ff ); 00629 fscanf(cfile, "x0_off %d\r\n", &tt.x0_off ); 00630 fscanf(cfile, "y0_off %d\r\n", &tt.y0_off ); 00631 fscanf(cfile, "x0_pp %d\r\n", &tt.x0_pp ); 00632 fscanf(cfile, "y0_pp %d\r\n", &tt.y0_pp ); 00633 fscanf(cfile, "x1_off %d\r\n", &tt.x1_off ); 00634 fscanf(cfile, "y1_off %d\r\n", &tt.y1_off ); 00635 fscanf(cfile, "x1_pp %d\r\n", &tt.x1_pp ); 00636 fscanf(cfile, "y1_pp %d\r\n", &tt.y1_pp ); 00637 fscanf(cfile, "x_mid %d\r\n", &tt.x_mid ); 00638 fscanf(cfile, "dMode0 %d\r\n", &dMode[0] ); 00639 fscanf(cfile, "dMode1 %d\r\n", &dMode[1] ); 00640 if(ff>1){ 00641 fscanf(cfile, "ledHi %f\r\n", &ledHi ); 00642 fscanf(cfile, "ledLo %f\r\n", &ledLo ); 00643 fscanf(cfile, "pollInt %d\r\n", &pollInt ); 00644 fscanf(cfile, "scale12V %f\r\n", &scale12V ); 00645 } 00646 if(ff>2){ 00647 fscanf(cfile, "skin %d\r\n", &skin ); 00648 fscanf(cfile, "dtePeriod %d\r\n", &dtePeriod ); 00649 } 00650 if(ff>3){ 00651 fscanf(cfile, "DebugMode %d\r\n", &readBool ); 00652 debugMode = (bool)readBool; 00653 } 00654 if(ff>4) { 00655 fscanf(cfile, "metric %d\r\n", &readBool ); 00656 metric = (bool)readBool; // This will get re-assigned based on dash selection 00657 fscanf(cfile, "firmware %d\r\n", &fwCount ); 00658 } 00659 if(ff>5){ 00660 fscanf(cfile, "showHealth %d\r\n", &readBool ); 00661 showHealth = (bool)readBool; 00662 } 00663 if(ff>6){ 00664 fscanf(cfile, "brakeMon %d\r\n", &readBool ); 00665 brakeMon = (bool)(readBool&1); 00666 regenMon = (bool)(readBool&2); 00667 heaterMon = (bool)(readBool&4); 00668 if(ff>10){ 00669 fscanf(cfile, "brkMonRate %f\r\n", &readFloat ); 00670 brkMonRate = 94737 * readFloat; 00671 fscanf(cfile, "brkMonThr %f\r\n", &readFloat ); 00672 brkMonThr = 1895 * readFloat; 00673 }else{ 00674 fscanf(cfile, "brkMonRate %d\r\n", &brkMonRate ); 00675 fscanf(cfile, "brkMonThr %d\r\n", &brkMonThr); 00676 brkMonRate = 378948; 00677 brkMonThr = 1895; 00678 } 00679 } 00680 if(ff>7){ 00681 for(char i=0;i<8;i++){ 00682 fscanf(cfile, "usrMsgId %s\r\n", &sTemp ); 00683 sscanf(sTemp,"%x", &readHex); 00684 uMsgId[i]=readHex; 00685 } 00686 } 00687 if(ff>8){ 00688 fscanf(cfile, "modelYear %d\r\n", &modelYear); 00689 fscanf(cfile, "autoSync %d\r\n", &readBool); 00690 autoSync = (bool)readBool; 00691 } 00692 if(ff>9){ 00693 fscanf(cfile, "kWperGid %f\r\n", &kWperGid ); 00694 } 00695 fclose(cfile); 00696 if((ff>11)||(ff<1)||(ledHi<0.1)||(scale12V<10)||(tt.x_mid<16000)||(ledHi>1)||(ledLo>1)||(dMode[0]>maxScreens)||(dMode[1]>maxScreens)){ //Sanity check a few things 00697 //Something wrong. Load defaults 00698 printMsg("Invalid config file. Loading defaults.\n"); 00699 wait(3); 00700 ff=11; 00701 tt.x0_off=5732; 00702 tt.y0_off=34009; 00703 tt.x0_pp=77; 00704 tt.y0_pp=106; 00705 tt.x1_off=33955; 00706 tt.y1_off=6310; 00707 tt.x1_pp=80; 00708 tt.y1_pp=104; 00709 tt.x_mid=31986; 00710 dMode[0]=2; 00711 dMode[1]=4; 00712 ledHi=0.800; 00713 ledLo=0.300; 00714 pollInt=300; 00715 scale12V=16.20; 00716 skin=0; 00717 dtePeriod=14; 00718 debugMode=false; 00719 metric=false; 00720 fwCount=1; 00721 showHealth=true; 00722 brakeMon=true; 00723 regenMon=true; 00724 heaterMon=true; 00725 brkMonRate=378947; // 4Wh per chirp 00726 brkMonThr=1895; // 1Wh per second 00727 uMsgId[0]=0x5103; 00728 uMsgId[1]=0x50a3; 00729 uMsgId[2]=0x54a4; 00730 uMsgId[3]=0x54b4; 00731 uMsgId[4]=0x54c0; 00732 uMsgId[5]=0x55b4; 00733 uMsgId[6]=0x0000; 00734 uMsgId[7]=0x0000; 00735 modelYear=2011; 00736 autoSync=false; 00737 kWperGid=0.080; 00738 } 00739 if(ff<11){//If not latest format, save as latest format 00740 saveConfig(); 00741 printMsg("Config file format updated.\n"); // config format updates 00742 } 00743 printMsg("Config file loaded.\n"); // config file loaded 00744 } 00745 } 00746 00747 void upDate(unsigned char field, bool upDownBar){ 00748 struct tm t; // pointer to a static tm structure 00749 time_t seconds ; 00750 seconds = time(NULL); 00751 t = *localtime(&seconds) ; 00752 switch(field){ 00753 case 0: // year 00754 if (upDownBar) { 00755 t.tm_year = t.tm_year+1; 00756 } else { 00757 t.tm_year = t.tm_year-1; 00758 } 00759 break; 00760 case 1: // month 00761 if (upDownBar) { 00762 t.tm_mon = (t.tm_mon<11)?t.tm_mon+1:0; 00763 } else { 00764 t.tm_mon = (t.tm_mon>0)?t.tm_mon-1:11; 00765 } 00766 break; 00767 case 2: // day 00768 if (upDownBar) { 00769 t.tm_mday = (t.tm_mday<31)?t.tm_mday+1:1; 00770 } else { 00771 t.tm_mday = (t.tm_mday>1)?t.tm_mday-1:31; 00772 } 00773 break; 00774 case 3: // hour 00775 if (upDownBar) { 00776 t.tm_hour = (t.tm_hour<23)?t.tm_hour+1:0; 00777 } else { 00778 t.tm_hour = (t.tm_hour>0)?t.tm_hour-1:23; 00779 } 00780 break; 00781 case 4: // minute 00782 if (upDownBar) { 00783 t.tm_min = (t.tm_min<59)?t.tm_min+1:0; 00784 } else { 00785 t.tm_min = (t.tm_min>0)?t.tm_min-1:59; 00786 } 00787 break; 00788 case 5: // second 00789 if (upDownBar) { 00790 t.tm_sec = (t.tm_sec<59)?t.tm_sec+1:0; 00791 } else { 00792 t.tm_sec = (t.tm_sec>0)?t.tm_sec-1:59; 00793 } 00794 break; 00795 default: 00796 break; 00797 } 00798 set_time(mktime(&t)); 00799 } 00800 00801 bool syncDateTime(){ // doesn't work on MY2013 00802 struct tm t; // pointer to a static tm structure 00803 time_t seconds ; 00804 CANMessage msg; 00805 static unsigned char lastHour, numMatched; 00806 seconds = time(NULL); 00807 t = *localtime(&seconds); 00808 if(modelYear<2013){ //MY2011,2012 00809 msg = lastMsg[indexLastMsg[0x5fa]]; 00810 t.tm_mon = (msg.data[5]>>4)-1; 00811 t.tm_mday = msg.data[2]>>3; 00812 msg = lastMsg[indexLastMsg[0x5fb]]; 00813 //t.tm_year = msg.data[1]; // Have not figured out where the year is 00814 msg = lastMsg[indexLastMsg[0x5fc]]; 00815 t.tm_hour = msg.data[0]>>3; 00816 t.tm_min = (msg.data[1]<<4&0x30)+(msg.data[2]>>4); 00817 t.tm_sec = msg.data[1]>>2; 00818 }else{ // model year 2013 or higher 00819 msg = lastMsg[indexLastMsg[0x5f9]]; 00820 t.tm_hour = msg.data[5]>>3; 00821 t.tm_min = msg.data[4]; 00822 msg = lastMsg[indexLastMsg[0x509]]; 00823 t.tm_sec = msg.data[2]>>2; 00824 } 00825 if(t.tm_hour==lastHour){ //filter 00826 numMatched++; 00827 }else{ 00828 numMatched=0; 00829 } 00830 lastHour=t.tm_hour; 00831 if((numMatched>5)&&(t.tm_mon>=0)&&(t.tm_mon<12)&&(t.tm_mday>0)&&(t.tm_mday<32)&&(t.tm_hour>=0)&&(t.tm_hour<24)&&(t.tm_min>=0)&&(t.tm_min<60)&&(t.tm_sec>=0)&&(t.tm_sec<60)){ // sanity check result before using 00832 set_time(mktime(&t)); 00833 numMatched=0; 00834 return(true); 00835 }else{ 00836 return(false); 00837 } 00838 00839 } 00840 00841 void logPackVoltages() { // Turbo3 - routine to dump CP values to text file 00842 char sTemp[40]; 00843 struct tm t; // pointer to a static tm structure 00844 short unsigned max, min, jv, i, bd; 00845 unsigned avg; 00846 unsigned short gids, SOC, packV_x2; 00847 unsigned long odo; 00848 signed short packA_x2; 00849 time_t seconds ; 00850 00851 CANMessage msg; 00852 00853 seconds = time(NULL); // Turbo3 00854 t = *localtime(&seconds) ; // Turbo3 00855 00856 msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids 00857 gids = (msg.data[0]<<2)+(msg.data[1]>>6); 00858 msg = lastMsg[indexLastMsg[0x5c5]]; //Get odometer 00859 odo = (msg.data[1]<16)+(msg.data[2]<<8)+msg.data[3]; 00860 msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC 00861 SOC = (msg.data[0]<<2)+(msg.data[1]>>6); 00862 msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts 00863 packV_x2 = (msg.data[2]<<2)+(msg.data[3]>>6); 00864 packA_x2 = (msg.data[0]<<3)+(msg.data[1]>>5); 00865 if (packA_x2 & 0x400) packA_x2 |= 0xf800; 00866 00867 max=0; 00868 min=9999; 00869 avg=0; 00870 for(i=0; i<96; i++) { 00871 bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4]; 00872 avg+=bd; 00873 if(bd>max) max=bd; 00874 if(bd<min) min=bd; 00875 } 00876 avg /= 96; 00877 if(min<3713) { 00878 jv=avg-(max-avg)*1.5; 00879 } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement 00880 jv=0; 00881 } 00882 00883 FIL bfile; 00884 FRESULT bfr; 00885 bfr = f_open(&bfile,"batvolt.txt",FA_WRITE|FA_OPEN_ALWAYS); 00886 if(bfr==FR_OK) { 00887 f_lseek(&bfile,0xffffffff); // go to end of file to append 00888 strftime(sTemp, 40, "%a %m/%d/%Y %X", &t); 00889 f_printf(&bfile,"%s,",sTemp); 00890 sprintf(sTemp,"%d,%d,%5.1f%%,%5.1f,%5.1f,%d,%d,%d,%d,%d",odo,gids,(float)SOC/10,(float)packV_x2/2,(float)packA_x2/2,max,min,avg,max-min,jv); 00891 f_printf(&bfile,"%s,",sTemp); 00892 f_printf(&bfile,"%d,%d,%d,%d,",(battData[(BatDataBaseG4*7)+ 3]<<8)+battData[(BatDataBaseG4*7)+ 4],battData[(BatDataBaseG4*7)+ 5],(battData[(BatDataBaseG4*7)+ 6]<<8)+battData[(BatDataBaseG4*7)+ 7],battData[(BatDataBaseG4*7)+ 8]); 00893 f_printf(&bfile,"%d,%d,%d,%d", (battData[(BatDataBaseG4*7)+ 9]<<8)+battData[(BatDataBaseG4*7)+10],battData[(BatDataBaseG4*7)+11],(battData[(BatDataBaseG4*7)+12]<<8)+battData[(BatDataBaseG4*7)+13],battData[(BatDataBaseG4*7)+14]); 00894 for(i=0; i<96; i++) { 00895 bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4]; 00896 f_printf(&bfile,",%d",bd); 00897 } 00898 f_printf(&bfile,"\r\n"); 00899 f_close(&bfile); 00900 } 00901 logCP=false; 00902 showCP=true; 00903 } 00904 00905 void tripLog() { // Daily log 00906 char sTemp[40]; 00907 unsigned char ambient; 00908 struct tm t; // pointer to a static tm structure 00909 short unsigned max, min, jv, i, bd; 00910 unsigned avg; 00911 unsigned short gids, SOC, packV_x2; 00912 unsigned long odo; 00913 signed short packA_x2; 00914 time_t seconds ; 00915 00916 CANMessage msg; 00917 00918 seconds = time(NULL); // Turbo3 00919 t = *localtime(&seconds) ; // Turbo3 00920 00921 msg = lastMsg[indexLastMsg[0x54c]]; //Get ambient 00922 ambient = msg.data[6]-56; 00923 msg = lastMsg[indexLastMsg[0x5bc]]; //Get gids 00924 gids = (msg.data[0]<<2)+(msg.data[1]>>6); 00925 msg = lastMsg[indexLastMsg[0x5c5]]; //Get odometer 00926 odo = (msg.data[1]<16)+(msg.data[2]<<8)+msg.data[3]; 00927 msg = lastMsg[indexLastMsg[0x55b]]; //Get SOC 00928 SOC = (msg.data[0]<<2)+(msg.data[1]>>6); 00929 msg = lastMsg[indexLastMsg[0x1db]]; //Get pack volts 00930 packV_x2 = (msg.data[2]<<2)+(msg.data[3]>>6); 00931 packA_x2 = (msg.data[0]<<3)+(msg.data[1]>>5); 00932 if (packA_x2 & 0x400) packA_x2 |= 0xf800; 00933 00934 max=0; 00935 min=9999; 00936 avg=0; 00937 for(i=0; i<96; i++) { 00938 bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4]; 00939 avg+=bd; 00940 if(bd>max) max=bd; 00941 if(bd<min) min=bd; 00942 } 00943 avg /= 96; 00944 if(min<3713) { 00945 jv=avg-(max-avg)*1.5; 00946 } else { // Only compute judgement value if min cellpair meets <= 3712mV requirement 00947 jv=0; 00948 } 00949 00950 FIL bfile; 00951 FRESULT bfr; 00952 bfr = f_open(&bfile,"triplog.txt",FA_WRITE|FA_OPEN_ALWAYS); 00953 if(bfr==FR_OK) { 00954 f_lseek(&bfile,0xffffffff); // go to end of file to append 00955 // timestamp, odometer, accV, gids, SOC, SOH2, Ah, Vbatt, Ibatt, Rest, maxCP, minCP, avgCO, maxCP-minCP, CVLI_jv, miles_trip, kWh_trip, CCkWh_trip, ambient, T1raw, T1, T2raw, T2, T3raw, T3, T4raw, T4, CP1, CP2, ... , CP96 00956 strftime(sTemp, 40, "%a %m/%d/%Y %X", &t); 00957 f_printf(&bfile,"%s,",sTemp); 00958 sprintf(sTemp,"%d,%3.1f,%d,%5.1f%%,%5.1f%%,%4.2f,%5.1f,%4.1f,%4.3f,%d,%d,%d,%d,%d,%4.1f,%4.2f,%4.2f",odo,accV,gids,(float)SOC/10, (float)SOH2_x100/100,(float)Ah_x10000/10000,(float)packV_x2/2,(float)packA_x2/2,Resr,max,min,avg,max-min,jv,miles_trip[0],kWh_trip[0],CCkWh_trip[0]); 00959 f_printf(&bfile,"%s,%d,",sTemp,ambient); 00960 f_printf(&bfile,"%d,%d,%d,%d,",(battData[(BatDataBaseG4*7)+ 3]<<8)+battData[(BatDataBaseG4*7)+ 4],battData[(BatDataBaseG4*7)+ 5],(battData[(BatDataBaseG4*7)+ 6]<<8)+battData[(BatDataBaseG4*7)+ 7],battData[(BatDataBaseG4*7)+ 8]); 00961 f_printf(&bfile,"%d,%d,%d,%d", (battData[(BatDataBaseG4*7)+ 9]<<8)+battData[(BatDataBaseG4*7)+10],battData[(BatDataBaseG4*7)+11],(battData[(BatDataBaseG4*7)+12]<<8)+battData[(BatDataBaseG4*7)+13],battData[(BatDataBaseG4*7)+14]); 00962 for(i=0; i<96; i++) { 00963 bd=(battData[BatDataBaseG2*7+i*2+3]<<8)+battData[BatDataBaseG2*7+i*2+4]; 00964 f_printf(&bfile,",%d",bd); 00965 } 00966 f_printf(&bfile,"\r\n"); 00967 f_close(&bfile); 00968 } 00969 } 00970 00971 //LM - updates firmware off a usb key, eliminating the need to plug 00972 //the CANary into a computer for updates. 00973 void updateFirmware() 00974 { 00975 FIL efile; // external usb file 00976 FRESULT sfr; // external file access flags 00977 unsigned int bytesRW; 00978 char sTemp[40]; 00979 const int bufSize = 2048; 00980 char buffer[bufSize]; 00981 FILE *lfile; 00982 00983 tt.set_font((unsigned char*) Arial12x12); 00984 tt.background(Blue); 00985 tt.foreground(Yellow); 00986 tt.locate(0,10); 00987 tt.cls(); 00988 00989 sfr = f_open(&efile,"firmware.bin",FA_READ|FA_OPEN_EXISTING); 00990 if(sfr != FR_OK) 00991 { 00992 printf("Couldn't find firmware.bin\n"); 00993 wait(3); 00994 lastDMode[whichTouched]=99;//force refresh 00995 return; 00996 } 00997 fwCount ++; 00998 printf("Saving config.\n"); 00999 saveConfig(); 01000 //delete all bin files in /local 01001 DIR *dir; 01002 struct dirent *ent; 01003 printf("Starting update.\n"); 01004 printf("Deleting old firmware files.\n"); 01005 if ((dir = opendir ("/local/")) != NULL) { 01006 // print all the files and directories within directory 01007 while ((ent = readdir (dir)) != NULL) { 01008 //printf("FILE: %s\n",ent->d_name); 01009 char dest[4] = ""; 01010 strncat(dest, &ent->d_name[strlen(ent->d_name)-3],3); 01011 dest[0] = tolower(dest[0]); 01012 dest[1] = tolower(dest[1]); 01013 dest[2] = tolower(dest[2]); 01014 if(strcmp(dest,"bin")==0) 01015 { 01016 sprintf(sTemp,"/local/%s",ent->d_name); 01017 int result = remove(sTemp); 01018 printf("deleted: %s\n",ent->d_name); 01019 } 01020 } 01021 closedir (dir); 01022 } else { 01023 //could not open directory 01024 printf("Couldn't open folder.\n"); 01025 wait(3); 01026 return; 01027 } 01028 printf("Copying new firmware.\n"); 01029 //Copy the new firmware from usb->local 01030 //The newest bin file is the one that is used by the mbed 01031 sprintf(sTemp,"/local/fw%d.bin",fwCount); 01032 printf("Writing %s.\n",sTemp); 01033 //wait(2); 01034 lfile = fopen(sTemp, "wb"); 01035 if(lfile == NULL) 01036 { 01037 printf("Couldn't open destination.\n"); 01038 wait(3); 01039 return; 01040 } 01041 01042 while (!f_eof(&efile)) 01043 { 01044 sfr=f_read(&efile,&buffer,bufSize,&bytesRW); 01045 fwrite(buffer, 1, bytesRW, lfile); 01046 } 01047 01048 fflush(lfile); 01049 fclose(lfile); 01050 f_close(&efile); 01051 printf("Succesful.\n\n"); 01052 printf("Rebooting in 5 seconds.\n"); 01053 wait(5); 01054 //Now run new firmware 01055 mbed_reset(); 01056 } 01057 01058 void updateConfig() 01059 { 01060 FIL efile; // external usb file 01061 FRESULT sfr; // external file access flags 01062 unsigned int bytesRW; 01063 const int bufSize = 2048; 01064 char buffer[bufSize]; 01065 FILE *lfile; 01066 01067 tt.set_font((unsigned char*) Arial12x12); 01068 tt.background(Blue); 01069 tt.foreground(Yellow); 01070 tt.locate(0,10); 01071 tt.cls(); 01072 01073 printMsg("Copy config file from USB\n"); 01074 // Check for config file on USB drive 01075 sfr = f_open(&efile,"CONFIG.TXT",FA_READ|FA_OPEN_EXISTING); 01076 if(sfr == FR_OK){ 01077 printf("Copy config file from USB\n"); 01078 lfile = fopen("/local/CONFIG.TXT", "w"); 01079 if(lfile != NULL) { 01080 while (!f_eof(&efile)){ 01081 sfr=f_read(&efile,&buffer,bufSize,&bytesRW); 01082 fwrite(buffer, 1, bytesRW, lfile); 01083 } 01084 fflush(lfile); 01085 fclose(lfile); 01086 } 01087 f_close(&efile); 01088 int fwc_tmp = fwCount; 01089 readConfig(); 01090 fwCount = fwc_tmp; // Do no overwrite fwcount when loading new config 01091 } 01092 01093 // Check for history file on USB drive 01094 printMsg("Copy ehist file from USB\n"); 01095 sfr = f_open(&efile,"ehist.cny",FA_READ|FA_OPEN_EXISTING); 01096 if(sfr == FR_OK){ 01097 printf("Copy ehist file from USB\n"); 01098 lfile = fopen("/local/ehist.cny", "w"); 01099 if(lfile != NULL) { 01100 while (!f_eof(&efile)){ 01101 sfr=f_read(&efile,&buffer,bufSize,&bytesRW); 01102 fwrite(buffer, 1, bytesRW, lfile); 01103 } 01104 fflush(lfile); 01105 fclose(lfile); 01106 } 01107 f_close(&efile); 01108 } 01109 printf("Succesful.\n\n"); 01110 wait(5); 01111 } 01112 01113 bool detectUSB(void){ 01114 FIL tfile; // external usb file 01115 bool usbEn = (f_open(&tfile,"usb.det",FA_WRITE|FA_OPEN_ALWAYS)==FR_OK); 01116 if(usbEn){ 01117 f_close(&tfile); 01118 f_unlink("usb.det"); 01119 } 01120 return(usbEn); 01121 } 01122 01123 void spkrOff(void){ 01124 if(bCount<2){ 01125 spkr.period(1.0/bFreq[bCount]); 01126 beepOff.attach(&spkrOff, bTime[bCount++]); 01127 }else{ 01128 spkr=0; 01129 dled.period(.001); 01130 } 01131 } 01132 01133 void beep(float freq, float time){ 01134 if (enableSound) { 01135 spkr.period(1.0/freq); 01136 spkr=0.5; 01137 if(!headlights){ //restore LCD pwm output (Beep pwm interferes with display pwm) 01138 dled = ledHi; 01139 } else { 01140 dled = ledLo; 01141 } 01142 beepOff.attach(&spkrOff, time); 01143 } 01144 } 01145 01146 void beep3(float freq1, float time1, float freq2, float time2, float freq3, float time3){ 01147 bFreq[0]=freq2; 01148 bTime[0]=time2; 01149 bFreq[1]=freq3; 01150 bTime[1]=time3; 01151 bCount=0; 01152 beep(freq1, time1); 01153 } 01154 01155 void chirp(void){ 01156 static unsigned short counter=0; 01157 01158 if(chirpInt>0){ 01159 if(++counter>chirpInt){ 01160 beep(1600,0.015); 01161 counter=0; 01162 } 01163 }else{ 01164 counter=0; 01165 } 01166 } 01167 01168 //Sample CONFIG.TXT 01169 /* 01170 format 11 01171 x0_off 5732 01172 y0_off 34009 01173 x0_pp 77 01174 y0_pp 106 01175 x1_off 33955 01176 y1_off 6310 01177 x1_pp 80 01178 y1_pp 104 01179 x_mid 31986 01180 dMode0 4 01181 dMode1 2 01182 ledHi 0.800 01183 ledLo 0.300 01184 pollInt 300 01185 scale12V 16.20 01186 skin 0 01187 dtePeriod 14 01188 DebugMode 0 01189 metric 0 01190 firmware 1 01191 showHealth 1 01192 brakeMon 1 01193 brkMonRate 4.0 01194 brkMonThr 1.0 01195 usrMsgId 5103 01196 usrMsgId 50a3 01197 usrMsgId 54a4 01198 usrMsgId 54b4 01199 usrMsgId 54c0 01200 usrMsgId 55b4 01201 usrMsgId 0000 01202 usrMsgId 0000 01203 modelYear 2011 01204 autoSync 1 01205 kWperGid 0.075 01206 */
Generated on Thu Jul 14 2022 20:47:27 by
1.7.2
