Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (49.9 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
#include <lights.h>
35

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

    
45

    
46
/* Internal Function Prototypes */
47

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

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

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

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

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

    
84
/*Global Variables*/
85

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

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

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

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

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

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

    
106

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

    
114

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

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

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

    
134

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

    
143

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

    
147
/*Function Implementations*/
148

    
149
/**
150
 * Interrupt for the robot. Adds bytes received from the xbee
151
 * to the buffer.
152
 **/
153
 
154
 
155
#ifndef FIREFLY
156
#define PORT UDR1
157
#define FLAG (UCSR1A & (1<<RXC1))
158
ISR(USART1_RX_vect) {
159
#else
160
#define PORT UDR0
161
#define FLAG (UCSR0A & (1<<RXC0))
162
SIGNAL(SIG_USART0_RECV) {
163
#endif
164
  // start of frame
165
  uint8_t apitype = PORT; // get frame start byte
166
  uint16_t i=0;
167
  uint16_t len=0;
168
  
169
  // check that we're in API mode
170
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
171
    // not in API mode
172
    WL_DEBUG_PRINT_P("|api off branch");
173
    
174
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT) {
175
      // get rest of command and put in basic buf
176
      xbee_basic_buf[i] = apitype;
177
      if (xbee_basic_buf[i++] != '\r') {
178
        while(i < PACKET_BUFFER_SIZE) {
179
          if (FLAG) {
180
            xbee_basic_buf[i] = PORT;
181
            if (xbee_basic_buf[i] == '\r')
182
              break;
183
            i++;
184
          }
185
        }
186
      }
187
      WL_DEBUG_PRINT_P("got packet, len=");
188
      WL_DEBUG_PRINT_INT(i);
189
      WL_DEBUG_PRINT_P("str=");
190
      WL_DEBUG_PRINT((char*)xbee_basic_buf);
191
      // signal handler that command response is done
192
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
193
    }
194
    WL_DEBUG_PRINT_P("return\r\n");
195
    return;
196
  }  
197
  //WL_DEBUG_PRINT_P("|api on branch");
198
    
199
  // get length and type
200
  while(i<3) {
201
    if (FLAG) {
202
      if (i==0) {
203
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
204
            && apitype == ESCAPE_MARKER)
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) {
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
    xbee_handle_at_command_response(atcommand,status,len-5);
336
    break; }
337
  case XBEE_FRAME_STATUS: {
338
    // modem status
339
    while(1) {
340
      if (FLAG) {
341
        if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
342
            && apitype == ESCAPE_MARKER) {
343
          apitype = PORT ^ ESCAPE_XOR;
344
          break;
345
        } else {
346
          apitype = PORT;
347
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
348
              && apitype == ESCAPE_MARKER)
349
            continue; // get escaped character
350
          break;
351
        }
352
      }
353
    }
354
    xbee_handle_status(apitype); // handle the modem status
355
    break; }
356
  case XBEE_FRAME_TX_STATUS: {
357
    // TX status
358
    uint8_t frame_id = 0;
359
    while(i<3) {
360
      if (FLAG) {
361
        if (i==1) {
362
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
363
              && apitype == ESCAPE_MARKER)
364
            apitype = PORT ^ ESCAPE_XOR;
365
          else {
366
            apitype = PORT;
367
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
368
                && apitype == ESCAPE_MARKER)
369
              continue; // get escaped character
370
          }
371
          frame_id = apitype;
372
        } else {
373
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
374
              && apitype == ESCAPE_MARKER)
375
            apitype = PORT ^ ESCAPE_XOR;
376
          else {
377
            apitype = PORT;
378
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
379
                && apitype == ESCAPE_MARKER)
380
              continue; // get escaped character
381
          }
382
          ackhandle(frame_id,apitype); // handle the status
383
          break;
384
        }
385
        i++;
386
      }
387
    }
388
    WL_DEBUG_PRINT_P("|XBEE_FRAME_TX_STATUS framenum:");
389
    WL_DEBUG_PRINT_HEX(frame_id);
390
    WL_DEBUG_PRINT_P(",status=");
391
    WL_DEBUG_PRINT_HEX(apitype);
392
    break; }
393
  case XBEE_FRAME_RX_64: {
394
    // receive a packet with 64bit address
395
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_64");
396
    break; } // TODO: implement this (even if we don't use it)
397
  case XBEE_FRAME_RX_16: {
398
    WL_DEBUG_PRINT_P("|B_last=");
399
    WL_DEBUG_PRINT_INT(basic_buf_last);
400
    // receive a packet with 16bit address
401
    uint16_t source = 0;
402
    uint8_t framenum = 0;
403
    uint8_t group = 0;
404
    uint8_t ptr=basic_buf_last;
405
    while(i<len) {
406
      if (FLAG) {
407
        WL_DEBUG_PRINT_P("|*i=");
408
        WL_DEBUG_PRINT_INT(i);
409
        WL_DEBUG_PRINT_P("|ptr=");
410
        WL_DEBUG_PRINT_INT(ptr);
411
        if (i==1) {
412
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
413
              && apitype == ESCAPE_MARKER)
414
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
415
          else {
416
            apitype = PORT;
417
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
418
                && apitype == ESCAPE_MARKER)
419
              continue; // get escaped character
420
          }
421
          source |= apitype<<8; // get source hi byte
422
        } else if (i==2) {
423
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
424
              && apitype == ESCAPE_MARKER)
425
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
426
          else {
427
            apitype = PORT;
428
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
429
                && apitype == ESCAPE_MARKER)
430
              continue; // get escaped character
431
          }
432
          source |= apitype; // get source lo byte
433
        } else if (i==3) {
434
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
435
              && apitype == ESCAPE_MARKER)
436
            apitype = PORT ^ ESCAPE_XOR; // get RSSI, and ignore
437
          else {
438
            apitype = PORT;
439
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
440
                && apitype == ESCAPE_MARKER)
441
              continue; // get escaped character
442
          }
443
        } else if (i==4) {
444
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
445
              && apitype == ESCAPE_MARKER)
446
            apitype = PORT ^ ESCAPE_XOR; // get options, and ignore
447
          else {
448
            apitype = PORT;
449
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
450
                && apitype == ESCAPE_MARKER)
451
              continue; // get escaped character
452
          }
453
        } else if (i==5) {
454
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
455
              && apitype == ESCAPE_MARKER)
456
            apitype = PORT ^ ESCAPE_XOR;
457
          else {
458
            apitype = PORT;
459
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
460
                && apitype == ESCAPE_MARKER)
461
              continue; // get escaped character
462
          }
463
          framenum = apitype; // get the frame number
464
/*          if (check_last_receive(source,framenum) != WL_SUCCESS) {
465
            // we've already received this frame
466
            ptr = 0xFF; // signal to skip processing
467
            break;
468
          }
469
*/      }
470
        else if (i==6) {
471
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
472
              && apitype == ESCAPE_MARKER)
473
            apitype = PORT ^ ESCAPE_XOR;
474
          else {
475
            apitype = PORT;
476
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
477
                && apitype == ESCAPE_MARKER)
478
              continue; // get escaped character
479
          }
480
          group = apitype; // get group number
481
            WL_DEBUG_PRINT_P("|ptr2=");
482
            WL_DEBUG_PRINT_INT(ptr);
483
          
484
          if (group == 0) {
485
            WL_DEBUG_PRINT_P("|last1=");
486
            WL_DEBUG_PRINT_INT(basic_buf_last);
487
            WL_DEBUG_PRINT_P("|ptr1=");
488
            WL_DEBUG_PRINT_INT(ptr);
489
            ptr = basic_buf_last;
490
            WL_DEBUG_PRINT_P("|last2=");
491
            WL_DEBUG_PRINT_INT(basic_buf_last);
492
            WL_DEBUG_PRINT_P("|ptr2=");
493
            WL_DEBUG_PRINT_INT(ptr);
494
            if (xbee_basic_buf_add(&ptr,0x00) != 0) {
495
              WL_DEBUG_PRINT_P("failed to write to buffer1");
496
              break;
497
            }
498
            WL_DEBUG_PRINT_P("|ptr3=");
499
            WL_DEBUG_PRINT_INT(ptr);
500
            // add source to basic buffer
501
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) {
502
              WL_DEBUG_PRINT_P("failed to write to buffer2");
503
              break;
504
            }
505
            WL_DEBUG_PRINT_P("|ptr4=");
506
            WL_DEBUG_PRINT_INT(ptr);
507
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) {
508
              WL_DEBUG_PRINT_P("failed to write to buffer3");
509
              break;
510
            }
511
            WL_DEBUG_PRINT_P("|ptr5=");
512
            WL_DEBUG_PRINT_INT(ptr);
513
          } else {
514
            ptr = other_buf_last;
515
            // add source and group to other buffer
516
            if (xbee_other_buf_add(&ptr,0x00) != 0) {
517
              WL_DEBUG_PRINT_P("failed to write to buffer3.5");
518
              break;
519
            }
520
            if (xbee_other_buf_add(&ptr,group) != 0) {
521
              WL_DEBUG_PRINT_P("failed to write to buffer4");
522
              break;
523
            }
524
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) {
525
              WL_DEBUG_PRINT_P("failed to write to buffer5");
526
              break;
527
            }
528
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) {
529
              WL_DEBUG_PRINT_P("failed to write to buffer6");
530
              break;
531
            }
532
          }
533
        }
534
        else {
535
          // put packet data on the correct buffer
536
          if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
537
              && apitype == ESCAPE_MARKER)
538
            apitype = PORT ^ ESCAPE_XOR;
539
          else {
540
            apitype = PORT;
541
            if (getStatus(XBEE_API_MASK) == XBEE_API_ESCAPE
542
                && apitype == ESCAPE_MARKER)
543
              continue; // get escaped character
544
          }
545
          if (group == 0) {
546
            if (xbee_basic_buf_add(&ptr,apitype) != 0) {
547
              WL_DEBUG_PRINT_P("failed to write to buffer7");
548
              break;
549
            }
550
          } else {
551
            if (xbee_other_buf_add(&ptr,apitype) != 0) {
552
              WL_DEBUG_PRINT_P("failed to write to buffer8");
553
              break;
554
            }
555
          }
556
        }
557
        i++;
558
      }
559
    }
560
    WL_DEBUG_PRINT_P("before_last=");
561
    if (group == 0)
562
      WL_DEBUG_PRINT_INT(basic_buf_last);
563
    else
564
      WL_DEBUG_PRINT_INT(other_buf_last);
565
    if (ptr != 0xFF && i > 6) {
566
      if (group == 0) {
567
        xbee_basic_buf[basic_buf_last] = i-5; // set length
568
        basic_buf_last = ptr;
569
      }
570
      else {
571
        xbee_other_buf[other_buf_last] = i-4; // set length  ** TODO: check this number
572
        // check if we have a high priority group
573
        /*for(;;)
574
          if (HIGH_PRIORITY) {
575
            // handle receive now
576
            ptr = 0xFF;
577
            break;
578
          }*/        
579
        //if (ptr != 0xFF) {
580
          // handle receive later
581
          other_buf_last = ptr;
582
        //}
583
      }
584
    }
585
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_16|len=");
586
    WL_DEBUG_PRINT_INT(len);
587
    WL_DEBUG_PRINT_P("|i=");
588
    WL_DEBUG_PRINT_INT(i);
589
    WL_DEBUG_PRINT_P("|source=");
590
    WL_DEBUG_PRINT_INT(source);
591
    WL_DEBUG_PRINT_P("|framenum=");
592
    WL_DEBUG_PRINT_INT(framenum);
593
    WL_DEBUG_PRINT_P("group=");
594
    WL_DEBUG_PRINT_INT(group);
595
    WL_DEBUG_PRINT_P("|ptr=");
596
    WL_DEBUG_PRINT_HEX(ptr);
597
    WL_DEBUG_PRINT_P("|first=");
598
    if (group == 0)
599
      WL_DEBUG_PRINT_INT(basic_buf_first);
600
    else
601
      WL_DEBUG_PRINT_INT(other_buf_first);
602
    WL_DEBUG_PRINT_P("|last=");
603
    if (group == 0)
604
      WL_DEBUG_PRINT_INT(basic_buf_last);
605
    else
606
      WL_DEBUG_PRINT_INT(other_buf_last);    
607
    WL_DEBUG_PRINT_P("|buffer=");
608
    if (group == 0) {
609
      for(uint8_t i=0;i<ptr;i++)
610
        WL_DEBUG_PRINT_HEX(xbee_basic_buf[i]);
611
    } else {
612
      for(uint8_t i=0;i<ptr;i++)
613
        WL_DEBUG_PRINT_HEX(xbee_other_buf[i]);
614
    }
615
    WL_DEBUG_PRINT_P("|\r\n");
616
    break; }
617
    default:
618
      WL_DEBUG_PRINT_P("|BAD APITYPE:");
619
      WL_DEBUG_PRINT_HEX(apitype);
620
      WL_DEBUG_PRINT_P("\r\n");
621
  } // end of switch statement
622
  while (1) {
623
    if (FLAG) {
624
      apitype = PORT; // get checksum, and ignore
625
      break;
626
    }
627
  }
628
  WL_DEBUG_PRINT_P("|interrupt - return\r\n");
629
} // end of interrupt 
630

    
631

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

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

    
721
/** status functions **/
722
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
723
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
724

    
725

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

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

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

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

    
939
/**
940
 * Sends a character to the XBee.
941
 *
942
 * @param c the byte to send
943
 * @return 0 for success, nonzero for failure
944
 **/
945
int8_t xbee_putc(uint8_t c) {
946

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

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

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

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

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

    
1020
#ifdef FIREFLY
1021
  loop_until_bit_is_set(UCSR0A, UDRE0);  
1022
  UDR0 = byte;
1023
#else
1024
  loop_until_bit_is_set(UCSR1A, UDRE1);
1025
  UDR1 = byte;
1026
#endif
1027
  
1028
  return WL_SUCCESS;
1029
}
1030

    
1031

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

    
1046
  return WL_SUCCESS;
1047
}
1048

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

    
1063
  return WL_SUCCESS;
1064
}
1065

    
1066

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

    
1077
  if (xbee_wait_for_ok() != WL_SUCCESS) {
1078
    return WL_ERROR_XBEE_COMMAND;
1079
  }
1080
  WL_DEBUG_PRINT_P("got OK\r\n");
1081
  
1082
  return WL_SUCCESS;
1083
}
1084

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

    
1098
  return WL_SUCCESS;
1099
}
1100

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

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

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

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

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

    
1222
  return 0;
1223
}
1224

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

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

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

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

    
1323

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

    
1342
  return WL_SUCCESS;
1343
}
1344

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

    
1362
  // send body
1363
  if (xbee_send(buf, len) != WL_SUCCESS)
1364
    return WL_ERROR_SEND;
1365
  
1366
  // send checksum
1367
  if (xbee_sendc(checksum) != WL_SUCCESS)
1368
    return WL_ERROR_SEND;
1369
  
1370
  return WL_SUCCESS;
1371
}
1372

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

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

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

    
1410
  return xbee_send_frame(buf, 4 + len);
1411
}
1412

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

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

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

    
1472
  // send packet
1473
  if (xbee_send(packet, len) != WL_SUCCESS)
1474
    return WL_ERROR_SEND;
1475

    
1476
  // send checksum
1477
  if (xbee_sendc(sum) != WL_SUCCESS)
1478
    return WL_ERROR_SEND;
1479

    
1480
  return WL_SUCCESS;
1481
}
1482

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

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

    
1578
  return WL_SUCCESS;
1579
}
1580

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

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

    
1647
/**
1648
 * Set the channel the XBee is using.
1649
 *
1650
 * @param channel the channel the XBee will not use,
1651
 * between 0x0B and 0x1A
1652
 *
1653
 * @see xbee_get_channel
1654
 **/
1655
int8_t xbee_set_channel(uint8_t channel)
1656
{
1657
  if (channel < 0x0B || channel > 0x1A)
1658
  {
1659
    WL_DEBUG_PRINT_P("Channel out of range.\r\n");
1660
    return WL_ERROR_ARGUMENT;
1661
  }
1662

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

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

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

    
1752
/**@} **/ // end xbee group
1753