System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Wed Feb 11 23:09:57 2015 +0000
Revision:
39:ddf38df9699e
Parent:
38:8efacce315ae
Updated CAN IDs for datalogging.  Changed profile encoding.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 30:91af74a299e1 1 #include "outDiagnostics.h"
pspatel321 38:8efacce315ae 2 #include "outMacros.h"
pspatel321 30:91af74a299e1 3
pspatel321 38:8efacce315ae 4 Timer serialLoop;
pspatel321 38:8efacce315ae 5 Timer CANloop;
pspatel321 38:8efacce315ae 6 int serialTime_ms = 0;
pspatel321 38:8efacce315ae 7 int CANtime_ms = 0;
pspatel321 38:8efacce315ae 8 const int max_charsPerLine = 80; // Max chars per line of printed information
pspatel321 34:18bcf276d3bf 9
pspatel321 36:0afc0fc8f86b 10 // Use the txEmpty interrupt from MODSERIAL to pace the thread so it always runs as fast as possible
pspatel321 38:8efacce315ae 11 osThreadId serialID=0;
pspatel321 38:8efacce315ae 12 void empty(MODSERIAL_IRQ_INFO *q)
pspatel321 38:8efacce315ae 13 {
pspatel321 36:0afc0fc8f86b 14 osSignalSet(serialID, 1);
pspatel321 34:18bcf276d3bf 15 }
pspatel321 36:0afc0fc8f86b 16 // Output a string to the MODSERIAL tx buffer, wait when buffer full
pspatel321 36:0afc0fc8f86b 17 void AddtoBuffer(char *str, bool newline=true)
pspatel321 34:18bcf276d3bf 18 {
pspatel321 36:0afc0fc8f86b 19 const int waitT = TX_SIZE * CHAR_TIME*1000; // Max wait time to empty the tx buffer = max time to send out all chars
pspatel321 36:0afc0fc8f86b 20 int len = strlen(str);
pspatel321 36:0afc0fc8f86b 21 int times = newline ? (len + 2) : (len); // If newline requested, add 2 chars for "\r\n"
pspatel321 36:0afc0fc8f86b 22 for (int i = 0; i < times; i++) {
pspatel321 36:0afc0fc8f86b 23 if (!pc.writeable()) { // Keep writing till it fills
pspatel321 36:0afc0fc8f86b 24 osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<3); // Check-in with watchdog thread
pspatel321 36:0afc0fc8f86b 25 Thread::signal_wait(1, waitT); // Wait for empty signal from MODSERIAL tx empty interrupt, timeout in waitT ms
pspatel321 34:18bcf276d3bf 26 }
pspatel321 36:0afc0fc8f86b 27 if (i < len) pc.putc(str[i]); // Print the string
pspatel321 36:0afc0fc8f86b 28 else if (i == len) pc.putc('\r'); // Add carriage return
pspatel321 36:0afc0fc8f86b 29 else if (i > len) pc.putc('\n'); // Add newline
pspatel321 34:18bcf276d3bf 30 }
pspatel321 30:91af74a299e1 31 }
pspatel321 30:91af74a299e1 32
pspatel321 34:18bcf276d3bf 33 // Print to internal string buffer, pad to maxLen chars and center it with char pad, str must be null terminated!
pspatel321 34:18bcf276d3bf 34 void padCenter(int LineLen, char *str, char pad)
pspatel321 34:18bcf276d3bf 35 {
pspatel321 36:0afc0fc8f86b 36 static char line[max_charsPerLine+5]; // String buffer to work with one line at a time
pspatel321 36:0afc0fc8f86b 37 int len = strlen(str); // Length of input string
pspatel321 36:0afc0fc8f86b 38 int padL = (LineLen-len)/2; // How many pad chars needed on left side?
pspatel321 36:0afc0fc8f86b 39 for (int i=0; i<padL; i++) line[i] = pad; // Fill in the left padding chars
pspatel321 36:0afc0fc8f86b 40 strcpy(line+padL, str); // Copy to line string
pspatel321 36:0afc0fc8f86b 41 for (int i = padL+len; i<LineLen; i++) line[i] = pad; // Fill remaining with padding chars
pspatel321 36:0afc0fc8f86b 42 line[LineLen-1] = '\0'; // Add null terminator
pspatel321 34:18bcf276d3bf 43
pspatel321 36:0afc0fc8f86b 44 AddtoBuffer(line);
pspatel321 34:18bcf276d3bf 45 }
pspatel321 34:18bcf276d3bf 46
pspatel321 34:18bcf276d3bf 47 // Generates the serial dashboard, uses MODSERIAL, self-paced (thread yields when buffer is full, resumes when empty)
pspatel321 34:18bcf276d3bf 48 void outDiagnostics::thread_serialOut(void const *args)
pspatel321 34:18bcf276d3bf 49 {
pspatel321 38:8efacce315ae 50 serialID = Thread::gettid(); // Record thread ID so empty() can signal this thread
pspatel321 38:8efacce315ae 51 char temp[max_charsPerLine+5]; // String buffer to sprintf into, max 1 line
pspatel321 38:8efacce315ae 52 pc.attach(&empty, MODSERIAL::TxEmpty); // Attach the tx empty interrupt which paces this thread
pspatel321 38:8efacce315ae 53 pc.printf("\033[2J"); // Clear the screen to get rid of reset message
pspatel321 34:18bcf276d3bf 54
pspatel321 38:8efacce315ae 55 // Use these bools to track changes in display mode between iterations
pspatel321 38:8efacce315ae 56 bool lastModeExtended = param->extendedSerial;
pspatel321 38:8efacce315ae 57 bool inExtendedMode = param->extendedSerial;
pspatel321 30:91af74a299e1 58
pspatel321 38:8efacce315ae 59 // For determining where the data displayed is coming from
pspatel321 38:8efacce315ae 60 bool freeze = false; // Not a freeze frame
pspatel321 38:8efacce315ae 61 bool notLiveProfile = false; // Live data
pspatel321 38:8efacce315ae 62
pspatel321 38:8efacce315ae 63 const char barSpace[4] = { ' ', 179, ' ', 0 }; // Commonly used string with char 179
pspatel321 38:8efacce315ae 64 OperatingInfo* dashOp = op;
pspatel321 38:8efacce315ae 65 Profile* dashParam = param;
pspatel321 38:8efacce315ae 66
pspatel321 34:18bcf276d3bf 67 serialLoop.reset();
pspatel321 38:8efacce315ae 68 serialLoop.start(); // Start the counter for tracking serial loop time
pspatel321 34:18bcf276d3bf 69
pspatel321 30:91af74a299e1 70 while(1) {
pspatel321 38:8efacce315ae 71 serialTime_ms = serialLoop.read_ms(); // Update loop timer, reset for next loop
pspatel321 34:18bcf276d3bf 72 serialLoop.reset();
pspatel321 30:91af74a299e1 73
pspatel321 38:8efacce315ae 74 // Update display mode, change detection used at end of while(1) loop
pspatel321 38:8efacce315ae 75 lastModeExtended = inExtendedMode;
pspatel321 38:8efacce315ae 76 inExtendedMode = param->extendedSerial;
pspatel321 38:8efacce315ae 77
pspatel321 38:8efacce315ae 78 // Determine whether to display freeze frame, change pointers accordingly
pspatel321 38:8efacce315ae 79 if (tempData.freeze != NULL) {
pspatel321 38:8efacce315ae 80 freeze = true; // Indicate showing freeze
pspatel321 38:8efacce315ae 81 dashOp = &(tempData.freeze->op.op); // Point to freeze
pspatel321 38:8efacce315ae 82 dashParam = &(tempData.freeze->param.param); // Point to freeze
pspatel321 38:8efacce315ae 83
pspatel321 38:8efacce315ae 84 // Determine whether to display a non-live profile, change pointers accordingly
pspatel321 38:8efacce315ae 85 } else if (tempData.viewProfile != NULL && tempData.viewProfileNum != -2) {
pspatel321 38:8efacce315ae 86 dashParam = tempData.viewProfile; // Point to other profile
pspatel321 38:8efacce315ae 87 notLiveProfile = true; // Indicate notLive
pspatel321 38:8efacce315ae 88
pspatel321 38:8efacce315ae 89 // Show live data only
pspatel321 38:8efacce315ae 90 } else {
pspatel321 38:8efacce315ae 91 freeze = false; // Not freeze
pspatel321 38:8efacce315ae 92 notLiveProfile = false; // Live profile
pspatel321 38:8efacce315ae 93 dashOp = op; // Point to live RAM data
pspatel321 38:8efacce315ae 94 dashParam = param; // Point to live RAM data
pspatel321 38:8efacce315ae 95 }
pspatel321 38:8efacce315ae 96
pspatel321 34:18bcf276d3bf 97 sprintf(temp, "\033[0;0H\033[0;0H");
pspatel321 38:8efacce315ae 98 AddtoBuffer(temp, false); // Move to 0,0, do not append newline
pspatel321 38:8efacce315ae 99
pspatel321 34:18bcf276d3bf 100 DIVIDER_LINE
pspatel321 34:18bcf276d3bf 101 TITLE(" Penn Electric Racing - REV0 System Management Controller Dashboard ")
pspatel321 34:18bcf276d3bf 102 DIVIDER_LINE
pspatel321 38:8efacce315ae 103
pspatel321 34:18bcf276d3bf 104 int tempLength=0;
pspatel321 34:18bcf276d3bf 105 tempLength += sprintf(temp, "Command Input:%c %s%c", tempData.parseGoodChar, tempData.inputStr, 176); // Command input: print header, reply, input string, and cursor marker
pspatel321 36:0afc0fc8f86b 106 for (int i = 0; i < max_charsPerLine - tempLength - 1; i++) { // Fill in the rest of the line with blanks
pspatel321 34:18bcf276d3bf 107 tempLength += sprintf(temp+tempLength, " "); // Append spaces
pspatel321 34:18bcf276d3bf 108 }
pspatel321 36:0afc0fc8f86b 109 AddtoBuffer(temp); // Add this to the chunk
pspatel321 38:8efacce315ae 110
pspatel321 38:8efacce315ae 111 const char profile[NUM_STORED_PROFILES+2][8] = {"Freeze", "Default", "1", "2", "3"};
pspatel321 38:8efacce315ae 112 if (inExtendedMode) {
pspatel321 38:8efacce315ae 113
pspatel321 38:8efacce315ae 114 // Parameters Section
pspatel321 38:8efacce315ae 115 snprintf(temp, max_charsPerLine, " Configuration Parameters %s%s%s%s", freeze?"(Viewing Freeze of Last Fault) ":"", (notLiveProfile && !freeze)?" (Viewing Profile ":"", (notLiveProfile && !freeze)?profile[tempData.viewProfileNum+1]:"", (notLiveProfile && !freeze)?") ":"");
pspatel321 38:8efacce315ae 116 TITLE(temp)
pspatel321 38:8efacce315ae 117 snprintf(temp, max_charsPerLine, "GLVchar: %5.2fA%sGLVdisch: %5.2fA%sGLVnomCap: %5.2fAh%sGLVtaps: %3d", dashParam->chargeCurrent,barSpace, dashParam->dischargeCurrent,barSpace, dashParam->nominalCapacity,barSpace, dashParam->glvBat_taps);
pspatel321 38:8efacce315ae 118 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 119 snprintf(temp, max_charsPerLine, "dcdcThres: %5.2fA%sdcdcOver: %5.2fA%sdcdcStart: %5.2fs %sdcdcStop: %5.2fs", dashParam->dcdcThreshold,barSpace, dashParam->dcdcOverCurrent,barSpace, dashParam->dcdcStartDelay,barSpace, dashParam->dcdcStopDelay);
pspatel321 38:8efacce315ae 120 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 121 snprintf(temp, max_charsPerLine, "dcdcTaps: %3d %simdStart: %5.1fs%samsStart: %5.1fs %sIntOverT: %5.1fC", dashParam->dcdc_taps,barSpace, dashParam->imdStartDelay,barSpace, dashParam->amsStartDelay,barSpace, dashParam->internalOverTemp);
pspatel321 38:8efacce315ae 122 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 123 snprintf(temp, max_charsPerLine, "CANtxSize: %4d %sCANrxSize: %4d %sSerialBaud: %6d%sSerialTx: %5d", dashParam->CANtxSize,barSpace, dashParam->CANrxSize,barSpace, dashParam->SerialBaud,barSpace, dashParam->SerialTxSize);
pspatel321 38:8efacce315ae 124 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 125 BLANK_LINE
pspatel321 38:8efacce315ae 126 }
pspatel321 38:8efacce315ae 127 snprintf(temp, max_charsPerLine, " Operating Info %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 128 TITLE(temp)
pspatel321 38:8efacce315ae 129
pspatel321 38:8efacce315ae 130 // Operating mode
pspatel321 38:8efacce315ae 131 const char modeStr[3][8] = {"FAULT", "OKAY", "INVALID"};
pspatel321 38:8efacce315ae 132 tempLength = 0;
pspatel321 38:8efacce315ae 133 tempLength += sprintf(temp+tempLength, "Sloop: %3dms CANloop: %3dms Time: %s", serialTime_ms, CANtime_ms, ctime(&dashOp->SysTime));
pspatel321 38:8efacce315ae 134 tempLength--;
pspatel321 38:8efacce315ae 135 char modeN = dashOp->mode;
pspatel321 38:8efacce315ae 136 if (modeN == FAULT) modeN=0;
pspatel321 38:8efacce315ae 137 else if (modeN == OKAY) modeN=1;
pspatel321 38:8efacce315ae 138 else modeN=2;
pspatel321 38:8efacce315ae 139 tempLength += sprintf(temp+tempLength, " Uptime: %5ds", dashOp->SysTime - dashOp->startTime);
pspatel321 34:18bcf276d3bf 140 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 141 tempLength = snprintf(temp, max_charsPerLine, "Profile: %7s%10s Mode: %7s%6s Faults: ", profile[dashOp->profileIndex+1], dashOp->profileModded?", MODIFIED":"", modeStr[modeN], dashOp->faultCode?"+ERROR":"");
pspatel321 38:8efacce315ae 142
pspatel321 38:8efacce315ae 143 // Fault codes
pspatel321 38:8efacce315ae 144 const char topErrStr[12][20] = {"WATCHDOG", "BROWNOUT", "CAN_FAULT", "INT_OVER_TEMP", "IMD_LATCH", "AMS_LATCH", "IMD_FAULT", "DCDC_FAULT", "GLVBAT_FAULT", "FREEZE_FRAME"};
pspatel321 38:8efacce315ae 145 int numFaults = 0;
pspatel321 38:8efacce315ae 146 for (int i = 0; i < sizeof(dashOp->faultCode)*8; i++) {
pspatel321 38:8efacce315ae 147 if (dashOp->faultCode & (1<<i)) numFaults++;
pspatel321 38:8efacce315ae 148 }
pspatel321 38:8efacce315ae 149 if (numFaults == 0) tempLength+=sprintf(temp+tempLength, "No Faults"); // Start new appending chain string, faults not present
pspatel321 38:8efacce315ae 150 else tempLength+=sprintf(temp+tempLength, "(%d 0x%04x)", numFaults, dashOp->faultCode); // Start new appending chain string, faults present
pspatel321 34:18bcf276d3bf 151 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 152 tempLength = 0;
pspatel321 38:8efacce315ae 153 temp[0] = 0;
pspatel321 34:18bcf276d3bf 154
pspatel321 38:8efacce315ae 155 // Print max number of strings that will fit per line, then dump line and continue till finished all error flags
pspatel321 38:8efacce315ae 156 int num = 0;
pspatel321 38:8efacce315ae 157 for (int i = 0; i < 29; i++) {
pspatel321 38:8efacce315ae 158 if (dashOp->faultCode & (1<<i)) { // Fault found
pspatel321 38:8efacce315ae 159 // Room for fault string?
pspatel321 38:8efacce315ae 160 if (max_charsPerLine-tempLength > strlen(topErrStr[i])+2) {
pspatel321 38:8efacce315ae 161 // Yes, append
pspatel321 38:8efacce315ae 162 tempLength += sprintf(temp+tempLength, "%s ", topErrStr[i]);
pspatel321 38:8efacce315ae 163 num++;
pspatel321 38:8efacce315ae 164 } else {
pspatel321 38:8efacce315ae 165 // No, Dump then start new line
pspatel321 38:8efacce315ae 166 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 167 tempLength = 0;
pspatel321 38:8efacce315ae 168 tempLength += sprintf(temp+tempLength, "%s ", topErrStr[i]);
pspatel321 38:8efacce315ae 169 num++;
pspatel321 38:8efacce315ae 170 }
pspatel321 38:8efacce315ae 171 }
pspatel321 38:8efacce315ae 172 if (num >= numFaults || numFaults == 0) {
pspatel321 38:8efacce315ae 173 // Done printing all faults
pspatel321 38:8efacce315ae 174 tempLength = 0;
pspatel321 38:8efacce315ae 175 num = 0;
pspatel321 38:8efacce315ae 176 if (numFaults != 0) {
pspatel321 38:8efacce315ae 177 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 178 }
pspatel321 38:8efacce315ae 179 break;
pspatel321 38:8efacce315ae 180 }
pspatel321 38:8efacce315ae 181 }
pspatel321 34:18bcf276d3bf 182 BLANK_LINE
pspatel321 38:8efacce315ae 183 snprintf(temp, max_charsPerLine, "ShtdwnCrct: %6s %s AIRs: %6s %s Charger: %4s %s IntTemp: %5.1f", (dashOp->signals & SHUTDOWN_CLOSED)?"CLOSED":"OPEN", barSpace, (dashOp->signals & AIRS_CLOSED)?"CLOSED":"OPEN", barSpace, (dashOp->signals & CHARGER_DET)?"DET":"NDET", barSpace, dashOp->internalTemp);
pspatel321 34:18bcf276d3bf 184 ADD_SPRINTF_LINE
pspatel321 30:91af74a299e1 185
pspatel321 34:18bcf276d3bf 186 BLANK_LINE
pspatel321 38:8efacce315ae 187 snprintf(temp, max_charsPerLine, " GLV Battery %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 188 TITLE(temp)
pspatel321 38:8efacce315ae 189 sprintf(temp, "Current: %4.3fA %s Cap: %4.3fAh %s Ah: %4.3fAh %s SOC: %5.3f", dashOp->glvBat.current, barSpace, dashOp->glvBat.capacity, barSpace, dashOp->glvBat.Ah, barSpace, dashOp->glvBat.SOC);
pspatel321 38:8efacce315ae 190 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 191 // GLV Fault codes
pspatel321 38:8efacce315ae 192 const char glvBatErrStr[12][20] = {"OVER_CHARGE_I", "OVER_DISCHARGE_I", "CAP_INIT", "SOC_INIT" };
pspatel321 38:8efacce315ae 193 numFaults = 0;
pspatel321 38:8efacce315ae 194 for (int i = 0; i < sizeof(dashOp->glvBat.error)*8; i++) {
pspatel321 38:8efacce315ae 195 if (dashOp->glvBat.error & (1<<i)) numFaults++;
pspatel321 38:8efacce315ae 196 }
pspatel321 38:8efacce315ae 197 if (numFaults == 0) tempLength+=sprintf(temp+tempLength, "No Faults"); // Start new appending chain string, faults not present
pspatel321 38:8efacce315ae 198 else tempLength+=sprintf(temp+tempLength, "(%d 0x%04x)", numFaults, dashOp->glvBat.error); // Start new appending chain string, faults present
pspatel321 38:8efacce315ae 199 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 200 tempLength = 0;
pspatel321 38:8efacce315ae 201 temp[0] = 0;
pspatel321 38:8efacce315ae 202
pspatel321 38:8efacce315ae 203 // Print max number of strings that will fit per line, then dump line and continue till finished all error flags
pspatel321 38:8efacce315ae 204 num = 0;
pspatel321 38:8efacce315ae 205 for (int i = 0; i < 29; i++) {
pspatel321 38:8efacce315ae 206 if (dashOp->glvBat.error & (1<<i)) { // Fault found
pspatel321 38:8efacce315ae 207 // Room for fault string?
pspatel321 38:8efacce315ae 208 if (max_charsPerLine-tempLength > strlen(glvBatErrStr[i])+2) {
pspatel321 38:8efacce315ae 209 // Yes, append
pspatel321 38:8efacce315ae 210 tempLength += sprintf(temp+tempLength, "%s ", glvBatErrStr[i]);
pspatel321 38:8efacce315ae 211 num++;
pspatel321 38:8efacce315ae 212 } else {
pspatel321 38:8efacce315ae 213 // No, Dump then start new line
pspatel321 38:8efacce315ae 214 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 215 tempLength = 0;
pspatel321 38:8efacce315ae 216 tempLength += sprintf(temp+tempLength, "%s ", glvBatErrStr[i]);
pspatel321 38:8efacce315ae 217 num++;
pspatel321 38:8efacce315ae 218 }
pspatel321 38:8efacce315ae 219 }
pspatel321 38:8efacce315ae 220 if (num >= numFaults || numFaults == 0) {
pspatel321 38:8efacce315ae 221 // Done printing all faults
pspatel321 38:8efacce315ae 222 tempLength = 0;
pspatel321 38:8efacce315ae 223 num = 0;
pspatel321 38:8efacce315ae 224 if (numFaults != 0) {
pspatel321 38:8efacce315ae 225 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 226 }
pspatel321 38:8efacce315ae 227 break;
pspatel321 38:8efacce315ae 228 }
pspatel321 38:8efacce315ae 229 }
pspatel321 38:8efacce315ae 230
pspatel321 34:18bcf276d3bf 231 BLANK_LINE
pspatel321 38:8efacce315ae 232 snprintf(temp, max_charsPerLine, " DC-DC Converter %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 233 TITLE(temp)
pspatel321 38:8efacce315ae 234 char DCDC = dashOp->dcdc.status;
pspatel321 38:8efacce315ae 235 const char dcdcModesStr[5][12] = {"INVALID","POWER-UP","POWER-DOWN","SET-ON","SET-OFF"};
pspatel321 38:8efacce315ae 236 int dcdcMode = 0;
pspatel321 38:8efacce315ae 237 if (DCDC & POWER_UP) dcdcMode = 1;
pspatel321 38:8efacce315ae 238 else if (DCDC & POWER_DOWN) dcdcMode = 2;
pspatel321 38:8efacce315ae 239 else if (DCDC & SET_ON) dcdcMode = 3;
pspatel321 38:8efacce315ae 240 else if (!(DCDC & SET_ON)) dcdcMode = 4;
pspatel321 38:8efacce315ae 241 sprintf(temp, "Active: %3s %s Mode: %10s %s Status: 0x%02x", (DCDC & CONV_ON)?"YES":"NO", barSpace, dcdcModesStr[dcdcMode], barSpace, DCDC);
pspatel321 34:18bcf276d3bf 242 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 243 sprintf(temp, "Current: %5.2fA %s Overcurrent: %3s %s SensorFault: %3s", dashOp->dcdc.current,barSpace, (DCDC & OVER_CURRENT)?"ERR":"OK",barSpace, (DCDC & SENSOR_FAULT)?"ERR":"OK");
pspatel321 34:18bcf276d3bf 244 ADD_SPRINTF_LINE
pspatel321 30:91af74a299e1 245
pspatel321 34:18bcf276d3bf 246 BLANK_LINE
pspatel321 38:8efacce315ae 247 snprintf(temp, max_charsPerLine, " DC-DC PWM Channels %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 248 TITLE(temp)
pspatel321 38:8efacce315ae 249 sprintf(temp, "Actual: FAN1: %5.3f FAN2: %5.3f %s PUMP1: %5.3f PUMP2: %5.3f", dashOp->dcdc.actual.fan1, dashOp->dcdc.actual.fan2, barSpace, dashOp->dcdc.actual.pump1, dashOp->dcdc.actual.pump2);
pspatel321 38:8efacce315ae 250 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 251 sprintf(temp, "Requested: FAN1: %5.3f FAN2: %5.3f %s PUMP1: %5.3f PUMP2: %5.3f", dashOp->dcdc.request.fan1, dashOp->dcdc.request.fan2, barSpace, dashOp->dcdc.request.pump1, dashOp->dcdc.request.pump2);
pspatel321 34:18bcf276d3bf 252 ADD_SPRINTF_LINE
pspatel321 34:18bcf276d3bf 253
pspatel321 34:18bcf276d3bf 254 BLANK_LINE
pspatel321 38:8efacce315ae 255 snprintf(temp, max_charsPerLine, " IMD %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 256 TITLE(temp)
pspatel321 39:ddf38df9699e 257 char imdStatN=6;
pspatel321 39:ddf38df9699e 258 if (dashOp->imd.status & OFF) imdStatN=0;
pspatel321 39:ddf38df9699e 259 if (dashOp->imd.status & NORMAL) imdStatN=1;
pspatel321 39:ddf38df9699e 260 if (dashOp->imd.status & UNDERVOLT) imdStatN=2;
pspatel321 39:ddf38df9699e 261 if (dashOp->imd.status & SPEEDSTART) imdStatN=3;
pspatel321 39:ddf38df9699e 262 if (dashOp->imd.status & ERROR) imdStatN=4;
pspatel321 39:ddf38df9699e 263 if (dashOp->imd.status & GROUNDERR) imdStatN=5;
pspatel321 39:ddf38df9699e 264 const char IMDstr[7][12] = {"OFF","NORMAL","UNDERVOLT","SPEEDSTART","ERROR","GROUNDERR","INVALID"};
pspatel321 39:ddf38df9699e 265 sprintf(temp, "Status: %10s Resistance: %7.0fKohm Error: %3s", IMDstr[imdStatN], dashOp->imd.resistance/1.0e3, dashOp->imd.error?"ERR":"OK");
pspatel321 34:18bcf276d3bf 266 ADD_SPRINTF_LINE
pspatel321 30:91af74a299e1 267
pspatel321 34:18bcf276d3bf 268 BLANK_LINE
pspatel321 38:8efacce315ae 269 snprintf(temp, max_charsPerLine, " Latch Monitors %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 270 TITLE(temp)
pspatel321 38:8efacce315ae 271 char AMSerr = dashOp->latch.ams;
pspatel321 38:8efacce315ae 272 char IMDerr = dashOp->latch.imd;
pspatel321 38:8efacce315ae 273 sprintf(temp, "AMS - OK: %4s Latch: %3s SoftFault: %3s HardFault: %3s", (AMSerr & OK_FAULT)?"LOW":"HIGH", (AMSerr & LATCHED_HARD)?"ERR":"OK", (AMSerr & LATCHED_SOFT)?"ERR":"OK", (AMSerr & HARD_FAULT)?"ERR":"OK");
pspatel321 38:8efacce315ae 274 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 275 sprintf(temp, "IMD - OK: %4s Latch: %3s SoftFault: %3s HardFault: %3s", (IMDerr & OK_FAULT)?"LOW":"HIGH", (IMDerr & LATCHED_HARD)?"ERR":"OK", (IMDerr & LATCHED_SOFT)?"ERR":"OK", (IMDerr & HARD_FAULT)?"ERR":"OK");
pspatel321 38:8efacce315ae 276 ADD_SPRINTF_LINE
pspatel321 38:8efacce315ae 277
pspatel321 34:18bcf276d3bf 278 BLANK_LINE
pspatel321 38:8efacce315ae 279 snprintf(temp, max_charsPerLine, " Shutdown Switches %s", freeze?"(Viewing Freeze of Last Fault) ":"");
pspatel321 38:8efacce315ae 280 TITLE(temp)
pspatel321 38:8efacce315ae 281 char switches = dashOp->switchState;
pspatel321 30:91af74a299e1 282 const char switchNames[12][26] = {"FUSE","AMS LATCH","IMD LATCH","PCM RELAY","BRAKE PLAUSIBILITY RELAY","LEFT E-STOP","INERTIA SWITCH","BRAKE OVER-TRAVEL SWITCH","COCKPIT E-STOP","RIGHT E-STOP","HVD","TSMS"};
pspatel321 30:91af74a299e1 283 if (switches == 0) sprintf(temp, "All switches are CLOSED.");
pspatel321 30:91af74a299e1 284 else sprintf(temp, "%s is OPEN.", switchNames[switches-1]);
pspatel321 30:91af74a299e1 285 ADD_SPRINTF_LINE
pspatel321 33:6bc82b6b62e5 286
pspatel321 38:8efacce315ae 287 // Erase screen every few counts to remove glitches
pspatel321 38:8efacce315ae 288 static int count = 0;
pspatel321 38:8efacce315ae 289 if (count % 50 == 0 || lastModeExtended != inExtendedMode) {
pspatel321 38:8efacce315ae 290 sprintf(temp, "\033[2J");
pspatel321 38:8efacce315ae 291 AddtoBuffer(temp, false); // Clear the screen
pspatel321 31:7eaa5e881b56 292 }
pspatel321 31:7eaa5e881b56 293 count++;
pspatel321 30:91af74a299e1 294 }
pspatel321 30:91af74a299e1 295 }
pspatel321 30:91af74a299e1 296
pspatel321 34:18bcf276d3bf 297 void outDiagnostics::thread_canOut(void const *args)
pspatel321 34:18bcf276d3bf 298 {
pspatel321 38:8efacce315ae 299 bool lastCANnoAck = param->CANnoAck; // Get initial noAck mode setting
pspatel321 38:8efacce315ae 300 bool thisCANnoAck = param->CANnoAck;
pspatel321 38:8efacce315ae 301
pspatel321 38:8efacce315ae 302 if (param->CANnoAck) { // Turn on noack mode
pspatel321 38:8efacce315ae 303 can.mode(NoAck);
pspatel321 38:8efacce315ae 304 } else { // Setup normal mode
pspatel321 38:8efacce315ae 305 can.mode(Normal);
pspatel321 38:8efacce315ae 306 }
pspatel321 38:8efacce315ae 307 can.mode(FIFO);
pspatel321 38:8efacce315ae 308
pspatel321 38:8efacce315ae 309 CANloop.reset();
pspatel321 38:8efacce315ae 310 CANloop.start();
pspatel321 38:8efacce315ae 311
pspatel321 30:91af74a299e1 312 while(1) {
pspatel321 30:91af74a299e1 313
pspatel321 38:8efacce315ae 314 CANtime_ms = CANloop.read_ms();
pspatel321 38:8efacce315ae 315 CANloop.reset();
pspatel321 38:8efacce315ae 316
pspatel321 38:8efacce315ae 317 // Update last and this variables to check for changes in noAck mode
pspatel321 38:8efacce315ae 318 lastCANnoAck = thisCANnoAck;
pspatel321 38:8efacce315ae 319 thisCANnoAck = param->CANnoAck;
pspatel321 38:8efacce315ae 320 if (thisCANnoAck && !lastCANnoAck) { // NoAck mode turn on
pspatel321 38:8efacce315ae 321 can.mode(NoAck);
pspatel321 38:8efacce315ae 322 can.mode(FIFO);
pspatel321 38:8efacce315ae 323 can.txFlush(); // Must flush buffer when switching modes, or else buffer gets stuck
pspatel321 38:8efacce315ae 324 }
pspatel321 38:8efacce315ae 325 if (!thisCANnoAck && lastCANnoAck) { // NoAck mode turn off
pspatel321 38:8efacce315ae 326 can.mode(Normal);
pspatel321 38:8efacce315ae 327 can.mode(FIFO);
pspatel321 38:8efacce315ae 328 can.txFlush(); // Must flush buffer when switching modes, or else buffer gets stuck
pspatel321 38:8efacce315ae 329 }
pspatel321 38:8efacce315ae 330
pspatel321 38:8efacce315ae 331 // OPERATING DIAGNOSTICS
pspatel321 38:8efacce315ae 332 // Error Frame
pspatel321 39:ddf38df9699e 333 CAN_SINGLE(faultCode, FAULTCODE_TX_ID)
pspatel321 38:8efacce315ae 334
pspatel321 38:8efacce315ae 335 // Mode
pspatel321 39:ddf38df9699e 336 CAN_SINGLE(mode, MODE_TX_ID)
pspatel321 38:8efacce315ae 337
pspatel321 38:8efacce315ae 338 // Flags
pspatel321 39:ddf38df9699e 339 CAN_SINGLE(signals, SIGNALS_TX_ID)
pspatel321 38:8efacce315ae 340
pspatel321 38:8efacce315ae 341 // Profile
pspatel321 39:ddf38df9699e 342 char byte=0;
pspatel321 39:ddf38df9699e 343 byte = (op->profileIndex != -1)? 1 << op->profileIndex : 1<<6;
pspatel321 39:ddf38df9699e 344 byte |= (op->profileModded) ? 1<<7 : 0; // Mark the last bit of the byte if the profile was modified (OR'd with profile id from above)
pspatel321 39:ddf38df9699e 345 SEND_CAN_SINGLE(byte, PROFILE_TX_ID);
pspatel321 38:8efacce315ae 346
pspatel321 38:8efacce315ae 347 // Time
pspatel321 39:ddf38df9699e 348 CAN_PAIR(SysTime, startTime, TIME_TX_ID)
pspatel321 34:18bcf276d3bf 349
pspatel321 31:7eaa5e881b56 350 // Internal temperature
pspatel321 39:ddf38df9699e 351 CAN_SINGLE(internalTemp, TEMP_TX_ID)
pspatel321 31:7eaa5e881b56 352
pspatel321 31:7eaa5e881b56 353 // GLV Battery
pspatel321 39:ddf38df9699e 354 CAN_SINGLE(glvBat.current, GLV_CURRENT_TX_ID)
pspatel321 39:ddf38df9699e 355 CAN_SINGLE(glvBat.capacity, GLV_CAPACITY_TX_ID)
pspatel321 39:ddf38df9699e 356 CAN_SINGLE(glvBat.Ah, GLV_AH_TX_ID)
pspatel321 39:ddf38df9699e 357 CAN_SINGLE(glvBat.SOC, GLV_SOC_TX_ID)
pspatel321 39:ddf38df9699e 358 CAN_SINGLE(glvBat.error, GLV_ERROR_TX_ID)
pspatel321 38:8efacce315ae 359
pspatel321 31:7eaa5e881b56 360 // DC-DC Converter
pspatel321 39:ddf38df9699e 361 CAN_SINGLE(dcdc.current, DCDC_CURRENT_TX_ID)
pspatel321 39:ddf38df9699e 362 CAN_SINGLE(dcdc.status, DCDC_STATUS_TX_ID)
pspatel321 31:7eaa5e881b56 363
pspatel321 34:18bcf276d3bf 364 // PWM Channels
pspatel321 39:ddf38df9699e 365 CAN_PAIR(dcdc.actual.fan1, dcdc.actual.fan2, PWM_FAN_TX_ID)
pspatel321 39:ddf38df9699e 366 CAN_PAIR(dcdc.actual.pump1, dcdc.actual.pump2, PWM_PUMP_TX_ID)
pspatel321 31:7eaa5e881b56 367
pspatel321 31:7eaa5e881b56 368 // IMD
pspatel321 39:ddf38df9699e 369 CAN_SINGLE(imd.status, IMD_STATUS_TX_ID)
pspatel321 39:ddf38df9699e 370 CAN_SINGLE(imd.resistance, IMD_RESIST_TX_ID)
pspatel321 31:7eaa5e881b56 371
pspatel321 31:7eaa5e881b56 372 // Latches
pspatel321 39:ddf38df9699e 373 CAN_SINGLE(latch.imd, IMD_LATCH_TX_ID)
pspatel321 39:ddf38df9699e 374 CAN_SINGLE(latch.ams, AMS_LATCH_TX_ID)
pspatel321 31:7eaa5e881b56 375
pspatel321 31:7eaa5e881b56 376 // Shutdown Switches
pspatel321 39:ddf38df9699e 377 uint16_t tmp=0;
pspatel321 39:ddf38df9699e 378 if (op->switchState != 0) tmp |= 1 << (op->switchState-1);
pspatel321 39:ddf38df9699e 379 SEND_CAN_SINGLE(tmp, SWITCHES_TX_ID);
pspatel321 38:8efacce315ae 380
pspatel321 36:0afc0fc8f86b 381 osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<4); // Signal watchdog thread
pspatel321 33:6bc82b6b62e5 382 Thread::wait(CAN_LOOP*1000);
pspatel321 34:18bcf276d3bf 383 }
pspatel321 30:91af74a299e1 384 }