Kyle Lemons
/
XBeeLib
XBee.hpp@0:86ff0a55c978, 2010-11-30 (annotated)
- Committer:
- etherealflaim
- Date:
- Tue Nov 30 21:28:18 2010 +0000
- Revision:
- 0:86ff0a55c978
- Child:
- 1:eefaa22e4b2c
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
etherealflaim | 0:86ff0a55c978 | 1 | #ifndef XBEE_HPP |
etherealflaim | 0:86ff0a55c978 | 2 | #define XBEE_HPP |
etherealflaim | 0:86ff0a55c978 | 3 | |
etherealflaim | 0:86ff0a55c978 | 4 | #include <queue> |
etherealflaim | 0:86ff0a55c978 | 5 | #include <cctype> |
etherealflaim | 0:86ff0a55c978 | 6 | #include <string> |
etherealflaim | 0:86ff0a55c978 | 7 | #include <vector> |
etherealflaim | 0:86ff0a55c978 | 8 | #include <cstring> |
etherealflaim | 0:86ff0a55c978 | 9 | |
etherealflaim | 0:86ff0a55c978 | 10 | #include "mbed.h" |
etherealflaim | 0:86ff0a55c978 | 11 | #include "handler.hpp" |
etherealflaim | 0:86ff0a55c978 | 12 | |
etherealflaim | 0:86ff0a55c978 | 13 | #define PRINT(c) ((isprint(c))?(c):('.')) |
etherealflaim | 0:86ff0a55c978 | 14 | |
etherealflaim | 0:86ff0a55c978 | 15 | /** This class encapsulates a simplistic XBee packet. |
etherealflaim | 0:86ff0a55c978 | 16 | * 1. The packet is 0x01 delimited. |
etherealflaim | 0:86ff0a55c978 | 17 | * 2. The packet has a source and destination, which are (nominally) 8-byte identifiers |
etherealflaim | 0:86ff0a55c978 | 18 | */ |
etherealflaim | 0:86ff0a55c978 | 19 | class XBeePacket |
etherealflaim | 0:86ff0a55c978 | 20 | { |
etherealflaim | 0:86ff0a55c978 | 21 | private: |
etherealflaim | 0:86ff0a55c978 | 22 | string m_data; |
etherealflaim | 0:86ff0a55c978 | 23 | int m_data_len; |
etherealflaim | 0:86ff0a55c978 | 24 | string m_source; |
etherealflaim | 0:86ff0a55c978 | 25 | string m_dest; |
etherealflaim | 0:86ff0a55c978 | 26 | bool m_packed; |
etherealflaim | 0:86ff0a55c978 | 27 | |
etherealflaim | 0:86ff0a55c978 | 28 | public: |
etherealflaim | 0:86ff0a55c978 | 29 | /// Construct an empty (invalid) XBeePacket |
etherealflaim | 0:86ff0a55c978 | 30 | inline XBeePacket() |
etherealflaim | 0:86ff0a55c978 | 31 | : m_data(""), m_data_len(0), m_source("_INVALID"), m_dest("********"), m_packed(false) |
etherealflaim | 0:86ff0a55c978 | 32 | { |
etherealflaim | 0:86ff0a55c978 | 33 | } |
etherealflaim | 0:86ff0a55c978 | 34 | |
etherealflaim | 0:86ff0a55c978 | 35 | /// Create an XBeePacket with the given data |
etherealflaim | 0:86ff0a55c978 | 36 | inline XBeePacket(const string data) |
etherealflaim | 0:86ff0a55c978 | 37 | : m_data(data), m_data_len(data.length()), m_source("_INVALID"), m_dest("********"), m_packed(false) |
etherealflaim | 0:86ff0a55c978 | 38 | { |
etherealflaim | 0:86ff0a55c978 | 39 | } |
etherealflaim | 0:86ff0a55c978 | 40 | |
etherealflaim | 0:86ff0a55c978 | 41 | /// Create an XBeePacket with the given source and data |
etherealflaim | 0:86ff0a55c978 | 42 | inline XBeePacket(const string src, const string data) |
etherealflaim | 0:86ff0a55c978 | 43 | : m_data(data), m_data_len(data.length()), m_source(src), m_dest("********"), m_packed(false) |
etherealflaim | 0:86ff0a55c978 | 44 | { |
etherealflaim | 0:86ff0a55c978 | 45 | } |
etherealflaim | 0:86ff0a55c978 | 46 | |
etherealflaim | 0:86ff0a55c978 | 47 | /// Create an XBeePacket with the given source, destination, and data |
etherealflaim | 0:86ff0a55c978 | 48 | inline XBeePacket(const string src, const string dst, const string data) |
etherealflaim | 0:86ff0a55c978 | 49 | : m_data(data), m_data_len(data.length()), m_source(src), m_dest(dst), m_packed(false) |
etherealflaim | 0:86ff0a55c978 | 50 | { |
etherealflaim | 0:86ff0a55c978 | 51 | } |
etherealflaim | 0:86ff0a55c978 | 52 | |
etherealflaim | 0:86ff0a55c978 | 53 | /// Append the given data to the packet |
etherealflaim | 0:86ff0a55c978 | 54 | inline void append(const string data) |
etherealflaim | 0:86ff0a55c978 | 55 | { |
etherealflaim | 0:86ff0a55c978 | 56 | m_data += data; |
etherealflaim | 0:86ff0a55c978 | 57 | m_data_len += data.length(); |
etherealflaim | 0:86ff0a55c978 | 58 | } |
etherealflaim | 0:86ff0a55c978 | 59 | |
etherealflaim | 0:86ff0a55c978 | 60 | /// Get the packet source (if set or unpacked) |
etherealflaim | 0:86ff0a55c978 | 61 | inline string source() { return m_source; } |
etherealflaim | 0:86ff0a55c978 | 62 | |
etherealflaim | 0:86ff0a55c978 | 63 | /// Set the packet source (before packing) |
etherealflaim | 0:86ff0a55c978 | 64 | inline void source(string src) { m_source = src; } |
etherealflaim | 0:86ff0a55c978 | 65 | |
etherealflaim | 0:86ff0a55c978 | 66 | /// Get the packet destination (if set or unpacked) |
etherealflaim | 0:86ff0a55c978 | 67 | inline string dest() { return m_dest; } |
etherealflaim | 0:86ff0a55c978 | 68 | |
etherealflaim | 0:86ff0a55c978 | 69 | /// Set the packet destination (before packing) |
etherealflaim | 0:86ff0a55c978 | 70 | inline void dest(string dst) { m_dest = dst; } |
etherealflaim | 0:86ff0a55c978 | 71 | |
etherealflaim | 0:86ff0a55c978 | 72 | /// Get the packet data (if set or unpacked) |
etherealflaim | 0:86ff0a55c978 | 73 | inline string data() { return m_data; } |
etherealflaim | 0:86ff0a55c978 | 74 | |
etherealflaim | 0:86ff0a55c978 | 75 | /// Set the packet data (before packing) |
etherealflaim | 0:86ff0a55c978 | 76 | inline void data(string dat) { m_data = dat; } |
etherealflaim | 0:86ff0a55c978 | 77 | |
etherealflaim | 0:86ff0a55c978 | 78 | /// Get a vector of the 0x01-delimited pieces of the data (after unpacking) |
etherealflaim | 0:86ff0a55c978 | 79 | inline vector<string> split_data() |
etherealflaim | 0:86ff0a55c978 | 80 | { |
etherealflaim | 0:86ff0a55c978 | 81 | vector<string> pieces; |
etherealflaim | 0:86ff0a55c978 | 82 | int begin = 0; |
etherealflaim | 0:86ff0a55c978 | 83 | int end = 0; |
etherealflaim | 0:86ff0a55c978 | 84 | while (end < m_data_len && (end = m_data.find(0x01, begin)) != string::npos) |
etherealflaim | 0:86ff0a55c978 | 85 | { |
etherealflaim | 0:86ff0a55c978 | 86 | pieces.push_back( m_data.substr(begin, end-begin) ); |
etherealflaim | 0:86ff0a55c978 | 87 | begin = end+1; |
etherealflaim | 0:86ff0a55c978 | 88 | } |
etherealflaim | 0:86ff0a55c978 | 89 | pieces.push_back( m_data.substr(begin) ); |
etherealflaim | 0:86ff0a55c978 | 90 | return pieces; |
etherealflaim | 0:86ff0a55c978 | 91 | } |
etherealflaim | 0:86ff0a55c978 | 92 | |
etherealflaim | 0:86ff0a55c978 | 93 | /// Clear the packet (zero the length, and reset the source and destination) |
etherealflaim | 0:86ff0a55c978 | 94 | inline void clear() |
etherealflaim | 0:86ff0a55c978 | 95 | { |
etherealflaim | 0:86ff0a55c978 | 96 | m_data = ""; |
etherealflaim | 0:86ff0a55c978 | 97 | m_data_len = 0; |
etherealflaim | 0:86ff0a55c978 | 98 | m_source = "_CLEARED"; |
etherealflaim | 0:86ff0a55c978 | 99 | m_dest = "********"; |
etherealflaim | 0:86ff0a55c978 | 100 | } |
etherealflaim | 0:86ff0a55c978 | 101 | |
etherealflaim | 0:86ff0a55c978 | 102 | /** Pack the packet with header, etc. |
etherealflaim | 0:86ff0a55c978 | 103 | * This function can be called separately to include the headers in, e.g., a dump() |
etherealflaim | 0:86ff0a55c978 | 104 | */ |
etherealflaim | 0:86ff0a55c978 | 105 | inline void pack() |
etherealflaim | 0:86ff0a55c978 | 106 | { |
etherealflaim | 0:86ff0a55c978 | 107 | string header = "iHvZ\001" + m_source + "\001" + m_dest + "\001"; |
etherealflaim | 0:86ff0a55c978 | 108 | m_data = header + m_data; |
etherealflaim | 0:86ff0a55c978 | 109 | m_data_len += header.length(); |
etherealflaim | 0:86ff0a55c978 | 110 | m_packed = true; |
etherealflaim | 0:86ff0a55c978 | 111 | } |
etherealflaim | 0:86ff0a55c978 | 112 | |
etherealflaim | 0:86ff0a55c978 | 113 | /** Unpack the packet header |
etherealflaim | 0:86ff0a55c978 | 114 | * This function should be called with received packets to extract the header |
etherealflaim | 0:86ff0a55c978 | 115 | */ |
etherealflaim | 0:86ff0a55c978 | 116 | inline bool unpack() |
etherealflaim | 0:86ff0a55c978 | 117 | { |
etherealflaim | 0:86ff0a55c978 | 118 | if (m_data.substr(0, 5) != "iHvZ\001") return false; |
etherealflaim | 0:86ff0a55c978 | 119 | int source_idx = m_data.find(0x01, 0) + 1; |
etherealflaim | 0:86ff0a55c978 | 120 | int dest_idx = m_data.find(0x01, source_idx) + 1; |
etherealflaim | 0:86ff0a55c978 | 121 | int data_idx = m_data.find(0x01, dest_idx) + 1; |
etherealflaim | 0:86ff0a55c978 | 122 | if (source_idx == string::npos || |
etherealflaim | 0:86ff0a55c978 | 123 | dest_idx == string::npos || |
etherealflaim | 0:86ff0a55c978 | 124 | data_idx == string::npos) return false; |
etherealflaim | 0:86ff0a55c978 | 125 | m_source = m_data.substr(source_idx, dest_idx - source_idx - 1); |
etherealflaim | 0:86ff0a55c978 | 126 | m_dest = m_data.substr(dest_idx, data_idx - dest_idx - 1); |
etherealflaim | 0:86ff0a55c978 | 127 | m_data = m_data.substr(data_idx); |
etherealflaim | 0:86ff0a55c978 | 128 | m_data_len = m_data.length(); |
etherealflaim | 0:86ff0a55c978 | 129 | return true; |
etherealflaim | 0:86ff0a55c978 | 130 | } |
etherealflaim | 0:86ff0a55c978 | 131 | |
etherealflaim | 0:86ff0a55c978 | 132 | /// Send the packet on the given Serial port (automatically packs if unpacked) |
etherealflaim | 0:86ff0a55c978 | 133 | inline void send(Serial &out) |
etherealflaim | 0:86ff0a55c978 | 134 | { |
etherealflaim | 0:86ff0a55c978 | 135 | if (!m_packed) pack(); |
etherealflaim | 0:86ff0a55c978 | 136 | |
etherealflaim | 0:86ff0a55c978 | 137 | out.puts(m_data.c_str()); |
etherealflaim | 0:86ff0a55c978 | 138 | out.putc('\n'); |
etherealflaim | 0:86ff0a55c978 | 139 | } |
etherealflaim | 0:86ff0a55c978 | 140 | |
etherealflaim | 0:86ff0a55c978 | 141 | /// Dump a text version (call before packing) of the packet to the serial port |
etherealflaim | 0:86ff0a55c978 | 142 | inline void dump(Serial &out) |
etherealflaim | 0:86ff0a55c978 | 143 | { |
etherealflaim | 0:86ff0a55c978 | 144 | out.printf("[%s] -> [%s] : [", m_source.c_str(), m_dest.c_str()); |
etherealflaim | 0:86ff0a55c978 | 145 | for (int i = 0; i < m_data_len; ++i) |
etherealflaim | 0:86ff0a55c978 | 146 | { |
etherealflaim | 0:86ff0a55c978 | 147 | char c = m_dest[i]; |
etherealflaim | 0:86ff0a55c978 | 148 | if (isprint(c)) |
etherealflaim | 0:86ff0a55c978 | 149 | out.putc(c); |
etherealflaim | 0:86ff0a55c978 | 150 | else |
etherealflaim | 0:86ff0a55c978 | 151 | out.printf("\\x%02X", c); |
etherealflaim | 0:86ff0a55c978 | 152 | } |
etherealflaim | 0:86ff0a55c978 | 153 | out.printf("] %d bytes\r\n", m_data_len); |
etherealflaim | 0:86ff0a55c978 | 154 | } |
etherealflaim | 0:86ff0a55c978 | 155 | |
etherealflaim | 0:86ff0a55c978 | 156 | /// If it is a broadcast packet (destionation ********) return true |
etherealflaim | 0:86ff0a55c978 | 157 | inline bool is_broadcast() { return m_dest == "********"; } |
etherealflaim | 0:86ff0a55c978 | 158 | }; |
etherealflaim | 0:86ff0a55c978 | 159 | |
etherealflaim | 0:86ff0a55c978 | 160 | /** Manage the pins connected to an XBee chip in transparent (broadcast) mode. |
etherealflaim | 0:86ff0a55c978 | 161 | * This is an interface for communicating XBeePackets across the XBee chip in transparent mode. |
etherealflaim | 0:86ff0a55c978 | 162 | * Receipt of a new packet can be either polled or notified via the attach() functions. |
etherealflaim | 0:86ff0a55c978 | 163 | */ |
etherealflaim | 0:86ff0a55c978 | 164 | class XBee |
etherealflaim | 0:86ff0a55c978 | 165 | { |
etherealflaim | 0:86ff0a55c978 | 166 | private: |
etherealflaim | 0:86ff0a55c978 | 167 | /* Unit ID */ |
etherealflaim | 0:86ff0a55c978 | 168 | string m_uid; |
etherealflaim | 0:86ff0a55c978 | 169 | |
etherealflaim | 0:86ff0a55c978 | 170 | /* Pins */ |
etherealflaim | 0:86ff0a55c978 | 171 | PinName m_xout, m_xin, m_xrstn, m_xassoc, m_xon; |
etherealflaim | 0:86ff0a55c978 | 172 | |
etherealflaim | 0:86ff0a55c978 | 173 | /* Pin handlers */ |
etherealflaim | 0:86ff0a55c978 | 174 | DigitalOut m_resetn; |
etherealflaim | 0:86ff0a55c978 | 175 | DigitalIn m_ison; |
etherealflaim | 0:86ff0a55c978 | 176 | Serial m_comm; |
etherealflaim | 0:86ff0a55c978 | 177 | |
etherealflaim | 0:86ff0a55c978 | 178 | /* USB logging */ |
etherealflaim | 0:86ff0a55c978 | 179 | Serial m_usb; |
etherealflaim | 0:86ff0a55c978 | 180 | |
etherealflaim | 0:86ff0a55c978 | 181 | /* Tickers and Timers */ |
etherealflaim | 0:86ff0a55c978 | 182 | Timeout m_timeout; |
etherealflaim | 0:86ff0a55c978 | 183 | |
etherealflaim | 0:86ff0a55c978 | 184 | /* Packet incoming queue */ |
etherealflaim | 0:86ff0a55c978 | 185 | queue<XBeePacket> m_queue; |
etherealflaim | 0:86ff0a55c978 | 186 | handler<void> *m_read_handler; |
etherealflaim | 0:86ff0a55c978 | 187 | |
etherealflaim | 0:86ff0a55c978 | 188 | public: |
etherealflaim | 0:86ff0a55c978 | 189 | /** Create an XBee chip connect |
etherealflaim | 0:86ff0a55c978 | 190 | * uid - The unit ID of the XBee chip (used in all outgoing XBeePackets) |
etherealflaim | 0:86ff0a55c978 | 191 | * xbee_din - The MBED pin connected to the XBEE DIN pin |
etherealflaim | 0:86ff0a55c978 | 192 | * xbee_dout - The MBED pin connected to the XBEE DOUT pin |
etherealflaim | 0:86ff0a55c978 | 193 | * xbee_rst - The MBED pin connected to the XBEE nRST pin |
etherealflaim | 0:86ff0a55c978 | 194 | * xbee_on - The MBED pin connected to the XBEE ON/nSLEEP pin |
etherealflaim | 0:86ff0a55c978 | 195 | */ |
etherealflaim | 0:86ff0a55c978 | 196 | inline XBee(string uid, PinName xbee_din, PinName xbee_dout, PinName xbee_rst, PinName xbee_on) |
etherealflaim | 0:86ff0a55c978 | 197 | : m_uid(uid), m_xout(xbee_din), m_xin(xbee_dout), m_xrstn(xbee_rst), m_xon(xbee_on), |
etherealflaim | 0:86ff0a55c978 | 198 | m_resetn(xbee_rst), m_ison(xbee_on), m_comm(xbee_din, xbee_dout), |
etherealflaim | 0:86ff0a55c978 | 199 | m_usb(USBTX, USBRX), m_read_handler(NULL) |
etherealflaim | 0:86ff0a55c978 | 200 | { |
etherealflaim | 0:86ff0a55c978 | 201 | m_usb.printf("Resetting XBee...\r\n"); |
etherealflaim | 0:86ff0a55c978 | 202 | // Reset the XBEE module |
etherealflaim | 0:86ff0a55c978 | 203 | m_resetn = 0; |
etherealflaim | 0:86ff0a55c978 | 204 | wait(.1); |
etherealflaim | 0:86ff0a55c978 | 205 | m_resetn = 1; |
etherealflaim | 0:86ff0a55c978 | 206 | wait(1); |
etherealflaim | 0:86ff0a55c978 | 207 | |
etherealflaim | 0:86ff0a55c978 | 208 | // Set up serial communications (9600 baud by default) |
etherealflaim | 0:86ff0a55c978 | 209 | m_comm.baud(9600); |
etherealflaim | 0:86ff0a55c978 | 210 | |
etherealflaim | 0:86ff0a55c978 | 211 | // Set up a handler for serial communications |
etherealflaim | 0:86ff0a55c978 | 212 | m_comm.attach(this, &XBee::rxirq); |
etherealflaim | 0:86ff0a55c978 | 213 | |
etherealflaim | 0:86ff0a55c978 | 214 | // Check sleep status |
etherealflaim | 0:86ff0a55c978 | 215 | m_usb.printf("XBee is %s\r\n", (m_ison)?"ON":"SLEEP"); |
etherealflaim | 0:86ff0a55c978 | 216 | |
etherealflaim | 0:86ff0a55c978 | 217 | setup(); |
etherealflaim | 0:86ff0a55c978 | 218 | } |
etherealflaim | 0:86ff0a55c978 | 219 | |
etherealflaim | 0:86ff0a55c978 | 220 | inline void broadcast(string data) |
etherealflaim | 0:86ff0a55c978 | 221 | { |
etherealflaim | 0:86ff0a55c978 | 222 | XBeePacket pkt(data); |
etherealflaim | 0:86ff0a55c978 | 223 | pkt.source(m_uid); |
etherealflaim | 0:86ff0a55c978 | 224 | pkt.send(m_comm); |
etherealflaim | 0:86ff0a55c978 | 225 | } |
etherealflaim | 0:86ff0a55c978 | 226 | |
etherealflaim | 0:86ff0a55c978 | 227 | inline void send(string to, string data) |
etherealflaim | 0:86ff0a55c978 | 228 | { |
etherealflaim | 0:86ff0a55c978 | 229 | XBeePacket pkt(data); |
etherealflaim | 0:86ff0a55c978 | 230 | pkt.source(m_uid); |
etherealflaim | 0:86ff0a55c978 | 231 | pkt.dest(to); |
etherealflaim | 0:86ff0a55c978 | 232 | pkt.send(m_comm); |
etherealflaim | 0:86ff0a55c978 | 233 | } |
etherealflaim | 0:86ff0a55c978 | 234 | |
etherealflaim | 0:86ff0a55c978 | 235 | private: |
etherealflaim | 0:86ff0a55c978 | 236 | |
etherealflaim | 0:86ff0a55c978 | 237 | inline void setup() |
etherealflaim | 0:86ff0a55c978 | 238 | { |
etherealflaim | 0:86ff0a55c978 | 239 | #if _XBEE_DEBUG > 0 |
etherealflaim | 0:86ff0a55c978 | 240 | m_usb.printf("Setting up XBee...\r\n"); |
etherealflaim | 0:86ff0a55c978 | 241 | #endif |
etherealflaim | 0:86ff0a55c978 | 242 | |
etherealflaim | 0:86ff0a55c978 | 243 | // Turns out, we can only really use this in broadcast mode. |
etherealflaim | 0:86ff0a55c978 | 244 | //commandMode(); |
etherealflaim | 0:86ff0a55c978 | 245 | //command("VR"); |
etherealflaim | 0:86ff0a55c978 | 246 | //command("AP", 1); |
etherealflaim | 0:86ff0a55c978 | 247 | //command("CN"); |
etherealflaim | 0:86ff0a55c978 | 248 | //wait(1); |
etherealflaim | 0:86ff0a55c978 | 249 | //m_usb.printf("Setup Complete.\r\n"); |
etherealflaim | 0:86ff0a55c978 | 250 | |
etherealflaim | 0:86ff0a55c978 | 251 | m_timeout.attach(this, &XBee::tickirq, .1); |
etherealflaim | 0:86ff0a55c978 | 252 | } |
etherealflaim | 0:86ff0a55c978 | 253 | |
etherealflaim | 0:86ff0a55c978 | 254 | /** Enter command mode. Send command("CN") to exit command mode. */ |
etherealflaim | 0:86ff0a55c978 | 255 | inline void commandMode() |
etherealflaim | 0:86ff0a55c978 | 256 | { |
etherealflaim | 0:86ff0a55c978 | 257 | wait(1.1); |
etherealflaim | 0:86ff0a55c978 | 258 | m_comm.printf("+++"); |
etherealflaim | 0:86ff0a55c978 | 259 | wait(1.1); |
etherealflaim | 0:86ff0a55c978 | 260 | } |
etherealflaim | 0:86ff0a55c978 | 261 | |
etherealflaim | 0:86ff0a55c978 | 262 | inline void command(const char *cmd) |
etherealflaim | 0:86ff0a55c978 | 263 | { |
etherealflaim | 0:86ff0a55c978 | 264 | m_comm.printf("AT%s\r", cmd); |
etherealflaim | 0:86ff0a55c978 | 265 | wait(.001); |
etherealflaim | 0:86ff0a55c978 | 266 | } |
etherealflaim | 0:86ff0a55c978 | 267 | |
etherealflaim | 0:86ff0a55c978 | 268 | inline void command(const char *cmd, int arg) |
etherealflaim | 0:86ff0a55c978 | 269 | { |
etherealflaim | 0:86ff0a55c978 | 270 | m_comm.printf("AT%s%X\r", cmd, arg); |
etherealflaim | 0:86ff0a55c978 | 271 | wait(.001); |
etherealflaim | 0:86ff0a55c978 | 272 | } |
etherealflaim | 0:86ff0a55c978 | 273 | |
etherealflaim | 0:86ff0a55c978 | 274 | inline void rxirq() |
etherealflaim | 0:86ff0a55c978 | 275 | { |
etherealflaim | 0:86ff0a55c978 | 276 | static XBeePacket nextPacket; |
etherealflaim | 0:86ff0a55c978 | 277 | static char buffer[256]; |
etherealflaim | 0:86ff0a55c978 | 278 | char *p = buffer; |
etherealflaim | 0:86ff0a55c978 | 279 | bool finished = false; |
etherealflaim | 0:86ff0a55c978 | 280 | |
etherealflaim | 0:86ff0a55c978 | 281 | // Receive all characters in buffer |
etherealflaim | 0:86ff0a55c978 | 282 | do |
etherealflaim | 0:86ff0a55c978 | 283 | { |
etherealflaim | 0:86ff0a55c978 | 284 | // Receive character |
etherealflaim | 0:86ff0a55c978 | 285 | *p = m_comm.getc(); |
etherealflaim | 0:86ff0a55c978 | 286 | |
etherealflaim | 0:86ff0a55c978 | 287 | // Check if it's end-of-packet |
etherealflaim | 0:86ff0a55c978 | 288 | if (*p == '\n') { |
etherealflaim | 0:86ff0a55c978 | 289 | finished = true; |
etherealflaim | 0:86ff0a55c978 | 290 | break; |
etherealflaim | 0:86ff0a55c978 | 291 | } |
etherealflaim | 0:86ff0a55c978 | 292 | |
etherealflaim | 0:86ff0a55c978 | 293 | // Move on to the next character |
etherealflaim | 0:86ff0a55c978 | 294 | ++p; |
etherealflaim | 0:86ff0a55c978 | 295 | } while (m_comm.readable() && p-buffer < 255); |
etherealflaim | 0:86ff0a55c978 | 296 | |
etherealflaim | 0:86ff0a55c978 | 297 | // Null terminate |
etherealflaim | 0:86ff0a55c978 | 298 | *p = '\0'; |
etherealflaim | 0:86ff0a55c978 | 299 | |
etherealflaim | 0:86ff0a55c978 | 300 | // Append the characters to the packet |
etherealflaim | 0:86ff0a55c978 | 301 | nextPacket.append(buffer); |
etherealflaim | 0:86ff0a55c978 | 302 | |
etherealflaim | 0:86ff0a55c978 | 303 | if (finished) |
etherealflaim | 0:86ff0a55c978 | 304 | { |
etherealflaim | 0:86ff0a55c978 | 305 | // Unpack the headers |
etherealflaim | 0:86ff0a55c978 | 306 | if (!nextPacket.unpack()) { |
etherealflaim | 0:86ff0a55c978 | 307 | m_usb.printf("Received garbled packet; dropping."); |
etherealflaim | 0:86ff0a55c978 | 308 | return; |
etherealflaim | 0:86ff0a55c978 | 309 | } |
etherealflaim | 0:86ff0a55c978 | 310 | |
etherealflaim | 0:86ff0a55c978 | 311 | if (nextPacket.is_broadcast() || nextPacket.dest() == m_uid) |
etherealflaim | 0:86ff0a55c978 | 312 | { |
etherealflaim | 0:86ff0a55c978 | 313 | #if _XBEE_DEBUG > 0 |
etherealflaim | 0:86ff0a55c978 | 314 | // Print the packet |
etherealflaim | 0:86ff0a55c978 | 315 | m_usb.printf("Received: "); |
etherealflaim | 0:86ff0a55c978 | 316 | nextPacket.dump(m_usb); |
etherealflaim | 0:86ff0a55c978 | 317 | #endif |
etherealflaim | 0:86ff0a55c978 | 318 | |
etherealflaim | 0:86ff0a55c978 | 319 | // Add it to the queue |
etherealflaim | 0:86ff0a55c978 | 320 | m_queue.push(nextPacket); |
etherealflaim | 0:86ff0a55c978 | 321 | } |
etherealflaim | 0:86ff0a55c978 | 322 | else |
etherealflaim | 0:86ff0a55c978 | 323 | { |
etherealflaim | 0:86ff0a55c978 | 324 | #if _XBEE_DEBUG > 0 |
etherealflaim | 0:86ff0a55c978 | 325 | m_usb.printf("Dropping: "); |
etherealflaim | 0:86ff0a55c978 | 326 | nextPacket.dump(m_usb); |
etherealflaim | 0:86ff0a55c978 | 327 | #endif |
etherealflaim | 0:86ff0a55c978 | 328 | } |
etherealflaim | 0:86ff0a55c978 | 329 | |
etherealflaim | 0:86ff0a55c978 | 330 | // Clear the packet |
etherealflaim | 0:86ff0a55c978 | 331 | nextPacket = XBeePacket(); |
etherealflaim | 0:86ff0a55c978 | 332 | } |
etherealflaim | 0:86ff0a55c978 | 333 | } |
etherealflaim | 0:86ff0a55c978 | 334 | |
etherealflaim | 0:86ff0a55c978 | 335 | inline void tickirq() |
etherealflaim | 0:86ff0a55c978 | 336 | { |
etherealflaim | 0:86ff0a55c978 | 337 | //m_usb.printf("Scanning...\r\n"); |
etherealflaim | 0:86ff0a55c978 | 338 | //XBeePacket pkt = XBeePacket::Command("ND"); |
etherealflaim | 0:86ff0a55c978 | 339 | //XBeePacket pkt = XBeePacket::Broadcast("Test"); |
etherealflaim | 0:86ff0a55c978 | 340 | //pkt.dump(m_usb); |
etherealflaim | 0:86ff0a55c978 | 341 | //pkt.send(m_comm); |
etherealflaim | 0:86ff0a55c978 | 342 | //m_comm.printf("TEST\r"); |
etherealflaim | 0:86ff0a55c978 | 343 | //XBeePacket pkt("TestPacket"); |
etherealflaim | 0:86ff0a55c978 | 344 | //m_usb.printf("Sending: "); |
etherealflaim | 0:86ff0a55c978 | 345 | //pkt.dump(m_usb); |
etherealflaim | 0:86ff0a55c978 | 346 | //pkt.send(m_comm); |
etherealflaim | 0:86ff0a55c978 | 347 | |
etherealflaim | 0:86ff0a55c978 | 348 | while (!m_queue.empty() && m_read_handler) |
etherealflaim | 0:86ff0a55c978 | 349 | (*m_read_handler)(); |
etherealflaim | 0:86ff0a55c978 | 350 | |
etherealflaim | 0:86ff0a55c978 | 351 | // Set the timeout again (we aren't going to use a ticker just in case the read handlers take awhile) |
etherealflaim | 0:86ff0a55c978 | 352 | m_timeout.attach(this, &XBee::tickirq, 0.1); |
etherealflaim | 0:86ff0a55c978 | 353 | } |
etherealflaim | 0:86ff0a55c978 | 354 | |
etherealflaim | 0:86ff0a55c978 | 355 | |
etherealflaim | 0:86ff0a55c978 | 356 | public: |
etherealflaim | 0:86ff0a55c978 | 357 | |
etherealflaim | 0:86ff0a55c978 | 358 | /// Return whether or not another XBeePacket is ready |
etherealflaim | 0:86ff0a55c978 | 359 | inline bool readable() |
etherealflaim | 0:86ff0a55c978 | 360 | { |
etherealflaim | 0:86ff0a55c978 | 361 | return !m_queue.empty(); |
etherealflaim | 0:86ff0a55c978 | 362 | } |
etherealflaim | 0:86ff0a55c978 | 363 | |
etherealflaim | 0:86ff0a55c978 | 364 | /// Get the next XBeePacket in line (make sure it's readable()!) |
etherealflaim | 0:86ff0a55c978 | 365 | inline XBeePacket read() |
etherealflaim | 0:86ff0a55c978 | 366 | { |
etherealflaim | 0:86ff0a55c978 | 367 | XBeePacket pkt = m_queue.front(); |
etherealflaim | 0:86ff0a55c978 | 368 | m_queue.pop(); |
etherealflaim | 0:86ff0a55c978 | 369 | return pkt; |
etherealflaim | 0:86ff0a55c978 | 370 | } |
etherealflaim | 0:86ff0a55c978 | 371 | |
etherealflaim | 0:86ff0a55c978 | 372 | /// Set the Unit ID |
etherealflaim | 0:86ff0a55c978 | 373 | inline string uid() { return m_uid; } |
etherealflaim | 0:86ff0a55c978 | 374 | |
etherealflaim | 0:86ff0a55c978 | 375 | /// Get the Unit ID |
etherealflaim | 0:86ff0a55c978 | 376 | inline void uid(string uid) { m_uid = uid; } |
etherealflaim | 0:86ff0a55c978 | 377 | |
etherealflaim | 0:86ff0a55c978 | 378 | /// Attach a member function to be called on all TCP packets |
etherealflaim | 0:86ff0a55c978 | 379 | template <class T> |
etherealflaim | 0:86ff0a55c978 | 380 | inline void attach(T *inst, void (T::*func)()) |
etherealflaim | 0:86ff0a55c978 | 381 | { |
etherealflaim | 0:86ff0a55c978 | 382 | delete m_read_handler; |
etherealflaim | 0:86ff0a55c978 | 383 | m_read_handler = new member_handler<T,void>(inst, func); |
etherealflaim | 0:86ff0a55c978 | 384 | } |
etherealflaim | 0:86ff0a55c978 | 385 | |
etherealflaim | 0:86ff0a55c978 | 386 | /// Attach a non-member function to be called on all TCP packets |
etherealflaim | 0:86ff0a55c978 | 387 | inline void attach(void (*func)()) |
etherealflaim | 0:86ff0a55c978 | 388 | { |
etherealflaim | 0:86ff0a55c978 | 389 | delete m_read_handler; |
etherealflaim | 0:86ff0a55c978 | 390 | m_read_handler = new function_handler<void>(func); |
etherealflaim | 0:86ff0a55c978 | 391 | } |
etherealflaim | 0:86ff0a55c978 | 392 | |
etherealflaim | 0:86ff0a55c978 | 393 | /// Detach the handler |
etherealflaim | 0:86ff0a55c978 | 394 | inline void detach() |
etherealflaim | 0:86ff0a55c978 | 395 | { |
etherealflaim | 0:86ff0a55c978 | 396 | delete m_read_handler; |
etherealflaim | 0:86ff0a55c978 | 397 | m_read_handler = NULL; |
etherealflaim | 0:86ff0a55c978 | 398 | } |
etherealflaim | 0:86ff0a55c978 | 399 | }; |
etherealflaim | 0:86ff0a55c978 | 400 | |
etherealflaim | 0:86ff0a55c978 | 401 | #endif /* XBEE_HPP */ |