System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

inCommands/inCommands.cpp

Committer:
pspatel321
Date:
2015-01-22
Revision:
36:0afc0fc8f86b
Parent:
34:18bcf276d3bf
Child:
38:8efacce315ae

File content as of revision 36:0afc0fc8f86b:

#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;
}

// 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()
{
 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
    
    char b = c;                                      // Casted to char type
    bool process = false;                            // Is string complete (ready to parse)?

    if (b == '\n' || b == '\r') {                    // Enter key was pressed, dump for processing
        tempData.inputStr[end] = 0;                  // Null terminate
        end = 0;                                     // Reset to start
        process = true;                              // Flag for processing

    } else if (b == '\b' || b == 127) {              // Backspace or delete
        if (end > 0) end--;                          // Move back one char
        tempData.inputStr[end] = 0;                  // Erase char

    } else if (b > 31 && b < 127) {                  // New valid displayable char
        tempData.inputStr[end++] = b;                // Add to buffer
        tempData.inputStr[end] = 0;                  // Add null terminator
        if (end >= RX_SIZE) {
            end = 0;                                 // Reset end location
            process = true;                          // Flag for processing
        }
    }
    // 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
    char *next;                                      // Used by strtof and strtoul

    // One word commands
    if (pieces == 1) {
        // Reset the microcontroller
        CMP(1, "reset") {
            NVIC_SystemReset();
            return 1;
        }
    }
    // Two word commands
    if (pieces == 2) {
        // Manual DC-DC on/off control
        CMP(1, "dcdc") {
            CMP(2, "on") {
                dcdc.set(1);
                return 1;
            }
            CMP(2, "off") {
                dcdc.set(0);
                return 1;
            }
            return -1;
        }
        // Artificially update the SOC (battery life %)
        CMP(1, "SOC") {
            CMP(2, "Reset") {                           // Command was "SOC reset" - reset to 100%, do this after a full charge
                glvBat.resetToSOC(1);
                return 1;
            }
            float soc = strtod(word[1], &next);         // Command was "SOC xxx" where xxx is float between 0 and 1
            if (*next == 0) {
                if (glvBat.resetToSOC(soc)) return 1;
            }
            return -1;
        }
        // Artificially update the AmpHours count (linked with SOC)
        CMP(1, "Ah") {
            CMP(2, "Reset") {                           // Command was "Amphours reset", equivalent to "SOC reset"
                glvBat.resetToSOC(1);
                return 1;
            }
            float ah = strtod(word[1], &next);          // Command was "Amphours xxx" where xxx is a float in amphours
            if (*next == 0) {
                if (glvBat.resetToAh(ah)) return 1;
            }
            return -1;
        }
        // Change the battery capacity setting for calculating Amphours
        CMP(1, "Capacity") {
            float cap = strtod(word[1], &next);         // Command was "SOC xxx" where xxx is float between 0 and 1
            if (*next == 0) {
                if (glvBat.changeCapacity(cap)) return 1;
            }
            return -1;
        }
    }
    // Three word commands
    if (pieces == 3) {
        // Fan Duty
        CMP(1, "Fan") {
            float val1 = strtod(word[1], &next);
            if (*next == 0) {
                float val2 = strtod(word[2], &next);
                if (*next == 0) {
                    dcdc.setPwm(FAN1, val1);
                    dcdc.setPwm(FAN2, val2);
                    return 1;
                }
            }
            return -1;
        }

        // Pump Duty
        CMP(1, "Pump") {
            float val1 = strtod(word[1], &next);
            if (*next == 0) {
                float val2 = strtod(word[2], &next);
                if (*next == 0) {
                    dcdc.setPwm(FAN1, val1);
                    dcdc.setPwm(FAN2, val2);
                    return 1;
                }
            }
            return -1;
        }
    }
    return -1;
}

void inCommands::thread_getInputs(void const* args)
{
    while(1) {
        inCommands::serviceCAN();
        inCommands::receiveMsgXbee();

        int ret = inCommands::serviceSerial();
        if (ret == -1) tempData.parseGoodChar = 'x';
        if (ret == 1)  tempData.parseGoodChar = 251;
        osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<2);      // Signal watchdog thread
    }
}