Dual CANbus monitor and instrumentation cluster

Dependencies:   SPI_TFTx2 TFT_fonts TOUCH_TFTx2 beep mbed

Fork of CANary by Tick Tock

Files at this revision

API Documentation at this revision

Comitter:
garygid
Date:
Tue Apr 16 21:13:59 2013 +0000
Parent:
77:7c136766466c
Child:
81:cf009a64eedd
Commit message:
logCan counts overflow Lost Messages, and others

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
utility.cpp Show annotated file Show diff for this revision Revisions of this file
utility.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Tue Apr 16 03:28:55 2013 +0000
+++ b/main.cpp	Tue Apr 16 21:13:59 2013 +0000
@@ -50,7 +50,7 @@
 // gg - revStr is used in 2 places
 // gg - and is easy to edit here
 // gg - added ZeroSecTick and revStr
-char revStr[7] = "77"; // gg - fix rev number
+char revStr[7] = "77-gg1"; // gg - fix rev number
 
 bool logEn = false, logOpen = false; 
 bool yesBattLog = false ; // gg - Batt Log
@@ -257,9 +257,9 @@
                     logMsg(sTemp); // starting alc log file 
                     
                     logTS(); // Date Time at start
-                    logErrMsg("Starting"); // Log startup msg for testing
+                    logEvent("Starting"); // Log startup msg for testing
                     sprintf(sTemp,"Cr%s",revStr);
-                    logErrMsg(sTemp); // gg - log firmware version
+                    logEvent(sTemp); // gg - log firmware version
                     
                     spkr.beep(2000,0.25);
                 }
@@ -329,7 +329,7 @@
                 if (secsNoTouch>100) secsNoTouch = 100; // also mostly reset user Idle counter
             } else if (logOpen){ // insert timestamp on each wake if logging enabled (disabled for now)
                 file = fopen(fileName, "ab");
-                logErrMsg("WakingUp"); // gg - use messeges
+                logEvent("WakingUp"); // gg - use messeges
                 logTS(); // Date-Time at wakeup
             }
         } // if idle
@@ -576,18 +576,24 @@
                             case 02: // left col, bottom row (not nav)
                                 if (dMode[whichTouched] == indexScreen) { // gg - index
                                     dMode[whichTouched] = config1Screen ; // GoTo Config Screen   
+                                } else {
+                                    lastDMode[whichTouched]=99;//repaint to clear highlight
                                 }
                                 break;
                                 
                              case 12: // left-middle col, bottom row (not nav)
                                 if (dMode[whichTouched] == indexScreen) { // gg - index
                                     dMode[whichTouched] = playbackScreen ; // GoTo Playback Screen   
+                                } else {
+                                    lastDMode[whichTouched]=99;//repaint to clear highlight
                                 }
                                 break;
                              
                              case 22: // right-middle col, bottom row (not nav)
                                 if (dMode[whichTouched] == indexScreen) { // gg - index
                                     dMode[whichTouched] = dateScreen ; // GoTo Set Date/Time Screen   
+                                } else {
+                                    lastDMode[whichTouched]=99;//repaint to clear highlight
                                 }
                                 break;
 
@@ -595,6 +601,8 @@
                                 if (dMode[whichTouched] == indexScreen) { // gg - index
                                     dMode[whichTouched] = logScreen ; // GoTo Log Screen
                                     sMode=0;
+                                } else {
+                                    lastDMode[whichTouched]=99;//repaint to clear highlight
                                 }
                                 break;
 
--- a/utility.cpp	Tue Apr 16 03:28:55 2013 +0000
+++ b/utility.cpp	Tue Apr 16 21:13:59 2013 +0000
@@ -38,87 +38,231 @@
     return ((isecs<<10)+msec) ; // return the two byte time stamp
 }
 
+//------------------------------------
+// gg - logcan
 void logCan (char mType, CANMessage canRXmsg) {
+   // re-arranged to put static first
+    static unsigned char ii = 0;
+    static unsigned char lasti = 0; // indexindex
+    static unsigned char bdi=0;
+    static signed short imotorRPM = 0;
+    static unsigned short nLost = 0; // gg - overrun
+
     char sTemp[40];    
-    unsigned short ts = getTimeStamp();
-    static unsigned char ii = 0, lasti = 0; // indexindex
     unsigned char changed,i;
-    static unsigned char bdi=0;
+    unsigned char ij;
     signed short packV;
     signed short packA;
-    static signed short imotorRPM = 0;
     signed long imWs_x4;
     
+    unsigned short ts = getTimeStamp();
     secsNoMsg=0; // reset deadman switch
+    
     if(logOpen){
         if(canRXmsg.id>0) {
-            writeBuffer[writePointer][0]=mType;
-            writeBuffer[writePointer][1]=(ts&0xff00)>>8;
-            writeBuffer[writePointer][2]=(ts&0x00ff);
-            writeBuffer[writePointer][3]=canRXmsg.id&0xff;
-            writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4);
-            for(i=5;i<13;i++){ // Is there a better way to do this? (writeBuffer[writePointer][i]=canRXmsg.data?)
-                writeBuffer[writePointer][i]=canRXmsg.data[i-5];
-            }
-            if (++writePointer >= maxBufLen) {
-                writePointer = 0;
-                led3 = !led3;
-            }
-            if (writePointer==readPointer) {
-                // Just overwrote an entry that hasn't been sent to thumbdrive
-                sprintf(sTemp,"Write buffer overrun.\n");
-                logMsg(sTemp); // write buffer overrun
-                spkr.beep(500,0.25);
+            // check to see if buffer is already full (read - write) = 1
+            // actually the last buffer location cannot be used because then 
+            //   the buffer would look empty after writePointer++
+            
+            //if (((writePointer+maxBufLen-readPointer)%maxBufLen)>(maxBufLen/16)) // modulo is slow?
+
+            // maxBufLen = 512, so pointers are 0 through 511
+            if( (readPointer - writePointer) == 1 || (writePointer - readPointer) == (maxBufLen - 1)) {
+                // the buffer is "full", so Lose this message
+                
+                // point to the last-stored message
+                int tempWritePointer = writePointer - 1 ;
+                if( tempWritePointer == -1 ) tempWritePointer = maxBufLen - 1;
+                char strLost[9] ;
+
+                if( nLost == 0 ) {
+                    // this is the first message lost 
+                    //   and we must overwrite the last message with an FFE comment message
+                    // So, there will be two messages lost as the comment message is laid in.
+                    nLost = 2;
+                    sprintf(strLost,"%s","Lost0002"); // indicate two messages lost
+                    
+                    // overlay the last message with a "Lost0002" comment
+                    writeBuffer[tempWritePointer][0]=0;
+                    writeBuffer[tempWritePointer][1]=(ts&0xff00)>>8; // Time Stamp (2 bytes_
+                    writeBuffer[tempWritePointer][2]=(ts&0x00ff);
+                    writeBuffer[tempWritePointer][3]=0xfe; // MsgID, low byte
+                    writeBuffer[tempWritePointer][4]=0xff; // Len nibble, and MsgID high nibble
+                        
+                    for(i=5;i<13;i++){ 
+                        writeBuffer[tempWritePointer][i]= strLost[i-5];
+                    }
+                } else {
+                    // increment the loat counter
+                    nLost += 1;
+                    
+                    // lay the new count into the comment
+                    sprintf(strLost,"%04d",nLost);
+                    for(i=9;i<13;i++){ 
+                        writeBuffer[tempWritePointer][i]= strLost[i-9];
+                    }
+                }
+            } else {
+                // is room to insert the message
+                // get it inserted quickly
+                writeBuffer[writePointer][0]=mType;
+                writeBuffer[writePointer][1]=(ts&0xff00)>>8; // Time Stamp (2 bytes_
+                writeBuffer[writePointer][2]=(ts&0x00ff);
+                writeBuffer[writePointer][3]=canRXmsg.id&0xff; // MsgID, low byte
+                writeBuffer[writePointer][4]=(canRXmsg.id>>8)+(canRXmsg.len<<4); // Len nibble, and MsgID high nibble
+                for(i=5;i<13;i++){ // Is there a better way to do this? (writeBuffer[writePointer][i]=canRXmsg.data?)
+                    writeBuffer[writePointer][i]=canRXmsg.data[i-5];
+                }
+                //--------------
+                // force unused data bytes to FF for CAN-Do compatibility - gg - force FF
+                if(canRXmsg.len < 8){
+                    for(i=canRXmsg.len; i<8; i++) {
+                        writeBuffer[writePointer][i+5]=0xFF;
+                    }
+                }
+                //--------------
+                // note, this is not protected from the interrupt
+                // due to the nLost code above, this no longer
+                //    overflows to writePointer = readPointer
+                //    which would make the buffer look empty
+                if (++writePointer >= maxBufLen) {
+                    writePointer = 0;
+                    led3 = !led3;
+                }
+                //--------------
+                // log a local message if we had lost messages. gg - logcan
+                if( nLost > 0 ) {
+                    // We previously lost messages that did not get into the buffer
+                    sprintf(sTemp,"-- Write Buffer Lost [%d]\n", nLost);
+                    logMsg(sTemp); // write buffer overrun
+                    spkr.beep(500,0.25);
+                    
+                    nLost = 0 ;
+                }
+                //--------------
             }
         }
     }
+    
+    //-------------------------------
+    // Some MsgIDS are FFF and FFE, but this array only holds 0 to 7FF
+    //   so, only remember messages 7FF or less - gg - logging bug
+    if( canRXmsg.id < 0x800 ) {
+        // message is 7FF or less - gg - logging bug
+        
+        // Check if this MsgID has an associated ii entry
+        if(indexLastMsg[canRXmsg.id]==0) { 
+            // no ii entry associated with this MsgID
+            
+            // BUG: but ii = 0 is a valid entry after this wraps 
+            //ii=ii<99?ii+1:0;
+            //ii=ii<99?ii+1:1; // FIX: reserve ii = 0 as the "invalid, not used, entry
+            
+            if(ii<99) {
+                // unused entries are available
+                ii += 1; // use next unused entry    
+                
+                // sever previous usage, if any
+                //if( iiUsedBy[ii] != 0 ) indexLastMsg[iiUsedBy[ii]]=0;    
+                 
+                // keep track of what MsgID is using this ii entry
+                //iiUsedBy[ii]=canRXmsg.id; // future                                            
+                                                            
+                indexLastMsg[canRXmsg.id]=ii; // Create MsgID linkage for first message                               
+                
+                // update the entry's data
+                lastMsg[ii]=canRXmsg; //Store in table
+                
+                changed = 0xff ; // all bytes are new, so all changed
+                msgChanged[ii]=changed;
+                
+            } else {
+                // no more available unused entries
+                // so just ignore this MsgID for now
+                // ii = 1; // start to re-use entries
+                
+                // BUG: after this wraps to re-use the ii's, the old MsgID 
+                //   that was using this ii needs to be invalidated           
+                //indexLastMsg[iiUsedBy[ii]]=0; // invalidate ii entry for old MsgID                     
+            }
 
-    if(indexLastMsg[canRXmsg.id]==0) { //Check if no entry
-        ii=ii<99?ii+1:0;
-        indexLastMsg[canRXmsg.id]=ii; //Create entry if first message
-    }
-    if(dMode[0]==changedScreen||dMode[1]==changedScreen){
-        changed=msgChanged[indexLastMsg[canRXmsg.id]];
-        for(i=0;i<8;i++){
-            if(lastMsg[indexLastMsg[canRXmsg.id]].data[i]!=canRXmsg.data[i]){
-                changed |= 1<<i;
+        } else {
+            // there was an old entry for this MsgID to compare to for changes 
+            ij = indexLastMsg[canRXmsg.id] ;
+            
+            // compare the old message with the new one to make the data-changed flags            
+            // BUG?: why do this only if viewing the changedScreen?
+            if(dMode[0]==changedScreen||dMode[1]==changedScreen){
+                
+                changed=msgChanged[ij]; // why get the old changed bits
+                // what clears the changed bits, dislaying them on the changedScreen?
+                
+                // compare the 8 old and new data bytes for changes
+                for(i=0;i<8;i++){
+                    if(lastMsg[ij].data[i]!=canRXmsg.data[i]){
+                        changed |= 1<<i;
+                    }
+                }
+                // store the changes
+                msgChanged[ij]=changed;
             }
+            
+            // after the comparison, if any, update the entry's data
+            lastMsg[ij]=canRXmsg; // Store in table
         }
-        msgChanged[indexLastMsg[canRXmsg.id]]=changed;
-    }
+    } // end of is 7FF or less
 
-    lastMsg[indexLastMsg[canRXmsg.id]]=canRXmsg; //Store in table
+    //-----------------------
+    // Miscellaneous on-receive operations below
+    if((mType==2)&&(canRXmsg.id==0x358)){ // CAR bus
+        // headlight/turn signal indicator
+        headlights = (canRXmsg.data[1]&0x80)?true:false;
 
-    //Miscellaneous on-recieve operations below
-    if((mType==2)&&(canRXmsg.id==0x358)){ // headlight/turn signal indicator
-        headlights = (canRXmsg.data[1]&0x80)?true:false;
-    }else if((mType==1)&&(canRXmsg.id==0x7bb)){ // is battery data?  Need to store all responses
+    //-----------------        
+    }else if((mType==1)&&(canRXmsg.id==0x7bb)){ // EV bus
+        // is battery-response data?  7bb [0]=SeqNum 1 2 [3]=Group
+        // Need to store all responses
+        
+        // the first SeqNum is 10 (less than 20-2F found later)
         if(canRXmsg.data[0]<0x20){
-            if(canRXmsg.data[3]==2){//cellpair data
-                bdi=0;
+            // the f1rst response in a series
+            if(canRXmsg.data[3]==2){ //cellpair data Group 2
+                bdi=0; // initial SeqNum = 10, so index 0
+                // next is 21 to 2F and then 20 to about 2C
                 sprintf(sTemp,"Getting cell pair data\n");
                 logMsg(sTemp);
-            }else if(canRXmsg.data[3]==4){//temperature data
-                bdi=0x20;
+            }else if(canRXmsg.data[3]==4){ //temperature data Group 4
+                bdi=0x20; // index 0 - 2 from SeqNum 20 - 22
                 sprintf(sTemp,"Getting temperature data\n");
                 logMsg(sTemp);
-            }else bdi=0;
+            }else bdi=0; // strange, BUG? the same as Group 2
+            
             lasti=0;
         }
-        i=canRXmsg.data[0]&0x0f; //lower nibble of D0 is index
-        if(lasti>i){ //detect rollover and offset index appropriately
-            bdi=0x10;
+        // handle this response
+        i=canRXmsg.data[0]&0x0f; // lower nibble of D0 is index, 0 to F
+        if(lasti>i){ //detect rollover to 20 (index 0) and offset index appropriately
+            bdi=0x10; // adding 10 to the index for CPs
         }
-        lasti=i; //remember the msb to detect rollover next time around
-        i+=bdi;
+        lasti=i; //remember the index nibble to detect rollover next time around
+        i+=bdi; // 0 to F then 10 through about 1C for CPs
+                // 20 through 22 for the Temperatures (Group 4)
+        
+        //--------------
+        // detect last response from the Temperature series.
         //if(i==22) logCP=true; //Turbo3
         //if( (i==22) && (yesBattLog) ) logCP=true; // only if enabled gg - Batt Log 
         if(i==22){
+            // is the last response from Temperatures
             logCP=yesBattLog; // Only log if logging enabled
             showCP=true; // Always show
         }
+        
+        // storing 7 bytes of data from each response (after the SeqNum)
         i*=7;
         if(i<0xfa){ // Is there a better way to do this?
+            // for CP data the base is 0, at i is (i*7)+6 and the last is 28*7+6 
+            // for Temp data,  base is 32*7, at i is (i*7)+6 and the last is 34*7+6      
             battData[i+0]=canRXmsg.data[1];
             battData[i+1]=canRXmsg.data[2];
             battData[i+2]=canRXmsg.data[3];
@@ -127,7 +271,24 @@
             battData[i+5]=canRXmsg.data[6];
             battData[i+6]=canRXmsg.data[7];
         }
-    }else if((mType==1)&&(canRXmsg.id==0x1db)){ //Battery Volts and Amps
+    
+    //----------------------   
+    }else if((mType==1)&&(canRXmsg.id==0x1db)){ // EV bus
+        // Battery Volts and Amps
+        packV=((canRXmsg.data[2]<<2)|(canRXmsg.data[3]>>6)); // 1 LSB = 0.5V
+        packA=((canRXmsg.data[0]<<3)|(canRXmsg.data[1]>>5)); // 1 LSB = 0.5A
+        if(packA>0x03ff){
+            packA|=0xf800;//extend sign;
+        }
+        imWs_x4 = packV; // Volts*milliSeconds*2
+        imWs_x4 *= -packA; // milliWattseconds*4
+        if (!((imotorRPM<2)&&(imWs_x4<0))){ //Ignore if charging from wall
+            mWs_x4 += imWs_x4; // total mWs_x4
+            numWsamples++;
+        }
+//-------------------------
+#if 0
+  }else if((mType==1)&&(canRXmsg.id==0x1db)){ //Battery Volts and Amps
         packV=((canRXmsg.data[2]<<2)|(canRXmsg.data[3]>>6)); // 1 LSB = 0.5V
         packA=((canRXmsg.data[0]<<3)|(canRXmsg.data[1]>>5)); // 1 LSB = 0.5A
         if(packA>0x03ff){
@@ -147,8 +308,20 @@
         motorRPM+=imotorRPM;
         numSsamples++;
     }
+#endif
+//-------------------------        
+    }else if((mType==1)&&(canRXmsg.id==0x1da)){ // EV bus
+        // Motor Speed
+        imotorRPM=((canRXmsg.data[4]<<8)|(canRXmsg.data[5]));
+        if(imotorRPM<0){ // take absolute value
+            imotorRPM=-imotorRPM;
+        }
+        motorRPM+=imotorRPM;
+        numSsamples++;
+    }
 }
 
+//---------------------------------
 void logTS () {
     CANMessage tsMsg;
     unsigned long secs = time(NULL); // seconds past 12:00:00 AM 1 Jan 1900
@@ -167,7 +340,9 @@
     logCan(0,tsMsg); // Date-Time
 }
 
-void logErrMsg (char * errMsg) {
+//----------------------------------
+// gg - logevent
+void logEvent (char * errMsg) {
     // log CAN-Do 8-character Pseudo Message
     CANMessage tsMsg;
     tsMsg.id=0xffe; // pseudo Message to CAN-Do log
--- a/utility.h	Tue Apr 16 03:28:55 2013 +0000
+++ b/utility.h	Tue Apr 16 21:13:59 2013 +0000
@@ -59,7 +59,7 @@
     unsigned short getTimeStamp();
     void logCan (char mType, CANMessage canRXmsg);
     void logTS ();    
-    void logErrMsg (char * errMsg); // gg - messeges
+    void logEvent (char * errMsg); // gg - messeges
     void sendCPreq();    
     void sendTreq();    
     void autoPollISR();