Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (33.5 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

    
35
#include <string.h>
36
#include <avr/interrupt.h>
37
#include <time.h>
38
#include "wl_defs.h"
39
#include "wireless.h"
40
#include "xbee.h"
41

    
42

    
43
/* Internal Function Prototypes */
44

    
45
/* I/O Functions */
46
static int8_t xbee_send_string(uint8_t* c);
47

    
48
/* Command Mode Functions */
49
static int8_t xbee_enter_command_mode(void);
50
static int8_t xbee_exit_command_mode(void);
51
static int8_t xbee_enter_api_mode(void);
52
static int8_t xbee_exit_api_mode(void);
53
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len);
54
static int8_t xbee_wait_for_ok(void);
55

    
56
/* API Mode Functions */
57
//TODO: does this exist?  static int8_t xbee_handle_packet(uint8_t* packet, uint16_t len);
58
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
59
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
60
static void xbee_handle_status(uint8_t status);
61
static int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len);
62
static uint8_t xbee_compute_checksum(uint8_t* packet, uint16_t len);
63
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len);
64
int8_t xbee_send_read_at_command(uint8_t* command);
65
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len);
66

    
67
/* Buffer Manipulation Functions */
68
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte);
69
uint8_t xbee_basic_buf_get(uint8_t *ptr);
70
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte);
71

    
72
/* private functions */
73
int8_t check_last_receive(uint16_t source,uint8_t framenum);
74
inline uint8_t getStatus(uint8_t mask);
75
inline void setStatus(uint8_t mask,uint8_t value);
76

    
77
/*Global Variables*/
78

    
79
// last few packet sources and frame nums
80
#define NUM_LAST_PACKETS 10
81
struct {
82
  uint16_t source;
83
  uint8_t framenum;
84
} lastPacket[NUM_LAST_PACKETS];
85

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

    
89
// beginning of first packet in basic buffer
90
static uint8_t basic_buf_first = 0;
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
static uint8_t basic_buf_last = 0;
95

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

    
99
// beginning of first packet in other buffer
100
static uint8_t other_buf_first = 0;
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
static uint8_t other_buf_last = 0;
105

    
106
// xbee status
107
#define XBEE_API_OFF 0x00
108
#define XBEE_API_ON 0x10
109
#define XBEE_API_ESCAPE 0x20
110
#define XBEE_API_MASK 0x30
111
#define XBEE_COMMAND_WAIT 0x80
112
#define XBEE_COMMAND_RESPONSE 0xC0
113
#define XBEE_COMMAND_NONE 0x00
114
#define XBEE_COMMAND_MASK 0xC0
115
#define XBEE_NOT_INITD 0xF0
116
#define LAST_PACKET_MASK 0x0F
117
uint8_t xbee_status = XBEE_NOT_INITD;
118

    
119
// xbee command response (for PAN, channel, address, etc)
120
static uint8_t xbee_command[4];
121

    
122
// external ack handler (wireless_send.c)
123
extern void ackhandle(uint8_t num,uint8_t val);
124

    
125

    
126
/**@addtogroup xbee
127
 * @{ **/
128

    
129
/*Function Implementations*/
130

    
131
/**
132
 * Interrupt for the robot. Adds bytes received from the xbee
133
 * to the buffer.
134
 **/
135
 
136
#ifndef FIREFLY
137
ISR(USART1_RX_vect)
138
{
139
WL_DEBUG_PRINT("\nOut of space in buffer.\n");
140
        /*char c = UDR1;
141
        arrival_buf[buffer_last] = c;
142
        int t = buffer_last + 1;
143
        if (t == XBEE_BUFFER_SIZE)
144
                t = 0;
145
        if (t == buffer_first)
146
        {
147
                
148
        }
149
        buffer_last = t;*/
150
}
151
#else
152
SIGNAL(SIG_USART0_RECV)
153
{
154
        WL_DEBUG_PRINT("Out of space in buffer.\n");
155
        /*char c = UDR0;
156
        arrival_buf[buffer_last] = c;
157
        int t = buffer_last + 1;
158
        if (t == XBEE_BUFFER_SIZE)
159
                t = 0;
160
        if (t == buffer_first)
161
        {
162
        }
163
        buffer_last = t;*/
164
}
165
#endif
166
 
167
 
168
#include <lights.h>
169
//#ifndef FIREFLY
170
//#define PORT UDR1
171
//#define FLAG RXC1
172
//ISR(USART1_RX_vect)
173
//#else
174
#define PORT UDR0
175
#define FLAG RXC0
176
/*SIGNAL(SIG_USART0_RECV)
177
{//#endif
178
  // start of frame
179
  uint8_t apitype = PORT; // get frame start byte
180
  uint16_t i=0;
181
  uint16_t len=0;
182
  
183
  orb_set_color(RED);
184
  
185
  usb_puts("xbee_interrupt");
186
  
187
  WL_DEBUG_PRINT("in interrupt|status=");
188
  WL_DEBUG_PRINT_HEX(xbee_status);
189
  
190
  // check that we're in API mode
191
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
192
    // not in API mode
193
    WL_DEBUG_PRINT("|API OFF");
194
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT) {
195
      // get rest of command and put in basic buf
196
      xbee_basic_buf[0] = apitype;
197
      if (xbee_basic_buf[i] != '\r') {
198
        while(i < PACKET_BUFFER_SIZE) {
199
          if (FLAG) {
200
            xbee_basic_buf[i] = PORT;
201
            if (xbee_basic_buf[i] == '\r')
202
              break;
203
          }
204
        }
205
      }
206
      WL_DEBUG_PRINT("got packet=");
207
      WL_DEBUG_PRINT(xbee_basic_buf);
208
      // signal handler that command response is done
209
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
210
    }
211
    WL_DEBUG_PRINT("return\r\n");
212
    return;
213
  }  
214
  WL_DEBUG_PRINT("|API ON");
215
    
216
  // get length and type
217
  while(i<3) {
218
    if (FLAG) {
219
      if (i==0)
220
        len |= PORT<<8;
221
      else if (i==1)
222
        len |= PORT;
223
      else if (i==2)
224
        apitype = PORT;
225
      i++;
226
    }
227
  }
228
  WL_DEBUG_PRINT("|len=");
229
  WL_DEBUG_PRINT_INT(len);
230
  WL_DEBUG_PRINT("|apitype=");
231
  WL_DEBUG_PRINT_HEX(apitype);
232
  WL_DEBUG_PRINT("\r\n");
233
  
234
  // do something based on the type
235
  i=1;
236
  switch(apitype) {
237
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
238
    // AT command response
239
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
240
      return; // we're currently processing a command, so drop the incoming one
241
    uint16_t atcommand=0;
242
    uint8_t ptr=basic_buf_last;
243
    while(i<len) {
244
      if (FLAG) {
245
        if (i==1)
246
          apitype = PORT; // get frame id, but ignore it
247
        else if (i==2)
248
          atcommand |= PORT<<8; // get command char1
249
        else if (i==3)
250
          atcommand |= PORT; // get command char2
251
        else if (i==4)
252
          apitype = PORT; // get status
253
        else {
254
          // put the command response on the basic buf temporarily
255
          if (xbee_basic_buf_add(&ptr,PORT) != 0)
256
            break;
257
        }
258
        i++;
259
      }
260
    }  
261
    // handle AT command  
262
    xbee_handle_at_command_response(atcommand,apitype,i-5); // TODO: rewrite function
263
    break; }
264
  case XBEE_FRAME_TX_STATUS: {
265
    // TX status
266
    uint8_t frame_id = 0;
267
    while(i<len) {
268
      if (FLAG) {
269
        if (i==1)
270
          frame_id = PORT;
271
        else {
272
          ackhandle(frame_id,PORT); // handle the status
273
          break;
274
        }
275
        i++;
276
      }
277
    }
278
    break; }
279
  case XBEE_FRAME_RX_64: {
280
    // receive a packet with 64bit address
281
    break; } // TODO: implement this (even if we don't use it)
282
  case XBEE_FRAME_RX_16: {
283
    // receive a packet with 16bit address
284
    uint16_t source = 0;
285
    uint8_t framenum = 0;
286
    uint8_t group = 0;
287
    uint8_t ptr=basic_buf_last;
288
    while(i<len) {
289
      if (FLAG) {
290
        if (i==1)
291
          source |= PORT<<8; // get source hi byte
292
        else if (i==2)
293
          source |= PORT; // get source lo byte
294
        else if (i==3)
295
          apitype = PORT; // get RSSI, and ignore
296
        else if (i==4)
297
          apitype = PORT; // get options, and ignore
298
        else if (i==5) {
299
          framenum = PORT; // get the frame number
300
          if (check_last_receive(source,framenum) != WL_SUCCESS) {
301
            // we've already received this frame
302
            ptr = 0xFF; // signal to skip processing
303
            break;
304
          }
305
        }
306
        else if (i==6) {
307
          group = PORT; // get group number
308
          if (group == 0) {
309
            ptr = basic_buf_last+1;
310
            // add source to buffer
311
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
312
              break;
313
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
314
              break;
315
          } else {
316
            ptr = other_buf_last+1;
317
            // add source and group to buffer
318
            if (xbee_other_buf_add(&ptr,group) != 0)
319
              break;
320
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
321
              break;
322
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
323
              break;
324
          }
325
        }
326
        else { // TODO: handle escaped characters supported by APIv2
327
          // put packet data on the correct buffer
328
          if (group == 0 && xbee_basic_buf_add(&ptr,PORT) != 0)
329
            break;
330
          else if (xbee_other_buf_add(&ptr,PORT) != 0)
331
            break;
332
        }
333
        i++;
334
      }
335
    }
336
    if (ptr != 0xFF && i > 6) {
337
      if (group == 0) {
338
        xbee_basic_buf[basic_buf_last] = i-6; // set length
339
        basic_buf_last = ptr;
340
      }
341
      else {        
342
        xbee_other_buf[other_buf_last] = i-6; // set length
343
        // check if we have a high priority group
344
        for(;;)
345
          if (HIGH_PRIORITY) {
346
            // handle receive now
347
            ptr = 0xFF;
348
            break;
349
          }        
350
        if (ptr != 0xFF) {
351
          // handle receive later
352
          other_buf_last = ptr;
353
        }
354
      }
355
    }
356
    break; }
357
  } // end of switch statement
358
  while (1) {
359
    if (FLAG) {
360
      apitype = PORT; // get checksum, and ignore
361
      break;
362
    }
363
  }
364
  WL_DEBUG_PRINT("return\r\n");
365
} // end of interrupt 
366
*/
367

    
368
/* adds a byte to the basic buffer */
369
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
370
  if (*ptr == basic_buf_first) {
371
    // buffer full
372
    WL_DEBUG_PRINT("basic buffer full\r\n");
373
    return -1;
374
  }
375
  xbee_basic_buf[(*ptr)++] = byte;
376
  if (*ptr == PACKET_BUFFER_SIZE)
377
    *ptr = 0;
378
  return 0;
379
}
380
/* gets a byte from the basic buffer */
381
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
382
  uint8_t byte = xbee_basic_buf[(*ptr)++];
383
  if (*ptr == PACKET_BUFFER_SIZE)
384
    *ptr = 0;
385
  return byte;
386
}
387
/* adds a byte to the other buffer */
388
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
389
  if (*ptr == other_buf_first) {
390
    // buffer full
391
    WL_DEBUG_PRINT("other buffer full\r\n");
392
    return -1;
393
  }
394
  xbee_other_buf[(*ptr)++] = byte;
395
  if (*ptr == PACKET_BUFFER_SIZE)
396
    *ptr = 0;
397
  return 0;
398
}
399

    
400
/**
401
 * Checks if packet is a duplicate
402
 **/
403
int8_t check_last_receive(uint16_t source,uint8_t framenum) {
404
  uint8_t i=0;
405
  for(;i<NUM_LAST_PACKETS;i++) {
406
    if (lastPacket[i].source == source && lastPacket[i].framenum == framenum)
407
      return -1; // duplicate packet, so return error
408
  }
409
  // save packet source and framenum
410
  i=getStatus(LAST_PACKET_MASK);
411
  lastPacket[i].source = source;
412
  lastPacket[i].framenum = framenum;
413
  if (++i>=NUM_LAST_PACKETS)
414
    i = 0;
415
  setStatus(LAST_PACKET_MASK,i);
416
  return WL_SUCCESS;
417
}
418

    
419
/** status functions **/
420
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
421
inline void setStatus(uint8_t mask,uint8_t value) { xbee_status = (xbee_status&(!mask))|value; }
422

    
423

    
424
/**
425
 * Initializes the XBee library so that other functions may be used.
426
 **/
427
int8_t xbee_init()
428
{
429
  WL_DEBUG_PRINT("in xbee_init\n");
430
  
431
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
432
    return WL_ERROR_INIT_ALREADY_INITD;
433
  }
434
  
435
  // clear last packet buffer
436
  for(int i=0;i<NUM_LAST_PACKETS;i++)
437
    lastPacket[i].source = lastPacket[i].framenum = 0;
438
  
439
  // Set startup baud rate of 9600
440
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
441
  // Enable receiver and transmitter and the receiving interrupt
442
#ifdef FIREFLY
443
  UCSR0A |= (1<<U2X0);
444
  UBRR0H = 0x00;
445
  UBRR0L = 103;
446
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
447
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); 
448
#else
449
  // Bayboard or robot
450
  UCSR1A |= (1<<U2X1);
451
  UBRR1H = 0x00;
452
  UBRR1L = 103;
453
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
454
  UCSR1B |= (1<<RXEN1) | (1<<TXEN1) | (1<<RXCIE1);
455
#endif
456
  sei();
457

    
458
  WL_DEBUG_PRINT("Entering command mode.\r\n");
459
  if (xbee_enter_command_mode() != 0) {
460
    WL_DEBUG_PRINT("error entering command mode\r\n");
461
    return -1;
462
  }
463
  WL_DEBUG_PRINT("Entered command mode.\r\n");
464

    
465
  
466
  // set baud on xbee
467
#if (XBEE_BAUD == 115200)
468
  xbee_send_string((uint8_t*)"ATBD7\r");
469
  xbee_send_string((uint8_t*)"ATBD7\r");
470
#elif (XBEE_BAUD == 57600)
471
  xbee_send_string((uint8_t*)"ATBD6\r");
472
#elif (XBEE_BAUD == 38400)
473
  xbee_send_string((uint8_t*)"ATBD5\r");
474
#elif (XBEE_BAUD == 19200)
475
  xbee_send_string((uint8_t*)"ATBD4\r");
476
#elif (XBEE_BAUD == 9600)
477
  // already at this baud rate
478
  //xbee_send_string("ATBD3\r\n");
479
#else
480
  WL_DEBUG_PRINT("undefined baud rate\r\n");
481
  return WL_ERROR_BAUD;
482
#endif  
483
  // exit command mode
484
  xbee_wait_for_ok();
485
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
486
  xbee_send_string((uint8_t*)"ATCN\r");
487
  xbee_wait_for_ok();
488
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
489
  
490
  // set UART baud
491
#ifdef FIREFLY
492
#if (XBEE_BAUD == 115200)
493
  UBRR0H = 0x00;
494
  UBRR0L = 8;
495
#elif (XBEE_BAUD == 57600)
496
  UBRR0H = 0x00;
497
  UBRR0L = 16;
498
#elif (XBEE_BAUD == 38400)
499
  UBRR0H = 0x00;
500
  UBRR0L = 25;
501
#elif (XBEE_BAUD == 19200)
502
  UBRR0H = 0x00;
503
  UBRR0L = 51;
504
#elif (XBEE_BAUD == 9600)
505
  /* this is the default baud rate, so do nothing
506
  UBRR0H = 0x00;
507
  UBRR0L = 103;*/
508
#else
509
  WL_DEBUG_PRINT("undefined baud rate\r\n");
510
  return WL_ERROR_BUAD;
511
#endif
512
#else // Bayboard or robot
513
#if (XBEE_BAUD == 115200)
514
  UBRR1H = 0x00;
515
  UBRR1L = 8;
516
#elif (XBEE_BAUD == 57600)
517
  UBRR1H = 0x00;
518
  UBRR1L = 16;
519
#elif (XBEE_BAUD == 38400)
520
  UBRR1H = 0x00;
521
  UBRR1L = 25;
522
#elif (XBEE_BAUD == 19200)
523
  UBRR1H = 0x00;
524
  UBRR1L = 51;
525
#elif (XBEE_BAUD == 9600)
526
  /* this is the default baud rate, so do nothing
527
  UBRR1H = 0x00;
528
  UBRR1L = 103;*/
529
#else
530
  WL_DEBUG_PRINT("undefined baud rate\r\n");
531
  return WL_ERROR_BUAD;
532
#endif
533
#endif
534
  delay_ms(50);
535

    
536
  // enter command mode
537
  WL_DEBUG_PRINT("entering command mode 2\r\n");
538
  xbee_send_string((uint8_t*)"+++");
539
  xbee_wait_for_ok();
540
  WL_DEBUG_PRINT("entered command mode 2\r\n");
541
  
542
  if (xbee_enter_api_mode() != 0) {
543
    WL_DEBUG_PRINT("can't enter api mode\r\n");
544
    return -1;
545
  }
546

    
547
  WL_DEBUG_PRINT("Entered api mode.\r\n");
548

    
549
  if (xbee_exit_command_mode() != 0) {
550
    WL_DEBUG_PRINT("can't exit command mode\r\n");
551
    return -1;
552
  }
553
  
554
  WL_DEBUG_PRINT("Left command mode.\r\n");
555
  
556
  // TODO: we should set the MY address to the robot address from eeprom
557
  
558
  
559
  // set status
560
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
561
  
562
  return WL_SUCCESS;
563
}
564

    
565
/**
566
 * Call when finished using the XBee library.
567
 **/
568
int8_t xbee_terminate()
569
{
570
  int ret=xbee_exit_api_mode();
571
  if (ret != WL_SUCCESS) {
572
    WL_DEBUG_PRINT("xbee termination failed\r\n");
573
    WL_DEBUG_PRINT_INT(ret);
574
    WL_DEBUG_PRINT("|\r\n");
575
    return WL_ERROR_TERMINATION_FAILED;
576
  }
577
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
578
  return WL_SUCCESS;
579
}
580

    
581
/**
582
 * Sends a character to the XBee.
583
 *
584
 * @param c the byte to send
585
 * @return 0 for success, nonzero for failure
586
 **/
587
int8_t xbee_putc(uint8_t c) {
588

    
589
  // Wait until buffer is clear for sending
590
  // Then load buffer with your character
591
#ifdef FIREFLY
592
  loop_until_bit_is_set(UCSR0A, UDRE0);  
593
  UDR0 = c;
594
#else
595
  loop_until_bit_is_set(UCSR1A, UDRE1);
596
  UDR1 = c;
597
#endif
598
  
599
  return WL_SUCCESS;
600
}
601

    
602
/**
603
 * Returns the first byte in the buffer received from xbee.
604
 * This function blocks execution until a character has been
605
 * received. xbee_init must be called before this function
606
 * may be used.
607
 * 
608
 * @return the first character in the xbee buffer, -1 on error
609
 * 
610
 * @see xbee_init, xbee_getc_nb
611
 **/
612
int16_t xbee_getc(void) {
613
    
614
  // Wait for the receive buffer to be filled
615
  // Then read the receive buffer
616
#ifdef FIREFLY
617
  loop_until_bit_is_set(UCSR0A, RXC0);  
618
  return UDR0;
619
#else
620
  loop_until_bit_is_set(UCSR1A, RXC1);
621
  return UDR1;
622
#endif
623
}
624

    
625
/**
626
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
627
 * it is returned, otherwise -1 is returned immediately. xbee_init
628
 * must be called before this function can be used.
629
 *
630
 * @param c The received byte. This will be set if a byte has been received.
631
 * 
632
 * @return -1 If no byte is available, 0 otherwise, positive for error
633
 *
634
 * @see xbee_getc
635
 **/
636
int8_t xbee_getc_nb(uint8_t *c) {
637

    
638
  // check if the receive buffer is filled
639
#ifdef FIREFLY
640
  if (UCSR0A & (1<<RXC0)) {
641
    (*c) = UDR0;
642
#else
643
  if (UCSR1A & (1<<RXC1)) {
644
    (*c) = UDR1;
645
#endif
646
    return WL_SUCCESS;
647
  }
648
  return -1; // Return empty
649
}
650

    
651
/**
652
 * Send a buffer buf of size bytes to the XBee.
653
 *
654
 * @param buf the buffer of data to send
655
 * @param size the number of bytes to send
656
 **/
657
int8_t xbee_send(uint8_t* buf, uint16_t size)
658
{
659
  uint16_t i=0; // check if we need this variable
660
  while(i<size) {
661
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
662
      return WL_ERROR_SEND;
663
  }  
664
  if (xbee_putc(buf[0]) != WL_SUCCESS)
665
    return WL_ERROR_SEND;
666

    
667
  return WL_SUCCESS;
668
}
669

    
670
/**
671
 * Sends a string to the XBee.
672
 *
673
 * @param c the string to send to the XBEE
674
 **/
675
static int8_t xbee_send_string(uint8_t* c)
676
{
677
  return xbee_send(c, strlen((char*)c));
678
}
679

    
680

    
681
/**
682
 * Enter into command mode.
683
 **/
684
static int8_t xbee_enter_command_mode(void)
685
{
686
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
687
    return WL_ERROR_XBEE_COMMAND;
688
  }
689

    
690
  if (xbee_wait_for_ok() != WL_SUCCESS) {
691
    return WL_ERROR_XBEE_COMMAND;
692
  }
693
  
694
  return WL_SUCCESS;
695
}
696

    
697
/**
698
 * Exit from command mode.
699
 **/
700
static int8_t xbee_exit_command_mode()
701
{
702
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
703
    return WL_ERROR_SEND;
704
  }
705
  xbee_wait_for_ok();
706

    
707
  return WL_SUCCESS;
708
}
709

    
710
/**
711
 * Enter API mode.
712
 **/
713
static int8_t xbee_enter_api_mode(void) {
714
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
715
    return WL_ERROR_SEND;
716
  }
717
  xbee_wait_for_ok();
718
  
719
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
720

    
721
  return WL_SUCCESS;
722
}
723

    
724
/**
725
 * Enter API mode 2.
726
 **/
727
static int8_t xbee_enter_api_mode2(void) {
728
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
729
    return WL_ERROR_SEND;
730
  }
731
  xbee_wait_for_ok();
732
  
733
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
734
  
735
  return WL_SUCCESS;
736
}
737

    
738
/**
739
 * Exit API mode.
740
 **/
741
static int8_t xbee_exit_api_mode()
742
{
743
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
744
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
745
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
746
  
747
  int16_t i=0;
748
  // change status to command wait
749
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
750
  xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)"0",1); // send command
751
  // wait for up to 30 ms
752
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
753
    delay_us(1); // wait 3us
754
  }
755
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P')
756
    i = WL_SUCCESS;
757
  else
758
    i = WL_ERROR_XBEE_COMMAND; // set error code
759
  setStatus(XBEE_API_MASK,XBEE_API_OFF); // reset status
760
  return (int8_t)i; // return
761
}
762

    
763
/**
764
 * Wait until the string "OK\r" is received from the XBee.
765
 **/
766
static int8_t xbee_wait_for_ok()
767
{
768
  return xbee_wait_for_string((uint8_t*)"OK\r", 3);
769
}
770

    
771
/**
772
 * Delay until the specified string is received from
773
 * the XBee.
774
 *
775
 * Only works when not in API mode
776
 *
777
 * @param s the string to receive
778
 * @param len the length of the string
779
 **/
780
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
781
{
782
  uint8_t i=0;
783
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
784
    // wait until the response is received (only wait 1 second)
785
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
786
      delay_us(1);
787
    }
788
    // check response
789
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
790
      // bad response
791
      WL_DEBUG_PRINT("Bad response when waiting for string ");
792
      WL_DEBUG_PRINT(s);
793
      WL_DEBUG_PRINT("\r\n");
794
      return -1;
795
    }
796
    
797
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
798
  }
799

    
800
  return 0;
801
}
802

    
803
/**
804
 * Delay until we receive a command response.
805
 * (either OK\r or some actual value)
806
 *
807
 * Only works when not in API mode
808
 *
809
 * @param s the string to store the response in
810
 * @param len the length of the string
811
 */
812
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
813
  uint8_t i=0;
814
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
815
    // wait until the response is received (only wait 1 second)
816
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
817
      delay_us(1);
818
    }
819
    // check response
820
    if (i >= 1000) {
821
      return -1;
822
    } else {
823
      i=strcspn((char*)xbee_basic_buf,"\r");
824
      if (i<PACKET_BUFFER_SIZE) {
825
        memcpy(s,xbee_basic_buf,i);
826
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
827
        return 0;
828
      }
829
      else
830
        return -1;      
831
    }
832
  }
833
  // TODO: do something for API mode
834
  
835
  return 0;
836
}
837

    
838
/**  TODO: since we don't use this, do we need it?
839
 *
840
 * Verifies that the packets checksum is correct.
841
 * (If the checksum is correct, the sum of the bytes
842
 * is 0xFF.)
843
 *
844
 * @param packet the packet received. This includes the first
845
 * three bytes, which are header information from the XBee.
846
 *
847
 * @param len The length of the packet received from the XBee
848
 *
849
 * @return 0 if the checksum is incorrect, nonzero
850
 * otherwise
851
 **/
852
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
853
{
854
  uint8_t sum = 0;
855
  while(--len > 0) {
856
    sum += packet[len];
857
  }
858
  sum += packet[0];
859
  return (sum == 0xFF);
860
}
861

    
862
/**
863
 * Returns the checksum of the given packet.
864
 *
865
 * @param buf the data for the packet to send
866
 * @param len the length of the packet in bytes
867
 *
868
 * @return the checksum of the packet, which will
869
 * become the last byte sent in the packet
870
 **/
871
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
872
{
873
  uint8_t sum = 0;
874
  while(--len > 0) {
875
    sum += buf[len];
876
  }
877
  sum += buf[0];
878
  return 0xFF - sum;
879
}
880

    
881
/**
882
 * Adds buf to the previous checksum total
883
 *
884
 * @param buf a byte buffer to add to the checksum
885
 * @param len the length of the buffer
886
 * @param sum the previous sum
887
 *
888
 * @return error code
889
 **/
890
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
891
  if (buf == NULL || sum == NULL)
892
    return WL_ERROR_ARGUMENT;
893
  while(--len > 0) {
894
    *sum += buf[len];
895
  }
896
  *sum += buf[0];
897
  return WL_SUCCESS;
898
}
899

    
900

    
901
/**
902
 * Sends header information. Header information includes
903
 * XBEE_FRAME_START and the packet length, as two bytes.
904
 *
905
 * @param type the packet type
906
 * @param len the size in bytes of the packet data
907
 *
908
 **/
909
int8_t xbee_send_header(uint8_t type, uint16_t len)
910
{  
911
  //packet prefix
912
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
913
    return WL_ERROR_SEND;
914
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
915
    return WL_ERROR_SEND;
916
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
917
    return WL_ERROR_SEND;
918

    
919
  return WL_SUCCESS;
920
}
921

    
922
/**
923
 * Adds header information and checksum to the given
924
 * packet and sends it. Header information includes
925
 * XBEE_FRAME_START and the packet length, as two bytes.
926
 *
927
 * @param buf the packet data
928
 * @param len the size in bytes of the packet data
929
 *
930
 **/
931
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
932
{
933
  uint8_t checksum = xbee_compute_checksum(buf, len);
934
  
935
  //packet prefix
936
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
937
    return WL_ERROR_SEND;
938
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
939
    return WL_ERROR_SEND;
940
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
941
    return WL_ERROR_SEND;
942

    
943
  if (xbee_send(buf, len) != WL_SUCCESS)
944
    return WL_ERROR_SEND;
945
  
946
  if (xbee_putc(checksum) != WL_SUCCESS)
947
    return WL_ERROR_SEND;
948
  
949
  return WL_SUCCESS;
950
}
951

    
952
/**
953
 * Sends an AT command to read a parameter.
954
 *
955
 * @param command the AT command to send. For exmaple,
956
 * use ID to read the PAN ID and MY to return the XBee ID.
957
 * See the XBee reference guide for a complete listing.
958
 **/
959
int8_t xbee_send_read_at_command(uint8_t* command)
960
{
961
  return xbee_send_modify_at_command(command, NULL, 0);
962
}
963

    
964
/**
965
 * Sends the given AT command.
966
 *
967
 * @param command the AT command to send (e.g., MY, ID)
968
 * @param value the value to pass as a parameter
969
 * (or NULL if there is no parameter)
970
 **/
971
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
972
{
973
  uint8_t buf[12];
974

    
975
  buf[0] = XBEE_FRAME_AT_COMMAND;
976
  buf[1] = 1;
977
  buf[2] = command[0];
978
  buf[3] = command[1];
979
  if (value != NULL)
980
  {
981
    if (len > 8)
982
    {
983
      WL_DEBUG_PRINT("AT Command too large.\r\n");
984
      return WL_ERROR_ARGUMENT;
985
    }
986
    memcpy(buf+4,value,len);
987
  }
988

    
989
  return xbee_send_frame(buf, 4 + len);
990
}
991

    
992
/**
993
 * Send the specified packet.
994
 *
995
 * @param packet the packet data to send
996
 * @param len the number of bytes in the packet
997
 *
998
 * @param dest the ID of the XBee to send the packet to,
999
 * or XBEE_BROADCAST to send the message to all robots
1000
 * in the PAN.
1001
 *
1002
 * @param options a combination of the flags
1003
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1004
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1005
 *
1006
 * @param frame the frame number to associate this packet
1007
 * with. This will be used to identify the response when
1008
 * the XBee alerts us as to whether or not our message
1009
 * was received.
1010
 **/
1011
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1012
{
1013
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1014
  uint8_t i = 0;
1015

    
1016
  if (len > 100)
1017
  {
1018
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1019
    return WL_ERROR_ARGUMENT;
1020
  }
1021
  
1022
  // calculate checksum
1023
  for(;i<len;i++)
1024
    sum += packet[len];
1025
  sum += frame;
1026
  sum += (dest&0xFF00) >> 8;
1027
  sum += dest&0x00FF;
1028
  sum += options;
1029
  sum = 0xFF - sum;
1030

    
1031
  //packet prefix
1032
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1033
    return WL_ERROR_SEND;
1034
  if (xbee_putc(0x00) != WL_SUCCESS)
1035
    return WL_ERROR_SEND;
1036
  if (xbee_putc(len+5) != WL_SUCCESS)
1037
    return WL_ERROR_SEND;
1038
    
1039
  //send header for TX request
1040
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1041
    return WL_ERROR_SEND;
1042
  if (xbee_putc(frame) != WL_SUCCESS)
1043
    return WL_ERROR_SEND;
1044
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1045
    return WL_ERROR_SEND;
1046
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1047
    return WL_ERROR_SEND;
1048
  if (xbee_putc(options) != WL_SUCCESS)
1049
    return WL_ERROR_SEND;
1050

    
1051
  // send packet
1052
  if (xbee_send(packet, len) != WL_SUCCESS)
1053
    return WL_ERROR_SEND;
1054

    
1055
  // send checksum
1056
  if (xbee_putc(sum) != WL_SUCCESS)
1057
    return WL_ERROR_SEND;
1058

    
1059
  return WL_SUCCESS;
1060
}
1061

    
1062
/**
1063
 * Handles modem status packets.
1064
 *
1065
 * @param status the type of status packet received.
1066
 **/
1067
void xbee_handle_status(uint8_t status)
1068
{
1069
  switch (status)
1070
  {
1071
    case 0:
1072
      WL_DEBUG_PRINT("XBee hardware reset.\r\n");
1073
      break;
1074
    case 1:
1075
      WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
1076
      break;
1077
    case 2:
1078
      WL_DEBUG_PRINT("Associated.\r\n");
1079
      break;
1080
    case 3:
1081
      WL_DEBUG_PRINT("Disassociated.\r\n");
1082
      break;
1083
    case 4:
1084
      WL_DEBUG_PRINT("Synchronization lost.\r\n");
1085
      break;
1086
    case 5:
1087
      WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1088
      break;
1089
    case 6:
1090
      WL_DEBUG_PRINT("Coordinator started.\r\n");
1091
      break;
1092
  }
1093
}
1094

    
1095
/**
1096
 * Handles AT command response packets.
1097
 * @param command the two character AT command, e.g. MY or ID
1098
 * @param result 0 for success, 1 for an error
1099
 * @param len the length in bytes of extra
1100
 **/
1101
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len)
1102
{
1103
  if (result == 1)
1104
  {
1105
    WL_DEBUG_PRINT("Error with AT");
1106
    WL_DEBUG_PRINT(command);
1107
    WL_DEBUG_PRINT(" packet. Result = ");
1108
    switch(result) {
1109
    case 1:
1110
      WL_DEBUG_PRINT("ERROR\r\n");
1111
      break;
1112
    case 2:
1113
      WL_DEBUG_PRINT("Invalid Command\r\n");
1114
      break;
1115
    case 3:
1116
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
1117
      break;
1118
    }
1119
    return WL_SUCCESS;
1120
  }
1121
  WL_DEBUG_PRINT("AT");
1122
  WL_DEBUG_PRINT(command);
1123
  WL_DEBUG_PRINT(" command was successful.\r\n");
1124
  
1125
  // TODO: program more command responses here (ND, etc)
1126
  switch(command) {
1127
  case ('I'<<8)+'D': // PAN
1128
  case ('C'<<8)+'H': // channel
1129
  case ('M'<<8)+'Y': // address
1130
    // copy command to handler
1131
    xbee_command[0] = (command&0xFF00)>>8;
1132
    xbee_command[1] = command&0x00FF;
1133
    result = basic_buf_last;
1134
    for(command=2;command<len+2;command++)
1135
      xbee_command[command] = xbee_basic_buf_get(&result);
1136
    break;
1137
  default:
1138
    WL_DEBUG_PRINT("unknown AT command");
1139
  }
1140
  
1141
  // signal handler that command response is done
1142
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE);
1143

    
1144
  return WL_SUCCESS;
1145
}
1146

    
1147
/**
1148
 * Sets the personal area network id.
1149
 *
1150
 * @param id the new personal area network (PAN) id
1151
 **/
1152
int8_t xbee_set_pan_id(uint16_t id)
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
  
1158
  int16_t i=0;
1159
  // change status to command wait
1160
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1161
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1162
  // wait for up to 30 ms
1163
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1164
    delay_us(1); // wait 3us
1165
  }
1166
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1167
    i = WL_SUCCESS;
1168
  else
1169
    i = WL_ERROR_XBEE_COMMAND; // set error code
1170
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1171
  return (int8_t)i; // return
1172
}
1173

    
1174
/**
1175
 * Get the PAN ID for the XBee.
1176
 *
1177
 * @return the personal area network id, or
1178
 * XBEE_PAN_DEFAULT if it has not yet been set.
1179
 **/
1180
uint16_t xbee_get_pan_id()
1181
{
1182
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1183
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1184
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1185
  
1186
  uint16_t i=0;
1187
  // change status to command wait
1188
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1189
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1190
  // wait for up to 30 ms
1191
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1192
    delay_us(1); // wait 3us
1193
  }
1194
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1195
    i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN
1196
  else
1197
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1198
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1199
  return i; // return
1200
}
1201

    
1202
/**
1203
 * Set the channel the XBee is using.
1204
 *
1205
 * @param channel the channel the XBee will not use,
1206
 * between 0x0B and 0x1A
1207
 *
1208
 * @see xbee_get_channel
1209
 **/
1210
int8_t xbee_set_channel(uint8_t channel)
1211
{
1212
  if (channel < 0x0B || channel > 0x1A)
1213
  {
1214
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1215
    return -1;
1216
  }
1217

    
1218
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1219
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1220
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1221
  
1222
  int16_t i=0;
1223
  // change status to command wait
1224
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1225
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1226
  // wait for up to 30 ms
1227
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1228
    delay_us(1); // wait 3us
1229
  }
1230
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1231
    i = WL_SUCCESS;
1232
  else
1233
    i = WL_ERROR_XBEE_COMMAND; // set error code
1234
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1235
  return (int8_t)i; // return
1236
}
1237

    
1238
/**
1239
 * Returns the channel which the XBee is currently using.
1240
 *
1241
 * @return the channel the XBee is using
1242
 *
1243
 * @see xbee_set_channel
1244
 **/
1245
int8_t xbee_get_channel(void)
1246
{
1247
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1248
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1249
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1250
  
1251
  int16_t i=0;
1252
  // change status to command wait
1253
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1254
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the channel
1255
  // wait for up to 30 ms
1256
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1257
    delay_us(1); // wait 3us
1258
  }
1259
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1260
    i = xbee_command[2]; // get channel
1261
  else
1262
    i = WL_ERROR_XBEE_COMMAND; // set error code
1263
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1264
  return i; // return
1265
}
1266

    
1267
/**
1268
 * Get the 16-bit address of the XBee.
1269
 * This is used to specify who to send messages to
1270
 * and who messages are from.
1271
 *
1272
 * @return the 16-bit address of the XBee.
1273
 **/
1274
uint16_t xbee_get_address(void)
1275
{
1276
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1277
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1278
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1279
  
1280
  uint16_t i=0;
1281
  // change status to command wait
1282
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1283
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1284
  // wait for up to 30 ms
1285
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1286
    delay_us(1); // wait 3us
1287
  }
1288
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y')
1289
    i = (xbee_command[2]<<8)+xbee_command[3]; // get address
1290
  else
1291
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1292
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1293
  return i; // return
1294
}
1295

    
1296
/**@} **/ // end xbee group
1297