Hiroshi Yamaguchi / XBee 1.0

Files at this revision

API Documentation at this revision

Comitter:
yamaguch
Date:
Tue Nov 01 09:04:12 2011 +0000
Child:
1:58a1c083cf8d
Commit message:
0.9

Changed in this revision

Dump.cpp Show annotated file Show diff for this revision Revisions of this file
IOSample.cpp Show annotated file Show diff for this revision Revisions of this file
IOSample.h Show annotated file Show diff for this revision Revisions of this file
Receive.cpp Show annotated file Show diff for this revision Revisions of this file
Scan.cpp Show annotated file Show diff for this revision Revisions of this file
Send.cpp Show annotated file Show diff for this revision Revisions of this file
XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XBee.h Show annotated file Show diff for this revision Revisions of this file
macros.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dump.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,147 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "XBee.h"
+#include "macros.h"
+#include <ctype.h>
+
+void XBee::dump() {
+    if (received != out || (in == out && free != 0))
+        return;
+
+    switch (getFrameType(buf[INDEX(out + 2)])) {
+        case ATCommandResponse: {
+            char id, name[2], status, data[16];
+            int length = 0;
+            scan(FrameID, &id);
+            scan(ATCommand, name, sizeof(name));
+            scan(Status, &status);
+            scan(CommandData, data, sizeof(data), &length);
+            mon.printf("ATCommandResponse, Id=%d, Nm=%c%c, St=%02X, ", id & 255, name[0], name[1], status);
+            if (name[0] == 'I' && name[1] == 'S' && status == 0)
+                dumpIOSample(data, length);
+            else
+                dump(data, length);
+        }
+        break;
+
+        case ModemStatus: {
+            char status;
+            scan(Status, &status);
+            mon.printf("ModemStatus, St=%02X\n", status);
+        }
+        break;
+
+        case ZigBeeTransmitStatus: {
+            char id, address16[2], retry, delivery, discovery;
+            scan(FrameID, &id);
+            scan(Address16, address16, sizeof(address16));
+            scan(RetryCount, &retry);
+            scan(DeliveryStatus, &delivery);
+            scan(DiscoveryStatus, &discovery);
+            mon.printf("ZigBeeTransmitStatus, Id=%d, ad=%02X%02X, Rty=%d, Dlv=%02X, Dsc=%02X\n",
+                       id & 255, address16[0], address16[1], retry & 255, delivery, discovery);
+        }
+        break;
+
+        case ZigBeeReceivePacket: {
+            char address64[8], address16[2], options, data[32];
+            int length = 0;
+            scan(Address64, address64, sizeof(address64));
+            scan(Address16, address16, sizeof(address16));
+            scan(ReceiveOptions, &options);
+            scan(ReceivedData, data, sizeof(data), &length);
+            mon.printf("ZigBeeReceivePacket, AD=%02X%02X%02X%02X %02X%02X%02X%02X, ad=%02X%02X, Op=%02X, Length=%d, ",
+                       address64[0], address64[1], address64[2], address64[3], address64[4], address64[5],
+                       address64[6], address64[7], address16[0], address16[1], options, length);
+            dump(data, min(sizeof(data), length));
+        }
+        break;
+
+        case ZigBeeIODataSampleRxIndicator: {
+            char address64[8], address16[2], options, data[16];
+            int length = 0;
+            scan(Address64, address64, sizeof(address64));
+            scan(Address16, address16, sizeof(address16));
+            scan(ReceiveOptions, &options);
+            scan(ReceivedData, data, sizeof(data), &length);
+            mon.printf("ZigBeeIODataSampleRxIndicator, AD=%02X%02X%02X%02X %02X%02X%02X%02X, ad=%02X%02X, Op=%02X, ",
+                       address64[0], address64[1], address64[2], address64[3], address64[4], address64[5],
+                       address64[6], address64[7], address16[0], address16[1], options);
+            dumpIOSample(data, length);
+        }
+        break;
+
+        case RemoteCommandResponse: {
+            char address64[8], address16[2], id, name[2], status, data[16];
+            int length = 0;
+            scan(Address64, address64, sizeof(address64));
+            scan(Address16, address16, sizeof(address16));
+            scan(FrameID, &id);
+            scan(ATCommand, name, sizeof(name));
+            scan(Status, &status);
+            scan(CommandData, data, sizeof(data), &length);
+            mon.printf("RemoteCommandResponse, AD=%02X%02X%02X%02X %02X%02X%02X%02X, ad=%02X%02X, Id=%d, Nm=%c%c, St=%02X, ",
+                       address64[0], address64[1], address64[2], address64[3], address64[4], address64[5],
+                       address64[6], address64[7], address16[0], address16[1], id & 255, name[0], name[1], status);
+            if (name[0] == 'I' && name[1] == 'S' && status == 0)
+                dumpIOSample(data, length);
+            else
+                dump(data, length);
+        }
+        break;
+
+        default: {
+            char data[32];
+            int length = 0;
+            scan(RawData, data, sizeof(data), &length);
+            mon.printf("Frametype:%02X, Length=%d, Data=", buf[INDEX(out + 2)] & 255, length);
+            dump(data, min(sizeof(data), length));
+        }
+    }
+}
+
+void XBee::dumpAll() {
+    mon.printf("cur = %04X\n", cur);
+    mon.printf("in = %04X\n", in);
+    mon.printf("out = %04X\n", out);
+    mon.printf("received = %04X\n", received);
+    mon.printf("free = %d\n", free);
+    for (int i = 0; i < BUFSIZE; i += 16) {
+        mon.printf("%04X: ", i);
+        dump(buf + i, 16);
+    }
+}
+
+void XBee::dump(char* data, int length) {
+    for (int i = 0; i < length; i++) mon.printf("%02X", data[i]);
+    mon.printf(" | ");
+    for (int i = 0; i < length; i++) mon.printf("%c", isprint(data[i]) ? data[i] : '.');
+    mon.printf("\n");
+}
+
+void XBee::dumpIOSample(char* data, int length) {
+    if (length > 0) {
+        IOSample sample(data);
+        sample.print(mon);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IOSample.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,83 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "IOSample.h"
+
+IOSample::BitArray::BitArray(int mask, int values) {
+    this->mask = mask;
+    this->values = values;
+}
+
+int IOSample::BitArray::operator[](int i) {
+    return valueAt(i);
+}
+
+int IOSample::BitArray::valueAt(int i) {
+    if (mask & 1 << i) {
+        return (values >> i) & 1;
+    } else
+        return -1;
+}
+
+IOSample::IntArray::IntArray(int mask, char *value) {
+    this->mask = mask;
+    this->values = value;
+}
+
+int IOSample::IntArray::operator[](int i) {
+    return valueAt(i);
+}
+
+int IOSample::IntArray::valueAt(int i) {
+    if (mask & 1 << i) {
+        int count = 0;
+        for (int j = 0; j < i; j++) {
+            if (mask & 1 << j) count++;
+        }
+        char *p = values + 2 * count;
+        return (p[0] << 8) | p[1];
+    } else
+        return -1;
+}
+
+IOSample::IOSample(char *data)
+        : dio((data[1] << 8 | data[2]), (data[1] << 8 | data[2]) ? (data[4] << 8 | data[5]) : 0),
+        ad(data[3], (data[1] << 8 | data[2]) ? data + 6 : data + 4) {}
+
+void IOSample::print(Serial& mon) {
+    bool first = true;
+    for (int i = 0; i < 16; i++)
+        if (dio[i] != -1)
+            if (first) {
+                mon.printf("DIO%d=%d", i, dio[i]);
+                first = false;
+            } else
+                mon.printf(", DIO%d=%d", i, dio[i]);
+    for (int i = 0; i < 8; i++)
+        if (ad[i] != -1)
+            if (first) {
+                mon.printf("AD%d=%d", i, ad[i]);
+                first = false;
+            } else
+                mon.printf(", AD%d=%d", i, ad[i]);
+    mon.printf("\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IOSample.h	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,99 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef IO_SAMPLE_H
+#define IO_SAMPLE_H
+
+#include "mbed.h"
+
+/**
+ * IO Sample wrapper class for formatted output
+ */
+class IOSample {
+public:
+	/**
+	 * class for defining a bit array
+	 */
+    class BitArray {
+    public:
+	
+	    /**
+	     * creates a BitArray object
+	     */
+        BitArray(int mask, int values);
+
+		/**
+		 * operator shorthand for representing the i-th value
+		 */
+        int operator[](int i);
+
+    private:
+        int mask;
+        int values;
+
+        int valueAt(int i);
+    };
+
+	/**
+	 * class for defining an int array
+	 */
+    class IntArray {
+    public:
+	
+	    /**
+	     * creates an IntArray object
+	     */
+        IntArray(int mask, char *value);
+
+		/**
+		 * operator shorthand for representing the i-th value
+		 */
+        int operator[](int i);
+
+    private:
+        int mask;
+        char *values;
+
+        int valueAt(int i);
+    };
+
+    /**
+     * creates an IOSample object
+     *
+     * @param data pointer to the raw IOSample data
+     */
+    IOSample(char *data);
+
+    /**
+     * prints DIO/AD values
+     *
+     * @param mon Serial object for output
+     */
+    void print(Serial& mon);
+
+    //** DIO array     
+    BitArray dio;
+    //** AD array
+    IntArray ad;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Receive.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,231 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "XBee.h"
+#include "macros.h"
+#define disableIRQ()    NVIC_DisableIRQ(UARTx_IRQn[_uidx])
+#define enableIRQ()     NVIC_EnableIRQ(UARTx_IRQn[_uidx])
+
+const IRQn_Type UARTx_IRQn[] = {UART0_IRQn, UART1_IRQn, UART2_IRQn, UART3_IRQn};
+
+XBee::FrameType XBee::receive(float timeout) {
+    flush();
+    while (true) {
+        disableIRQ();
+        if (out != in || free == 0) {
+            FrameType type = getFrameType(buf[INDEX(out + 2)]);
+            if (type != None) {
+                received = out;
+                enableIRQ();
+                return type;
+            }
+            int size = SIZE(buf, out);
+            out = INDEX(out + 2 + size);
+            free += (2 + size);
+            enableIRQ();
+            continue;
+        } else if (timeout <= 0) {
+            enableIRQ();
+            return None;
+        }
+        enableIRQ();
+        wait(0.001);
+        timeout -= 0.001;
+    }
+}
+
+/*
+ * function seekFor() -
+ *
+ * searches buf[] in range between the index out and in for a specified frametype packet.
+ * if the frame is found before timeout, returns the index of the packet, otherwise -1.
+ *
+ */
+int XBee::seekFor(FrameType type, float timeout) {
+    int index = out;
+    while (true) {
+        if (index != in) {
+            if (getFrameType(buf[INDEX(index + 2)]) == type)
+                return index;
+            int size = SIZE(buf, index);
+            index = INDEX(index + 2 + size);
+            continue;
+        } else if (timeout <= 0) {
+            return -1;
+        }
+        wait(0.001);
+        timeout -= 0.001;
+    }
+}
+
+XBee::FrameType XBee::getFrameType(char c) {
+    switch (c) {
+        case 0x00:
+            return None;
+        case 0x88:
+            return ATCommandResponse;
+        case 0x8A:
+            return ModemStatus;
+        case 0x8B:
+            return ZigBeeTransmitStatus;
+        case 0x90:
+            return ZigBeeReceivePacket;
+        case 0x91:
+            return ZigBeeExplicitRxIndicator;
+        case 0x92:
+            return ZigBeeIODataSampleRxIndicator;
+        case 0x94:
+            return XBeeSensorReadIndicator;
+        case 0x95:
+            return NodeIdentificationIndicator;
+        case 0x97:
+            return RemoteCommandResponse;
+        default:
+            return Other;
+    }
+}
+
+void XBee::flush() {
+    disableIRQ();
+    if (received == out) {
+        do {
+            int size = SIZE(buf, out);
+            out = INDEX(out + 2 + size);
+            free += 2 + size;
+        } while (out != in && getFrameType(buf[INDEX(out + 2)]) == None);
+        if (debug) leds = leds & 12; //**LEDS=xx00
+    }
+    enableIRQ();
+}
+
+void XBee::rxInterruptHandler() {
+    if (debug) leds = leds ^ 4; //**LEDS=x@xx
+
+    while (readable()) {
+        char c = getc() & 255;
+        switch (state) {
+            case LENGTH1:
+                cur = in;
+                buf[cur] = c;
+                state = LENGTH2;
+                break;
+            case LENGTH2:
+                if ((buf[cur] << 8 | c) + 2 < BUFSIZE) {
+                    state = DATA;
+                    while (free < (buf[cur] << 8 | c) + 2) {
+                        int size = SIZE(buf, out);
+                        out = INDEX(out + 2 + size);
+                        free += size + 2;
+                    }
+                    buf[INDEX(cur + 1)] = c;
+                    cur = INDEX(cur + 2);
+                    if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
+                } else {
+                    state = UNKNOWN;
+                    if (debug) leds = leds & 12; //**LEDS=xx00
+                }
+                break;
+            case DATA:
+                buf[cur] = c;
+                cur = INDEX(cur + 1);
+                if (debug) leds =  (leds & 12) | (cur & 3); //**LEDS=xx@@
+                if (cur == INDEX(in + 2 + SIZE(buf, in))) state = SUMCHECK;
+                break;
+            case SUMCHECK:
+                for (int i = INDEX(in + 2); i != cur; i = INDEX(i + 1)) {
+                    c += buf[i];
+                }
+                if (c == 255) {
+                    if (debug) leds = (leds & 12) | 3; //**LEDS=xx11
+                    in = cur;
+                    free = in <= out ? out - in : BUFSIZE + out - in;
+                }
+                state = UNKNOWN;
+                break;
+            default:
+                if (c == PREAMBLE) state = LENGTH1;
+                if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
+        }
+    }
+}
+
+void XBee::rxInterruptHandler2() {
+    static bool escaped = false;
+
+    if (debug) leds = leds ^ 4; // x@xx
+
+    while (readable()) {
+        char c = getc() & 255;
+
+        if (escaped) {
+            c ^= 0x20;
+            escaped = false;
+        } else if (c == ESCAPE) {
+            escaped = true;
+            continue;
+        }
+
+        switch (state) {
+            case LENGTH1:
+                cur = in;
+                buf[cur] = c;
+                state = LENGTH2;
+                break;
+            case LENGTH2:
+                if ((buf[cur] << 8 | c) + 2 < BUFSIZE) {
+                    state = DATA;
+                    while (free < (buf[cur] << 8 | c) + 2) {
+                        int size = SIZE(buf, out);
+                        out = INDEX(out + size + 2);
+                        free += (size + 2);
+                    }
+                    buf[INDEX(cur + 1)] = c;
+                    cur = INDEX(cur + 2);
+                    if (debug) leds = (leds & 12) | 2; // xx10
+                } else {
+                    state = UNKNOWN;
+                    leds = leds & 12; //** update leds
+                }
+                break;
+            case DATA:
+                buf[cur] = c;
+                cur = INDEX(cur + 1);
+                if (debug) leds =  (leds & 12) | (cur & 3); //**LEDS=xx@@
+                if (cur == INDEX(in + 2 + SIZE(buf, in))) state = SUMCHECK;
+                break;
+            case SUMCHECK:
+                for (int i = INDEX(in + 2); i != cur; i = INDEX(i + 1)) {
+                    c += buf[i];
+                }
+                if (c == 255) {
+                    if (debug) leds = (leds & 12) | 3; //**LEDS=xx11
+                    in = cur;
+                    free = in <= out ? out - in : BUFSIZE + out - in;
+                }
+                state = UNKNOWN;
+                break;
+            default:
+                if (c == PREAMBLE) state = LENGTH1;
+                if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,136 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "XBee.h"
+#include "macros.h"
+
+bool XBee::scan(ValueType type, char *value, int maxlength, int *length) {
+    if (received != out || (in == out && free != 0))
+        return false;
+
+    return scan(out, type, value, maxlength, length);
+}
+
+bool XBee::scan(int index, ValueType type, char *value, int maxlength, int *length) {
+    int from = 0;
+    int len = 1;
+    FrameType frameType = getFrameType(buf[INDEX(index + 2)]);
+
+    if (frameType == (FrameType) None)
+        return false;
+
+    switch (type) {
+        case FrameID:
+            from = 1;
+            break;
+        case ATCommand:
+            switch (frameType) {
+                case ATCommandResponse:
+                    from = 2;
+                    break;
+                case RemoteCommandResponse:
+                    from = 12;
+                    break;
+            }
+            len = 2;
+            break;
+        case Status:
+            switch (frameType) {
+                case ATCommandResponse:
+                    from = 4;
+                    break;
+                case ModemStatus:
+                    from = 1;
+                    break;
+                case RemoteCommandResponse:
+                    from = 14;
+                    break;
+            }
+            break;
+        case CommandData:
+            switch (frameType) {
+                case ATCommandResponse:
+                    from = 5;
+                    len = SIZE(buf, index) - 5;
+                    break;
+                case RemoteCommandResponse:
+                    from = 15;
+                    len = SIZE(buf, index) - 15;
+                    break;
+            }
+            break;
+        case Address16:
+            switch (frameType) {
+                case ZigBeeTransmitStatus:
+                    from = 4;
+                    break;
+                case ZigBeeReceivePacket:
+                case ZigBeeIODataSampleRxIndicator:
+                    from = 9;
+                    break;
+                case RemoteCommandResponse:
+                    from = 10;
+                    break;
+            }
+            len = 2;
+            break;
+        case Address64:
+            switch (frameType) {
+                case ZigBeeReceivePacket:
+                case ZigBeeIODataSampleRxIndicator:
+                    from = 1;
+                    break;
+                case RemoteCommandResponse:
+                    from = 2;
+                    break;
+            }
+            len = 8;
+            break;
+        case RetryCount:
+            from = 4;
+            break;
+        case DeliveryStatus:
+            from = 5;
+            break;
+        case DiscoveryStatus:
+            from = 6;
+            break;
+        case ReceiveOptions:
+            from = 11;
+            break;
+        case ReceivedData:
+            from = 12;
+            len = SIZE(buf, index) - 12;
+            break;
+        case RawData:
+            from = 1;
+            len = SIZE(buf, index) - 1;
+            break;
+    }
+
+    if (from > 0) {
+        copy(value, INDEX(index + 2 + from), min(len, maxlength));
+        if (length) *length = len;
+        return true;
+    } else
+        return false;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Send.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,158 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "XBee.h"
+#include "macros.h"
+#include <stdarg.h>
+
+void XBee::sendCommand(char *command, char *param, int param_length, bool queue) {
+    char buf[param_length + 4];
+
+    createAtRequest(frame_id, command, param, param_length, queue, buf, sizeof(buf));
+    sendFrame(buf, param_length + 4);
+    frame_id = frame_id % 255 + 1;
+}
+
+void XBee::sendRemoteCommand(char *command, char *param, int param_length, char options) {
+    char buf[param_length + 15];
+
+    createRemoteAtRequest(frame_id, command, param, param_length, options, buf, sizeof(buf));
+    sendFrame(buf, param_length + 15);
+    frame_id = frame_id % 255 + 1;
+}
+
+void XBee::send(char *data, int length) {
+    char buf[length + 14];
+
+    createTxRequest(frame_id, data, length, buf, sizeof(buf));
+    sendFrame(buf, length + 14);
+    frame_id = frame_id % 255 + 1;
+}
+
+bool XBee::sendConfirm(char *data, int length) {
+    send(data, length);
+
+    int index = seekFor(ZigBeeTransmitStatus, 3.0);
+    if (index != -1) {
+        char delivery;
+        scan(index, DeliveryStatus, &delivery);
+        buf[INDEX(index + 2)] = 0x00;
+        return delivery == 0;
+    }
+    return false;
+}
+
+int XBee::printf(const char *format, ...) {
+    va_list argv;
+    va_start(argv, format);
+    char buf[256];
+    int length = vsnprintf(buf, sizeof buf, format, argv);
+    return length > 0 && sendConfirm(buf, length) ? length : -1;
+}
+
+void XBee::send(char c) {
+    while (!writeable()) wait_us(100);
+    putc(c);
+}
+
+void XBee::send2(char c) {
+    switch (c) {
+        case 0x7E:
+        case 0x7D:
+        case 0x11:
+        case 0x13:
+            send(ESCAPE);
+            send(c ^ 0x20);
+            break;
+        default:
+            send(c);
+    }
+}
+
+void XBee::sendFrame(char* frame, int length) {
+    char checksum = 255;
+    if (debug) leds = leds | 8; //**LEDS=1xxx
+
+    send(PREAMBLE);
+
+    if (apiMode == 2) {
+        send2((length >> 8) & 255);
+        send2(length & 255);
+        for (int i = 0; i < length; i++) {
+            send2(frame[i]);
+            checksum -= frame[i];
+        }
+        send2(checksum);
+    } else {
+        send((length >> 8) & 255);
+        send(length & 255);
+        for (int i = 0; i < length; i++) {
+            send(frame[i]);
+            checksum -= frame[i];
+        }
+        send(checksum);
+    }
+    if (debug) leds = leds & 7; //**LEDS=0xxx
+}
+
+int XBee::createTxRequest(char frame_id, char* data, int data_length, char* buf, int buf_size) {
+    if (data_length + 14 > buf_size) return -1;
+
+    buf[0] = 0x10; // frame type
+    buf[1] = frame_id;
+    for (int i = 0; i < 8; i++) buf[i + 2] = destination64[i];
+    buf[10] = destination16[0]; // 16 bit dest address
+    buf[11] = destination16[1]; // 16 bit dest address
+    buf[12] = 0;
+    buf[13] = 0;
+    for (int i = 0; i < data_length; i++) buf[i + 14] = data[i];
+
+    return data_length + 14;
+}
+
+int XBee::createAtRequest(char frame_id, char* command, char* param, int param_length, bool queue, char* buf, int buf_size) {
+    if (param_length + 4 > buf_size) return -1;
+
+    buf[0] = queue ? 0x09 : 0x08; // frame type
+    buf[1] = frame_id;
+    buf[2] = command[0];
+    buf[3] = command[1];
+    for (int i = 0; i < param_length; i++) buf[i + 4] = param[i];
+
+    return param_length + 4;
+}
+
+int XBee::createRemoteAtRequest(char frame_id, char* command, char* param, int param_length, char options, char* buf, int buf_size) {
+    if (param_length + 4 > buf_size) return -1;
+
+    buf[0] = 0x17; // frame type
+    buf[1] = frame_id;
+    memcpy(buf + 2, destination64, 8);
+    buf[10] = destination16[0];
+    buf[11] = destination16[1];
+    buf[12] = options;
+    buf[13] = command[0];
+    buf[14] = command[1];
+    for (int i = 0; i < param_length; i++) buf[i + 15] = param[i];
+
+    return param_length + 15;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee.cpp	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,140 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "XBee.h"
+#include "macros.h"
+
+XBee::XBee(Serial& ser, int apiMode, bool debug)
+        : Serial(ser), mon(USBTX, USBRX), leds(LED1, LED2, LED3, LED4), apiMode(apiMode),
+        state(UNKNOWN), in(0), out(0), received(-1), free(BUFSIZE), frame_id(1), debug(debug) {
+    memset(buf, 0, BUFSIZE);
+    attach(this, apiMode == 1 ? &XBee::rxInterruptHandler : &XBee::rxInterruptHandler2, Serial::RxIrq);
+}
+
+XBee::XBee(Serial& ser, Serial& mon, int apiMode, bool debug)
+        : Serial(ser), mon(mon), leds(LED1, LED2, LED3, LED4), apiMode(apiMode),
+        state(UNKNOWN), in(0), out(0), received(-1), free(BUFSIZE), frame_id(1), debug(debug) {
+    memset(buf, 0, BUFSIZE);
+    attach(this, apiMode == 1 ? &XBee::rxInterruptHandler : &XBee::rxInterruptHandler2, Serial::RxIrq);
+}
+
+bool XBee::init(float timeout) {
+    while (readable()) getc();
+    while (timeout > 0 && getFirmwareVersion() == -1) {
+        timeout -= 1;
+        wait(0.8);
+    }
+
+    switch (getFirmwareVersion() & 0xFF00) {
+        case 0x2100:
+            setDestination(0xFFFFULL, 0xFFFE);
+            return true;
+
+        case 0x2300:
+        case 0x2900:
+            setDestination(0x00ULL);
+            return true;
+
+        default:
+            return false;
+    }
+}
+
+void XBee::setDestination(unsigned long long address64, unsigned short address16) {
+    char addr64[] = {BYTE(address64, 7), BYTE(address64, 6), BYTE(address64, 5), BYTE(address64, 4),
+                     BYTE(address64, 3), BYTE(address64, 2), BYTE(address64, 1), BYTE(address64, 0)
+                    };
+    char addr16[] = {BYTE(address16, 1), BYTE(address16, 0)};
+    setDestination(addr64, addr16);
+}
+
+void XBee::setDestination(char address64[]) {
+    char address16[] = {0xFF, 0xFE};
+    setDestination(address64, address16);
+}
+
+void XBee::setDestination(char address64[], char address16[]) {
+    for (int i = 0; i < sizeof(destination64); i++)
+        destination64[i] = address64[i];
+    destination16[0] = address16[0];
+    destination16[1] = address16[1];
+}
+
+XBee::operator bool() {
+    return getFirmwareVersion() != -1;
+}
+
+char XBee::getFrameID() {
+    return frame_id;
+}
+
+void *XBee::executeCommand(char *command, char* param, int param_length) {
+    static char data[21];
+    bool succeeded = false;
+    char id = getFrameID();
+
+    sendCommand(command, param, param_length);
+    int index = seekFor(XBee::ATCommandResponse, 0.1);
+    if (index != -1) {
+        char id2, status;
+        if (scan(index, FrameID, &id2) && id == id2 && scan(index, Status, &status) && status == 0) {
+            memset(data, 0, sizeof(data));
+            if ((command[0] == 'N' && command[1] == 'I') ||
+                (command[0] == 'I' && command[1] == 'S')) {
+                if (scan(index, CommandData, data, sizeof(data)))
+                    succeeded = true;
+            } else {
+                char buf2[8];
+                int length;
+                if (scan(index, CommandData, buf2, sizeof(buf2), &length) && length <= sizeof(buf2)) {
+                    for (int i = 0; i < length; i++)
+                        data[i] = buf2[length - i - 1];
+                    succeeded = true;
+                }
+            }
+        }
+        buf[INDEX(index + 2)] = 0x00;
+    }
+
+    return succeeded ? data : 0;
+}
+
+int XBee::getFirmwareVersion() {
+    static int firmwareVersion = -1;
+
+    if (firmwareVersion == -1) {
+        unsigned short *data = (unsigned short *) executeCommand("VR");
+        if (data) firmwareVersion = *data; //data[0] << 8 | data[1];
+    }
+    return firmwareVersion;
+}
+
+void XBee::copy(char *toBuf, int fromIndex, int length) {
+    int length1 = min(BUFSIZE - fromIndex, length);
+    memcpy(toBuf, &buf[fromIndex], length1);
+    if (length1 < length)
+        memcpy(toBuf + length1, &buf[0], length - length1);
+}
+
+void XBee::setDebug(bool debug) {
+    this->debug = debug;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBee.h	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,272 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef XBEE_H
+#define XBEE_H
+
+#include "mbed.h"
+#include "IOSample.h"
+
+const int BUFSIZE = 512;
+const char ESCAPE = 0x7D;
+const char PREAMBLE = 0x7E;
+
+/**
+ * class for XBee module API mode interface
+ */
+class XBee : public Serial {
+public:
+    /***/
+    enum FrameType {
+        None = 0,
+        ATCommandResponse,
+        ModemStatus,
+        ZigBeeTransmitStatus,
+        ZigBeeReceivePacket,
+        ZigBeeExplicitRxIndicator,
+        ZigBeeIODataSampleRxIndicator,
+        XBeeSensorReadIndicator,
+        NodeIdentificationIndicator,
+        RemoteCommandResponse,
+        Other
+    };
+    /***/
+    enum ValueType {
+        FrameID,
+        ATCommand,
+        Status,
+        CommandData,
+        Address16,
+        Address64,
+        RetryCount,
+        DeliveryStatus,
+        DiscoveryStatus,
+        ReceiveOptions,
+        ReceivedData,
+        RawData
+    };
+
+    /**
+     * creates an XBee interface object.
+     *
+     * @param ser Serial object through which XBee module is connected to mbed
+     * @param apiMode API mode either 1 or 2 (use escape; default)
+     * @param debug display debugging (I/O state) information through LEDs
+     */
+    XBee(Serial& ser, int apiMode = 2, bool debug = false);
+
+    /**
+     * creates an XBee interface object.
+     *
+     * @param ser Serial object through which XBee module is connected to mbed
+     * @param mon alternate Serial object for monitoring (use serial ports other than USBTX/USBRX)
+     * @param apiMode API mode either 1 or 2 (use escape; default)
+     * @param debug display debugging (I/O state) information through LEDs
+     */
+    XBee(Serial& ser, Serial& mon, int apiMode = 2, bool debug = false);
+
+    /**
+     * initializes XBee module.
+     *
+     * issues VR command to test XBee modem connection
+     *
+     * @returns true if initialization succeeded, false otherwise
+     */
+    bool init(float timeout = 15.0);
+
+    /**
+     * sets destination addresses.
+     *
+     * @param address64 64-bit destination address in unsigned long long
+     * @param address16 16-bit destination address in unsigned short
+     */
+    void setDestination(unsigned long long address64, unsigned short address16 = 0xFFFE);
+
+    /**
+      * sets destination addresses.
+      *
+      * @param address64 64-bit destination address in bytes (big endian)
+      * @param address16 16-bit destination address in bytes
+      */
+    void setDestination(char address64[], char address16[]);
+
+    /**
+      * sets 64-bit destination address.
+      *
+      * this function is used when 16-bit address is unknown
+      * @param address64 64-bit destination address in bytes (big endian)
+      */
+    void setDestination(char address64[]);
+
+    /**
+     * sends an AT command.
+     *
+     * @param command AT command char string
+     * @param param parameter to the AT command (pointer to byte array)
+     * @param param_length parameter length in bytes
+     * @param queue true if command paramter is to be queued
+     */
+    void sendCommand(char* command, char* param = 0, int param_length = 0, bool queue = false);
+
+    /**
+     * sends a remote AT command.
+     *
+     * sends an AT command to the XBee(s) at the destination address
+     *
+     * @param command AT command char string
+     * @param param parameter to the AT command (pointer to byte array)
+     * @param param_length parameter length in bytes
+     * @param options remote command options
+     */
+    void sendRemoteCommand(char* command, char* param = 0, int param_length = 0, char options = 0x02);
+
+
+    /**
+     * executes an AT command then gets its result.
+     *
+     * @param command AT command char string
+     * @param param parameter to the AT command (pointer to byte array)
+     * @param param_length parameter length in bytes
+     *
+     * @returns pointer to the command result, if the result is a number (char, short, long, long long),
+     *          the address to the number will be returned; otherwise the address to the byte array
+     *          containing the command response will be returned.
+     */
+    void *executeCommand(char *command, char* param = 0, int laram_length = 0);
+
+    /**
+     * sends data to the XBee(s) at the destination address.
+     *
+     * @param data address to the data (byte array)
+     * @param length data length in bytes
+     */
+    void send(char *data, int length);
+
+    /**
+     * sends data and confirm the transmit status.
+     *
+     * @param data address to the data (byte array)
+     * @param length data length in bytes
+     *
+     * @returns true if sent successfully, false otherwise (either timeout or send error occurred)
+     */
+    bool sendConfirm(char *data, int length);
+
+    /**
+     * sends data to the destination using printf format.
+     *
+     * @param format printf format string, followed by corresponding arguments
+     *
+     * @returns the number of charancters sent, or negative if error occurred
+     */
+    int printf(const char *format, ...);
+
+    /**
+     * receives data frame from the XBee module.
+     *
+     * @param timeout seconds bofer time out
+     *
+     * @returns FrameType of the received frame data
+     */
+    FrameType receive(float timeout = 3.0);
+
+    /**
+     * scan received data according to the specified format.
+     *
+     * @param type ValueType of the data to be scanned
+     * @param value pointer to the byte array to store the scanned value
+     * @param maxlength max size of the value in bytes
+     * @param length pointer to an int to receive the actual data length
+     *
+     * @param true if scan succeeded, false otherwise
+     */
+    bool scan(ValueType type, char *value, int maxlength = 1, int *length = 0);
+
+    /**
+     * gets the XBee firmware version.
+     *
+     * @returns XBee firmwre version in int (unsigned short value)
+     */
+    int getFirmwareVersion();
+
+    /**
+     * gets the current frame ID.
+     *
+     * @returns frame ID number being used in the next send request
+     */
+    char getFrameID();
+
+    /**
+    * sets to run in debug mode.
+    *
+    * @param debug true to display debugging information
+    */
+    void setDebug(bool debug);
+
+    /**
+    * displays received data in dump format.
+    */
+    void dump();
+
+    /**
+     * displays the internal data fields and receive buffer in dump format.
+     */
+    void dumpAll();
+
+    /**
+     * operator overloading for testing XBee modem connection status.
+     *
+     * @returns false if XBee modem connection has an error
+     */
+    operator bool();
+
+private:
+    Serial mon;
+    BusOut leds;
+    int apiMode;
+    volatile enum {UNKNOWN, LENGTH1, LENGTH2, DATA, SUMCHECK} state;
+    volatile int cur, in, out, received, free;
+    char frame_id;
+    char destination64[8];
+    char destination16[2];
+    char buf[BUFSIZE];
+    bool debug;
+
+    void send(char c);
+    void send2(char c);
+    void sendFrame(char* frame, int length);
+    int createTxRequest(char frame_id, char* data, int data_length, char* buf, int buf_size);
+    int createAtRequest(char frame_id, char* command, char* param, int param_length, bool queue, char* buf, int buf_size);
+    int createRemoteAtRequest(char frame_id, char* command, char* param, int param_length, char options, char* buf, int buf_size);
+    int seekFor(FrameType type, float timeout);
+    FrameType getFrameType(char c);
+    bool scan(int i, ValueType type, char *value, int maxlength = 1, int *length = 0);
+    void flush();
+    void rxInterruptHandler();
+    void rxInterruptHandler2();
+
+    void dump(char* data, int length);
+    void dumpIOSample(char *data, int length);
+    void copy(char *toBuf, int fromIndex, int length);
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/macros.h	Tue Nov 01 09:04:12 2011 +0000
@@ -0,0 +1,26 @@
+/*
+Copyright (c) 2011, Senio Networks, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#define min(x, y)       ((x) < (y) ? (x) : (y))
+#define BYTE(a, n)      ((char *) &(a))[n]
+#define INDEX(n)        ((n) % BUFSIZE)
+#define SIZE(b, i)      (b[i] << 8 | b[INDEX(i + 1)])
\ No newline at end of file