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@33:6bc82b6b62e5, 2015-01-06 (annotated)
- Committer:
- pspatel321
- Date:
- Tue Jan 06 20:45:26 2015 +0000
- Revision:
- 33:6bc82b6b62e5
- Child:
- 34:18bcf276d3bf
Updated IDs to match AMS, added a constants.h file.
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 | 33:6bc82b6b62e5 | 3 | CANxbee::CANxbee(PinName tx, PinName rx, int _baud, int txSize, int rxSize) : serial(tx, rx, txSize, rxSize) { |
| pspatel321 | 33:6bc82b6b62e5 | 4 | serial.baud(_baud); |
| pspatel321 | 33:6bc82b6b62e5 | 5 | rx_i = 0; |
| pspatel321 | 33:6bc82b6b62e5 | 6 | rxBuff[0] = 0; |
| pspatel321 | 33:6bc82b6b62e5 | 7 | building = false; |
| pspatel321 | 33:6bc82b6b62e5 | 8 | } |
| pspatel321 | 33:6bc82b6b62e5 | 9 | |
| pspatel321 | 33:6bc82b6b62e5 | 10 | // Send a CAN message, first reformat it into a char array, then send over Xbees |
| pspatel321 | 33:6bc82b6b62e5 | 11 | bool CANxbee::send(CANMessage &msg) { |
| pspatel321 | 33:6bc82b6b62e5 | 12 | char buff[14]; // Build the string-ified CAN message here |
| pspatel321 | 33:6bc82b6b62e5 | 13 | int size; |
| pspatel321 | 33:6bc82b6b62e5 | 14 | |
| pspatel321 | 33:6bc82b6b62e5 | 15 | buff[0] = 'C'; |
| pspatel321 | 33:6bc82b6b62e5 | 16 | int i; |
| pspatel321 | 33:6bc82b6b62e5 | 17 | if (msg.format == 0) { // Standard, 11-bit ID |
| pspatel321 | 33:6bc82b6b62e5 | 18 | buff[1] = (0 << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2); |
| pspatel321 | 33:6bc82b6b62e5 | 19 | buff[2] = msg.id & 0xFF; // Lower byte of ID |
| pspatel321 | 33:6bc82b6b62e5 | 20 | buff[3] = (msg.id & 0x7FF) >> 8; |
| pspatel321 | 33:6bc82b6b62e5 | 21 | for (i = 0; (i < msg.len) && (i < 8); i++) { |
| pspatel321 | 33:6bc82b6b62e5 | 22 | buff[i+4] = msg.data[i]; // Get data bytes |
| pspatel321 | 33:6bc82b6b62e5 | 23 | } |
| pspatel321 | 33:6bc82b6b62e5 | 24 | buff[i+4] = '\n'; // Terminate message |
| pspatel321 | 33:6bc82b6b62e5 | 25 | size = i+4+1; |
| pspatel321 | 33:6bc82b6b62e5 | 26 | |
| pspatel321 | 33:6bc82b6b62e5 | 27 | } else if (msg.format == 1) { // Extended, 29-bit ID |
| pspatel321 | 33:6bc82b6b62e5 | 28 | buff[1] = (1 << 0) | (msg.type << 1) | ((msg.len & 0xf) << 2); |
| pspatel321 | 33:6bc82b6b62e5 | 29 | buff[2] = msg.id & 0x000000FF; // Lower byte of ID |
| pspatel321 | 33:6bc82b6b62e5 | 30 | buff[3] = msg.id & 0x0000FF00 >> 8; |
| pspatel321 | 33:6bc82b6b62e5 | 31 | buff[4] = msg.id & 0x00FF0000 >> 16; |
| pspatel321 | 33:6bc82b6b62e5 | 32 | buff[5] = msg.id & 0x1F000000 >> 24; |
| pspatel321 | 33:6bc82b6b62e5 | 33 | for (i = 0; (i < msg.len) && (i < 8); i++) { |
| pspatel321 | 33:6bc82b6b62e5 | 34 | buff[i+6] = msg.data[i]; // Get data bytes |
| pspatel321 | 33:6bc82b6b62e5 | 35 | } |
| pspatel321 | 33:6bc82b6b62e5 | 36 | buff[i+6] = '\n'; // Terminate message |
| pspatel321 | 33:6bc82b6b62e5 | 37 | size = i+6+1; |
| pspatel321 | 33:6bc82b6b62e5 | 38 | } else return false; // Bad message |
| pspatel321 | 33:6bc82b6b62e5 | 39 | |
| pspatel321 | 33:6bc82b6b62e5 | 40 | bool success=false; |
| pspatel321 | 33:6bc82b6b62e5 | 41 | |
| pspatel321 | 33:6bc82b6b62e5 | 42 | // Begin thread-safe section |
| pspatel321 | 33:6bc82b6b62e5 | 43 | __disable_irq(); |
| pspatel321 | 33:6bc82b6b62e5 | 44 | |
| pspatel321 | 33:6bc82b6b62e5 | 45 | // Check if enough spaces in buffer |
| pspatel321 | 33:6bc82b6b62e5 | 46 | if ((serial.txBufferGetSize(0) - serial.txBufferGetCount()) >= size) { |
| pspatel321 | 33:6bc82b6b62e5 | 47 | for (int i = 0; i < size; i++) serial.putc(buff[i]); // Send the message out |
| pspatel321 | 33:6bc82b6b62e5 | 48 | success = true; |
| pspatel321 | 33:6bc82b6b62e5 | 49 | } |
| pspatel321 | 33:6bc82b6b62e5 | 50 | |
| pspatel321 | 33:6bc82b6b62e5 | 51 | // End thread-safe section |
| pspatel321 | 33:6bc82b6b62e5 | 52 | __enable_irq(); |
| pspatel321 | 33:6bc82b6b62e5 | 53 | |
| pspatel321 | 33:6bc82b6b62e5 | 54 | return success; |
| pspatel321 | 33:6bc82b6b62e5 | 55 | } |
| pspatel321 | 33:6bc82b6b62e5 | 56 | |
| pspatel321 | 33:6bc82b6b62e5 | 57 | // 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 | 58 | bool CANxbee::receive(CANMessage &msg) { |
| pspatel321 | 33:6bc82b6b62e5 | 59 | int newChar = serial.getcNb(); |
| pspatel321 | 33:6bc82b6b62e5 | 60 | if (newChar == -1) return false; // No new char |
| pspatel321 | 33:6bc82b6b62e5 | 61 | char c = newChar & 0xFF; // Cast to char |
| pspatel321 | 33:6bc82b6b62e5 | 62 | bool process=false; |
| pspatel321 | 33:6bc82b6b62e5 | 63 | |
| pspatel321 | 33:6bc82b6b62e5 | 64 | char len=0; |
| pspatel321 | 33:6bc82b6b62e5 | 65 | // Listen for a 'C', start of new message |
| pspatel321 | 33:6bc82b6b62e5 | 66 | if (c == 'C' && !building) { |
| pspatel321 | 33:6bc82b6b62e5 | 67 | rxBuff[rx_i] = 'C'; |
| pspatel321 | 33:6bc82b6b62e5 | 68 | rx_i++; |
| pspatel321 | 33:6bc82b6b62e5 | 69 | building = true; // Now building a string |
| pspatel321 | 33:6bc82b6b62e5 | 70 | return false; |
| pspatel321 | 33:6bc82b6b62e5 | 71 | } |
| pspatel321 | 33:6bc82b6b62e5 | 72 | // Keep building a new message until too big or encounter '\n' |
| pspatel321 | 33:6bc82b6b62e5 | 73 | if (building) { |
| pspatel321 | 33:6bc82b6b62e5 | 74 | rxBuff[rx_i] = c; |
| pspatel321 | 33:6bc82b6b62e5 | 75 | rx_i++; |
| pspatel321 | 33:6bc82b6b62e5 | 76 | if (c == '\n') { // Newline! process this string |
| pspatel321 | 33:6bc82b6b62e5 | 77 | process = true; |
| pspatel321 | 33:6bc82b6b62e5 | 78 | building = false; // Reset to keep capturing on next call |
| pspatel321 | 33:6bc82b6b62e5 | 79 | len = rx_i; |
| pspatel321 | 33:6bc82b6b62e5 | 80 | rx_i = 0; |
| pspatel321 | 33:6bc82b6b62e5 | 81 | } |
| pspatel321 | 33:6bc82b6b62e5 | 82 | else if (rx_i >= sizeof(rxBuff)) { // Too big, bad string |
| pspatel321 | 33:6bc82b6b62e5 | 83 | rx_i = 0; |
| pspatel321 | 33:6bc82b6b62e5 | 84 | building = false; |
| pspatel321 | 33:6bc82b6b62e5 | 85 | return false; |
| pspatel321 | 33:6bc82b6b62e5 | 86 | } |
| pspatel321 | 33:6bc82b6b62e5 | 87 | } |
| pspatel321 | 33:6bc82b6b62e5 | 88 | if (!process) return false; |
| pspatel321 | 33:6bc82b6b62e5 | 89 | |
| pspatel321 | 33:6bc82b6b62e5 | 90 | // A string is ready, process it here |
| pspatel321 | 33:6bc82b6b62e5 | 91 | if (rxBuff[0] != 'C') return false; // No start char, not valid |
| pspatel321 | 33:6bc82b6b62e5 | 92 | |
| pspatel321 | 33:6bc82b6b62e5 | 93 | // Extract the data from the header byte |
| pspatel321 | 33:6bc82b6b62e5 | 94 | bool extended = rxBuff[1] & 1; |
| pspatel321 | 33:6bc82b6b62e5 | 95 | bool rtr = rxBuff[1] & 2; |
| pspatel321 | 33:6bc82b6b62e5 | 96 | char DLC = rxBuff[1] >> 2; |
| pspatel321 | 33:6bc82b6b62e5 | 97 | int id=0; |
| pspatel321 | 33:6bc82b6b62e5 | 98 | if (DLC > 8) return false; // Bad DLC |
| pspatel321 | 33:6bc82b6b62e5 | 99 | if (!extended) { // Standard ID |
| pspatel321 | 33:6bc82b6b62e5 | 100 | if (len > 12 || len < 5) return false; // Too big/too small for standard size |
| pspatel321 | 33:6bc82b6b62e5 | 101 | if (rxBuff[3] & 0x7 != rxBuff[3]) return false; // Last byte of ID bad |
| pspatel321 | 33:6bc82b6b62e5 | 102 | if (len != 5 + DLC) return false; // Improper number of bytes |
| pspatel321 | 33:6bc82b6b62e5 | 103 | id = rxBuff[2] | (rxBuff[3] << 8); // Build the ID |
| pspatel321 | 33:6bc82b6b62e5 | 104 | for (int i = 0; i < DLC; i++) msg.data[i] = rxBuff[i+4]; // Build the data array |
| pspatel321 | 33:6bc82b6b62e5 | 105 | |
| pspatel321 | 33:6bc82b6b62e5 | 106 | } else { // Extended ID |
| pspatel321 | 33:6bc82b6b62e5 | 107 | if (len > 14 || len < 7) return false; // Too big/too small for extended size |
| pspatel321 | 33:6bc82b6b62e5 | 108 | if (rxBuff[5] & 0x1F != rxBuff[5]) return false; // Last byte of ID bad |
| pspatel321 | 33:6bc82b6b62e5 | 109 | if (len != 7 + DLC) return false; // Improper number of bytes |
| pspatel321 | 33:6bc82b6b62e5 | 110 | id = rxBuff[2] | (rxBuff[3] << 8) | (rxBuff[4] << 16) | (rxBuff[5] << 24); // Build the ID |
| pspatel321 | 33:6bc82b6b62e5 | 111 | for (int i = 0; i < DLC; i++) msg.data[i] = rxBuff[i+6]; // Build the data array |
| pspatel321 | 33:6bc82b6b62e5 | 112 | } |
| pspatel321 | 33:6bc82b6b62e5 | 113 | msg.id = id; |
| pspatel321 | 33:6bc82b6b62e5 | 114 | msg.len = DLC; |
| pspatel321 | 33:6bc82b6b62e5 | 115 | if (rtr) msg.type = CANRemote; |
| pspatel321 | 33:6bc82b6b62e5 | 116 | else msg.type = CANData; |
| pspatel321 | 33:6bc82b6b62e5 | 117 | if (extended) msg.format = CANExtended; |
| pspatel321 | 33:6bc82b6b62e5 | 118 | else msg.format = CANStandard; |
| pspatel321 | 33:6bc82b6b62e5 | 119 | return true; // Successfully parsed, passed all checks, arguement was updated |
| pspatel321 | 33:6bc82b6b62e5 | 120 | } |
