System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Sat Feb 07 08:54:51 2015 +0000
Revision:
38:8efacce315ae
Parent:
36:0afc0fc8f86b
Child:
39:ddf38df9699e
Updated with profiles, operating info, etc. Just like the other programs.  Awaiting test in car.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 34:18bcf276d3bf 1 #include "inCommands.h"
pspatel321 38:8efacce315ae 2 #include "runTime.h"
pspatel321 38:8efacce315ae 3 #include "inMacros.h"
pspatel321 34:18bcf276d3bf 4
pspatel321 34:18bcf276d3bf 5 // Compare string to a word in the serial input, shorter to type
pspatel321 34:18bcf276d3bf 6 #define CMP(w, string) if (!strcasecmp(word[w-1], string))
pspatel321 36:0afc0fc8f86b 7
pspatel321 34:18bcf276d3bf 8 // Serial input
pspatel321 38:8efacce315ae 9 int serviceSerial()
pspatel321 34:18bcf276d3bf 10 {
pspatel321 38:8efacce315ae 11 static int end = 0; // End of string position
pspatel321 34:18bcf276d3bf 12
pspatel321 36:0afc0fc8f86b 13 int c=0;
pspatel321 36:0afc0fc8f86b 14 if (pc.readable()) c = pc.getc();
pspatel321 38:8efacce315ae 15 if (c == -1 || c == 0) return 0;
pspatel321 38:8efacce315ae 16
pspatel321 34:18bcf276d3bf 17 char b = c; // Casted to char type
pspatel321 34:18bcf276d3bf 18 bool process = false; // Is string complete (ready to parse)?
pspatel321 34:18bcf276d3bf 19
pspatel321 34:18bcf276d3bf 20 if (b == '\n' || b == '\r') { // Enter key was pressed, dump for processing
pspatel321 34:18bcf276d3bf 21 tempData.inputStr[end] = 0; // Null terminate
pspatel321 34:18bcf276d3bf 22 end = 0; // Reset to start
pspatel321 34:18bcf276d3bf 23 process = true; // Flag for processing
pspatel321 34:18bcf276d3bf 24
pspatel321 34:18bcf276d3bf 25 } else if (b == '\b' || b == 127) { // Backspace or delete
pspatel321 34:18bcf276d3bf 26 if (end > 0) end--; // Move back one char
pspatel321 34:18bcf276d3bf 27 tempData.inputStr[end] = 0; // Erase char
pspatel321 34:18bcf276d3bf 28
pspatel321 34:18bcf276d3bf 29 } else if (b > 31 && b < 127) { // New valid displayable char
pspatel321 36:0afc0fc8f86b 30 tempData.inputStr[end++] = b; // Add to buffer
pspatel321 34:18bcf276d3bf 31 tempData.inputStr[end] = 0; // Add null terminator
pspatel321 34:18bcf276d3bf 32 if (end >= RX_SIZE) {
pspatel321 34:18bcf276d3bf 33 end = 0; // Reset end location
pspatel321 34:18bcf276d3bf 34 process = true; // Flag for processing
pspatel321 34:18bcf276d3bf 35 }
pspatel321 34:18bcf276d3bf 36 }
pspatel321 34:18bcf276d3bf 37 // Continue to parsing section only if flagged as complete and string not empty
pspatel321 36:0afc0fc8f86b 38 if (!process || strlen((char*)tempData.inputStr) == 0) return 0;
pspatel321 38:8efacce315ae 39
pspatel321 36:0afc0fc8f86b 40 static char word[3][RX_SIZE+1]; // Hold 3 words
pspatel321 34:18bcf276d3bf 41 int pieces = sscanf(tempData.inputStr, "%s %s %s", word[0], word[1], word[2]); // Populate words
pspatel321 34:18bcf276d3bf 42 tempData.inputStr[0] = 0; // Empty the string displayed on screen
pspatel321 36:0afc0fc8f86b 43 char *next; // Used by strtof and strtoul
pspatel321 34:18bcf276d3bf 44
pspatel321 34:18bcf276d3bf 45 // One word commands
pspatel321 34:18bcf276d3bf 46 if (pieces == 1) {
pspatel321 34:18bcf276d3bf 47 // Reset the microcontroller
pspatel321 34:18bcf276d3bf 48 CMP(1, "reset") {
pspatel321 34:18bcf276d3bf 49 NVIC_SystemReset();
pspatel321 34:18bcf276d3bf 50 return 1;
pspatel321 34:18bcf276d3bf 51 }
pspatel321 38:8efacce315ae 52 // Clear non-volatile fault flags, then reset the microcontroller
pspatel321 38:8efacce315ae 53 CMP(1, "resetClear") {
pspatel321 38:8efacce315ae 54 runTime::clearFaults();
pspatel321 38:8efacce315ae 55 NVIC_SystemReset();
pspatel321 38:8efacce315ae 56 return 1;
pspatel321 38:8efacce315ae 57 }
pspatel321 38:8efacce315ae 58 return -1;
pspatel321 34:18bcf276d3bf 59 }
pspatel321 36:0afc0fc8f86b 60 // Two word commands
pspatel321 34:18bcf276d3bf 61 if (pieces == 2) {
pspatel321 38:8efacce315ae 62 // Change the serial dashboard display mode
pspatel321 38:8efacce315ae 63 CMP(1, "display") {
pspatel321 38:8efacce315ae 64 CMP(2, "compact") {
pspatel321 38:8efacce315ae 65 if (param->change_extendedSerial(0)) {
pspatel321 38:8efacce315ae 66 op->profileModded=true;
pspatel321 38:8efacce315ae 67 return 1; // Change function defined by macro
pspatel321 38:8efacce315ae 68 }
pspatel321 38:8efacce315ae 69 }
pspatel321 38:8efacce315ae 70 CMP(2, "extended") {
pspatel321 38:8efacce315ae 71 if (param->change_extendedSerial(1)) {
pspatel321 38:8efacce315ae 72 op->profileModded=true;
pspatel321 38:8efacce315ae 73 return 1; // Change function defined by macro
pspatel321 38:8efacce315ae 74 }
pspatel321 38:8efacce315ae 75 }
pspatel321 38:8efacce315ae 76 }
pspatel321 38:8efacce315ae 77 // Change ACK setting for CAN (noAck allows testing of CAN without other nodes)
pspatel321 38:8efacce315ae 78 CMP(1, "CANack") {
pspatel321 38:8efacce315ae 79 CMP(2, "noack") { // NoAck test mode
pspatel321 38:8efacce315ae 80 if (param->change_CANnoAck(1)) {
pspatel321 38:8efacce315ae 81 op->profileModded=true;
pspatel321 38:8efacce315ae 82 return 1;
pspatel321 38:8efacce315ae 83 }
pspatel321 38:8efacce315ae 84 }
pspatel321 38:8efacce315ae 85 CMP(2, "ack") { // Normal CAN protocol
pspatel321 38:8efacce315ae 86 if (param->change_CANnoAck(0)) {
pspatel321 38:8efacce315ae 87 op->profileModded=true;
pspatel321 38:8efacce315ae 88 return 1;
pspatel321 38:8efacce315ae 89 }
pspatel321 38:8efacce315ae 90 }
pspatel321 38:8efacce315ae 91 return -1;
pspatel321 38:8efacce315ae 92 }
pspatel321 38:8efacce315ae 93 // Artificially capture a freeze frame, save to flash
pspatel321 38:8efacce315ae 94 CMP(1, "capture") {
pspatel321 38:8efacce315ae 95 CMP(2, "freeze") {
pspatel321 38:8efacce315ae 96 if (!FreezeFrame::getError()) { // Only allow capture if spot available (last error frame was cleared manually)
pspatel321 38:8efacce315ae 97 if (FreezeFrame::writeFrame()) { // Copy RAM frame to freezree sector in flash
pspatel321 38:8efacce315ae 98 return 1;
pspatel321 38:8efacce315ae 99 }
pspatel321 38:8efacce315ae 100 }
pspatel321 38:8efacce315ae 101 }
pspatel321 38:8efacce315ae 102 return -1;
pspatel321 38:8efacce315ae 103 }
pspatel321 38:8efacce315ae 104 // Clear fault conditions
pspatel321 38:8efacce315ae 105 CMP(1, "clear") {
pspatel321 38:8efacce315ae 106 CMP(2, "freeze") { // Clear the freeze frame (mark as read)
pspatel321 38:8efacce315ae 107 FreezeFrame::clearError(); // Clear the non-volatile error marker
pspatel321 34:18bcf276d3bf 108 return 1;
pspatel321 34:18bcf276d3bf 109 }
pspatel321 38:8efacce315ae 110 CMP(2, "faults") { // Clear everything
pspatel321 38:8efacce315ae 111 runTime::clearFaults();
pspatel321 38:8efacce315ae 112 return 1;
pspatel321 38:8efacce315ae 113 }
pspatel321 38:8efacce315ae 114 return -1;
pspatel321 38:8efacce315ae 115 }
pspatel321 38:8efacce315ae 116 // Change the display contents
pspatel321 38:8efacce315ae 117 CMP(1, "view") {
pspatel321 38:8efacce315ae 118 CMP(2, "freeze") { // View the last stored freeze frame
pspatel321 38:8efacce315ae 119 if (FreezeFrame::getFrame(&tempData.freeze)) { // Fetch the pointer from flash
pspatel321 38:8efacce315ae 120 return 1;
pspatel321 38:8efacce315ae 121 }
pspatel321 38:8efacce315ae 122 }
pspatel321 38:8efacce315ae 123 CMP(2, "live") { // View live data from RAM
pspatel321 38:8efacce315ae 124 tempData.freeze = NULL; // Zero the pointer
pspatel321 34:18bcf276d3bf 125 return 1;
pspatel321 34:18bcf276d3bf 126 }
pspatel321 34:18bcf276d3bf 127 return -1;
pspatel321 34:18bcf276d3bf 128 }
pspatel321 34:18bcf276d3bf 129 // Artificially update the SOC (battery life %)
pspatel321 34:18bcf276d3bf 130 CMP(1, "SOC") {
pspatel321 34:18bcf276d3bf 131 CMP(2, "Reset") { // Command was "SOC reset" - reset to 100%, do this after a full charge
pspatel321 34:18bcf276d3bf 132 glvBat.resetToSOC(1);
pspatel321 34:18bcf276d3bf 133 return 1;
pspatel321 34:18bcf276d3bf 134 }
pspatel321 34:18bcf276d3bf 135 float soc = strtod(word[1], &next); // Command was "SOC xxx" where xxx is float between 0 and 1
pspatel321 34:18bcf276d3bf 136 if (*next == 0) {
pspatel321 34:18bcf276d3bf 137 if (glvBat.resetToSOC(soc)) return 1;
pspatel321 34:18bcf276d3bf 138 }
pspatel321 34:18bcf276d3bf 139 return -1;
pspatel321 34:18bcf276d3bf 140 }
pspatel321 34:18bcf276d3bf 141 // Artificially update the AmpHours count (linked with SOC)
pspatel321 34:18bcf276d3bf 142 CMP(1, "Ah") {
pspatel321 34:18bcf276d3bf 143 CMP(2, "Reset") { // Command was "Amphours reset", equivalent to "SOC reset"
pspatel321 34:18bcf276d3bf 144 glvBat.resetToSOC(1);
pspatel321 34:18bcf276d3bf 145 return 1;
pspatel321 34:18bcf276d3bf 146 }
pspatel321 34:18bcf276d3bf 147 float ah = strtod(word[1], &next); // Command was "Amphours xxx" where xxx is a float in amphours
pspatel321 34:18bcf276d3bf 148 if (*next == 0) {
pspatel321 34:18bcf276d3bf 149 if (glvBat.resetToAh(ah)) return 1;
pspatel321 34:18bcf276d3bf 150 }
pspatel321 34:18bcf276d3bf 151 return -1;
pspatel321 34:18bcf276d3bf 152 }
pspatel321 34:18bcf276d3bf 153 // Change the battery capacity setting for calculating Amphours
pspatel321 34:18bcf276d3bf 154 CMP(1, "Capacity") {
pspatel321 34:18bcf276d3bf 155 float cap = strtod(word[1], &next); // Command was "SOC xxx" where xxx is float between 0 and 1
pspatel321 34:18bcf276d3bf 156 if (*next == 0) {
pspatel321 34:18bcf276d3bf 157 if (glvBat.changeCapacity(cap)) return 1;
pspatel321 34:18bcf276d3bf 158 }
pspatel321 36:0afc0fc8f86b 159 return -1;
pspatel321 34:18bcf276d3bf 160 }
pspatel321 38:8efacce315ae 161
pspatel321 38:8efacce315ae 162 bool parsed=false;
pspatel321 38:8efacce315ae 163
pspatel321 38:8efacce315ae 164 CHANGE_VAR("GLVchar", chargeCurrent)
pspatel321 38:8efacce315ae 165 CHANGE_VAR("GLVdisch", dischargeCurrent)
pspatel321 38:8efacce315ae 166 CHANGE_VAR("GLVnomCap", nominalCapacity)
pspatel321 38:8efacce315ae 167 CHANGE_VAR("GLVtaps", glvBat_taps)
pspatel321 38:8efacce315ae 168 CHANGE_VAR("dcdcThres", dcdcThreshold)
pspatel321 38:8efacce315ae 169 CHANGE_VAR("dcdcOver", dcdcOverCurrent)
pspatel321 38:8efacce315ae 170 CHANGE_VAR("dcdcStart", dcdcStartDelay)
pspatel321 38:8efacce315ae 171 CHANGE_VAR("dcdcStop", dcdcStopDelay)
pspatel321 38:8efacce315ae 172 CHANGE_VAR("dcdcTaps", dcdc_taps)
pspatel321 38:8efacce315ae 173 CHANGE_VAR("imdStart", imdStartDelay)
pspatel321 38:8efacce315ae 174 CHANGE_VAR("amsStart", amsStartDelay)
pspatel321 38:8efacce315ae 175 CHANGE_VAR("IntOverT", internalOverTemp)
pspatel321 38:8efacce315ae 176 CHANGE_VAR("CANtxSize", CANtxSize)
pspatel321 38:8efacce315ae 177 CHANGE_VAR("CANrxSize", CANrxSize)
pspatel321 38:8efacce315ae 178 CHANGE_VAR("SerialBaud", SerialBaud)
pspatel321 38:8efacce315ae 179 CHANGE_VAR("SerialTx", SerialTxSize)
pspatel321 38:8efacce315ae 180 CHANGE_VAR("XbeeBaud", XbeeBaud)
pspatel321 38:8efacce315ae 181 CHANGE_VAR("XbeeTxSize", XbeeTxSize)
pspatel321 38:8efacce315ae 182 CHANGE_VAR("XbeeRxSize", XbeeRxSize)
pspatel321 38:8efacce315ae 183 CHANGE_VAR("CANack", CANnoAck)
pspatel321 38:8efacce315ae 184
pspatel321 38:8efacce315ae 185 if (!parsed) return -1;
pspatel321 38:8efacce315ae 186
pspatel321 38:8efacce315ae 187 CMP(1, "GLVnomCap") return glvBat.changeCapacity(param->nominalCapacity)?1:-1;
pspatel321 38:8efacce315ae 188 CMP(1, "GLVtaps") return glvBat.size(param->glvBat_taps)?1:-1;
pspatel321 38:8efacce315ae 189 CMP(1, "dcdcTaps") return dcdc.size(param->dcdc_taps)?1:-1;
pspatel321 38:8efacce315ae 190 CMP(1, "CANtxSize") return can.txSize(param->CANtxSize)?1:-1;
pspatel321 38:8efacce315ae 191 CMP(1, "CANrxSize") return can.rxSize(param->CANrxSize)?1:-1;
pspatel321 38:8efacce315ae 192 CMP(1, "SerialBaud") pc.baud(param->SerialBaud);
pspatel321 38:8efacce315ae 193 CMP(1, "SerialTx") return (pc.txBufferSetSize(param->SerialTxSize) == 0)?1:-1;
pspatel321 38:8efacce315ae 194 CMP(1, "XbeeBaud") xbeeRelay.baud(param->XbeeBaud);
pspatel321 38:8efacce315ae 195 CMP(1, "XbeeTxSize") return (xbeeRelay.txSize(param->XbeeTxSize))?1:-1;
pspatel321 38:8efacce315ae 196 CMP(1, "XbeeRxSize") return (xbeeRelay.rxSize(param->XbeeRxSize))?1:-1;
pspatel321 38:8efacce315ae 197
pspatel321 38:8efacce315ae 198 return 1;
pspatel321 34:18bcf276d3bf 199 }
pspatel321 36:0afc0fc8f86b 200 // Three word commands
pspatel321 34:18bcf276d3bf 201 if (pieces == 3) {
pspatel321 34:18bcf276d3bf 202 // Fan Duty
pspatel321 34:18bcf276d3bf 203 CMP(1, "Fan") {
pspatel321 34:18bcf276d3bf 204 float val1 = strtod(word[1], &next);
pspatel321 34:18bcf276d3bf 205 if (*next == 0) {
pspatel321 34:18bcf276d3bf 206 float val2 = strtod(word[2], &next);
pspatel321 34:18bcf276d3bf 207 if (*next == 0) {
pspatel321 38:8efacce315ae 208 op->dcdc.request.fan1 = val1;
pspatel321 38:8efacce315ae 209 op->dcdc.request.fan2 = val2;
pspatel321 34:18bcf276d3bf 210 return 1;
pspatel321 34:18bcf276d3bf 211 }
pspatel321 34:18bcf276d3bf 212 }
pspatel321 34:18bcf276d3bf 213 return -1;
pspatel321 34:18bcf276d3bf 214 }
pspatel321 34:18bcf276d3bf 215
pspatel321 34:18bcf276d3bf 216 // Pump Duty
pspatel321 34:18bcf276d3bf 217 CMP(1, "Pump") {
pspatel321 34:18bcf276d3bf 218 float val1 = strtod(word[1], &next);
pspatel321 34:18bcf276d3bf 219 if (*next == 0) {
pspatel321 34:18bcf276d3bf 220 float val2 = strtod(word[2], &next);
pspatel321 34:18bcf276d3bf 221 if (*next == 0) {
pspatel321 38:8efacce315ae 222 op->dcdc.request.pump1 = val1;
pspatel321 38:8efacce315ae 223 op->dcdc.request.pump2 = val2;
pspatel321 38:8efacce315ae 224 return 1;
pspatel321 38:8efacce315ae 225 }
pspatel321 38:8efacce315ae 226 }
pspatel321 38:8efacce315ae 227 return -1;
pspatel321 38:8efacce315ae 228 }
pspatel321 38:8efacce315ae 229 // Set the system time (RTC)
pspatel321 38:8efacce315ae 230 CMP(1, "Time") {
pspatel321 38:8efacce315ae 231 struct tm t; // Time & date struct
pspatel321 38:8efacce315ae 232 int ret = sscanf(word[1], "%d/%d/%d", &t.tm_mon, &t.tm_mday, &t.tm_year); // Populate date
pspatel321 38:8efacce315ae 233 t.tm_year = t.tm_year - 1900; // Year mod to fix 0 index
pspatel321 38:8efacce315ae 234 t.tm_mon = t.tm_mon - 1; // Month mod to fix 0 index
pspatel321 38:8efacce315ae 235 if (ret == 3) { // All 3 items found
pspatel321 38:8efacce315ae 236 ret = sscanf(word[2], "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec); // Populate time
pspatel321 38:8efacce315ae 237 if (ret == 3) { // All 3 items found
pspatel321 38:8efacce315ae 238 set_time(mktime(&t)); // Set the RTC
pspatel321 38:8efacce315ae 239 time_t diff = time(NULL) - op->SysTime; // Get change in time from old to new
pspatel321 38:8efacce315ae 240 op->startTime += diff; // Shift the startTime to new timebase
pspatel321 34:18bcf276d3bf 241 return 1;
pspatel321 34:18bcf276d3bf 242 }
pspatel321 34:18bcf276d3bf 243 }
pspatel321 34:18bcf276d3bf 244 return -1;
pspatel321 34:18bcf276d3bf 245 }
pspatel321 38:8efacce315ae 246
pspatel321 38:8efacce315ae 247 // Profile manipulations between RAM and flash
pspatel321 38:8efacce315ae 248 CMP(1, "Profile") {
pspatel321 38:8efacce315ae 249 // Write, copy RAM to a flash sector
pspatel321 38:8efacce315ae 250 CMP(2, "Write") {
pspatel321 38:8efacce315ae 251 unsigned int index = strtoul(word[2], &next, 10); // Get index from command "profile write xxx"
pspatel321 38:8efacce315ae 252 if (index <= NUM_STORED_PROFILES && index > 0 && *next == 0) { // Check within bounds
pspatel321 38:8efacce315ae 253 bool s = Profile::saveProfile(index); // Write to flash
pspatel321 38:8efacce315ae 254 if (s) { // Successful?
pspatel321 38:8efacce315ae 255 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 256 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 257 return 1;
pspatel321 38:8efacce315ae 258 }
pspatel321 38:8efacce315ae 259 }
pspatel321 38:8efacce315ae 260 return -1;
pspatel321 38:8efacce315ae 261 }
pspatel321 38:8efacce315ae 262 // Load, read from flash to RAM
pspatel321 38:8efacce315ae 263 CMP(2, "Load") {
pspatel321 38:8efacce315ae 264 CMP(3, "default") { // The hard-coded flash profile (found in FreezeFrame.cpp)
pspatel321 38:8efacce315ae 265 Profile::loadProfile(0); // Copy default to RAM
pspatel321 38:8efacce315ae 266 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 267 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 268 return 1;
pspatel321 38:8efacce315ae 269 }
pspatel321 38:8efacce315ae 270 CMP(3, "freeze") { // Get the profile portion of the last freeze frame captured
pspatel321 38:8efacce315ae 271 if(Profile::loadProfile(-1)) { // Attemp to retrieve and copy to RAM
pspatel321 38:8efacce315ae 272 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 273 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 274 return 1;
pspatel321 38:8efacce315ae 275 }
pspatel321 38:8efacce315ae 276 }
pspatel321 38:8efacce315ae 277 int index = strtol(word[2], &next, 10); // Command was "profile load xxx"
pspatel321 38:8efacce315ae 278 if (index <= NUM_STORED_PROFILES && index >= -1 && *next == 0) { // Valid index found?
pspatel321 38:8efacce315ae 279 if (Profile::loadProfile(index)) { // Attempt to retrieve and copy to RAM
pspatel321 38:8efacce315ae 280 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 281 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 282 return 1;
pspatel321 38:8efacce315ae 283 }
pspatel321 38:8efacce315ae 284 }
pspatel321 38:8efacce315ae 285 return -1;
pspatel321 38:8efacce315ae 286 }
pspatel321 38:8efacce315ae 287 // View the profile only (NOT loaded to RAM, just display changed)
pspatel321 38:8efacce315ae 288 CMP(2, "view") {
pspatel321 38:8efacce315ae 289 CMP(3, "default") { // View the hard-coded flash profile
pspatel321 38:8efacce315ae 290 if (Profile::getProfile(&tempData.viewProfile, 0)) { // Attempt to fetch pointer
pspatel321 38:8efacce315ae 291 tempData.viewProfileNum = 0; // Mark the index of the fetched profile
pspatel321 38:8efacce315ae 292 return 1;
pspatel321 38:8efacce315ae 293 }
pspatel321 38:8efacce315ae 294 }
pspatel321 38:8efacce315ae 295 CMP(3, "freeze") { // View the profile portion only of the last captured freeze frame
pspatel321 38:8efacce315ae 296 if (Profile::getProfile(&tempData.viewProfile, -1)) { // Attempt to fetch pointer
pspatel321 38:8efacce315ae 297 tempData.viewProfileNum = -1; // Mark the index of the fetched profile
pspatel321 38:8efacce315ae 298 return 1;
pspatel321 38:8efacce315ae 299 }
pspatel321 38:8efacce315ae 300 }
pspatel321 38:8efacce315ae 301 CMP(3, "live") { // Revert to normal, live view
pspatel321 38:8efacce315ae 302 tempData.viewProfileNum = -2; // Mark live
pspatel321 38:8efacce315ae 303 tempData.viewProfile = NULL; // Clear the pointer
pspatel321 38:8efacce315ae 304 return 1;
pspatel321 38:8efacce315ae 305 }
pspatel321 38:8efacce315ae 306
pspatel321 38:8efacce315ae 307 int index = strtol(word[2], &next, 10); // Command was "profile view xxx"
pspatel321 38:8efacce315ae 308 if (index <= NUM_STORED_PROFILES && index >= -1 && *next == 0) { // Valid index found?
pspatel321 38:8efacce315ae 309 if (Profile::getProfile(&tempData.viewProfile, index)) { // Attempt to fetch pointer
pspatel321 38:8efacce315ae 310 tempData.viewProfileNum = index; // Mark the index of the fetched profile
pspatel321 38:8efacce315ae 311 return 1;
pspatel321 38:8efacce315ae 312 }
pspatel321 38:8efacce315ae 313 }
pspatel321 38:8efacce315ae 314 return -1;
pspatel321 38:8efacce315ae 315 }
pspatel321 38:8efacce315ae 316 }
pspatel321 34:18bcf276d3bf 317 }
pspatel321 34:18bcf276d3bf 318 return -1;
pspatel321 36:0afc0fc8f86b 319 }
pspatel321 38:8efacce315ae 320 // Called when AMS AIRs Mode message stops coming in
pspatel321 38:8efacce315ae 321 Timeout timer_AIRS_CLOSED;
pspatel321 38:8efacce315ae 322 void timeout_AIRS_CLOSED()
pspatel321 38:8efacce315ae 323 {
pspatel321 38:8efacce315ae 324 op->signals &= ~AIRS_CLOSED;
pspatel321 38:8efacce315ae 325 }
pspatel321 38:8efacce315ae 326
pspatel321 38:8efacce315ae 327 // Called when Charger CAN messages stop coming in
pspatel321 38:8efacce315ae 328 Timeout timer_CHARGER_DET;
pspatel321 38:8efacce315ae 329 void timeout_CHARGER_DET()
pspatel321 38:8efacce315ae 330 {
pspatel321 38:8efacce315ae 331 op->signals &= ~CHARGER_DET;
pspatel321 38:8efacce315ae 332 }
pspatel321 38:8efacce315ae 333
pspatel321 38:8efacce315ae 334 // Called when PCM messages stop coming in
pspatel321 38:8efacce315ae 335 Timeout timer_FANS;
pspatel321 38:8efacce315ae 336 void timeout_FANS()
pspatel321 38:8efacce315ae 337 {
pspatel321 38:8efacce315ae 338 op->dcdc.request.fan1 = 0;
pspatel321 38:8efacce315ae 339 op->dcdc.request.fan2 = 0;
pspatel321 38:8efacce315ae 340 }
pspatel321 38:8efacce315ae 341 Timeout timer_PUMPS;
pspatel321 38:8efacce315ae 342 void timeout_PUMPS()
pspatel321 38:8efacce315ae 343 {
pspatel321 38:8efacce315ae 344 op->dcdc.request.pump1 = 0;
pspatel321 38:8efacce315ae 345 op->dcdc.request.pump2 = 0;
pspatel321 38:8efacce315ae 346 }
pspatel321 38:8efacce315ae 347
pspatel321 38:8efacce315ae 348 #define REFRESH_TIMEOUT(NAME) \
pspatel321 38:8efacce315ae 349 timer_##NAME.detach(); \
pspatel321 38:8efacce315ae 350 timer_##NAME.attach(&timeout_##NAME, CAN_DEVICE_TIMEOUT);
pspatel321 38:8efacce315ae 351
pspatel321 38:8efacce315ae 352 bool serviceCAN(CANMessage* fromXbee)
pspatel321 38:8efacce315ae 353 {
pspatel321 38:8efacce315ae 354 CANMessage msg;
pspatel321 38:8efacce315ae 355 if (fromXbee != NULL) {
pspatel321 38:8efacce315ae 356 memcpy((void*)&msg, (void*)fromXbee, sizeof(CANMessage));
pspatel321 38:8efacce315ae 357 } else {
pspatel321 38:8efacce315ae 358 if (!can.rxRead(msg)) return false;
pspatel321 38:8efacce315ae 359 }
pspatel321 38:8efacce315ae 360 // Redirect global car reset
pspatel321 38:8efacce315ae 361 if (msg.id == GLOBAL_CAR_RESET_RX_ID) msg.id = RESETCLEAR_RX_ID;
pspatel321 38:8efacce315ae 362
pspatel321 38:8efacce315ae 363 switch (msg.id) {
pspatel321 38:8efacce315ae 364 // Reset microntroller
pspatel321 38:8efacce315ae 365 case (RESET_RX_ID):
pspatel321 38:8efacce315ae 366 if (msg.len == 0) { // Length must = 0
pspatel321 38:8efacce315ae 367 NVIC_SystemReset();
pspatel321 38:8efacce315ae 368 CAN_SUCCESS
pspatel321 38:8efacce315ae 369 }
pspatel321 38:8efacce315ae 370 CAN_FAIL
pspatel321 38:8efacce315ae 371
pspatel321 38:8efacce315ae 372
pspatel321 38:8efacce315ae 373 // Clear non-volatile fault flags, then reset microcontroller
pspatel321 38:8efacce315ae 374 case (RESETCLEAR_RX_ID):
pspatel321 38:8efacce315ae 375 if (msg.len == 0) { // Length must = 0
pspatel321 38:8efacce315ae 376 FreezeFrame::clearError();
pspatel321 38:8efacce315ae 377 NVIC_SystemReset();
pspatel321 38:8efacce315ae 378 CAN_SUCCESS
pspatel321 38:8efacce315ae 379 }
pspatel321 38:8efacce315ae 380 CAN_FAIL
pspatel321 38:8efacce315ae 381
pspatel321 38:8efacce315ae 382 // Artificially capture a freeze frame
pspatel321 38:8efacce315ae 383 case (CAPTURE_RX_ID):
pspatel321 38:8efacce315ae 384 if (msg.len == 0) { // Length must = 0
pspatel321 38:8efacce315ae 385 if (!FreezeFrame::getError()) { // Only allow capture if freeze frame from the last error was read
pspatel321 38:8efacce315ae 386 if (FreezeFrame::writeFrame()) { // Capture the RAM contents to flash
pspatel321 38:8efacce315ae 387 CAN_SUCCESS
pspatel321 38:8efacce315ae 388 }
pspatel321 38:8efacce315ae 389 }
pspatel321 38:8efacce315ae 390 }
pspatel321 38:8efacce315ae 391 CAN_FAIL
pspatel321 38:8efacce315ae 392
pspatel321 38:8efacce315ae 393 // Clear fault conditions
pspatel321 38:8efacce315ae 394 case (CLEAR_RX_ID):
pspatel321 38:8efacce315ae 395 if (msg.len == 1) { // One data byte
pspatel321 38:8efacce315ae 396 if (msg.data[0] == 0) { // Clear only freeze frame error if = 0
pspatel321 38:8efacce315ae 397 FreezeFrame::clearError(); // Clear non-volatile freeze frame marker
pspatel321 38:8efacce315ae 398 CAN_SUCCESS
pspatel321 38:8efacce315ae 399 }
pspatel321 38:8efacce315ae 400 if (msg.data[0] == 1) { // Clear everything if = 1
pspatel321 38:8efacce315ae 401 runTime::clearFaults();
pspatel321 38:8efacce315ae 402 op->faultCode = 0;
pspatel321 38:8efacce315ae 403 CAN_SUCCESS
pspatel321 38:8efacce315ae 404 }
pspatel321 38:8efacce315ae 405 }
pspatel321 38:8efacce315ae 406 CAN_FAIL
pspatel321 38:8efacce315ae 407
pspatel321 38:8efacce315ae 408 // Set the time (RTC)
pspatel321 38:8efacce315ae 409 case (TIME_RX_ID):
pspatel321 38:8efacce315ae 410 if (msg.len == 6*sizeof(char)) { // 6 Bytes
pspatel321 38:8efacce315ae 411 struct tm t; // Time & date struct
pspatel321 38:8efacce315ae 412 t.tm_mon = msg.data[0]; // Month in byte[0]
pspatel321 38:8efacce315ae 413 t.tm_mday = msg.data[1]; // Day
pspatel321 38:8efacce315ae 414 t.tm_year = msg.data[2]; // Year (offset from 2000)
pspatel321 38:8efacce315ae 415 t.tm_year = t.tm_year - 1900 + 2000; // Apply year index mod and offset
pspatel321 38:8efacce315ae 416 t.tm_mon = t.tm_mon - 1; // Month index mod
pspatel321 38:8efacce315ae 417 t.tm_hour = msg.data[3]; // Get hour of time in byte[3] (24 hr format)
pspatel321 38:8efacce315ae 418 t.tm_min = msg.data[4]; // Minutes
pspatel321 38:8efacce315ae 419 t.tm_sec = msg.data[5]; // Seconds
pspatel321 38:8efacce315ae 420 set_time(mktime(&t)); // Set RTC
pspatel321 38:8efacce315ae 421 time_t diff = time(NULL) - op->SysTime; // Old time to new time change
pspatel321 38:8efacce315ae 422 op->startTime += diff; // Shift the startTime to new timebase
pspatel321 38:8efacce315ae 423 CAN_SUCCESS
pspatel321 38:8efacce315ae 424 }
pspatel321 38:8efacce315ae 425 CAN_FAIL
pspatel321 38:8efacce315ae 426
pspatel321 38:8efacce315ae 427 // RAM and flash profile manipulations
pspatel321 38:8efacce315ae 428 case (PROFILE_RX_ID):
pspatel321 38:8efacce315ae 429 if (msg.len == 2*sizeof(char)) { // 2 command bytes
pspatel321 38:8efacce315ae 430 if (msg.data[0] == 0) { // Load profile from a flash location to RAM
pspatel321 38:8efacce315ae 431 int index = msg.data[1]; // Second byte contains profile index
pspatel321 38:8efacce315ae 432 if (msg.data[1] == 0xff) index = -1; // If freeze (special case)
pspatel321 38:8efacce315ae 433 if (Profile::loadProfile(index)) { // Attempt to load (copy flash to RAM)
pspatel321 38:8efacce315ae 434 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 435 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 436 CAN_SUCCESS
pspatel321 38:8efacce315ae 437 }
pspatel321 38:8efacce315ae 438 }
pspatel321 38:8efacce315ae 439 if (msg.data[0] == 1) { // Write profile to flash from RAM
pspatel321 38:8efacce315ae 440 int index = msg.data[1]; // Get which slot to write to from message
pspatel321 38:8efacce315ae 441 if (msg.data[1] == 0xff) index = -1; // If freeze (special case)
pspatel321 38:8efacce315ae 442 bool s = Profile::saveProfile(index); // Write profile to flash slot
pspatel321 38:8efacce315ae 443 if (s) {
pspatel321 38:8efacce315ae 444 op->profileIndex = Profile::usingProfile(); // Change the currently loaded profile marker
pspatel321 38:8efacce315ae 445 op->profileModded = false; // Mark it as a fresh, unmodified profile
pspatel321 38:8efacce315ae 446 CAN_SUCCESS
pspatel321 38:8efacce315ae 447 }
pspatel321 38:8efacce315ae 448 }
pspatel321 38:8efacce315ae 449 }
pspatel321 38:8efacce315ae 450 CAN_FAIL
pspatel321 38:8efacce315ae 451
pspatel321 38:8efacce315ae 452 case FAN_CONTROL_ID:
pspatel321 38:8efacce315ae 453 if (msg.len != 2*sizeof(float)) return false;
pspatel321 38:8efacce315ae 454 REFRESH_TIMEOUT(FANS)
pspatel321 38:8efacce315ae 455 op->dcdc.request.fan1 = *((float*)((void*)(&msg.data[0])));
pspatel321 38:8efacce315ae 456 op->dcdc.request.fan2 = *((float*)((void*)(&msg.data[4])));
pspatel321 38:8efacce315ae 457 return true;
pspatel321 38:8efacce315ae 458
pspatel321 38:8efacce315ae 459 case PUMP_CONTROL_ID:
pspatel321 38:8efacce315ae 460 if (msg.len != 2*sizeof(float)) return false;
pspatel321 38:8efacce315ae 461 REFRESH_TIMEOUT(PUMPS)
pspatel321 38:8efacce315ae 462 op->dcdc.request.pump1 = *((float*)((void*)(&msg.data[0])));
pspatel321 38:8efacce315ae 463 op->dcdc.request.pump2 = *((float*)((void*)(&msg.data[4])));
pspatel321 38:8efacce315ae 464 return true;
pspatel321 38:8efacce315ae 465
pspatel321 38:8efacce315ae 466 case AMS_MODE_ID:
pspatel321 38:8efacce315ae 467 if (msg.len != sizeof(char)) return false;
pspatel321 38:8efacce315ae 468 REFRESH_TIMEOUT(AIRS_CLOSED)
pspatel321 38:8efacce315ae 469 if (msg.data[0] & 1<<2) { // AIRs closed?
pspatel321 38:8efacce315ae 470 op->signals |= AIRS_CLOSED;
pspatel321 38:8efacce315ae 471 } else {
pspatel321 38:8efacce315ae 472 op->signals &= ~AIRS_CLOSED;
pspatel321 38:8efacce315ae 473 }
pspatel321 38:8efacce315ae 474 return true;
pspatel321 38:8efacce315ae 475 case CHARGER_ERR_ID:
pspatel321 38:8efacce315ae 476 REFRESH_TIMEOUT(CHARGER_DET)
pspatel321 38:8efacce315ae 477 op->signals |= CHARGER_DET;
pspatel321 38:8efacce315ae 478 return true;
pspatel321 38:8efacce315ae 479 default:
pspatel321 38:8efacce315ae 480 break;
pspatel321 38:8efacce315ae 481 }
pspatel321 38:8efacce315ae 482 bool parsed=false;
pspatel321 38:8efacce315ae 483
pspatel321 38:8efacce315ae 484 CAN_CHANGE(chargeCurrent, PROFILE_CHARGECURRENT_RX_ID )
pspatel321 38:8efacce315ae 485 CAN_CHANGE(dischargeCurrent, PROFILE_DISCHARGECURRENT_RX_ID )
pspatel321 38:8efacce315ae 486 CAN_CHANGE(nominalCapacity, PROFILE_NOMINALCAPACITY_RX_ID )
pspatel321 38:8efacce315ae 487 CAN_CHANGE(glvBat_taps, PROFILE_GLVBATTAPS_RX_ID )
pspatel321 38:8efacce315ae 488 CAN_CHANGE(dcdcThreshold, PROFILE_DCDCONTHRESHOLD_RX_ID )
pspatel321 38:8efacce315ae 489 CAN_CHANGE(dcdcOverCurrent, PROFILE_DCDCOVERCURRENT_RX_ID )
pspatel321 38:8efacce315ae 490 CAN_CHANGE(dcdcStartDelay, PROFILE_DCDCSTARTDELAY_RX_ID )
pspatel321 38:8efacce315ae 491 CAN_CHANGE(dcdcStopDelay, PROFILE_DCDCSTOPDELAY_RX_ID )
pspatel321 38:8efacce315ae 492 CAN_CHANGE(dcdc_taps, PROFILE_DCDC_TAPS_RX_ID )
pspatel321 38:8efacce315ae 493 CAN_CHANGE(imdStartDelay, PROFILE_IMDSTARTDELAY_RX_ID )
pspatel321 38:8efacce315ae 494 CAN_CHANGE(internalOverTemp, PROFILE_INTERNALOVERTEMP_RX_ID )
pspatel321 38:8efacce315ae 495 CAN_CHANGE(CANnoAck, PROFILE_CANNOACK_RX_ID )
pspatel321 38:8efacce315ae 496 CAN_CHANGE(extendedSerial, PROFILE_EXTENDSERIAL_RX_ID )
pspatel321 38:8efacce315ae 497 CAN_CHANGE(CANtxSize, PROFILE_CANTXSIZE_RX_ID )
pspatel321 38:8efacce315ae 498 CAN_CHANGE(CANrxSize, PROFILE_CANRXSIZE_RX_ID )
pspatel321 38:8efacce315ae 499 CAN_CHANGE(SerialBaud, PROFILE_SERIALBAUD_RX_ID )
pspatel321 38:8efacce315ae 500 CAN_CHANGE(SerialTxSize, PROFILE_SERIALTXSIZE_RX_ID )
pspatel321 38:8efacce315ae 501 CAN_CHANGE(XbeeBaud, PROFILE_XBEEBAUD_RX_ID )
pspatel321 38:8efacce315ae 502 CAN_CHANGE(XbeeTxSize, PROFILE_XBEETXSIZE_RX_ID )
pspatel321 38:8efacce315ae 503 CAN_CHANGE(XbeeRxSize, PROFILE_XBEERXSIZE_RX_ID )
pspatel321 38:8efacce315ae 504
pspatel321 38:8efacce315ae 505 if (!parsed) return false;
pspatel321 38:8efacce315ae 506
pspatel321 38:8efacce315ae 507 if (msg.id == PROFILE_NOMINALCAPACITY_RX_ID ) return glvBat.changeCapacity(param->nominalCapacity)?1:-1;
pspatel321 38:8efacce315ae 508 if (msg.id == PROFILE_GLVBATTAPS_RX_ID ) return glvBat.size(param->glvBat_taps)?1:-1;
pspatel321 38:8efacce315ae 509 if (msg.id == PROFILE_DCDC_TAPS_RX_ID ) return dcdc.size(param->dcdc_taps)?1:-1;
pspatel321 38:8efacce315ae 510 if (msg.id == PROFILE_CANTXSIZE_RX_ID ) return can.txSize(param->CANtxSize)?1:-1;
pspatel321 38:8efacce315ae 511 if (msg.id == PROFILE_CANRXSIZE_RX_ID ) return can.rxSize(param->CANrxSize)?1:-1;
pspatel321 38:8efacce315ae 512 if (msg.id == PROFILE_SERIALBAUD_RX_ID ) pc.baud(param->SerialBaud);
pspatel321 38:8efacce315ae 513 if (msg.id == PROFILE_SERIALTXSIZE_RX_ID ) return (pc.txBufferSetSize(param->SerialTxSize) == 0)?1:-1;
pspatel321 38:8efacce315ae 514 if (msg.id == PROFILE_XBEEBAUD_RX_ID ) xbeeRelay.baud(param->XbeeBaud);
pspatel321 38:8efacce315ae 515 if (msg.id == PROFILE_XBEETXSIZE_RX_ID ) return (xbeeRelay.txSize(param->XbeeTxSize))?1:-1;
pspatel321 38:8efacce315ae 516 if (msg.id == PROFILE_XBEERXSIZE_RX_ID ) return (xbeeRelay.rxSize(param->XbeeRxSize))?1:-1;
pspatel321 38:8efacce315ae 517
pspatel321 38:8efacce315ae 518 return true;
pspatel321 38:8efacce315ae 519 }
pspatel321 38:8efacce315ae 520 // Check for incoming messages from the xbees, relay them to the CAN function and send them out on the bus
pspatel321 38:8efacce315ae 521 bool receiveMsgXbee()
pspatel321 38:8efacce315ae 522 {
pspatel321 38:8efacce315ae 523 CANMessage msg;
pspatel321 38:8efacce315ae 524 if (xbeeRelay.receive(msg)) { // Incoming CAN message string received
pspatel321 38:8efacce315ae 525 if (!can.txWrite(msg)) op->faultCode |= CAN_FAULT; // Send it out on the CAN bus
pspatel321 38:8efacce315ae 526 serviceCAN(&msg); // Send it into the local serviceCAN routine
pspatel321 38:8efacce315ae 527 return true;
pspatel321 38:8efacce315ae 528 } else return false;
pspatel321 38:8efacce315ae 529 }
pspatel321 38:8efacce315ae 530
pspatel321 36:0afc0fc8f86b 531
pspatel321 36:0afc0fc8f86b 532 void inCommands::thread_getInputs(void const* args)
pspatel321 36:0afc0fc8f86b 533 {
pspatel321 36:0afc0fc8f86b 534 while(1) {
pspatel321 38:8efacce315ae 535 serviceCAN(0);
pspatel321 38:8efacce315ae 536 receiveMsgXbee();
pspatel321 36:0afc0fc8f86b 537
pspatel321 38:8efacce315ae 538 int ret = serviceSerial();
pspatel321 36:0afc0fc8f86b 539 if (ret == -1) tempData.parseGoodChar = 'x';
pspatel321 36:0afc0fc8f86b 540 if (ret == 1) tempData.parseGoodChar = 251;
pspatel321 36:0afc0fc8f86b 541 osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<2); // Signal watchdog thread
pspatel321 36:0afc0fc8f86b 542 }
pspatel321 30:91af74a299e1 543 }