Dual CANbus monitor and instrumentation cluster supporting ILI9341 display controller

Dependencies:   SPI_TFTx2_ILI9341 TOUCH_TFTx2_ILI9341 TFT_fonts mbed

Fork of CANary by Tick Tock

Revision:
80:24f1793171e7
Parent:
77:7c136766466c
Child:
81:cf009a64eedd
--- 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