Penn Electric Racing / Mbed 2 deprecated SystemManagement

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CAN-xbee.cpp Source File

CAN-xbee.cpp

00001 #include "CAN-xbee.h"
00002 
00003 // Creates stringified version of CANMessage msg in char* buff (must be at least 15 chars)
00004 // Returns -1 for bad message, or else returns size of char* buff including the terminating '\n'
00005 int convert2array(CANMessage &msg, char* buff) {
00006     
00007     // Check message integrity
00008     if (msg.len > 8) return -1;
00009     if ((msg.format == CANStandard) && ((msg.id & 0x7FF) != msg.id)) return -1;
00010     if ((msg.format == CANExtended) && ((msg.id & 0x1FFFFFFF) != msg.id)) return -1;
00011     
00012     int i = 0;
00013     buff[i++] = 'C';      // Start of message
00014     buff[i++] = (msg.format << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2);     // Header byte, message info on ID size, RTR, # data bytes
00015     if (msg.format == CANStandard) {
00016         buff[i++] = (msg.id & 0x0FF);               // Lower byte of ID
00017         buff[i++] = (msg.id & 0x700) >> 8;          // Upper byte of ID
00018     } else {
00019         buff[i++] = (msg.id & 0x000000FF);          // Lowest byte of ID
00020         buff[i++] = (msg.id & 0x0000FF00) >> 8;
00021         buff[i++] = (msg.id & 0x00FF0000) >> 16;
00022         buff[i++] = (msg.id & 0x1F000000) >> 24;    // Highest byte of ID
00023     }
00024     for (int j = 0; j < msg.len; j++) {
00025         buff[i++] = msg.data[j];
00026     }
00027     buff[i++] = '\n';
00028     return i;
00029 }
00030 
00031 bool convert2msg(CANMessage &msg, char* buff) {
00032     // Check for 'D' for done
00033     if (buff[0] != 'D') return -1;
00034     
00035     bool extended = buff[1] & 1;
00036     bool rtr = buff[1] & 2;
00037     char DLC = buff[1] >> 2;
00038     if (DLC > 8) return false;     // Bad length
00039     
00040     // Standard frame, get id and data
00041     if (!extended) {
00042         if (buff[3] & 0x7 != buff[3]) return false;                 // Last byte of ID bad
00043         msg.id = buff[2] | (int)(buff[3] << 8);                     // Build the ID
00044         for (int i = 0; i < DLC; i++) msg.data[i] = buff[i+4];      // Build the data array
00045         
00046     // Extended frame, get id and data
00047     } else {
00048         if (buff[5] & 0x1F != buff[5]) return false;                            // Last byte of ID bad
00049         msg.id = buff[2] | (buff[3] << 8) | (buff[4] << 16) | (buff[5] << 24);  // Build the ID
00050         for (int i = 0; i < DLC; i++) msg.data[i] = buff[i+6];                  // Build the data array
00051     }
00052     msg.len = DLC;
00053     if (rtr) msg.type = CANRemote;
00054     else msg.type = CANData;
00055     if (extended) msg.format = CANExtended;
00056     else msg.format = CANStandard;
00057     return true;                        // Successfully parsed, passed all checks, arguement was updated
00058 }
00059 
00060 CANxbee::CANxbee(PinName tx, PinName rx, int _baud, int txSize, int rxSize) : serial(tx, rx, txSize, rxSize) {
00061     serial.baud(_baud);
00062     rx_i = 0;
00063     rxBuff[0] = 0;
00064     getChars = -1;
00065 }
00066 
00067 // Send a CAN message, first reformat it into a char array, then send over Xbees
00068 bool CANxbee::send(CANMessage &msg, unsigned int* length) {
00069     char buff[15];                      // Build the string-ified CAN message here
00070     int size = convert2array(msg, buff);
00071     *length = 0;
00072     if (size == -1) return false;       // Bad message, string not formed
00073     
00074     int bytesLeft = serial.txBufferGetSize(0) - serial.txBufferGetCount();
00075     
00076     if (bytesLeft >= size) {
00077         for (int i = 0; i < size; i++) serial.putc(buff[i]);    // Send the message out
00078         *length = size;
00079         return true;
00080     }
00081     return false;
00082 }
00083 
00084 // Continuously call this function in main program, when it returns true, it holds a newly received CAN message that came via Xbee
00085 bool CANxbee::receive(CANMessage &msg) {
00086     int newChar = serial.getcNb();
00087     if (newChar == -1) return false;        // No new char
00088     char c = newChar & 0xFF;                // Cast to char
00089     
00090     // Listen for a 'C', start of new message as long as not already building message
00091     if (c == 'C' && (rxBuff[0] != 'C')) {
00092         rx_i = 0;               // Reset to start of message
00093         rxBuff[rx_i++] = 'C';   // Add the 'C', increment
00094         return false;
00095     }
00096     
00097     // 'C' already found, now filling in contents of message
00098     if (rxBuff[0] == 'C') {
00099         if (getChars == -1) {           // Get the header byte
00100             rxBuff[rx_i++] = c;         // Add to string, increment
00101             bool extended = c & 1;      // Is this an extended message? (4 ID bytes)
00102             char DLC = c >> 2;          // How long is the data section?
00103             if (DLC > 8) {              // Bad DLC, reset variables
00104                 getChars = -1;
00105                 rxBuff[0] = 0;
00106                 rx_i = 0;
00107                 return false;
00108             }
00109             getChars = DLC + extended?4:2;  // Need to obtain getChars more characters to complete this message
00110         } else {                            // This is not a header byte, add to contents of message
00111             rxBuff[rx_i++] = c;
00112             getChars--;
00113             if (getChars <= 0) {            // Just added the last char, done message, reset variables
00114                 rxBuff[0] = 'D';            // Mark 'D' for done
00115                 rx_i = 0;
00116                 getChars = -1;
00117             }
00118         }
00119     }
00120     if (rxBuff[0] != 'D') return false;
00121     
00122     // A string is ready, process it here
00123     if (convert2msg(msg, rxBuff)) return true;
00124     else return false;
00125 }