Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / projects / libwireless / xbee.c @ 1825

History | View | Annotate | Download (50.3 KB)

1
/**
2
 * Copyright (c) 2009 Colony Project
3
 *
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25

    
26
/**
27
 * @file xbee.c
28
 * @brief XBee Interface
29
 *
30
 * Implementation of low level communication with the XBee in API mode.
31
 *
32
 * @author Colony Project, CMU Robotics Club
33
 **/
34
// TODO Why are we including lights? Because lights are awesome. No, really, figure this out.
35
#include <lights.h>
36

    
37
#include <string.h>
38
#include <avr/io.h>
39
#include <avr/interrupt.h>
40
#include <time.h>
41
#include <wl_defs.h>
42
#include <wireless.h>
43
#include <eeprom.h>
44
#include "xbee.h"
45

    
46

    
47
/* Internal Function Prototypes */
48

    
49
/* I/O Functions */
50
static int8_t xbee_send_string(uint8_t* c);
51
int8_t xbee_putc(uint8_t c);
52
int16_t xbee_getc(void);
53
int8_t xbee_getc_nb(uint8_t *c);
54

    
55
/* Command Mode Functions */
56
static int8_t xbee_enter_command_mode(void);
57
static int8_t xbee_exit_command_mode(void);
58
static int8_t xbee_enter_api_mode(void);
59
static int8_t xbee_enter_api_mode2(void);
60
static int8_t xbee_exit_api_mode(void);
61
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len);
62
static int8_t xbee_wait_for_ok(void);
63

    
64
/* API Mode Functions */
65
//TODO: does this exist?  static int8_t xbee_handle_packet(uint8_t* packet, uint16_t len);
66
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t status, uint8_t len);
67
static void xbee_handle_status(uint8_t status);
68
static int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len);
69
static uint8_t xbee_compute_checksum(uint8_t* packet, uint16_t len);
70
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len);
71
int8_t xbee_send_read_at_command(uint8_t* command);
72
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len);
73

    
74
/* Buffer Manipulation Functions */
75
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte);
76
uint8_t xbee_basic_buf_get(uint8_t *ptr);
77
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte);
78
//uint8_t xbee_other_buf_get(uint8_t *ptr);
79

    
80
/* private functions */
81
int8_t check_last_receive(uint16_t source,uint8_t framenum);
82
inline uint8_t getStatus(uint8_t mask);
83
inline void setStatus(uint8_t mask,uint8_t value);
84

    
85
/*Global Variables*/
86

    
87
// array for basic packets
88
uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE];
89

    
90
// beginning of first packet in basic buffer
91
uint8_t basic_buf_first = (PACKET_BUFFER_SIZE-1);
92

    
93
// byte after end of last packet in basic buffer (only access < basic_buf_last)
94
// aka, the first free byte in basic buffer
95
uint8_t basic_buf_last = 0;
96

    
97
// array for other packets
98
uint8_t xbee_other_buf[PACKET_BUFFER_SIZE];
99

    
100
// beginning of first packet in other buffer
101
uint8_t other_buf_first = (PACKET_BUFFER_SIZE-1);
102

    
103
// byte after end of last packet in other buffer (only access < other_buf_last)
104
// aka, the first free byte in other buffer
105
uint8_t other_buf_last = 0;
106

    
107

    
108
// last few packet sources and frame nums
109
#define NUM_LAST_PACKETS 10
110
struct {
111
  uint16_t source;
112
  uint8_t framenum;
113
} lastPacket[NUM_LAST_PACKETS];
114

    
115

    
116
// xbee status
117
#define XBEE_API_OFF 0x00
118
#define XBEE_API_ON 0x10
119
#define XBEE_API_ESCAPE 0x20
120
#define XBEE_API_MASK 0x30
121
#define XBEE_COMMAND_WAIT 0x80
122
#define XBEE_COMMAND_RESPONSE 0xC0
123
#define XBEE_COMMAND_NONE 0x00
124
#define XBEE_COMMAND_MASK 0xC0
125
#define XBEE_NOT_INITD 0xF0
126
#define LAST_PACKET_MASK 0x0F
127
uint8_t xbee_status = XBEE_NOT_INITD; //This is the super-byte
128

    
129
// xbee command response (for PAN, channel, address, etc)
130
static uint8_t xbee_command[8];
131

    
132
// external ack handler (wireless_send.c)
133
extern void ackhandle(uint8_t num,uint8_t val);
134

    
135

    
136
// define escaped bytes in API mode 2
137
#define ESCAPE_MARKER 0x7D
138
#define ESCAPE_XOR 0x20
139
#define ESCAPE1 0x7E
140
#define ESCAPE2 0x7D
141
#define ESCAPE3 0x11
142
#define ESCAPE4 0x13
143

    
144

    
145
/**@addtogroup xbee
146
 * @{ **/
147

    
148
/*Function Implementations*/
149

    
150
/**
151
 * Interrupt for the robot. Adds bytes received from the xbee
152
 * to the buffer.
153
 **/
154
 
155
 
156
#ifndef FIREFLY
157
#define PORT UDR1
158
#define FLAG (UCSR1A & (1<<RXC1))
159
ISR(USART1_RX_vect) {
160
#else
161
#define PORT UDR0
162
#define FLAG (UCSR0A & (1<<RXC0))
163
SIGNAL(SIG_USART0_RECV) {
164
#endif
165
  // start of frame
166
  uint8_t apitype = PORT; // get frame start byte
167
  uint16_t i=0;
168
  uint16_t len=0;
169
  
170
  // check that we're in API mode
171
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
172
    // not in API mode
173
    WL_DEBUG_PRINT_P("|api off branch");
174
    
175
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT) {
176
      // get rest of command and put in basic buf
177
      xbee_basic_buf[i] = apitype;
178
      if (xbee_basic_buf[i++] != '\r') {
179
        while(i < PACKET_BUFFER_SIZE) {
180
          if (FLAG) {
181
            xbee_basic_buf[i] = PORT;
182
            if (xbee_basic_buf[i] == '\r')
183
              break;
184
            i++;
185
          }
186
        }
187
      }
188
      WL_DEBUG_PRINT_P("got packet, len=");
189
      WL_DEBUG_PRINT_INT(i);
190
      WL_DEBUG_PRINT_P("str=");
191
      WL_DEBUG_PRINT((char*)xbee_basic_buf);
192
      // signal handler that command response is done
193
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
194
    }
195
    WL_DEBUG_PRINT_P("return\r\n");
196
    return;
197
  }  
198
  //WL_DEBUG_PRINT_P("|api on branch");
199
    
200
  // get length and type
201
  while(i<3) {
202
    if (FLAG) { //if there is a byte to read //checks for escape characters in API mode 2. This repeats below (should be a function)
203
      if (i==0) {
204
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE             && apitype == ESCAPE_MARKER) //apitype is used here as dummy var
205
          apitype = PORT ^ ESCAPE_XOR;
206
        else {
207
          apitype = PORT;
208
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
209
              && apitype == ESCAPE_MARKER)
210
            continue; // get escaped character
211
        }
212
        len |= apitype<<8; // get len hi byte
213
      } else if (i==1) {
214
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
215
            && apitype == ESCAPE_MARKER)
216
          apitype = PORT ^ ESCAPE_XOR;
217
        else {
218
          apitype = PORT;
219
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
220
              && apitype == ESCAPE_MARKER)
221
            continue; // get escaped character
222
        }
223
        len |= apitype; // get len lo byte
224
      } else if (i==2) {
225
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
226
            && apitype == ESCAPE_MARKER)
227
          apitype = PORT ^ ESCAPE_XOR;
228
        else {
229
          apitype = PORT;
230
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
231
              && apitype == ESCAPE_MARKER)
232
            continue; // get escaped character
233
        }
234
        // get api type
235
        break;
236
      }
237
      i++;
238
    }
239
  }
240
  
241
  // do something based on the type
242
  i=1;
243
  switch(apitype) {
244
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
245
    // AT command response
246
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
247
    {        WL_DEBUG_PRINT_P("ERROR: SOMETHING STRANGE HAS OCCURRED. THE ROBOT WILL SELF DESTRUCT IN 5 MINUTES!\r\n");//We better get rid of this sometime...
248
      return;} // we're currently processing a command, so drop the incoming one  ***** TODO: we need to read the whole length of the frame to do this right ****
249
    uint16_t atcommand=0;
250
    uint8_t ptr=basic_buf_last;
251
    uint8_t status=0;
252
    while(i<len) {
253
      if (FLAG) {  //more escape characters
254
        if (i==1) {
255
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
256
              && apitype == ESCAPE_MARKER)
257
            apitype = PORT ^ ESCAPE_XOR; // get frame id, and ignore
258
          else {
259
            apitype = PORT;
260
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
261
                && apitype == ESCAPE_MARKER)
262
              continue; // get escaped character
263
          }
264
          apitype = PORT; // get frame id, but ignore it
265
        } else if (i==2) {
266
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
267
              && apitype == ESCAPE_MARKER)
268
            apitype = PORT ^ ESCAPE_XOR;
269
          else {
270
            apitype = PORT;
271
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
272
                && apitype == ESCAPE_MARKER)
273
              continue; // get escaped character
274
          }
275
          atcommand |= apitype<<8; // get command char1
276
        } else if (i==3) {
277
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
278
              && apitype == ESCAPE_MARKER)
279
            apitype = PORT ^ ESCAPE_XOR;
280
          else {
281
            apitype = PORT;
282
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
283
                && apitype == ESCAPE_MARKER)
284
              continue; // get escaped character
285
          }
286
          atcommand |= apitype; // get command char2
287
        } else if (i==4) {
288
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
289
              && apitype == ESCAPE_MARKER)
290
            apitype = PORT ^ ESCAPE_XOR;
291
          else {
292
            apitype = PORT;
293
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
294
                && apitype == ESCAPE_MARKER)
295
              continue; // get escaped character
296
          }
297
          status = apitype; // get status
298
        } else {
299
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
300
              && apitype == ESCAPE_MARKER)
301
            apitype = PORT ^ ESCAPE_XOR;
302
          else {
303
            apitype = PORT;
304
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
305
                && apitype == ESCAPE_MARKER)
306
              continue; // get escaped character
307
          }
308
          // put the command response on the basic buf temporarily
309
          if (xbee_basic_buf_add(&ptr,apitype) != 0)
310
            break;
311
        }
312
        i++;
313
      }
314
    }
315
    // handle AT command    
316
    WL_DEBUG_PRINT_P("|XBEE_FRAME_AT_COMMAND_RESPONSE");
317
    WL_DEBUG_PRINT_P("|i=");
318
    WL_DEBUG_PRINT_INT(i);
319
    WL_DEBUG_PRINT_P("|len=");
320
    WL_DEBUG_PRINT_INT(len);
321
    WL_DEBUG_PRINT_P("|status:");
322
    WL_DEBUG_PRINT_INT(status);
323
    WL_DEBUG_PRINT_P("|atcommand:");
324
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand>>8));
325
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand&0xFF));
326
    WL_DEBUG_PRINT_P("|first=");
327
    WL_DEBUG_PRINT_INT(basic_buf_first);
328
    WL_DEBUG_PRINT_P("|last=");
329
    WL_DEBUG_PRINT_INT(basic_buf_last);
330
    WL_DEBUG_PRINT_P("|buf=");
331
    uint8_t ptr2 = basic_buf_last;
332
    for(uint8_t j=0;j<(len-5);j++)
333
      WL_DEBUG_PRINT_HEX(xbee_basic_buf_get(&ptr2));
334
    WL_DEBUG_PRINT_P("|\r\n");
335
        //end of DEBUG_PRINT
336
    xbee_handle_at_command_response(atcommand,status,len-5);
337
    break; }
338
  case XBEE_FRAME_STATUS: {
339
    // modem status
340
    while(1) {
341
      if (FLAG) {
342
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
343
            && apitype == ESCAPE_MARKER) {
344
          apitype = PORT ^ ESCAPE_XOR;
345
          break;
346
        } else {
347
          apitype = PORT;
348
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
349
              && apitype == ESCAPE_MARKER)
350
            continue; // get escaped character
351
          break;
352
        }
353
      }
354
    }
355
    xbee_handle_status(apitype); // handle the modem status
356
    break; }
357
  case XBEE_FRAME_TX_STATUS: {
358
    // TX status
359
    uint8_t frame_id = 0;
360
    while(i<3) {
361
      if (FLAG) {
362
        if (i==1) {
363
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
364
              && apitype == ESCAPE_MARKER)
365
            apitype = PORT ^ ESCAPE_XOR;
366
          else {
367
            apitype = PORT;
368
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
369
                && apitype == ESCAPE_MARKER)
370
              continue; // get escaped character
371
          }
372
          frame_id = apitype;
373
        } else {
374
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
375
              && apitype == ESCAPE_MARKER)
376
            apitype = PORT ^ ESCAPE_XOR;
377
          else {
378
            apitype = PORT;
379
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
380
                && apitype == ESCAPE_MARKER)
381
              continue; // get escaped character
382
          }
383
          ackhandle(frame_id,apitype); // handle the status (stored in apitype)
384
          break;
385
        }
386
        i++;
387
      }
388
    }
389
    WL_DEBUG_PRINT_P("|XBEE_FRAME_TX_STATUS framenum:");
390
    WL_DEBUG_PRINT_HEX(frame_id);
391
    WL_DEBUG_PRINT_P(",status=");
392
    WL_DEBUG_PRINT_HEX(apitype);
393
    break; }
394
  case XBEE_FRAME_RX_64: {
395
    // receive a packet with 64bit address
396
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_64");
397
    break; } // TODO: implement this (even if we don't use it)
398
  case XBEE_FRAME_RX_16: {
399
    WL_DEBUG_PRINT_P("|B_last=");
400
    WL_DEBUG_PRINT_INT(basic_buf_last);
401
    // receive a packet with 16bit address
402
    uint16_t source = 0;
403
    uint8_t framenum = 0;
404
    uint8_t group = 0;
405
    uint8_t ptr=basic_buf_last;
406
    while(i<len) {
407
      if (FLAG) {
408
        WL_DEBUG_PRINT_P("|*i=");
409
        WL_DEBUG_PRINT_INT(i);
410
        WL_DEBUG_PRINT_P("|ptr=");
411
        WL_DEBUG_PRINT_INT(ptr);
412
        if (i==1) {
413
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
414
              && apitype == ESCAPE_MARKER)
415
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
416
          else {
417
            apitype = PORT;
418
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
419
                && apitype == ESCAPE_MARKER)
420
              continue; // get escaped character
421
          }
422
          source |= apitype<<8; // get source hi byte
423
        } else if (i==2) {
424
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
425
              && apitype == ESCAPE_MARKER)
426
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
427
          else {
428
            apitype = PORT;
429
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
430
                && apitype == ESCAPE_MARKER)
431
              continue; // get escaped character
432
          }
433
          source |= apitype; // get source lo byte
434
        } else if (i==3) {
435
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
436
              && apitype == ESCAPE_MARKER)
437
            apitype = PORT ^ ESCAPE_XOR; // get RSSI, and ignore
438
          else {
439
            apitype = PORT;
440
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
441
                && apitype == ESCAPE_MARKER)
442
              continue; // get escaped character
443
          }
444
        } else if (i==4) {
445
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
446
              && apitype == ESCAPE_MARKER)
447
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
448
          else {
449
            apitype = PORT;
450
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
451
                && apitype == ESCAPE_MARKER)
452
              continue; // get escaped character
453
          }
454
        } else if (i==5) {
455
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
456
              && apitype == ESCAPE_MARKER)
457
            apitype = PORT ^ ESCAPE_XOR;
458
          else {
459
            apitype = PORT;
460
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
461
                && apitype == ESCAPE_MARKER)
462
              continue; // get escaped character
463
          }
464
          framenum = apitype; // get the frame number
465
/*          if (check_last_receive(source,framenum) != WL_SUCCESS) {
466
            // we've already received this frame
467
            ptr = 0xFF; // signal to skip processing
468
            break;
469
          }
470
*/      }
471
        else if (i==6) {
472
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
473
              && apitype == ESCAPE_MARKER)
474
            apitype = PORT ^ ESCAPE_XOR;
475
          else {
476
            apitype = PORT;
477
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
478
                && apitype == ESCAPE_MARKER)
479
              continue; // get escaped character
480
          }
481
          group = apitype; // get group number
482
            WL_DEBUG_PRINT_P("|ptr2=");
483
            WL_DEBUG_PRINT_INT(ptr);
484
          
485
          if (group == 0) { //writes the packet to the buffer
486
            WL_DEBUG_PRINT_P("|last1=");
487
            WL_DEBUG_PRINT_INT(basic_buf_last);
488
            WL_DEBUG_PRINT_P("|ptr1=");
489
            WL_DEBUG_PRINT_INT(ptr);
490
            ptr = basic_buf_last;
491
            WL_DEBUG_PRINT_P("|last2=");
492
            WL_DEBUG_PRINT_INT(basic_buf_last);
493
            WL_DEBUG_PRINT_P("|ptr2=");
494
            WL_DEBUG_PRINT_INT(ptr);
495
            if (xbee_basic_buf_add(&ptr,0x00) != 0) {
496
              WL_DEBUG_PRINT_P("failed to write to buffer1");
497
              break;
498
            }
499
            WL_DEBUG_PRINT_P("|ptr3=");
500
            WL_DEBUG_PRINT_INT(ptr);
501
            // add source to basic buffer
502
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) {
503
              WL_DEBUG_PRINT_P("failed to write to buffer2");
504
              break;
505
            }
506
            WL_DEBUG_PRINT_P("|ptr4=");
507
            WL_DEBUG_PRINT_INT(ptr);
508
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) {
509
              WL_DEBUG_PRINT_P("failed to write to buffer3");
510
              break;
511
            }
512
            WL_DEBUG_PRINT_P("|ptr5=");
513
            WL_DEBUG_PRINT_INT(ptr);
514
          } else {
515
            ptr = other_buf_last;
516
            // add source and group to other buffer
517
            if (xbee_other_buf_add(&ptr,0x00) != 0) {
518
              WL_DEBUG_PRINT_P("failed to write to buffer3.5");
519
              break;
520
            }
521
            if (xbee_other_buf_add(&ptr,group) != 0) {
522
              WL_DEBUG_PRINT_P("failed to write to buffer4");
523
              break;
524
            }
525
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) {
526
              WL_DEBUG_PRINT_P("failed to write to buffer5");
527
              break;
528
            }
529
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) {
530
              WL_DEBUG_PRINT_P("failed to write to buffer6");
531
              break;
532
            }
533
          }
534
        }
535
        else {
536
          // put packet data on the correct buffer
537
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
538
              && apitype == ESCAPE_MARKER)
539
            apitype = PORT ^ ESCAPE_XOR;
540
          else {
541
            apitype = PORT;
542
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
543
                && apitype == ESCAPE_MARKER)
544
              continue; // get escaped character
545
          }
546
          if (group == 0) {
547
            if (xbee_basic_buf_add(&ptr,apitype) != 0) {
548
              WL_DEBUG_PRINT_P("failed to write to buffer7");
549
              break;
550
            }
551
          } else {
552
            if (xbee_other_buf_add(&ptr,apitype) != 0) {
553
              WL_DEBUG_PRINT_P("failed to write to buffer8");
554
              break;
555
            }
556
          }
557
        }
558
        i++;
559
      }
560
    }
561
    WL_DEBUG_PRINT_P("before_last=");
562
    if (group == 0)
563
      WL_DEBUG_PRINT_INT(basic_buf_last);
564
    else
565
      WL_DEBUG_PRINT_INT(other_buf_last);
566
    if (ptr != 0xFF && i > 6) {
567
      if (group == 0) {
568
        xbee_basic_buf[basic_buf_last] = i-5; // set length
569
        basic_buf_last = ptr;
570
      }
571
      else {
572
        xbee_other_buf[other_buf_last] = i-4; // set length  ** TODO: check this number
573
        // check if we have a high priority group
574
        /*for(;;)
575
          if (HIGH_PRIORITY) {
576
            // handle receive now
577
            ptr = 0xFF;
578
            break;
579
          }*/        
580
        //if (ptr != 0xFF) {
581
          // handle receive later
582
          other_buf_last = ptr;
583
        //}
584
      }
585
    }
586
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_16|len=");
587
    WL_DEBUG_PRINT_INT(len);
588
    WL_DEBUG_PRINT_P("|i=");
589
    WL_DEBUG_PRINT_INT(i);
590
    WL_DEBUG_PRINT_P("|source=");
591
    WL_DEBUG_PRINT_INT(source);
592
    WL_DEBUG_PRINT_P("|framenum=");
593
    WL_DEBUG_PRINT_INT(framenum);
594
    WL_DEBUG_PRINT_P("group=");
595
    WL_DEBUG_PRINT_INT(group);
596
    WL_DEBUG_PRINT_P("|ptr=");
597
    WL_DEBUG_PRINT_HEX(ptr);
598
    WL_DEBUG_PRINT_P("|first=");
599
    if (group == 0)
600
      WL_DEBUG_PRINT_INT(basic_buf_first);
601
    else
602
      WL_DEBUG_PRINT_INT(other_buf_first);
603
    WL_DEBUG_PRINT_P("|last=");
604
    if (group == 0)
605
      WL_DEBUG_PRINT_INT(basic_buf_last);
606
    else
607
      WL_DEBUG_PRINT_INT(other_buf_last);    
608
    WL_DEBUG_PRINT_P("|buffer=");
609
    if (group == 0) {
610
      for(uint8_t i=0;i<ptr;i++)
611
        WL_DEBUG_PRINT_HEX(xbee_basic_buf[i]);
612
    } else {
613
      for(uint8_t i=0;i<ptr;i++)
614
        WL_DEBUG_PRINT_HEX(xbee_other_buf[i]);
615
    }
616
    WL_DEBUG_PRINT_P("|\r\n");
617
    break; }
618
    default:
619
      WL_DEBUG_PRINT_P("|BAD APITYPE:");
620
      WL_DEBUG_PRINT_HEX(apitype);
621
      WL_DEBUG_PRINT_P("\r\n");
622
  } // end of switch statement
623
  while (1) {
624
    if (FLAG) {
625
      apitype = PORT; // get checksum, and ignore
626
      break;
627
    }
628
  }
629
  WL_DEBUG_PRINT_P("|interrupt - return\r\n");
630
} // end of interrupt 
631

    
632

    
633
/* adds a byte to the basic buffer */
634
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
635
  if (*ptr == basic_buf_first) {
636
    // buffer full
637
    WL_DEBUG_PRINT_P("basic buffer full\r\n");
638
    WL_DEBUG_PRINT_P("ptr=");
639
    WL_DEBUG_PRINT_INT(*ptr);
640
    WL_DEBUG_PRINT_P("|basic_buf_first=");
641
    WL_DEBUG_PRINT_INT(basic_buf_first);
642
    WL_DEBUG_PRINT_P("|basic_buf_last=");
643
    WL_DEBUG_PRINT_INT(basic_buf_last);
644
    WL_DEBUG_PRINT_P("\r\n");
645
    return -1;
646
  }  
647
  WL_DEBUG_PRINT_P("|add_ptr1=");
648
  WL_DEBUG_PRINT_INT(*ptr);
649
  xbee_basic_buf[(*ptr)++] = byte;
650
  if (*ptr == PACKET_BUFFER_SIZE)
651
    *ptr = 0;
652
  WL_DEBUG_PRINT_P("|add_ptr2=");
653
  WL_DEBUG_PRINT_INT(*ptr);
654
  return 0;
655
}
656
/* gets a byte from the basic buffer */
657
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
658
  uint8_t byte = xbee_basic_buf[(*ptr)++];
659
  if (*ptr == PACKET_BUFFER_SIZE)
660
    *ptr = 0;
661
  return byte;
662
}
663
/* adds a byte to the other buffer */
664
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
665
  if (*ptr == other_buf_first) {
666
    // buffer full
667
    WL_DEBUG_PRINT_P("other buffer full\r\n");
668
    return -1;
669
  }
670
  xbee_other_buf[(*ptr)++] = byte;
671
  if (*ptr == PACKET_BUFFER_SIZE)
672
    *ptr = 0;
673
  return 0;
674
}
675
/* gets a byte from the other buffer */
676
uint8_t xbee_other_buf_get(uint8_t *ptr) {
677
  uint8_t byte = xbee_other_buf[(*ptr)++];
678
  if (*ptr == PACKET_BUFFER_SIZE)
679
    *ptr = 0;
680
  return byte;
681
}
682

    
683
/**
684
 * Checks if packet is a duplicate
685
 **/
686
int8_t check_last_receive(uint16_t source,uint8_t framenum) {
687
  uint8_t i=0;
688
  for(;i<NUM_LAST_PACKETS;i++) {
689
    if (lastPacket[i].source == source && lastPacket[i].framenum == framenum) {
690
      WL_DEBUG_PRINT_P("Duplicate Packet: LP.src=");
691
      WL_DEBUG_PRINT_INT(lastPacket[i].source);
692
      WL_DEBUG_PRINT_P("|GET.src=");
693
      WL_DEBUG_PRINT_INT(source);
694
      WL_DEBUG_PRINT_P("|LP.framenum=");
695
      WL_DEBUG_PRINT_INT(lastPacket[i].framenum);
696
      WL_DEBUG_PRINT_P("|GET.framenum=");
697
      WL_DEBUG_PRINT_INT(framenum);
698
      WL_DEBUG_PRINT_P("\r\n");      
699
      return -1; // duplicate packet, so return error
700
    }
701
  }
702
  // save packet source and framenum
703
  i=getStatus(LAST_PACKET_MASK);
704
  lastPacket[i].source = source;
705
  lastPacket[i].framenum = framenum;
706
  if (++i>=NUM_LAST_PACKETS)
707
    i = 0;
708
    
709
  setStatus(LAST_PACKET_MASK,i);
710
  WL_DEBUG_PRINT_P("check last receive: LP.src=");
711
  WL_DEBUG_PRINT_INT(lastPacket[i].source);
712
  WL_DEBUG_PRINT_P("|GET.src=");
713
  WL_DEBUG_PRINT_INT(source);
714
  WL_DEBUG_PRINT_P("|LP.framenum=");
715
  WL_DEBUG_PRINT_INT(lastPacket[i].framenum);
716
  WL_DEBUG_PRINT_P("|GET.framenum=");
717
  WL_DEBUG_PRINT_INT(framenum);
718
  WL_DEBUG_PRINT_P("\r\n");
719
  return WL_SUCCESS;
720
}
721

    
722
/** status functions **/
723
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
724
void setStatus(uint8_t mask,uint8_t value) {
725
  xbee_status = ((xbee_status&(~mask))|value); //xbee is the super-byte
726
}
727

    
728

    
729
/**
730
 * Initializes the XBee library so that other functions may be used.
731
 **/
732
int8_t xbee_init() {
733
  WL_DEBUG_PRINT_P("in xbee_init\r\n");
734
  
735
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
736
    return WL_ERROR_INIT_ALREADY_INITD;
737
  }
738
  
739
  // set status
740
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
741
  
742
  // clear last packet buffer
743
  int i=0;
744
  for(;i<NUM_LAST_PACKETS;i++)
745
    lastPacket[i].source = lastPacket[i].framenum = 0;
746
    
747
  // clear basic and other buffers
748
  //uint8_t j=0;
749
  i=0;
750
  while(i<PACKET_BUFFER_SIZE) { xbee_basic_buf[i++] = 0xFF; }
751
  i=0;
752
  while(i<PACKET_BUFFER_SIZE) { xbee_other_buf[i++] = 0xFF; }
753
    
754
  // Set startup baud rate of 9600
755
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
756
  // Enable receiver and transmitter and the receiving interrupt
757
  // DO NOT TOUCH
758
#ifdef FIREFLY
759
  UBRR0H = 0x00;
760
  UBRR0L = 103;
761
  UCSR0A |= (1<<U2X0);
762
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
763
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
764
#else
765
  // Bayboard or robot  
766
  UBRR1H = 0x00; // baud rate
767
  UBRR1L = 103;  // baud rate
768
  UCSR1A |= (1<<U2X1); // double transmit speed 
769
  //Enable receiver and transmitter on USART1
770
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
771
        
772
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
773
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
774
  
775
  UCSR1B |= (1<<RXCIE1);  // enable receive, transmit (1<<RXCIE)
776
#endif
777
  sei();
778
 
779
  // enter command mode
780
  WL_DEBUG_PRINT_P("entering command mode\r\n");
781
  xbee_send_string((uint8_t*)"+++");
782
  xbee_wait_for_ok();
783
  WL_DEBUG_PRINT_P("entered command mode\r\n");
784

    
785
  
786
  // set baud on xbee
787
#if (XBEE_BAUD == 115200)
788
  xbee_send_string((uint8_t*)"ATBD7\r");
789
#elif (XBEE_BAUD == 57600)
790
  xbee_send_string((uint8_t*)"ATBD6\r");
791
#elif (XBEE_BAUD == 38400)
792
  xbee_send_string((uint8_t*)"ATBD5\r");
793
#elif (XBEE_BAUD == 19200)
794
  xbee_send_string((uint8_t*)"ATBD4\r");
795
#elif (XBEE_BAUD == 9600)
796
  // already at this baud rate
797
  xbee_send_string((uint8_t*)"ATBD3\r\n");
798
#else
799
  WL_DEBUG_PRINT_P("undefined baud rate\r\n");
800
  return WL_ERROR_BAUD;
801
#endif  
802
  // exit command mode
803
  xbee_wait_for_ok();
804
  WL_DEBUG_PRINT_P("got ok from baud reset\r\n");
805
  xbee_send_string((uint8_t*)"ATCN\r");
806
  xbee_wait_for_ok();
807
  WL_DEBUG_PRINT_P("got ok from exiting command mode\r\n");
808
  
809
  // set UART baud
810
#ifdef FIREFLY
811
#if (XBEE_BAUD == 115200)
812
  UBRR0H = 0x00;
813
  UBRR0L = 8;
814
#elif (XBEE_BAUD == 57600)
815
  UBRR0H = 0x00;
816
  UBRR0L = 16;
817
#elif (XBEE_BAUD == 38400)
818
  UBRR0H = 0x00;
819
  UBRR0L = 25;
820
#elif (XBEE_BAUD == 19200)
821
  UBRR0H = 0x00;
822
  UBRR0L = 51;
823
#elif (XBEE_BAUD == 9600)
824
  /* this is the default baud rate, so do nothing
825
  UBRR0H = 0x00;
826
  UBRR0L = 103;*/
827
#else
828
  WL_DEBUG_PRINT_P("undefined baud rate\r\n");
829
  return WL_ERROR_BUAD;
830
#endif
831
#else // Bayboard or robot
832
#if (XBEE_BAUD == 115200)
833
  UBRR1H = 0x00;
834
  UBRR1L = 8;
835
#elif (XBEE_BAUD == 57600)
836
  UBRR1H = 0x00;
837
  UBRR1L = 16;
838
#elif (XBEE_BAUD == 38400)
839
  UBRR1H = 0x00;
840
  UBRR1L = 25;
841
#elif (XBEE_BAUD == 19200)
842
  UBRR1H = 0x00;
843
  UBRR1L = 51;
844
#elif (XBEE_BAUD == 9600)
845
  /* this is the default baud rate, so do nothing
846
  UBRR1H = 0x00;
847
  UBRR1L = 103;*/
848
#else
849
  WL_DEBUG_PRINT_P("undefined baud rate\r\n");
850
  return WL_ERROR_BUAD;
851
#endif
852
#endif
853
  // wait half second for the baud change to stabalize
854
  delay_ms(500);
855

    
856
  // enter command mode
857
  WL_DEBUG_PRINT_P("entering command mode 2\r\n");
858
  xbee_send_string((uint8_t*)"+++");
859
  xbee_wait_for_ok();
860
  WL_DEBUG_PRINT_P("entered command mode 2\r\n");
861
  
862
  if (xbee_enter_api_mode2() != 0) {
863
    WL_DEBUG_PRINT_P("can't enter api mode 2\r\n");
864
    return -1;
865
  }
866
  
867
#ifdef WL_DEBUG
868
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
869
    WL_DEBUG_PRINT_P("|API OFF|");
870
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
871
    WL_DEBUG_PRINT_P("|API ON|");
872
  } else {
873
    WL_DEBUG_PRINT_P("|API ERROR|");
874
  }
875
#endif
876
  
877
  // set MY address
878
  uint8_t newmy = get_robotid();
879
  uint8_t newmyarr[2] = {0x00,newmy};
880
  if (newmy == 0xFF) {
881
    WL_DEBUG_PRINT_P("can't get MY address from EEPROM\r\n");
882
  } else {
883
    WL_DEBUG_PRINT_P("MY address from eeprom:");
884
    WL_DEBUG_PRINT_HEX(newmyarr[0]);
885
    WL_DEBUG_PRINT_HEX(newmyarr[1]);
886
    WL_DEBUG_PRINT_P("\r\n");
887
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); 
888
    if (xbee_send_modify_at_command((uint8_t*)"MY",newmyarr,2) != WL_SUCCESS) {
889
      WL_DEBUG_PRINT_P("setting MY address failed\r\n");
890
    }
891
    // wait for up to 30 ms
892
    newmy = 0;
893
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && newmy++ < 10000) {
894
      delay_us(1); // wait 3us
895
    }  
896
    if (newmy < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
897
      WL_DEBUG_PRINT_P("setting MY address successful\r\n");
898
    } else
899
      WL_DEBUG_PRINT_P("setting MY address failed\r\n");
900
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
901
  }
902
    
903
  // get MY address
904
  uint16_t address = xbee_get_address();
905
  if (address == WL_ERROR_XBEE_COMMAND_16BIT) {
906
    WL_DEBUG_PRINT_P("getting MY address failed\r\n");
907
  }
908
  WL_DEBUG_PRINT_P("MY address:");
909
  WL_DEBUG_PRINT_HEX((uint8_t)((address&0xFF00)>>8));
910
  WL_DEBUG_PRINT_HEX((uint8_t)(address&0x00FF));
911
  WL_DEBUG_PRINT_P("\r\n");
912
  
913
  // set PAN
914
  xbee_set_pan(0);
915
  
916
  return WL_SUCCESS;
917
}
918

    
919
/**
920
 * Call when finished using the XBee library.
921
 **/
922
int8_t xbee_terminate()
923
{
924
  int ret=xbee_exit_api_mode();
925
  if (ret != WL_SUCCESS) {
926
    WL_DEBUG_PRINT_P("xbee termination failed\r\n");
927
    WL_DEBUG_PRINT_INT(ret);
928
    WL_DEBUG_PRINT_P("|\r\n");
929
    return WL_ERROR_TERMINATION_FAILED;
930
  }
931
  delay_ms(1000);
932
  // reset baud to defaults
933
  xbee_enter_command_mode();
934
  xbee_send_string((uint8_t*)"ATBD 3\r");
935
  xbee_wait_for_ok();
936
  xbee_exit_command_mode();
937
  UBRR1H = 0x00;
938
  UBRR1L = 103;
939
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
940
  return WL_SUCCESS;
941
}
942

    
943
/**
944
 * Sends a character to the XBee.
945
 *
946
 * @param c the byte to send
947
 * @return 0 for success, nonzero for failure
948
 **/
949
int8_t xbee_putc(uint8_t c) {
950

    
951
  // Wait until buffer is clear for sending
952
  // Then load buffer with your character
953
  
954
#ifdef FIREFLY
955
  loop_until_bit_is_set(UCSR0A, UDRE0);  
956
  UDR0 = c;
957
#else
958
  loop_until_bit_is_set(UCSR1A, UDRE1);
959
  UDR1 = c;
960
#endif
961
  
962
  return WL_SUCCESS;
963
}
964

    
965
/**
966
 * Returns the first byte in the buffer received from xbee.
967
 * This function blocks execution until a character has been
968
 * received. xbee_init must be called before this function
969
 * may be used.
970
 * 
971
 * @return the first character in the xbee buffer, -1 on error
972
 * 
973
 * @see xbee_init, xbee_getc_nb
974
 **/
975
int16_t xbee_getc(void) {
976
    
977
  // Wait for the receive buffer to be filled
978
  // Then read the receive buffer
979
#ifdef FIREFLY
980
  loop_until_bit_is_set(UCSR0A, RXC0);  
981
  return UDR0;
982
#else
983
  loop_until_bit_is_set(UCSR1A, RXC1);
984
  return UDR1;
985
#endif
986
}
987

    
988
/**
989
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
990
 * it is returned, otherwise -1 is returned immediately. xbee_init
991
 * must be called before this function can be used.
992
 *
993
 * @param c The received byte. This will be set if a byte has been received.
994
 * 
995
 * @return -1 If no byte is available, 0 otherwise, positive for error
996
 *
997
 * @see xbee_getc
998
 **/
999
int8_t xbee_getc_nb(uint8_t *c) {
1000

    
1001
  // check if the receive buffer is filled
1002
#ifdef FIREFLY
1003
  if (UCSR0A & (1<<RXC0)) {
1004
    (*c) = UDR0;
1005
#else
1006
  if (UCSR1A & (1<<RXC1)) {
1007
    (*c) = UDR1;
1008
#endif
1009
    return WL_SUCCESS;
1010
  }
1011
  return -1; // Return empty
1012
}
1013

    
1014
/**
1015
 * Send byte to the xbee in API mode.
1016
 *
1017
 * @param byte the byte to be sent
1018
 **/
1019
int8_t xbee_sendc(uint8_t byte) {
1020
  if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE && 
1021
      (byte == ESCAPE1 || byte == ESCAPE2 || byte == ESCAPE3 || byte == ESCAPE4))
1022
    byte ^= ESCAPE_XOR;
1023

    
1024
#ifdef FIREFLY
1025
  loop_until_bit_is_set(UCSR0A, UDRE0);  
1026
  UDR0 = byte;
1027
#else
1028
  loop_until_bit_is_set(UCSR1A, UDRE1);
1029
  UDR1 = byte;
1030
#endif
1031
  
1032
  return WL_SUCCESS;
1033
}
1034

    
1035

    
1036
/**
1037
 * Send a buffer buf of size bytes to the XBee in API mode
1038
 *
1039
 * @param buf the buffer of data to send
1040
 * @param size the number of bytes to send
1041
 **/
1042
int8_t xbee_send(uint8_t* buf, uint16_t size)
1043
{
1044
  uint16_t i=0; // check if we need this variable
1045
  while(i<size) {
1046
    if (xbee_sendc(buf[i++]) != WL_SUCCESS)
1047
      return WL_ERROR_SEND;
1048
  }
1049

    
1050
  return WL_SUCCESS;
1051
}
1052

    
1053
/**
1054
 * Sends a string direct to the XBee.
1055
 *
1056
 * @param c the string to send to the XBEE
1057
 **/
1058
static int8_t xbee_send_string(uint8_t* c)
1059
{
1060
  uint16_t size = strlen((char*)c);
1061
  uint16_t i=0; // check if we need this variable
1062
  while(i<size) {
1063
    if (xbee_putc(c[i++]) != WL_SUCCESS)
1064
      return WL_ERROR_SEND;
1065
  }
1066

    
1067
  return WL_SUCCESS;
1068
}
1069

    
1070

    
1071
/**
1072
 * Enter into command mode.
1073
 **/
1074
static int8_t xbee_enter_command_mode(void)
1075
{
1076
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
1077
    return WL_ERROR_XBEE_COMMAND;
1078
  }
1079
  WL_DEBUG_PRINT_P("sent command +++|");
1080

    
1081
  if (xbee_wait_for_ok() != WL_SUCCESS) {
1082
    return WL_ERROR_XBEE_COMMAND;
1083
  }
1084
  WL_DEBUG_PRINT_P("got OK\r\n");
1085
  
1086
  return WL_SUCCESS;
1087
}
1088

    
1089
/**
1090
 * Exit from command mode.
1091
 **/
1092
static int8_t xbee_exit_command_mode()
1093
{
1094
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
1095
    return WL_ERROR_SEND;
1096
  }
1097
  if (xbee_wait_for_ok() != WL_SUCCESS) {
1098
    WL_DEBUG_PRINT_P("failed to exit command mode\r\n");
1099
    return WL_ERROR_SEND;
1100
  }
1101

    
1102
  return WL_SUCCESS;
1103
}
1104

    
1105
/**
1106
 * Enter API mode 1.
1107
 **/
1108
static int8_t xbee_enter_api_mode(void) {
1109
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
1110
    return WL_ERROR_SEND;
1111
  }
1112
  if (xbee_wait_for_ok() != WL_SUCCESS) {
1113
    WL_DEBUG_PRINT_P("failed to enter API mode\r\n");
1114
    return WL_ERROR_SEND;
1115
  }
1116
  if (xbee_exit_command_mode() != WL_SUCCESS) {
1117
    WL_DEBUG_PRINT_P("failed to enter API mode\r\n");
1118
    return WL_ERROR_SEND;
1119
  }    
1120
  WL_DEBUG_PRINT_P("got OK after entering API mode\r\n");
1121
  
1122
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
1123
  
1124
  return WL_SUCCESS;
1125
}
1126

    
1127
/**
1128
 * Enter API mode 2.
1129
 **/
1130
static int8_t xbee_enter_api_mode2(void) {
1131
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
1132
    return WL_ERROR_SEND;
1133
  }
1134
  if (xbee_wait_for_ok() != WL_SUCCESS) {
1135
    WL_DEBUG_PRINT_P("failed to enter API mode2\r\n");
1136
    return WL_ERROR_SEND;
1137
  }
1138
  if (xbee_exit_command_mode() != WL_SUCCESS) {
1139
    WL_DEBUG_PRINT_P("failed to enter API mode2\r\n");
1140
    return WL_ERROR_SEND;
1141
  }    
1142
  WL_DEBUG_PRINT_P("got OK after entering API mode2\r\n");
1143
  
1144
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
1145
  
1146
  return WL_SUCCESS;
1147
}
1148

    
1149
/**
1150
 * Exit API mode.
1151
 **/
1152
static int8_t xbee_exit_api_mode()
1153
{
1154
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1155
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1156
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1157
  WL_DEBUG_PRINT_P("now exiting API mode\r\n");
1158
  
1159
  int16_t i=0;
1160
  // change status to command wait
1161
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1162
  if (xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)(&i),1) != WL_SUCCESS) { // send command
1163
    WL_DEBUG_PRINT_P("error sending AP 0 command\r\n");
1164
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1165
    return WL_ERROR_XBEE_COMMAND;
1166
  }
1167
  // wait for up to 30 ms
1168
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1169
    delay_us(1); // wait 3us
1170
  }
1171
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
1172
    WL_DEBUG_PRINT_P("done exiting API mode\r\n");
1173
    i = WL_SUCCESS;
1174
  } else {
1175
    WL_DEBUG_PRINT_P("failed to exit API mode\r\n");
1176
    i = WL_ERROR_XBEE_COMMAND; // set error code
1177
  }
1178
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1179
  setStatus(XBEE_API_MASK,XBEE_API_OFF);
1180
  
1181
  return (int8_t)i; // return
1182
}
1183

    
1184
/**
1185
 * Wait until the string "OK\r" is received from the XBee.
1186
 **/
1187
static int8_t xbee_wait_for_ok()
1188
{
1189
  //delay_ms(1000);
1190
  //return WL_SUCCESS;
1191
  return xbee_wait_for_string((uint8_t*)"OK", 2);
1192
}
1193

    
1194
/**
1195
 * Delay until the specified string is received from
1196
 * the XBee.
1197
 *
1198
 * Only works when not in API mode
1199
 *
1200
 * @param s the string to receive
1201
 * @param len the length of the string
1202
 **/
1203
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
1204
{
1205
  uint8_t i=0;  
1206
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
1207
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
1208
    // wait until the response is received (only wait 1 second)
1209
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
1210
      delay_us(1);
1211
    }
1212
    // check response
1213
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
1214
      // bad response
1215
      WL_DEBUG_PRINT_P("Bad response when waiting for string ");
1216
      WL_DEBUG_PRINT((char*)s);
1217
      WL_DEBUG_PRINT_P("\r\n");
1218
      return -1;
1219
    }
1220
    
1221
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
1222
  }
1223
  
1224
  WL_DEBUG_PRINT_P("done waiting for string.\r\n");
1225

    
1226
  return 0;
1227
}
1228

    
1229
/**
1230
 * Delay until we receive a command response.
1231
 * Then copy the response to S and set the len
1232
 *
1233
 * Only works when not in API mode
1234
 *
1235
 * @param s the string to store the response in
1236
 * @param len the length of the string
1237
 */
1238
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
1239
  uint8_t i=0;
1240
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
1241
    // wait until the response is received (only wait 1 second)
1242
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
1243
      delay_us(1); //3 us
1244
    }
1245
    // check response
1246
    if (i >= 1000) {
1247
      return -1;
1248
    } else {
1249
      i=strcspn((char*)xbee_basic_buf,"\r");
1250
      if (i<PACKET_BUFFER_SIZE) {
1251
        memcpy(s,xbee_basic_buf,i);
1252
        len = i;
1253
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
1254
        return 0;
1255
      }
1256
      else
1257
        return -1;      
1258
    }
1259
  }
1260
  // TODO: do something for API mode
1261
  
1262
  return 0;
1263
}
1264

    
1265
/**  TODO: since we don't use this, do we need it?
1266
 *
1267
 * Verifies that the packets checksum is correct.
1268
 * (If the checksum is correct, the sum of the bytes
1269
 * is 0xFF.)
1270
 *
1271
 * @param packet the packet received. This includes the first
1272
 * three bytes, which are header information from the XBee.
1273
 *
1274
 * @param len The length of the packet received from the XBee
1275
 *
1276
 * @return 0 if the checksum is incorrect, nonzero
1277
 * otherwise
1278
 **/
1279
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
1280
{
1281
  uint8_t sum = 0;
1282
  while(--len > 0) {
1283
    sum += packet[len];
1284
  }
1285
  sum += packet[0];
1286
  return (sum == 0xFF);
1287
}
1288

    
1289
/**
1290
 * Returns the checksum of the given packet.
1291
 *
1292
 * @param buf the data for the packet to send
1293
 * @param len the length of the packet in bytes
1294
 *
1295
 * @return the checksum of the packet, which will
1296
 * become the last byte sent in the packet
1297
 **/
1298
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
1299
{
1300
  uint8_t sum = 0;
1301
  while(--len > 0) {
1302
    sum += buf[len];
1303
  }
1304
  sum += buf[0];
1305
  return 0xFF - sum;
1306
}
1307

    
1308
/**
1309
 * Adds buf to the previous checksum total
1310
 *
1311
 * @param buf a byte buffer to add to the checksum
1312
 * @param len the length of the buffer
1313
 * @param sum the previous sum
1314
 *
1315
 * @return error code
1316
 **/
1317
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
1318
  if (buf == NULL || sum == NULL)
1319
    return WL_ERROR_ARGUMENT;
1320
  while(--len > 0) {
1321
    *sum += buf[len];
1322
  }
1323
  *sum += buf[0];
1324
  return WL_SUCCESS;
1325
}
1326

    
1327

    
1328
/**
1329
 * Sends header information. Header information includes
1330
 * XBEE_FRAME_START and the packet length, as two bytes.
1331
 *
1332
 * @param type the packet type
1333
 * @param len the size in bytes of the packet data
1334
 *
1335
 **/
1336
int8_t xbee_send_header(uint16_t len)
1337
{  
1338
  //packet prefix
1339
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1340
    return WL_ERROR_SEND;
1341
  if (xbee_sendc((uint8_t)((len&0xFF00)>>8)) != WL_SUCCESS)
1342
    return WL_ERROR_SEND;
1343
  if (xbee_sendc((uint8_t)(len&0x00FF)) != WL_SUCCESS)
1344
    return WL_ERROR_SEND;
1345

    
1346
  return WL_SUCCESS;
1347
}
1348

    
1349
/**
1350
 * Adds header information and checksum to the given
1351
 * packet and sends it. Header information includes
1352
 * XBEE_FRAME_START and the packet length, as two bytes.
1353
 *
1354
 * @param buf the packet data
1355
 * @param len the size in bytes of the packet data
1356
 *
1357
 **/
1358
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
1359
{
1360
  uint8_t checksum = xbee_compute_checksum(buf, len);
1361
  
1362
  // send header
1363
  if (xbee_send_header(len) != WL_SUCCESS)
1364
    return WL_ERROR_SEND;
1365

    
1366
  // send body
1367
  if (xbee_send(buf, len) != WL_SUCCESS)
1368
    return WL_ERROR_SEND;
1369
  
1370
  // send checksum
1371
  if (xbee_sendc(checksum) != WL_SUCCESS)
1372
    return WL_ERROR_SEND;
1373
  
1374
  return WL_SUCCESS;
1375
}
1376

    
1377
/**
1378
 * Sends an AT command to read a parameter.
1379
 *
1380
 * @param command the AT command to send. For exmaple,
1381
 * use ID to read the PAN ID and MY to return the XBee ID.
1382
 * See the XBee reference guide for a complete listing.
1383
 **/
1384
int8_t xbee_send_read_at_command(uint8_t* command)
1385
{
1386
  return xbee_send_modify_at_command(command, NULL, 0);
1387
}
1388

    
1389
/**
1390
 * Sends the given AT command.
1391
 *
1392
 * @param command the AT command to send (e.g., MY, ID)
1393
 * @param value the value to pass as a parameter
1394
 * (or NULL if there is no parameter)
1395
 **/
1396
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1397
{
1398
  uint8_t buf[12];
1399

    
1400
  buf[0] = XBEE_FRAME_AT_COMMAND;
1401
  buf[1] = 1;
1402
  buf[2] = command[0];
1403
  buf[3] = command[1];
1404
  if (value != NULL)
1405
  {
1406
    if (len > 8)
1407
    {
1408
      WL_DEBUG_PRINT_P("AT Command too large.\r\n");
1409
      return WL_ERROR_ARGUMENT;
1410
    }
1411
    memcpy(buf+4,value,len);
1412
  }
1413

    
1414
  return xbee_send_frame(buf, 4 + len);
1415
}
1416

    
1417
/**
1418
 * Send the specified packet. (wl_send depreciates this)
1419
 *
1420
 * @param packet the packet data to send
1421
 * @param len the number of bytes in the packet
1422
 *
1423
 * @param dest the ID of the XBee to send the packet to,
1424
 * or XBEE_BROADCAST to send the message to all robots
1425
 * in the PAN.
1426
 *
1427
 * @param options a combination of the flags
1428
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1429
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1430
 *
1431
 * @param frame the frame number to associate this packet
1432
 * with. This will be used to identify the response when
1433
 * the XBee alerts us as to whether or not our message
1434
 * was received.
1435
 **/
1436
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1437
{
1438
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1439
  uint8_t i = 0;
1440

    
1441
  if (len > 100)
1442
  {
1443
    WL_DEBUG_PRINT_P("Packet is too large.\r\n");
1444
    return WL_ERROR_ARGUMENT;
1445
  }
1446
  
1447
  // calculate checksum
1448
  for(;i<len;i++)
1449
    sum += packet[len];
1450
  sum += frame;
1451
  sum += (dest&0xFF00) >> 8;
1452
  sum += dest&0x00FF;
1453
  sum += options;
1454
  sum = 0xFF - sum;
1455

    
1456
  //packet prefix
1457
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1458
    return WL_ERROR_SEND;
1459
  if (xbee_sendc(0x00) != WL_SUCCESS)
1460
    return WL_ERROR_SEND;
1461
  if (xbee_sendc(len+5) != WL_SUCCESS)
1462
    return WL_ERROR_SEND;
1463
    
1464
  //send header for TX request
1465
  if (xbee_sendc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1466
    return WL_ERROR_SEND;
1467
  if (xbee_sendc(frame) != WL_SUCCESS)
1468
    return WL_ERROR_SEND;
1469
  if (xbee_sendc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1470
    return WL_ERROR_SEND;
1471
  if (xbee_sendc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1472
    return WL_ERROR_SEND;
1473
  if (xbee_sendc(options) != WL_SUCCESS)
1474
    return WL_ERROR_SEND;
1475

    
1476
  // send packet
1477
  if (xbee_send(packet, len) != WL_SUCCESS)
1478
    return WL_ERROR_SEND;
1479

    
1480
  // send checksum
1481
  if (xbee_sendc(sum) != WL_SUCCESS)
1482
    return WL_ERROR_SEND;
1483

    
1484
  return WL_SUCCESS;
1485
}
1486

    
1487
/**
1488
 * Handles modem status packets.
1489
 *
1490
 * @param status the type of status packet received.
1491
 **/
1492
void xbee_handle_status(uint8_t status)
1493
{
1494
  switch (status)
1495
  {
1496
    case 0:
1497
      WL_DEBUG_PRINT_P("XBee hardware reset.\r\n");
1498
      break;
1499
    case 1:
1500
      WL_DEBUG_PRINT_P("Watchdog timer reset.\r\n");
1501
      break;
1502
    case 2:
1503
      WL_DEBUG_PRINT_P("Associated.\r\n");
1504
      break;
1505
    case 3:
1506
      WL_DEBUG_PRINT_P("Disassociated.\r\n");
1507
      break;
1508
    case 4:
1509
      WL_DEBUG_PRINT_P("Synchronization lost.\r\n");
1510
      break;
1511
    case 5:
1512
      WL_DEBUG_PRINT_P("Coordinator realignment.\r\n");
1513
      break;
1514
    case 6:
1515
      WL_DEBUG_PRINT_P("Coordinator started.\r\n");
1516
      break;
1517
  }
1518
}
1519

    
1520
/**
1521
 * Handles AT command response packets.
1522
 * @param command the two character AT command, e.g. MY or ID
1523
 * @param result 0 for success, 1 for an error
1524
 * @param len the length in bytes of extra
1525
 **/
1526
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t status, uint8_t len)
1527
{
1528
  WL_DEBUG_PRINT_P("HANDLE AT COMMAND\r\n");
1529
  if (status != 0)
1530
  {
1531
    WL_DEBUG_PRINT_P("Error with AT");
1532
    WL_DEBUG_PRINT((char*)command);
1533
    WL_DEBUG_PRINT_P(" packet. Result = ");
1534
    switch(status) {
1535
    case 1:
1536
      WL_DEBUG_PRINT_P("ERROR\r\n");
1537
      break;
1538
    case 2:
1539
      WL_DEBUG_PRINT_P("Invalid Command\r\n");
1540
      break;
1541
    case 3:
1542
      WL_DEBUG_PRINT_P("Invalid Parameter\r\n");
1543
      break;
1544
    }
1545
    return WL_SUCCESS;
1546
  }
1547
  WL_DEBUG_PRINT_P("AT");
1548
  WL_DEBUG_PRINT_CHAR((uint8_t)(command>>8));
1549
  WL_DEBUG_PRINT_CHAR((uint8_t)(command));
1550
  WL_DEBUG_PRINT_P(" command is being handled\r\n");
1551
  
1552
  // TODO: program more command responses here (ND, etc)
1553
  switch(command) {
1554
  case ('I'<<8)+'D': // PAN
1555
  case ('C'<<8)+'H': // channel
1556
  case ('M'<<8)+'Y': // address
1557
  case ('A'<<8)+'P': // api mode
1558
    // copy command to handler
1559
    xbee_command[0] = (command&0xFF00)>>8;
1560
    xbee_command[1] = command&0x00FF;
1561
    uint8_t ptr = basic_buf_last;
1562
    for(command=2;command<len+2;command++) {
1563
      xbee_command[command] = xbee_basic_buf_get(&ptr);
1564
      if (xbee_command[command] == '\r')
1565
        break; // done with command
1566
      WL_DEBUG_PRINT_HEX(xbee_command[command]);
1567
    }
1568
    xbee_command[command] = '\0';
1569
    WL_DEBUG_PRINT_P("len=");
1570
    WL_DEBUG_PRINT_INT(len);
1571
    WL_DEBUG_PRINT_P("ID,CH,or MY command result:");
1572
    WL_DEBUG_PRINT((char*)xbee_command);
1573
    WL_DEBUG_PRINT_P("\r\n");
1574
    break;
1575
  default:
1576
    WL_DEBUG_PRINT_P("unknown AT command");
1577
  }
1578
  
1579
  // signal handler that command response is done
1580
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
1581

    
1582
  return WL_SUCCESS;
1583
}
1584

    
1585
/**
1586
 * Sets the personal area network id.
1587
 *
1588
 * @param id the new personal area network (PAN) id
1589
 **/
1590
int8_t xbee_set_pan(uint16_t id)
1591
{
1592
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1593
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1594
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1595
  
1596
  
1597
  uint8_t arr[2] = {(id&0xFF00)>>8,(id&0x00FF)};
1598
  WL_DEBUG_PRINT_P("setting PAN address:");
1599
  WL_DEBUG_PRINT_HEX(arr[0]);
1600
  WL_DEBUG_PRINT_HEX(arr[1]);
1601
  WL_DEBUG_PRINT_P("\r\n");
1602
  
1603
  // change status to command wait
1604
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1605
  xbee_send_modify_at_command((uint8_t*)"ID",arr,2); // send command to set the channel
1606
  // wait for up to 30 ms
1607
  uint16_t i=0;
1608
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1609
    delay_us(1); // wait 3us
1610
  }
1611
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1612
    i = WL_SUCCESS;
1613
  else
1614
    i = WL_ERROR_XBEE_COMMAND; // set error code
1615
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1616
  return (int8_t)i; // return
1617
}
1618

    
1619
/**
1620
 * Get the PAN ID for the XBee.
1621
 *
1622
 * @return the personal area network id, or
1623
 * XBEE_PAN_DEFAULT if it has not yet been set.
1624
 **/
1625
uint16_t xbee_get_pan()
1626
{
1627
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1628
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1629
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1630
  
1631
  uint16_t i=0;
1632
  // change status to command wait
1633
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1634
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1635
  // wait for up to 30 ms
1636
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1637
    delay_us(1); // wait 3us
1638
  }
1639
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1640
    i = (xbee_command[2]<<8)|xbee_command[3]; // do ntoh16 coversion
1641
  else
1642
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1643
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1644
  WL_DEBUG_PRINT_P("got PAN address:");
1645
  WL_DEBUG_PRINT_HEX((i&0xFF00)>>8);
1646
  WL_DEBUG_PRINT_HEX((i&0x00FF));
1647
  WL_DEBUG_PRINT_P("\r\n");
1648
  return i; // return
1649
}
1650

    
1651
/**
1652
 * Set the channel the XBee is using.
1653
 *
1654
 * @param channel the channel the XBee will use,
1655
 * between 0x0B and 0x1A
1656
 *
1657
 * @reutrn success or error code
1658
 *
1659
 * @see xbee_get_channel
1660
 **/
1661
int8_t xbee_set_channel(uint8_t channel)
1662
{
1663
  if (channel < 0x0B || channel > 0x1A)
1664
  {
1665
    WL_DEBUG_PRINT_P("Channel out of range.\r\n");
1666
    return WL_ERROR_ARGUMENT;
1667
  }
1668

    
1669
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1670
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1671
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1672
  
1673
  WL_DEBUG_PRINT_P("setting channel:");
1674
  WL_DEBUG_PRINT_HEX(channel);
1675
  WL_DEBUG_PRINT_P("\r\n");
1676
  int16_t i=0;
1677
  // change status to command wait
1678
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1679
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1680
  // wait for up to 30 ms
1681
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1682
    delay_us(1); // wait 3us
1683
  }
1684
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1685
    i = WL_SUCCESS;
1686
  else
1687
    i = WL_ERROR_XBEE_COMMAND; // set error code
1688
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1689
  return (int8_t)i; // return
1690
}
1691

    
1692
/**
1693
 * Returns the channel which the XBee is currently using.
1694
 *
1695
 * @return the channel the XBee is using
1696
 *
1697
 * @see xbee_set_channel
1698
 **/
1699
int8_t xbee_get_channel(void)
1700
{
1701
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1702
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1703
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1704
  
1705
  int16_t i=0;
1706
  // change status to command wait
1707
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1708
  xbee_send_read_at_command((uint8_t*)"CH"); // send command to get the channel
1709
  // wait for up to 30 ms
1710
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1711
    delay_us(1); // wait 3us
1712
  }
1713
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1714
    i = (int8_t)xbee_command[2]; // get channel
1715
  else
1716
    i = WL_ERROR_XBEE_COMMAND; // set error code
1717
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1718
  WL_DEBUG_PRINT_P("got channel:");
1719
  WL_DEBUG_PRINT_HEX((uint8_t)i);
1720
  WL_DEBUG_PRINT_P("\r\n");
1721
  return i; // return
1722
}
1723

    
1724
/**
1725
 * Get the 16-bit address of the XBee.
1726
 * This is used to specify who to send messages to
1727
 * and who messages are from.
1728
 *
1729
 * @return the 16-bit address of the XBee.
1730
 **/
1731
uint16_t xbee_get_address(void)
1732
{
1733
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1734
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1735
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1736
  
1737
  uint16_t i=0;
1738
  // change status to command wait 
1739
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1740
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1741
  // wait for up to 30 ms
1742
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1743
    delay_us(1); // wait 3us
1744
  }
1745
  
1746
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
1747
    i = (xbee_command[2]<<8)|xbee_command[3]; // do ntoh16 coversion
1748
  } else
1749
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1750
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1751
  WL_DEBUG_PRINT_P("got MY address:");
1752
  WL_DEBUG_PRINT_HEX((i&0xFF00)>>8);
1753
  WL_DEBUG_PRINT_HEX((i&0x00FF));
1754
  WL_DEBUG_PRINT_P("\r\n");
1755
  return i; // return
1756
}
1757

    
1758
/**@} **/ // end xbee group
1759