System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Revision:
38:8efacce315ae
Parent:
36:0afc0fc8f86b
Child:
39:ddf38df9699e
--- a/inCommands/inCommands.cpp	Thu Jan 22 07:59:48 2015 +0000
+++ b/inCommands/inCommands.cpp	Sat Feb 07 08:54:51 2015 +0000
@@ -1,95 +1,19 @@
 #include "inCommands.h"
-
-bool inCommands::serviceCAN(CANMessage* fromXbee)
-{
-    CANMessage msg;
-    if (fromXbee != NULL) {
-        memcpy((void*)&msg, (void*)fromXbee, sizeof(CANMessage));
-    } else {
-        if (!can.rxRead(msg)) return false;
-    }
-
-    switch (msg.id) {
-        case FAN_CONTROL_ID:
-            if (msg.len != 2*sizeof(float)) break;
-            memcpy((void*)&CANdata.dcdcFan1Duty, &msg.data[0], sizeof(float));
-            memcpy((void*)&CANdata.dcdcFan2Duty, &msg.data[4], sizeof(float));
-            dcdc.setPwm(FAN1, CANdata.dcdcFan1Duty);
-            dcdc.setPwm(FAN2, CANdata.dcdcFan2Duty);
-            break;
-
-        case PUMP_CONTROL_ID:
-            if (msg.len != 2*sizeof(float)) break;
-            memcpy((void*)&CANdata.dcdcPump1Duty, &msg.data[0], sizeof(float));
-            memcpy((void*)&CANdata.dcdcPump2Duty, &msg.data[4], sizeof(float));
-            dcdc.setPwm(PUMP1, CANdata.dcdcPump1Duty);
-            dcdc.setPwm(PUMP2, CANdata.dcdcPump2Duty);
-            break;
-
-        case DCDC_CONTROL_ID:
-            if (msg.len != sizeof(char)) break;
-            if (msg.data[0] == 1) dcdc.set(1);
-            else dcdc.set(0);
-            break;
-
-        case AMS_MODE_ID:
-            if (msg.len != sizeof(char)) break;
-            if (msg.data[0] & 1<<2) {     // AIRs closed?
-                CANdata.airsClosed = true;
-                dcdc.set(1);
-            } else {
-                CANdata.airsClosed = false;
-                dcdc.set(0);
-            }
-            break;
-
-        case GLVBAT_SETSOC_ID:
-            if (msg.len != sizeof(float)) break;
-            glvBat.resetToSOC(*((float*)(&msg.data[0])));
-            break;
-
-        case GLVBAT_SETAH_ID:
-            if (msg.len != sizeof(float)) break;
-            glvBat.resetToAh(*((float*)(&msg.data[0])));
-            break;
-
-        case GLVBAT_SETCAPAC_ID:
-            if (msg.len != sizeof(float)) break;
-            glvBat.changeCapacity(*((float*)(&msg.data[0])));
-            break;
-        case STEERING_RESET_ID:
-            NVIC_SystemReset();
-            break;
-        default:
-            break;
-    }
-
-    return true;
-
-}
-// Check for incoming messages from the xbees, relay them to the CAN function and send them out on the bus
-bool inCommands::receiveMsgXbee()
-{
-    CANMessage msg;
-    if (xbeeRelay.receive(msg)) {                       // Incoming CAN message string received
-        if (!can.txWrite(msg)) data.canFault = true;    // Send it out on the CAN bus
-        serviceCAN(&msg);                               // Send it into the local serviceCAN routine
-        return true;
-    } else return false;
-}
+#include "runTime.h"
+#include "inMacros.h"
 
 // Compare string to a word in the serial input, shorter to type
 #define CMP(w, string)                                              if (!strcasecmp(word[w-1], string))
 
 // Serial input
-int inCommands::serviceSerial()
+int serviceSerial()
 {
- static int end = 0;                                 // End of string position
+    static int end = 0;                              // End of string position
 
     int c=0;
     if (pc.readable()) c = pc.getc();
-    if (c == -1) return -2;                          // Invalid char, no char available
-    
+    if (c == -1 || c == 0) return 0;
+
     char b = c;                                      // Casted to char type
     bool process = false;                            // Is string complete (ready to parse)?
 
@@ -112,7 +36,7 @@
     }
     // Continue to parsing section only if flagged as complete and string not empty
     if (!process || strlen((char*)tempData.inputStr) == 0) return 0;
-    
+
     static char word[3][RX_SIZE+1];                  // Hold 3 words
     int pieces = sscanf(tempData.inputStr, "%s %s %s", word[0], word[1], word[2]);      // Populate words
     tempData.inputStr[0] = 0;                        // Empty the string displayed on screen
@@ -125,17 +49,79 @@
             NVIC_SystemReset();
             return 1;
         }
+        // Clear non-volatile fault flags, then reset the microcontroller
+        CMP(1, "resetClear") {
+            runTime::clearFaults();
+            NVIC_SystemReset();
+            return 1;
+        }
+        return -1;
     }
     // Two word commands
     if (pieces == 2) {
-        // Manual DC-DC on/off control
-        CMP(1, "dcdc") {
-            CMP(2, "on") {
-                dcdc.set(1);
+        // Change the serial dashboard display mode
+        CMP(1, "display") {
+            CMP(2, "compact") {
+                if (param->change_extendedSerial(0)) {
+                    op->profileModded=true;
+                    return 1;  // Change function defined by macro
+                }
+            }
+            CMP(2, "extended") {
+                if (param->change_extendedSerial(1)) {
+                    op->profileModded=true;
+                    return 1;  // Change function defined by macro
+                }
+            }
+        }
+        // Change ACK setting for CAN (noAck allows testing of CAN without other nodes)
+        CMP(1, "CANack") {
+            CMP(2, "noack") {                           // NoAck test mode
+                if (param->change_CANnoAck(1)) {
+                    op->profileModded=true;
+                    return 1;
+                }
+            }
+            CMP(2, "ack") {                             // Normal CAN protocol
+                if (param->change_CANnoAck(0)) {
+                    op->profileModded=true;
+                    return 1;
+                }
+            }
+            return -1;
+        }
+        // Artificially capture a freeze frame, save to flash
+        CMP(1, "capture") {
+            CMP(2, "freeze") {
+                if (!FreezeFrame::getError()) {         // Only allow capture if spot available (last error frame was cleared manually)
+                    if (FreezeFrame::writeFrame()) {    // Copy RAM frame to freezree sector in flash
+                        return 1;
+                    }
+                }
+            }
+            return -1;
+        }
+        // Clear fault conditions
+        CMP(1, "clear") {
+            CMP(2, "freeze") {                          // Clear the freeze frame (mark as read)
+                FreezeFrame::clearError();              // Clear the non-volatile error marker
                 return 1;
             }
-            CMP(2, "off") {
-                dcdc.set(0);
+            CMP(2, "faults") {                          // Clear everything
+                runTime::clearFaults();
+                return 1;
+            }
+            return -1;
+        }
+        // Change the display contents
+        CMP(1, "view") {
+            CMP(2, "freeze") {                          // View the last stored freeze frame
+                if (FreezeFrame::getFrame(&tempData.freeze)) {  // Fetch the pointer from flash
+                    return 1;
+                }
+            }
+            CMP(2, "live") {                            // View live data from RAM
+                tempData.freeze = NULL;                 // Zero the pointer
                 return 1;
             }
             return -1;
@@ -172,6 +158,44 @@
             }
             return -1;
         }
+
+        bool parsed=false;
+
+        CHANGE_VAR("GLVchar",       chargeCurrent)
+        CHANGE_VAR("GLVdisch",      dischargeCurrent)
+        CHANGE_VAR("GLVnomCap",     nominalCapacity)
+        CHANGE_VAR("GLVtaps",       glvBat_taps)
+        CHANGE_VAR("dcdcThres",     dcdcThreshold)
+        CHANGE_VAR("dcdcOver",      dcdcOverCurrent)
+        CHANGE_VAR("dcdcStart",     dcdcStartDelay)
+        CHANGE_VAR("dcdcStop",      dcdcStopDelay)
+        CHANGE_VAR("dcdcTaps",      dcdc_taps)
+        CHANGE_VAR("imdStart",      imdStartDelay)
+        CHANGE_VAR("amsStart",      amsStartDelay)
+        CHANGE_VAR("IntOverT",      internalOverTemp)
+        CHANGE_VAR("CANtxSize",     CANtxSize)
+        CHANGE_VAR("CANrxSize",     CANrxSize)
+        CHANGE_VAR("SerialBaud",    SerialBaud)
+        CHANGE_VAR("SerialTx",      SerialTxSize)
+        CHANGE_VAR("XbeeBaud",      XbeeBaud)
+        CHANGE_VAR("XbeeTxSize",    XbeeTxSize)
+        CHANGE_VAR("XbeeRxSize",    XbeeRxSize)
+        CHANGE_VAR("CANack",        CANnoAck)
+
+        if (!parsed) return -1;
+
+        CMP(1, "GLVnomCap")             return glvBat.changeCapacity(param->nominalCapacity)?1:-1;
+        CMP(1, "GLVtaps")               return glvBat.size(param->glvBat_taps)?1:-1;
+        CMP(1, "dcdcTaps")              return dcdc.size(param->dcdc_taps)?1:-1;
+        CMP(1, "CANtxSize")             return can.txSize(param->CANtxSize)?1:-1;
+        CMP(1, "CANrxSize")             return can.rxSize(param->CANrxSize)?1:-1;
+        CMP(1, "SerialBaud")            pc.baud(param->SerialBaud);
+        CMP(1, "SerialTx")              return (pc.txBufferSetSize(param->SerialTxSize) == 0)?1:-1;
+        CMP(1, "XbeeBaud")              xbeeRelay.baud(param->XbeeBaud);
+        CMP(1, "XbeeTxSize")            return (xbeeRelay.txSize(param->XbeeTxSize))?1:-1;
+        CMP(1, "XbeeRxSize")            return (xbeeRelay.rxSize(param->XbeeRxSize))?1:-1;
+
+        return 1;
     }
     // Three word commands
     if (pieces == 3) {
@@ -181,8 +205,8 @@
             if (*next == 0) {
                 float val2 = strtod(word[2], &next);
                 if (*next == 0) {
-                    dcdc.setPwm(FAN1, val1);
-                    dcdc.setPwm(FAN2, val2);
+                    op->dcdc.request.fan1 = val1;
+                    op->dcdc.request.fan2 = val2;
                     return 1;
                 }
             }
@@ -195,24 +219,323 @@
             if (*next == 0) {
                 float val2 = strtod(word[2], &next);
                 if (*next == 0) {
-                    dcdc.setPwm(FAN1, val1);
-                    dcdc.setPwm(FAN2, val2);
+                    op->dcdc.request.pump1 = val1;
+                    op->dcdc.request.pump2 = val2;
+                    return 1;
+                }
+            }
+            return -1;
+        }
+        // Set the system time (RTC)
+        CMP(1, "Time") {
+            struct tm t;    // Time & date struct
+            int ret = sscanf(word[1], "%d/%d/%d", &t.tm_mon, &t.tm_mday, &t.tm_year);   // Populate date
+            t.tm_year = t.tm_year - 1900;       // Year mod to fix 0 index
+            t.tm_mon = t.tm_mon - 1;            // Month mod to fix 0 index
+            if (ret == 3) {                     // All 3 items found
+                ret = sscanf(word[2], "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);    // Populate time
+                if (ret == 3) {                 // All 3 items found
+                    set_time(mktime(&t));       // Set the RTC
+                    time_t diff = time(NULL) - op->SysTime;     // Get change in time from old to new
+                    op->startTime += diff;                      // Shift the startTime to new timebase
                     return 1;
                 }
             }
             return -1;
         }
+
+        // Profile manipulations between RAM and flash
+        CMP(1, "Profile") {
+            // Write, copy RAM to a flash sector
+            CMP(2, "Write") {
+                unsigned int index = strtoul(word[2], &next, 10);               // Get index from command "profile write xxx"
+                if (index <= NUM_STORED_PROFILES && index > 0 && *next == 0) {  // Check within bounds
+                    bool s = Profile::saveProfile(index);                       // Write to flash
+                    if (s) {                                                    // Successful?
+                        op->profileModded = false;                              // Mark it as a fresh, unmodified profile
+                        op->profileIndex = Profile::usingProfile();             // Change the currently loaded profile marker
+                        return 1;
+                    }
+                }
+                return -1;
+            }
+            // Load, read from flash to RAM
+            CMP(2, "Load") {
+                CMP(3, "default") {                                             // The hard-coded flash profile (found in FreezeFrame.cpp)
+                    Profile::loadProfile(0);                                    // Copy default to RAM
+                    op->profileIndex = Profile::usingProfile();                 // Change the currently loaded profile marker
+                    op->profileModded = false;                                  // Mark it as a fresh, unmodified profile
+                    return 1;
+                }
+                CMP(3, "freeze") {                                              // Get the profile portion of the last freeze frame captured
+                    if(Profile::loadProfile(-1)) {                              // Attemp to retrieve and copy to RAM
+                        op->profileModded = false;                              // Mark it as a fresh, unmodified profile
+                        op->profileIndex = Profile::usingProfile();             // Change the currently loaded profile marker
+                        return 1;
+                    }
+                }
+                int index = strtol(word[2], &next, 10);                          // Command was "profile load xxx"
+                if (index <= NUM_STORED_PROFILES && index >= -1 && *next == 0) { // Valid index found?
+                    if (Profile::loadProfile(index)) {                           // Attempt to retrieve and copy to RAM
+                        op->profileModded = false;                               // Mark it as a fresh, unmodified profile
+                        op->profileIndex = Profile::usingProfile();              // Change the currently loaded profile marker
+                        return 1;
+                    }
+                }
+                return -1;
+            }
+            // View the profile only (NOT loaded to RAM, just display changed)
+            CMP(2, "view") {
+                CMP(3, "default") {                                             // View the hard-coded flash profile
+                    if (Profile::getProfile(&tempData.viewProfile, 0)) {        // Attempt to fetch pointer
+                        tempData.viewProfileNum = 0;                            // Mark the index of the fetched profile
+                        return 1;
+                    }
+                }
+                CMP(3, "freeze") {                                              // View the profile portion only of the last captured freeze frame
+                    if (Profile::getProfile(&tempData.viewProfile, -1)) {       // Attempt to fetch pointer
+                        tempData.viewProfileNum = -1;                           // Mark the index of the fetched profile
+                        return 1;
+                    }
+                }
+                CMP(3, "live") {                                                // Revert to normal, live view
+                    tempData.viewProfileNum = -2;                               // Mark live
+                    tempData.viewProfile = NULL;                                // Clear the pointer
+                    return 1;
+                }
+
+                int index = strtol(word[2], &next, 10);                          // Command was "profile view xxx"
+                if (index <= NUM_STORED_PROFILES && index >= -1 && *next == 0) { // Valid index found?
+                    if (Profile::getProfile(&tempData.viewProfile, index)) {     // Attempt to fetch pointer
+                        tempData.viewProfileNum = index;                         // Mark the index of the fetched profile
+                        return 1;
+                    }
+                }
+                return -1;
+            }
+        }
     }
     return -1;
 }
+// Called when AMS AIRs Mode message stops coming in
+Timeout timer_AIRS_CLOSED;
+void timeout_AIRS_CLOSED()
+{
+    op->signals  &= ~AIRS_CLOSED;
+}
+
+// Called when Charger CAN messages stop coming in
+Timeout timer_CHARGER_DET;
+void timeout_CHARGER_DET()
+{
+    op->signals  &= ~CHARGER_DET;
+}
+
+// Called when PCM messages stop coming in
+Timeout timer_FANS;
+void timeout_FANS()
+{
+    op->dcdc.request.fan1  = 0;
+    op->dcdc.request.fan2  = 0;
+}
+Timeout timer_PUMPS;
+void timeout_PUMPS()
+{
+    op->dcdc.request.pump1  = 0;
+    op->dcdc.request.pump2  = 0;
+}
+
+#define REFRESH_TIMEOUT(NAME)           \
+timer_##NAME.detach();                  \
+timer_##NAME.attach(&timeout_##NAME, CAN_DEVICE_TIMEOUT);
+
+bool serviceCAN(CANMessage* fromXbee)
+{
+    CANMessage msg;
+    if (fromXbee != NULL) {
+        memcpy((void*)&msg, (void*)fromXbee, sizeof(CANMessage));
+    } else {
+        if (!can.rxRead(msg)) return false;
+    }
+    // Redirect global car reset
+    if (msg.id == GLOBAL_CAR_RESET_RX_ID) msg.id = RESETCLEAR_RX_ID;
+
+    switch (msg.id) {
+            // Reset microntroller
+        case (RESET_RX_ID):
+            if (msg.len == 0) {     // Length must = 0
+                NVIC_SystemReset();
+                CAN_SUCCESS
+            }
+            CAN_FAIL
+
+        
+        // Clear non-volatile fault flags, then reset microcontroller
+        case (RESETCLEAR_RX_ID):
+            if (msg.len == 0) {                 // Length must = 0
+                FreezeFrame::clearError();
+                NVIC_SystemReset();
+                CAN_SUCCESS
+            }
+            CAN_FAIL
+
+        // Artificially capture a freeze frame
+        case (CAPTURE_RX_ID):
+            if (msg.len == 0) {                         // Length must = 0
+                if (!FreezeFrame::getError()) {         // Only allow capture if freeze frame from the last error was read
+                    if (FreezeFrame::writeFrame()) {    // Capture the RAM contents to flash
+                        CAN_SUCCESS
+                    }
+                }
+            }
+            CAN_FAIL
+
+        // Clear fault conditions
+        case (CLEAR_RX_ID):
+            if (msg.len == 1) {                         // One data byte
+                if (msg.data[0] == 0) {                 // Clear only freeze frame error if = 0
+                    FreezeFrame::clearError();          // Clear non-volatile freeze frame marker
+                    CAN_SUCCESS
+                }
+                if (msg.data[0] == 1) {                 // Clear everything if = 1
+                    runTime::clearFaults();
+                    op->faultCode = 0;
+                    CAN_SUCCESS
+                }
+            }
+            CAN_FAIL
+
+            // Set the time (RTC)
+        case (TIME_RX_ID):
+            if (msg.len == 6*sizeof(char)) {                    // 6 Bytes
+                struct tm t;                                    // Time & date struct
+                t.tm_mon  = msg.data[0];                        // Month in byte[0]
+                t.tm_mday = msg.data[1];                        // Day
+                t.tm_year = msg.data[2];                        // Year (offset from 2000)
+                t.tm_year = t.tm_year - 1900 + 2000;            // Apply year index mod and offset
+                t.tm_mon  = t.tm_mon - 1;                       // Month index mod
+                t.tm_hour = msg.data[3];                        // Get hour of time in byte[3] (24 hr format)
+                t.tm_min  = msg.data[4];                        // Minutes
+                t.tm_sec  = msg.data[5];                        // Seconds
+                set_time(mktime(&t));                           // Set RTC
+                time_t diff = time(NULL) - op->SysTime;         // Old time to new time change
+                op->startTime += diff;                          // Shift the startTime to new timebase
+                CAN_SUCCESS
+            }
+            CAN_FAIL
+
+            // RAM and flash profile manipulations
+        case (PROFILE_RX_ID):
+            if (msg.len == 2*sizeof(char)) {                    // 2 command bytes
+                if (msg.data[0] == 0) {                         // Load profile from a flash location to RAM
+                    int index = msg.data[1];                    // Second byte contains profile index
+                    if (msg.data[1] == 0xff) index = -1;        // If freeze (special case)
+                    if (Profile::loadProfile(index)) {          // Attempt to load (copy flash to RAM)
+                        op->profileIndex = Profile::usingProfile();     // Change the currently loaded profile marker
+                        op->profileModded = false;                      // Mark it as a fresh, unmodified profile
+                        CAN_SUCCESS
+                    }
+                }
+                if (msg.data[0] == 1) {                         // Write profile to flash from RAM
+                    int index = msg.data[1];                    // Get which slot to write to from message
+                    if (msg.data[1] == 0xff) index = -1;        // If freeze (special case)
+                    bool s = Profile::saveProfile(index);       // Write profile to flash slot
+                    if (s) {
+                        op->profileIndex = Profile::usingProfile();     // Change the currently loaded profile marker
+                        op->profileModded = false;                      // Mark it as a fresh, unmodified profile
+                        CAN_SUCCESS
+                    }
+                }
+            }
+            CAN_FAIL
+
+        case FAN_CONTROL_ID:
+            if (msg.len != 2*sizeof(float)) return false;
+            REFRESH_TIMEOUT(FANS)
+            op->dcdc.request.fan1 = *((float*)((void*)(&msg.data[0])));
+            op->dcdc.request.fan2 = *((float*)((void*)(&msg.data[4])));
+            return true;
+
+        case PUMP_CONTROL_ID:
+            if (msg.len != 2*sizeof(float)) return false;
+            REFRESH_TIMEOUT(PUMPS)
+            op->dcdc.request.pump1 = *((float*)((void*)(&msg.data[0])));
+            op->dcdc.request.pump2 = *((float*)((void*)(&msg.data[4])));
+            return true;
+
+        case AMS_MODE_ID:
+            if (msg.len != sizeof(char)) return false;
+            REFRESH_TIMEOUT(AIRS_CLOSED)
+            if (msg.data[0] & 1<<2) {     // AIRs closed?
+                op->signals |= AIRS_CLOSED;
+            } else {
+                op->signals &= ~AIRS_CLOSED;
+            }
+            return true;
+        case CHARGER_ERR_ID:
+            REFRESH_TIMEOUT(CHARGER_DET)
+            op->signals |= CHARGER_DET;
+            return true;
+        default:
+            break;
+    }
+    bool parsed=false;
+
+    CAN_CHANGE(chargeCurrent,           PROFILE_CHARGECURRENT_RX_ID     )
+    CAN_CHANGE(dischargeCurrent,        PROFILE_DISCHARGECURRENT_RX_ID  )
+    CAN_CHANGE(nominalCapacity,         PROFILE_NOMINALCAPACITY_RX_ID   )
+    CAN_CHANGE(glvBat_taps,             PROFILE_GLVBATTAPS_RX_ID        )
+    CAN_CHANGE(dcdcThreshold,           PROFILE_DCDCONTHRESHOLD_RX_ID   )
+    CAN_CHANGE(dcdcOverCurrent,         PROFILE_DCDCOVERCURRENT_RX_ID   )
+    CAN_CHANGE(dcdcStartDelay,          PROFILE_DCDCSTARTDELAY_RX_ID    )
+    CAN_CHANGE(dcdcStopDelay,           PROFILE_DCDCSTOPDELAY_RX_ID     )
+    CAN_CHANGE(dcdc_taps,               PROFILE_DCDC_TAPS_RX_ID         )
+    CAN_CHANGE(imdStartDelay,           PROFILE_IMDSTARTDELAY_RX_ID     )
+    CAN_CHANGE(internalOverTemp,        PROFILE_INTERNALOVERTEMP_RX_ID  )
+    CAN_CHANGE(CANnoAck,                PROFILE_CANNOACK_RX_ID          )
+    CAN_CHANGE(extendedSerial,          PROFILE_EXTENDSERIAL_RX_ID      )
+    CAN_CHANGE(CANtxSize,               PROFILE_CANTXSIZE_RX_ID         )
+    CAN_CHANGE(CANrxSize,               PROFILE_CANRXSIZE_RX_ID         )
+    CAN_CHANGE(SerialBaud,              PROFILE_SERIALBAUD_RX_ID        )
+    CAN_CHANGE(SerialTxSize,            PROFILE_SERIALTXSIZE_RX_ID      )
+    CAN_CHANGE(XbeeBaud,                PROFILE_XBEEBAUD_RX_ID          )
+    CAN_CHANGE(XbeeTxSize,              PROFILE_XBEETXSIZE_RX_ID        )
+    CAN_CHANGE(XbeeRxSize,              PROFILE_XBEERXSIZE_RX_ID        )
+
+    if (!parsed) return false;
+
+    if (msg.id == PROFILE_NOMINALCAPACITY_RX_ID )   return glvBat.changeCapacity(param->nominalCapacity)?1:-1;
+    if (msg.id == PROFILE_GLVBATTAPS_RX_ID      )   return glvBat.size(param->glvBat_taps)?1:-1;
+    if (msg.id == PROFILE_DCDC_TAPS_RX_ID       )   return dcdc.size(param->dcdc_taps)?1:-1;
+    if (msg.id == PROFILE_CANTXSIZE_RX_ID       )   return can.txSize(param->CANtxSize)?1:-1;
+    if (msg.id == PROFILE_CANRXSIZE_RX_ID       )   return can.rxSize(param->CANrxSize)?1:-1;
+    if (msg.id == PROFILE_SERIALBAUD_RX_ID      )   pc.baud(param->SerialBaud);
+    if (msg.id == PROFILE_SERIALTXSIZE_RX_ID    )   return (pc.txBufferSetSize(param->SerialTxSize) == 0)?1:-1;
+    if (msg.id == PROFILE_XBEEBAUD_RX_ID        )   xbeeRelay.baud(param->XbeeBaud);
+    if (msg.id == PROFILE_XBEETXSIZE_RX_ID      )   return (xbeeRelay.txSize(param->XbeeTxSize))?1:-1;
+    if (msg.id == PROFILE_XBEERXSIZE_RX_ID      )   return (xbeeRelay.rxSize(param->XbeeRxSize))?1:-1;
+
+    return true;
+}
+// Check for incoming messages from the xbees, relay them to the CAN function and send them out on the bus
+bool receiveMsgXbee()
+{
+    CANMessage msg;
+    if (xbeeRelay.receive(msg)) {                       // Incoming CAN message string received
+        if (!can.txWrite(msg)) op->faultCode |= CAN_FAULT;    // Send it out on the CAN bus
+        serviceCAN(&msg);                               // Send it into the local serviceCAN routine
+        return true;
+    } else return false;
+}
+
 
 void inCommands::thread_getInputs(void const* args)
 {
     while(1) {
-        inCommands::serviceCAN();
-        inCommands::receiveMsgXbee();
+        serviceCAN(0);
+        receiveMsgXbee();
 
-        int ret = inCommands::serviceSerial();
+        int ret = serviceSerial();
         if (ret == -1) tempData.parseGoodChar = 'x';
         if (ret == 1)  tempData.parseGoodChar = 251;
         osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<2);      // Signal watchdog thread