XBee API mode library
Diff: Receive.cpp
- Revision:
- 0:0232a97b3883
- Child:
- 3:8453df14bd30
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Receive.cpp Thu Jul 26 10:33:11 2012 +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" + +#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