Hiroshi Yamaguchi / XBee 1.0
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Receive.cpp Source File

Receive.cpp

00001 /*
00002 Copyright (c) 2011, Senio Networks, Inc.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 #include "XBee.h"
00024 
00025 #define disableIRQ()    NVIC_DisableIRQ(UARTx_IRQn[_uidx])
00026 #define enableIRQ()     NVIC_EnableIRQ(UARTx_IRQn[_uidx])
00027 
00028 const IRQn_Type UARTx_IRQn[] = {UART0_IRQn, UART1_IRQn, UART2_IRQn, UART3_IRQn};
00029 
00030 XBee::FrameType XBee::receive(float timeout) {
00031     flush();
00032     while (true) {
00033         disableIRQ();
00034         if (out != in || free == 0) {
00035             FrameType type = getFrameType(buf[INDEX(out + 2)]);
00036             if (type != None) {
00037                 received = out;
00038                 enableIRQ();
00039                 return type;
00040             }
00041             int size = SIZE(buf, out);
00042             out = INDEX(out + 2 + size);
00043             free += (2 + size);
00044             enableIRQ();
00045             continue;
00046         } else if (timeout <= 0) {
00047             enableIRQ();
00048             return None;
00049         }
00050         enableIRQ();
00051         wait(0.001);
00052         timeout -= 0.001;
00053     }
00054 }
00055 
00056 /*
00057  * function seekFor() -
00058  *
00059  * searches buf[] in range between the index out and in for a specified frametype packet.
00060  * if the frame is found before timeout, returns the index of the packet, otherwise -1.
00061  *
00062  */
00063 int XBee::seekFor(FrameType type, float timeout) {
00064     int index = out;
00065     while (true) {
00066         if (index != in) {
00067             if (getFrameType(buf[INDEX(index + 2)]) == type)
00068                 return index;
00069             int size = SIZE(buf, index);
00070             index = INDEX(index + 2 + size);
00071             continue;
00072         } else if (timeout <= 0) {
00073             return -1;
00074         }
00075         wait(0.001);
00076         timeout -= 0.001;
00077     }
00078 }
00079 
00080 XBee::FrameType XBee::getFrameType(char c) {
00081     switch (c) {
00082         case 0x00:
00083             return None;
00084         case 0x88:
00085             return ATCommandResponse;
00086         case 0x8A:
00087             return ModemStatus;
00088         case 0x8B:
00089             return ZigBeeTransmitStatus;
00090         case 0x90:
00091             return ZigBeeReceivePacket;
00092         case 0x91:
00093             return ZigBeeExplicitRxIndicator;
00094         case 0x92:
00095             return ZigBeeIODataSampleRxIndicator;
00096         case 0x94:
00097             return XBeeSensorReadIndicator;
00098         case 0x95:
00099             return NodeIdentificationIndicator;
00100         case 0x97:
00101             return RemoteCommandResponse;
00102         default:
00103             return Other;
00104     }
00105 }
00106 
00107 void XBee::flush() {
00108     disableIRQ();
00109     if (received == out) {
00110         do {
00111             int size = SIZE(buf, out);
00112             out = INDEX(out + 2 + size);
00113             free += 2 + size;
00114         } while (out != in && getFrameType(buf[INDEX(out + 2)]) == None);
00115         if (debug) leds = leds & 12; //**LEDS=xx00
00116     }
00117     enableIRQ();
00118 }
00119 
00120 void XBee::rxInterruptHandler() {
00121     if (debug) leds = leds ^ 4; //**LEDS=x@xx
00122 
00123     while (readable()) {
00124         char c = getc() & 255;
00125         switch (state) {
00126             case LENGTH1:
00127                 cur = in;
00128                 buf[cur] = c;
00129                 state = LENGTH2;
00130                 break;
00131             case LENGTH2:
00132                 if ((buf[cur] << 8 | c) + 2 < BUFSIZE) {
00133                     state = DATA;
00134                     while (free < (buf[cur] << 8 | c) + 2) {
00135                         int size = SIZE(buf, out);
00136                         out = INDEX(out + 2 + size);
00137                         free += size + 2;
00138                     }
00139                     buf[INDEX(cur + 1)] = c;
00140                     cur = INDEX(cur + 2);
00141                     if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
00142                 } else {
00143                     state = UNKNOWN;
00144                     if (debug) leds = leds & 12; //**LEDS=xx00
00145                 }
00146                 break;
00147             case DATA:
00148                 buf[cur] = c;
00149                 cur = INDEX(cur + 1);
00150                 if (debug) leds =  (leds & 12) | (cur & 3); //**LEDS=xx@@
00151                 if (cur == INDEX(in + 2 + SIZE(buf, in))) state = SUMCHECK;
00152                 break;
00153             case SUMCHECK:
00154                 for (int i = INDEX(in + 2); i != cur; i = INDEX(i + 1)) {
00155                     c += buf[i];
00156                 }
00157                 if (c == 255) {
00158                     if (debug) leds = (leds & 12) | 3; //**LEDS=xx11
00159                     in = cur;
00160                     free = in <= out ? out - in : BUFSIZE + out - in;
00161                 }
00162                 state = UNKNOWN;
00163                 break;
00164             default:
00165                 if (c == PREAMBLE) state = LENGTH1;
00166                 if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
00167         }
00168     }
00169 }
00170 
00171 void XBee::rxInterruptHandler2() {
00172     static bool escaped = false;
00173 
00174     if (debug) leds = leds ^ 4; // x@xx
00175 
00176     while (readable()) {
00177         char c = getc() & 255;
00178 
00179         if (escaped) {
00180             c ^= 0x20;
00181             escaped = false;
00182         } else if (c == ESCAPE) {
00183             escaped = true;
00184             continue;
00185         }
00186 
00187         switch (state) {
00188             case LENGTH1:
00189                 cur = in;
00190                 buf[cur] = c;
00191                 state = LENGTH2;
00192                 break;
00193             case LENGTH2:
00194                 if ((buf[cur] << 8 | c) + 2 < BUFSIZE) {
00195                     state = DATA;
00196                     while (free < (buf[cur] << 8 | c) + 2) {
00197                         int size = SIZE(buf, out);
00198                         out = INDEX(out + size + 2);
00199                         free += (size + 2);
00200                     }
00201                     buf[INDEX(cur + 1)] = c;
00202                     cur = INDEX(cur + 2);
00203                     if (debug) leds = (leds & 12) | 2; // xx10
00204                 } else {
00205                     state = UNKNOWN;
00206                     leds = leds & 12; //** update leds
00207                 }
00208                 break;
00209             case DATA:
00210                 buf[cur] = c;
00211                 cur = INDEX(cur + 1);
00212                 if (debug) leds =  (leds & 12) | (cur & 3); //**LEDS=xx@@
00213                 if (cur == INDEX(in + 2 + SIZE(buf, in))) state = SUMCHECK;
00214                 break;
00215             case SUMCHECK:
00216                 for (int i = INDEX(in + 2); i != cur; i = INDEX(i + 1)) {
00217                     c += buf[i];
00218                 }
00219                 if (c == 255) {
00220                     if (debug) leds = (leds & 12) | 3; //**LEDS=xx11
00221                     in = cur;
00222                     free = in <= out ? out - in : BUFSIZE + out - in;
00223                 }
00224                 state = UNKNOWN;
00225                 break;
00226             default:
00227                 if (c == PREAMBLE) state = LENGTH1;
00228                 if (debug) leds = (leds & 12) | 1; //**LEDS=xx01
00229         }
00230     }
00231 }