Dual CANbus monitor and instrumentation cluster supporting ILI9341 display controller
Dependencies: SPI_TFTx2_ILI9341 TOUCH_TFTx2_ILI9341 TFT_fonts mbed
Fork of CANary by
Diff: utility.cpp
- 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