Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
Libs/XbeeManager/CAN-xbee/CAN-xbee.cpp@38:8efacce315ae, 2015-02-07 (annotated)
- Committer:
- pspatel321
- Date:
- Sat Feb 07 08:54:51 2015 +0000
- Revision:
- 38:8efacce315ae
- Parent:
- 34:18bcf276d3bf
Updated with profiles, operating info, etc. Just like the other programs. Awaiting test in car.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| pspatel321 | 33:6bc82b6b62e5 | 1 | #include "CAN-xbee.h" |
| pspatel321 | 33:6bc82b6b62e5 | 2 | |
| pspatel321 | 34:18bcf276d3bf | 3 | // Creates stringified version of CANMessage msg in char* buff (must be at least 15 chars) |
| pspatel321 | 34:18bcf276d3bf | 4 | // Returns -1 for bad message, or else returns size of char* buff including the terminating '\n' |
| pspatel321 | 34:18bcf276d3bf | 5 | int convert2array(CANMessage &msg, char* buff) { |
| pspatel321 | 34:18bcf276d3bf | 6 | |
| pspatel321 | 34:18bcf276d3bf | 7 | // Check message integrity |
| pspatel321 | 34:18bcf276d3bf | 8 | if (msg.len > 8) return -1; |
| pspatel321 | 34:18bcf276d3bf | 9 | if ((msg.format == CANStandard) && ((msg.id & 0x7FF) != msg.id)) return -1; |
| pspatel321 | 34:18bcf276d3bf | 10 | if ((msg.format == CANExtended) && ((msg.id & 0x1FFFFFFF) != msg.id)) return -1; |
| pspatel321 | 34:18bcf276d3bf | 11 | |
| pspatel321 | 34:18bcf276d3bf | 12 | int i = 0; |
| pspatel321 | 38:8efacce315ae | 13 | buff[i++] = 'C'; // Start of message |
| pspatel321 | 38:8efacce315ae | 14 | buff[i++] = (msg.format << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2); // Header byte, message info on ID size, RTR, # data bytes |
| pspatel321 | 34:18bcf276d3bf | 15 | if (msg.format == CANStandard) { |
| pspatel321 | 34:18bcf276d3bf | 16 | buff[i++] = (msg.id & 0x0FF); // Lower byte of ID |
| pspatel321 | 34:18bcf276d3bf | 17 | buff[i++] = (msg.id & 0x700) >> 8; // Upper byte of ID |
| pspatel321 | 34:18bcf276d3bf | 18 | } else { |
| pspatel321 | 34:18bcf276d3bf | 19 | buff[i++] = (msg.id & 0x000000FF); // Lowest byte of ID |
| pspatel321 | 34:18bcf276d3bf | 20 | buff[i++] = (msg.id & 0x0000FF00) >> 8; |
| pspatel321 | 34:18bcf276d3bf | 21 | buff[i++] = (msg.id & 0x00FF0000) >> 16; |
| pspatel321 | 34:18bcf276d3bf | 22 | buff[i++] = (msg.id & 0x1F000000) >> 24; // Highest byte of ID |
| pspatel321 | 34:18bcf276d3bf | 23 | } |
| pspatel321 | 34:18bcf276d3bf | 24 | for (int j = 0; j < msg.len; j++) { |
| pspatel321 | 34:18bcf276d3bf | 25 | buff[i++] = msg.data[j]; |
| pspatel321 | 34:18bcf276d3bf | 26 | } |
| pspatel321 | 34:18bcf276d3bf | 27 | buff[i++] = '\n'; |
| pspatel321 | 38:8efacce315ae | 28 | return i; |
| pspatel321 | 34:18bcf276d3bf | 29 | } |
| pspatel321 | 34:18bcf276d3bf | 30 | |
| pspatel321 | 34:18bcf276d3bf | 31 | bool convert2msg(CANMessage &msg, char* buff) { |
| pspatel321 | 34:18bcf276d3bf | 32 | // Check for 'D' for done |
| pspatel321 | 34:18bcf276d3bf | 33 | if (buff[0] != 'D') return -1; |
| pspatel321 | 34:18bcf276d3bf | 34 | |
| pspatel321 | 34:18bcf276d3bf | 35 | bool extended = buff[1] & 1; |
| pspatel321 | 34:18bcf276d3bf | 36 | bool rtr = buff[1] & 2; |
| pspatel321 | 34:18bcf276d3bf | 37 | char DLC = buff[1] >> 2; |
| pspatel321 | 34:18bcf276d3bf | 38 | if (DLC > 8) return false; // Bad length |
| pspatel321 | 34:18bcf276d3bf | 39 | |
| pspatel321 | 34:18bcf276d3bf | 40 | // Standard frame, get id and data |
| pspatel321 | 34:18bcf276d3bf | 41 | if (!extended) { |
| pspatel321 | 34:18bcf276d3bf | 42 | if (buff[3] & 0x7 != buff[3]) return false; // Last byte of ID bad |
| pspatel321 | 34:18bcf276d3bf | 43 | msg.id = buff[2] | (int)(buff[3] << 8); // Build the ID |
| pspatel321 | 34:18bcf276d3bf | 44 | for (int i = 0; i < DLC; i++) msg.data[i] = buff[i+4]; // Build the data array |
| pspatel321 | 34:18bcf276d3bf | 45 | |
| pspatel321 | 34:18bcf276d3bf | 46 | // Extended frame, get id and data |
| pspatel321 | 34:18bcf276d3bf | 47 | } else { |
| pspatel321 | 34:18bcf276d3bf | 48 | if (buff[5] & 0x1F != buff[5]) return false; // Last byte of ID bad |
| pspatel321 | 34:18bcf276d3bf | 49 | msg.id = buff[2] | (buff[3] << 8) | (buff[4] << 16) | (buff[5] << 24); // Build the ID |
| pspatel321 | 34:18bcf276d3bf | 50 | for (int i = 0; i < DLC; i++) msg.data[i] = buff[i+6]; // Build the data array |
| pspatel321 | 34:18bcf276d3bf | 51 | } |
| pspatel321 | 34:18bcf276d3bf | 52 | msg.len = DLC; |
| pspatel321 | 34:18bcf276d3bf | 53 | if (rtr) msg.type = CANRemote; |
| pspatel321 | 34:18bcf276d3bf | 54 | else msg.type = CANData; |
| pspatel321 | 34:18bcf276d3bf | 55 | if (extended) msg.format = CANExtended; |
| pspatel321 | 34:18bcf276d3bf | 56 | else msg.format = CANStandard; |
| pspatel321 | 34:18bcf276d3bf | 57 | return true; // Successfully parsed, passed all checks, arguement was updated |
| pspatel321 | 34:18bcf276d3bf | 58 | } |
| pspatel321 | 34:18bcf276d3bf | 59 | |
| pspatel321 | 33:6bc82b6b62e5 | 60 | CANxbee::CANxbee(PinName tx, PinName rx, int _baud, int txSize, int rxSize) : serial(tx, rx, txSize, rxSize) { |
| pspatel321 | 33:6bc82b6b62e5 | 61 | serial.baud(_baud); |
| pspatel321 | 33:6bc82b6b62e5 | 62 | rx_i = 0; |
| pspatel321 | 33:6bc82b6b62e5 | 63 | rxBuff[0] = 0; |
| pspatel321 | 34:18bcf276d3bf | 64 | getChars = -1; |
| pspatel321 | 33:6bc82b6b62e5 | 65 | } |
| pspatel321 | 33:6bc82b6b62e5 | 66 | |
| pspatel321 | 33:6bc82b6b62e5 | 67 | // Send a CAN message, first reformat it into a char array, then send over Xbees |
| pspatel321 | 38:8efacce315ae | 68 | bool CANxbee::send(CANMessage &msg, unsigned int* length) { |
| pspatel321 | 34:18bcf276d3bf | 69 | char buff[15]; // Build the string-ified CAN message here |
| pspatel321 | 34:18bcf276d3bf | 70 | int size = convert2array(msg, buff); |
| pspatel321 | 38:8efacce315ae | 71 | *length = 0; |
| pspatel321 | 34:18bcf276d3bf | 72 | if (size == -1) return false; // Bad message, string not formed |
| pspatel321 | 33:6bc82b6b62e5 | 73 | |
| pspatel321 | 34:18bcf276d3bf | 74 | int bytesLeft = serial.txBufferGetSize(0) - serial.txBufferGetCount(); |
| pspatel321 | 33:6bc82b6b62e5 | 75 | |
| pspatel321 | 34:18bcf276d3bf | 76 | if (bytesLeft >= size) { |
| pspatel321 | 33:6bc82b6b62e5 | 77 | for (int i = 0; i < size; i++) serial.putc(buff[i]); // Send the message out |
| pspatel321 | 38:8efacce315ae | 78 | *length = size; |
| pspatel321 | 38:8efacce315ae | 79 | return true; |
| pspatel321 | 33:6bc82b6b62e5 | 80 | } |
| pspatel321 | 38:8efacce315ae | 81 | return false; |
| pspatel321 | 33:6bc82b6b62e5 | 82 | } |
| pspatel321 | 33:6bc82b6b62e5 | 83 | |
| pspatel321 | 33:6bc82b6b62e5 | 84 | // Continuously call this function in main program, when it returns true, it holds a newly received CAN message that came via Xbee |
| pspatel321 | 33:6bc82b6b62e5 | 85 | bool CANxbee::receive(CANMessage &msg) { |
| pspatel321 | 33:6bc82b6b62e5 | 86 | int newChar = serial.getcNb(); |
| pspatel321 | 33:6bc82b6b62e5 | 87 | if (newChar == -1) return false; // No new char |
| pspatel321 | 33:6bc82b6b62e5 | 88 | char c = newChar & 0xFF; // Cast to char |
| pspatel321 | 33:6bc82b6b62e5 | 89 | |
| pspatel321 | 34:18bcf276d3bf | 90 | // Listen for a 'C', start of new message as long as not already building message |
| pspatel321 | 34:18bcf276d3bf | 91 | if (c == 'C' && (rxBuff[0] != 'C')) { |
| pspatel321 | 34:18bcf276d3bf | 92 | rx_i = 0; // Reset to start of message |
| pspatel321 | 34:18bcf276d3bf | 93 | rxBuff[rx_i++] = 'C'; // Add the 'C', increment |
| pspatel321 | 33:6bc82b6b62e5 | 94 | return false; |
| pspatel321 | 33:6bc82b6b62e5 | 95 | } |
| pspatel321 | 34:18bcf276d3bf | 96 | |
| pspatel321 | 34:18bcf276d3bf | 97 | // 'C' already found, now filling in contents of message |
| pspatel321 | 34:18bcf276d3bf | 98 | if (rxBuff[0] == 'C') { |
| pspatel321 | 34:18bcf276d3bf | 99 | if (getChars == -1) { // Get the header byte |
| pspatel321 | 34:18bcf276d3bf | 100 | rxBuff[rx_i++] = c; // Add to string, increment |
| pspatel321 | 34:18bcf276d3bf | 101 | bool extended = c & 1; // Is this an extended message? (4 ID bytes) |
| pspatel321 | 34:18bcf276d3bf | 102 | char DLC = c >> 2; // How long is the data section? |
| pspatel321 | 34:18bcf276d3bf | 103 | if (DLC > 8) { // Bad DLC, reset variables |
| pspatel321 | 34:18bcf276d3bf | 104 | getChars = -1; |
| pspatel321 | 34:18bcf276d3bf | 105 | rxBuff[0] = 0; |
| pspatel321 | 34:18bcf276d3bf | 106 | rx_i = 0; |
| pspatel321 | 34:18bcf276d3bf | 107 | return false; |
| pspatel321 | 34:18bcf276d3bf | 108 | } |
| pspatel321 | 34:18bcf276d3bf | 109 | getChars = DLC + extended?4:2; // Need to obtain getChars more characters to complete this message |
| pspatel321 | 34:18bcf276d3bf | 110 | } else { // This is not a header byte, add to contents of message |
| pspatel321 | 34:18bcf276d3bf | 111 | rxBuff[rx_i++] = c; |
| pspatel321 | 34:18bcf276d3bf | 112 | getChars--; |
| pspatel321 | 34:18bcf276d3bf | 113 | if (getChars <= 0) { // Just added the last char, done message, reset variables |
| pspatel321 | 34:18bcf276d3bf | 114 | rxBuff[0] = 'D'; // Mark 'D' for done |
| pspatel321 | 34:18bcf276d3bf | 115 | rx_i = 0; |
| pspatel321 | 34:18bcf276d3bf | 116 | getChars = -1; |
| pspatel321 | 34:18bcf276d3bf | 117 | } |
| pspatel321 | 33:6bc82b6b62e5 | 118 | } |
| pspatel321 | 33:6bc82b6b62e5 | 119 | } |
| pspatel321 | 34:18bcf276d3bf | 120 | if (rxBuff[0] != 'D') return false; |
| pspatel321 | 33:6bc82b6b62e5 | 121 | |
| pspatel321 | 33:6bc82b6b62e5 | 122 | // A string is ready, process it here |
| pspatel321 | 34:18bcf276d3bf | 123 | if (convert2msg(msg, rxBuff)) return true; |
| pspatel321 | 34:18bcf276d3bf | 124 | else return false; |
| pspatel321 | 33:6bc82b6b62e5 | 125 | } |
