Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (35.2 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/interrupt.h>
38
#include <time.h>
39
#include <wl_defs.h>
40
#include <wireless.h>
41
#include "xbee.h"
42

    
43

    
44
/* Internal Function Prototypes */
45

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

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

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

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

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

    
78
/*Global Variables*/
79

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

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

    
90
// beginning of first packet in basic buffer
91
static uint8_t basic_buf_first = 0;
92

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

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

    
100
// beginning of first packet in other buffer
101
static uint8_t other_buf_first = 0;
102

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

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

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

    
123
// external ack handler (wireless_send.c)
124
void ackhandle(uint8_t num,uint8_t val) { return; } // disabled
125

    
126
// message buffer
127
uint8_t step=99;
128
uint8_t message[100];
129

    
130

    
131
/**@addtogroup xbee
132
 * @{ **/
133

    
134
/*Function Implementations*/
135

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

    
346

    
347
/* adds a byte to the basic buffer */
348
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
349
  if (*ptr == basic_buf_first) {
350
    // buffer full
351
    WL_DEBUG_PRINT("basic buffer full\r\n");
352
    return -1;
353
  }
354
  xbee_basic_buf[(*ptr)++] = byte;
355
  if (*ptr == PACKET_BUFFER_SIZE)
356
    *ptr = 0;
357
  return 0;
358
}
359
/* gets a byte from the basic buffer */
360
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
361
  uint8_t byte = xbee_basic_buf[(*ptr)++];
362
  if (*ptr == PACKET_BUFFER_SIZE)
363
    *ptr = 0;
364
  return byte;
365
}
366
/* adds a byte to the other buffer */
367
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
368
  if (*ptr == other_buf_first) {
369
    // buffer full
370
    WL_DEBUG_PRINT("other buffer full\r\n");
371
    return -1;
372
  }
373
  xbee_other_buf[(*ptr)++] = byte;
374
  if (*ptr == PACKET_BUFFER_SIZE)
375
    *ptr = 0;
376
  return 0;
377
}
378

    
379
/**
380
 * Checks if packet is a duplicate
381
 **/
382
int8_t check_last_receive(uint16_t source,uint8_t framenum) {
383
  uint8_t i=0;
384
  for(;i<NUM_LAST_PACKETS;i++) {
385
    if (lastPacket[i].source == source && lastPacket[i].framenum == framenum)
386
      return -1; // duplicate packet, so return error
387
  }
388
  // save packet source and framenum
389
  i=getStatus(LAST_PACKET_MASK);
390
  lastPacket[i].source = source;
391
  lastPacket[i].framenum = framenum;
392
  if (++i>=NUM_LAST_PACKETS)
393
    i = 0;
394
  setStatus(LAST_PACKET_MASK,i);
395
  return WL_SUCCESS;
396
}
397

    
398
/** status functions **/
399
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
400
inline void setStatus(uint8_t mask,uint8_t value) { xbee_status = (xbee_status&(!mask))|value; }
401

    
402

    
403
/**
404
 * Initializes the XBee library so that other functions may be used.
405
 **/
406
int8_t xbee_init()
407
{
408
  WL_DEBUG_PRINT("in xbee_init\r\n");
409
  
410
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
411
    return WL_ERROR_INIT_ALREADY_INITD;
412
  }
413
  
414
  // clear last packet buffer
415
  for(int i=0;i<NUM_LAST_PACKETS;i++)
416
    lastPacket[i].source = lastPacket[i].framenum = 0;
417
  
418
  // Set startup baud rate of 9600
419
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
420
  // Enable receiver and transmitter and the receiving interrupt
421
/*#ifdef FIREFLY
422
  UCSR0A |= (1<<U2X0);
423
  UBRR0H = 0x00;
424
  UBRR0L = 103;
425
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
426
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
427
#else*/
428
  // Bayboard or robot
429
  UCSR1A |= (1<<U2X1); // double transmit speed 
430
  UBRR1H = 0x00; // baud rate
431
  UBRR1L = 103;  // baud rate
432
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
433
  UCSR1B |= (1<<RXEN1) | (1<<TXEN1);
434
  UCSR1B |= _BV(RXCIE);  // enable receive, transmit (1<<RXCIE)
435
  WL_DEBUG_PRINT("receive interrupt flag=");
436
  WL_DEBUG_PRINT_HEX(UCSR1B&(_BV(RXCIE)));
437
  WL_DEBUG_PRINT("|\r\n");
438
//#endif
439
  sei();
440
  
441
  
442
//#ifdef ROBOT
443
  // enable basic xbee serial communications
444
 // xbee_init();
445
 
446
/* #if (XBEE_BAUD == 115200)
447
  UBRR1H = 0x00;
448
  UBRR1L = 8;
449
  UCSR1A |= _BV(U2X1); // set bit 1
450
#elif (XBEE_BAUD == 9600)
451
  UBRR1H = 0x00;
452
  UBRR1L = 103;
453
  UCSR1A |= _BV(U2X1);
454
#else //Baud rate is defined in the header file, we should not get here
455
  return;
456
#endif
457

458
  //Enable receiver and transmitter on USART1
459
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
460
        
461
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
462
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
463

464
        // enable the receiving interrupt for USART1
465
#ifdef FIREFLY
466
        UCSR0B |= _BV(RXCIE) | _BV(RXEN);
467
#else
468
#ifdef BAYBOARD
469
        UCSR1B |= _BV(RXCIE1);
470
#else
471
  // dragonfly register 
472
        UCSR1B |= _BV(RXCIE);
473
#endif
474
#endif
475
        sei();
476
//#else*/
477

    
478
  WL_DEBUG_PRINT("Entering command mode.\r\n");
479
  if (xbee_enter_command_mode() != 0) {
480
    WL_DEBUG_PRINT("error entering command mode\r\n");
481
    return -1;
482
  }
483
  WL_DEBUG_PRINT("\r\n***************UDR0=|");
484
  WL_DEBUG_PRINT(UDR0);
485
  WL_DEBUG_PRINT("|Entered command mode.\r\n");
486

    
487
  
488
  // set baud on xbee
489
#if (XBEE_BAUD == 115200)
490
  xbee_send_string((uint8_t*)"ATBD7\r");
491
  xbee_send_string((uint8_t*)"ATBD7\r");
492
#elif (XBEE_BAUD == 57600)
493
  xbee_send_string((uint8_t*)"ATBD6\r");
494
#elif (XBEE_BAUD == 38400)
495
  xbee_send_string((uint8_t*)"ATBD5\r");
496
#elif (XBEE_BAUD == 19200)
497
  xbee_send_string((uint8_t*)"ATBD4\r");
498
#elif (XBEE_BAUD == 9600)
499
  // already at this baud rate
500
  //xbee_send_string("ATBD3\r\n");
501
#else
502
  WL_DEBUG_PRINT("undefined baud rate\r\n");
503
  return WL_ERROR_BAUD;
504
#endif  
505
  // exit command mode
506
  xbee_wait_for_ok();
507
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
508
  xbee_send_string((uint8_t*)"ATCN\r");
509
  xbee_wait_for_ok();
510
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
511
  
512
  // set UART baud
513
#ifdef FIREFLY
514
#if (XBEE_BAUD == 115200)
515
  UBRR0H = 0x00;
516
  UBRR0L = 8;
517
#elif (XBEE_BAUD == 57600)
518
  UBRR0H = 0x00;
519
  UBRR0L = 16;
520
#elif (XBEE_BAUD == 38400)
521
  UBRR0H = 0x00;
522
  UBRR0L = 25;
523
#elif (XBEE_BAUD == 19200)
524
  UBRR0H = 0x00;
525
  UBRR0L = 51;
526
#elif (XBEE_BAUD == 9600)
527
  /* this is the default baud rate, so do nothing
528
  UBRR0H = 0x00;
529
  UBRR0L = 103;*/
530
#else
531
  WL_DEBUG_PRINT("undefined baud rate\r\n");
532
  return WL_ERROR_BUAD;
533
#endif
534
#else // Bayboard or robot
535
#if (XBEE_BAUD == 115200)
536
  UBRR1H = 0x00;
537
  UBRR1L = 8;
538
#elif (XBEE_BAUD == 57600)
539
  UBRR1H = 0x00;
540
  UBRR1L = 16;
541
#elif (XBEE_BAUD == 38400)
542
  UBRR1H = 0x00;
543
  UBRR1L = 25;
544
#elif (XBEE_BAUD == 19200)
545
  UBRR1H = 0x00;
546
  UBRR1L = 51;
547
#elif (XBEE_BAUD == 9600)
548
  /* this is the default baud rate, so do nothing
549
  UBRR1H = 0x00;
550
  UBRR1L = 103;*/
551
#else
552
  WL_DEBUG_PRINT("undefined baud rate\r\n");
553
  return WL_ERROR_BUAD;
554
#endif
555
#endif
556
  delay_ms(50);
557

    
558
  // enter command mode
559
  WL_DEBUG_PRINT("entering command mode 2\r\n");
560
  xbee_send_string((uint8_t*)"+++");
561
  xbee_wait_for_ok();
562
  WL_DEBUG_PRINT("entered command mode 2\r\n");
563
  
564
  if (xbee_enter_api_mode() != 0) {
565
    WL_DEBUG_PRINT("can't enter api mode\r\n");
566
    return -1;
567
  }
568

    
569
  WL_DEBUG_PRINT("Entered api mode.\r\n");
570

    
571
  if (xbee_exit_command_mode() != 0) {
572
    WL_DEBUG_PRINT("can't exit command mode\r\n");
573
    return -1;
574
  }
575
  
576
  WL_DEBUG_PRINT("Left command mode.\r\n");
577
  
578
  // TODO: we should set the MY address to the robot address from eeprom
579
  
580
  if (xbee_get_address() == WL_ERROR_XBEE_COMMAND_16BIT) {
581
    WL_DEBUG_PRINT("getting MY address failed\r\n");
582
  }
583
  WL_DEBUG_PRINT("MY address successful\r\n");
584
  
585
  // set status
586
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
587
  
588
  return WL_SUCCESS;
589
}
590

    
591
/**
592
 * Call when finished using the XBee library.
593
 **/
594
int8_t xbee_terminate()
595
{
596
  int ret=xbee_exit_api_mode();
597
  if (ret != WL_SUCCESS) {
598
    WL_DEBUG_PRINT("xbee termination failed\r\n");
599
    WL_DEBUG_PRINT_INT(ret);
600
    WL_DEBUG_PRINT("|\r\n");
601
    return WL_ERROR_TERMINATION_FAILED;
602
  }
603
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
604
  return WL_SUCCESS;
605
}
606

    
607
/**
608
 * Sends a character to the XBee.
609
 *
610
 * @param c the byte to send
611
 * @return 0 for success, nonzero for failure
612
 **/
613
int8_t xbee_putc(uint8_t c) {
614

    
615
  // Wait until buffer is clear for sending
616
  // Then load buffer with your character
617
  
618
  
619
#ifdef FIREFLY
620
  loop_until_bit_is_set(UCSR0A, UDRE0);  
621
  UDR0 = c;
622
#else
623
  loop_until_bit_is_set(UCSR1A, UDRE1);
624
  UDR1 = c;
625
#endif
626
  WL_DEBUG_PRINT("xbee_putc:");
627
  WL_DEBUG_PRINT_HEX(c);
628
  WL_DEBUG_PRINT("|\r\n");
629
  
630
  return WL_SUCCESS;
631
}
632

    
633
/**
634
 * Returns the first byte in the buffer received from xbee.
635
 * This function blocks execution until a character has been
636
 * received. xbee_init must be called before this function
637
 * may be used.
638
 * 
639
 * @return the first character in the xbee buffer, -1 on error
640
 * 
641
 * @see xbee_init, xbee_getc_nb
642
 **/
643
int16_t xbee_getc(void) {
644
    
645
  // Wait for the receive buffer to be filled
646
  // Then read the receive buffer
647
#ifdef FIREFLY
648
  loop_until_bit_is_set(UCSR0A, RXC0);  
649
  return UDR0;
650
#else
651
  loop_until_bit_is_set(UCSR1A, RXC1);
652
  return UDR1;
653
#endif
654
}
655

    
656
/**
657
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
658
 * it is returned, otherwise -1 is returned immediately. xbee_init
659
 * must be called before this function can be used.
660
 *
661
 * @param c The received byte. This will be set if a byte has been received.
662
 * 
663
 * @return -1 If no byte is available, 0 otherwise, positive for error
664
 *
665
 * @see xbee_getc
666
 **/
667
int8_t xbee_getc_nb(uint8_t *c) {
668

    
669
  // check if the receive buffer is filled
670
#ifdef FIREFLY
671
  if (UCSR0A & (1<<RXC0)) {
672
    (*c) = UDR0;
673
#else
674
  if (UCSR1A & (1<<RXC1)) {
675
    (*c) = UDR1;
676
#endif
677
    return WL_SUCCESS;
678
  }
679
  return -1; // Return empty
680
}
681

    
682
/**
683
 * Send a buffer buf of size bytes to the XBee.
684
 *
685
 * @param buf the buffer of data to send
686
 * @param size the number of bytes to send
687
 **/
688
int8_t xbee_send(uint8_t* buf, uint16_t size)
689
{
690
  uint16_t i=0; // check if we need this variable
691
  while(i<size) {
692
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
693
      return WL_ERROR_SEND;
694
  }
695

    
696
  return WL_SUCCESS;
697
}
698

    
699
/**
700
 * Sends a string to the XBee.
701
 *
702
 * @param c the string to send to the XBEE
703
 **/
704
static int8_t xbee_send_string(uint8_t* c)
705
{
706
  return xbee_send(c, strlen((char*)c));
707
}
708

    
709

    
710
/**
711
 * Enter into command mode.
712
 **/
713
static int8_t xbee_enter_command_mode(void)
714
{
715
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
716
    return WL_ERROR_XBEE_COMMAND;
717
  }
718
  WL_DEBUG_PRINT("sent command +++|");
719

    
720
  if (xbee_wait_for_ok() != WL_SUCCESS) {
721
    return WL_ERROR_XBEE_COMMAND;
722
  }
723
  WL_DEBUG_PRINT("got OK\r\n");
724
  
725
  return WL_SUCCESS;
726
}
727

    
728
/**
729
 * Exit from command mode.
730
 **/
731
static int8_t xbee_exit_command_mode()
732
{
733
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
734
    return WL_ERROR_SEND;
735
  }
736
  xbee_wait_for_ok();
737

    
738
  return WL_SUCCESS;
739
}
740

    
741
/**
742
 * Enter API mode.
743
 **/
744
static int8_t xbee_enter_api_mode(void) {
745
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
746
    return WL_ERROR_SEND;
747
  }
748
  if (xbee_wait_for_ok() != 0) {
749
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
750
    return WL_ERROR_SEND;
751
  }
752
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
753
  
754
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
755

    
756
  return WL_SUCCESS;
757
}
758

    
759
/**
760
 * Enter API mode 2.
761
 **/
762
static int8_t xbee_enter_api_mode2(void) {
763
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
764
    return WL_ERROR_SEND;
765
  }
766
  if (xbee_wait_for_ok() != 0) {
767
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
768
    return WL_ERROR_SEND;
769
  }
770
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
771
  
772
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
773
  
774
  return WL_SUCCESS;
775
}
776

    
777
/**
778
 * Exit API mode.
779
 **/
780
static int8_t xbee_exit_api_mode()
781
{
782
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
783
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
784
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
785
  WL_DEBUG_PRINT("now exiting API mode\r\n");
786
  
787
  int16_t i=0;
788
  // change status to command wait
789
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
790
  xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)"0",1); // send command
791
  // wait for up to 30 ms
792
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
793
    delay_us(1); // wait 3us
794
  }
795
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
796
    WL_DEBUG_PRINT("done exiting API mode\r\n");
797
    i = WL_SUCCESS;
798
  } else {
799
    WL_DEBUG_PRINT("failed to exit API mode\r\n");
800
    i = WL_ERROR_XBEE_COMMAND; // set error code
801
  }
802
  setStatus(XBEE_API_MASK,XBEE_API_OFF); // reset status
803
  return (int8_t)i; // return
804
}
805

    
806
/**
807
 * Wait until the string "OK\r" is received from the XBee.
808
 **/
809
static int8_t xbee_wait_for_ok()
810
{
811
  return xbee_wait_for_string((uint8_t*)"OK\r", 3);
812
}
813

    
814
/**
815
 * Delay until the specified string is received from
816
 * the XBee.
817
 *
818
 * Only works when not in API mode
819
 *
820
 * @param s the string to receive
821
 * @param len the length of the string
822
 **/
823
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
824
{
825
  uint8_t i=0;
826
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
827
    // wait until the response is received (only wait 1 second)
828
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
829
      delay_us(1);
830
    }
831
    // check response
832
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
833
      // bad response
834
      WL_DEBUG_PRINT("Bad response when waiting for string ");
835
      WL_DEBUG_PRINT(s);
836
      WL_DEBUG_PRINT("\r\n");
837
      return -1;
838
    }
839
    
840
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
841
  }
842
  
843
  WL_DEBUG_PRINT("done waiting for string. interrupt status=");
844
  WL_DEBUG_PRINT_INT(step);
845
  WL_DEBUG_PRINT("\r\n");
846

    
847
  return 0;
848
}
849

    
850
/**
851
 * Delay until we receive a command response.
852
 * (either OK\r or some actual value)
853
 *
854
 * Only works when not in API mode
855
 *
856
 * @param s the string to store the response in
857
 * @param len the length of the string
858
 */
859
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
860
  uint8_t i=0;
861
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
862
    // wait until the response is received (only wait 1 second)
863
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
864
      delay_us(1);
865
    }
866
    // check response
867
    if (i >= 1000) {
868
      return -1;
869
    } else {
870
      i=strcspn((char*)xbee_basic_buf,"\r");
871
      if (i<PACKET_BUFFER_SIZE) {
872
        memcpy(s,xbee_basic_buf,i);
873
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
874
        return 0;
875
      }
876
      else
877
        return -1;      
878
    }
879
  }
880
  // TODO: do something for API mode
881
  
882
  return 0;
883
}
884

    
885
/**  TODO: since we don't use this, do we need it?
886
 *
887
 * Verifies that the packets checksum is correct.
888
 * (If the checksum is correct, the sum of the bytes
889
 * is 0xFF.)
890
 *
891
 * @param packet the packet received. This includes the first
892
 * three bytes, which are header information from the XBee.
893
 *
894
 * @param len The length of the packet received from the XBee
895
 *
896
 * @return 0 if the checksum is incorrect, nonzero
897
 * otherwise
898
 **/
899
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
900
{
901
  uint8_t sum = 0;
902
  while(--len > 0) {
903
    sum += packet[len];
904
  }
905
  sum += packet[0];
906
  return (sum == 0xFF);
907
}
908

    
909
/**
910
 * Returns the checksum of the given packet.
911
 *
912
 * @param buf the data for the packet to send
913
 * @param len the length of the packet in bytes
914
 *
915
 * @return the checksum of the packet, which will
916
 * become the last byte sent in the packet
917
 **/
918
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
919
{
920
  uint8_t sum = 0;
921
  while(--len > 0) {
922
    sum += buf[len];
923
  }
924
  sum += buf[0];
925
  return 0xFF - sum;
926
}
927

    
928
/**
929
 * Adds buf to the previous checksum total
930
 *
931
 * @param buf a byte buffer to add to the checksum
932
 * @param len the length of the buffer
933
 * @param sum the previous sum
934
 *
935
 * @return error code
936
 **/
937
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
938
  if (buf == NULL || sum == NULL)
939
    return WL_ERROR_ARGUMENT;
940
  while(--len > 0) {
941
    *sum += buf[len];
942
  }
943
  *sum += buf[0];
944
  return WL_SUCCESS;
945
}
946

    
947

    
948
/**
949
 * Sends header information. Header information includes
950
 * XBEE_FRAME_START and the packet length, as two bytes.
951
 *
952
 * @param type the packet type
953
 * @param len the size in bytes of the packet data
954
 *
955
 **/
956
int8_t xbee_send_header(uint8_t type, uint16_t len)
957
{  
958
  //packet prefix
959
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
960
    return WL_ERROR_SEND;
961
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
962
    return WL_ERROR_SEND;
963
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
964
    return WL_ERROR_SEND;
965

    
966
  return WL_SUCCESS;
967
}
968

    
969
/**
970
 * Adds header information and checksum to the given
971
 * packet and sends it. Header information includes
972
 * XBEE_FRAME_START and the packet length, as two bytes.
973
 *
974
 * @param buf the packet data
975
 * @param len the size in bytes of the packet data
976
 *
977
 **/
978
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
979
{
980
  uint8_t checksum = xbee_compute_checksum(buf, len);
981
  
982
  //packet prefix
983
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
984
    return WL_ERROR_SEND;
985
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
986
    return WL_ERROR_SEND;
987
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
988
    return WL_ERROR_SEND;
989

    
990
  if (xbee_send(buf, len) != WL_SUCCESS)
991
    return WL_ERROR_SEND;
992
  
993
  if (xbee_putc(checksum) != WL_SUCCESS)
994
    return WL_ERROR_SEND;
995
  
996
  return WL_SUCCESS;
997
}
998

    
999
/**
1000
 * Sends an AT command to read a parameter.
1001
 *
1002
 * @param command the AT command to send. For exmaple,
1003
 * use ID to read the PAN ID and MY to return the XBee ID.
1004
 * See the XBee reference guide for a complete listing.
1005
 **/
1006
int8_t xbee_send_read_at_command(uint8_t* command)
1007
{
1008
  return xbee_send_modify_at_command(command, NULL, 0);
1009
}
1010

    
1011
/**
1012
 * Sends the given AT command.
1013
 *
1014
 * @param command the AT command to send (e.g., MY, ID)
1015
 * @param value the value to pass as a parameter
1016
 * (or NULL if there is no parameter)
1017
 **/
1018
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1019
{
1020
  uint8_t buf[12];
1021

    
1022
  buf[0] = XBEE_FRAME_AT_COMMAND;
1023
  buf[1] = 1;
1024
  buf[2] = command[0];
1025
  buf[3] = command[1];
1026
  if (value != NULL)
1027
  {
1028
    if (len > 8)
1029
    {
1030
      WL_DEBUG_PRINT("AT Command too large.\r\n");
1031
      return WL_ERROR_ARGUMENT;
1032
    }
1033
    memcpy(buf+4,value,len);
1034
  }
1035

    
1036
  return xbee_send_frame(buf, 4 + len);
1037
}
1038

    
1039
/**
1040
 * Send the specified packet.
1041
 *
1042
 * @param packet the packet data to send
1043
 * @param len the number of bytes in the packet
1044
 *
1045
 * @param dest the ID of the XBee to send the packet to,
1046
 * or XBEE_BROADCAST to send the message to all robots
1047
 * in the PAN.
1048
 *
1049
 * @param options a combination of the flags
1050
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1051
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1052
 *
1053
 * @param frame the frame number to associate this packet
1054
 * with. This will be used to identify the response when
1055
 * the XBee alerts us as to whether or not our message
1056
 * was received.
1057
 **/
1058
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1059
{
1060
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1061
  uint8_t i = 0;
1062

    
1063
  if (len > 100)
1064
  {
1065
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1066
    return WL_ERROR_ARGUMENT;
1067
  }
1068
  
1069
  // calculate checksum
1070
  for(;i<len;i++)
1071
    sum += packet[len];
1072
  sum += frame;
1073
  sum += (dest&0xFF00) >> 8;
1074
  sum += dest&0x00FF;
1075
  sum += options;
1076
  sum = 0xFF - sum;
1077

    
1078
  //packet prefix
1079
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1080
    return WL_ERROR_SEND;
1081
  if (xbee_putc(0x00) != WL_SUCCESS)
1082
    return WL_ERROR_SEND;
1083
  if (xbee_putc(len+5) != WL_SUCCESS)
1084
    return WL_ERROR_SEND;
1085
    
1086
  //send header for TX request
1087
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1088
    return WL_ERROR_SEND;
1089
  if (xbee_putc(frame) != WL_SUCCESS)
1090
    return WL_ERROR_SEND;
1091
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1092
    return WL_ERROR_SEND;
1093
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1094
    return WL_ERROR_SEND;
1095
  if (xbee_putc(options) != WL_SUCCESS)
1096
    return WL_ERROR_SEND;
1097

    
1098
  // send packet
1099
  if (xbee_send(packet, len) != WL_SUCCESS)
1100
    return WL_ERROR_SEND;
1101

    
1102
  // send checksum
1103
  if (xbee_putc(sum) != WL_SUCCESS)
1104
    return WL_ERROR_SEND;
1105

    
1106
  return WL_SUCCESS;
1107
}
1108

    
1109
/**
1110
 * Handles modem status packets.
1111
 *
1112
 * @param status the type of status packet received.
1113
 **/
1114
void xbee_handle_status(uint8_t status)
1115
{
1116
  switch (status)
1117
  {
1118
    case 0:
1119
      WL_DEBUG_PRINT("XBee hardware reset.\r\n");
1120
      break;
1121
    case 1:
1122
      WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
1123
      break;
1124
    case 2:
1125
      WL_DEBUG_PRINT("Associated.\r\n");
1126
      break;
1127
    case 3:
1128
      WL_DEBUG_PRINT("Disassociated.\r\n");
1129
      break;
1130
    case 4:
1131
      WL_DEBUG_PRINT("Synchronization lost.\r\n");
1132
      break;
1133
    case 5:
1134
      WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1135
      break;
1136
    case 6:
1137
      WL_DEBUG_PRINT("Coordinator started.\r\n");
1138
      break;
1139
  }
1140
}
1141

    
1142
/**
1143
 * Handles AT command response packets.
1144
 * @param command the two character AT command, e.g. MY or ID
1145
 * @param result 0 for success, 1 for an error
1146
 * @param len the length in bytes of extra
1147
 **/
1148
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len)
1149
{
1150
  WL_DEBUG_PRINT("HANDLE AT COMMAND\r\ninterrupt status=");
1151
  WL_DEBUG_PRINT_INT(step);
1152
  WL_DEBUG_PRINT("\r\n");
1153
  if (result == 1)
1154
  {
1155
    WL_DEBUG_PRINT("Error with AT");
1156
    WL_DEBUG_PRINT(command);
1157
    WL_DEBUG_PRINT(" packet. Result = ");
1158
    switch(result) {
1159
    case 1:
1160
      WL_DEBUG_PRINT("ERROR\r\n");
1161
      break;
1162
    case 2:
1163
      WL_DEBUG_PRINT("Invalid Command\r\n");
1164
      break;
1165
    case 3:
1166
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
1167
      break;
1168
    }
1169
    return WL_SUCCESS;
1170
  }
1171
  WL_DEBUG_PRINT("AT");
1172
  WL_DEBUG_PRINT(command);
1173
  WL_DEBUG_PRINT(" command was successful.\r\n");
1174
  
1175
  // TODO: program more command responses here (ND, etc)
1176
  switch(command) {
1177
  case ('I'<<8)+'D': // PAN
1178
  case ('C'<<8)+'H': // channel
1179
  case ('M'<<8)+'Y': // address
1180
    // copy command to handler
1181
    xbee_command[0] = (command&0xFF00)>>8;
1182
    xbee_command[1] = command&0x00FF;
1183
    result = basic_buf_last;
1184
    for(command=2;command<len+2;command++)
1185
      xbee_command[command] = xbee_basic_buf_get(&result);
1186
    break;
1187
  default:
1188
    WL_DEBUG_PRINT("unknown AT command");
1189
  }
1190
  
1191
  // signal handler that command response is done
1192
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE);
1193

    
1194
  return WL_SUCCESS;
1195
}
1196

    
1197
/**
1198
 * Sets the personal area network id.
1199
 *
1200
 * @param id the new personal area network (PAN) id
1201
 **/
1202
int8_t xbee_set_pan_id(uint16_t id)
1203
{
1204
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1205
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1206
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1207
  
1208
  int16_t i=0;
1209
  // change status to command wait
1210
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1211
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1212
  // wait for up to 30 ms
1213
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1214
    delay_us(1); // wait 3us
1215
  }
1216
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1217
    i = WL_SUCCESS;
1218
  else
1219
    i = WL_ERROR_XBEE_COMMAND; // set error code
1220
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1221
  return (int8_t)i; // return
1222
}
1223

    
1224
/**
1225
 * Get the PAN ID for the XBee.
1226
 *
1227
 * @return the personal area network id, or
1228
 * XBEE_PAN_DEFAULT if it has not yet been set.
1229
 **/
1230
uint16_t xbee_get_pan_id()
1231
{
1232
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1233
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1234
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1235
  
1236
  uint16_t i=0;
1237
  // change status to command wait
1238
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1239
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1240
  // wait for up to 30 ms
1241
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1242
    delay_us(1); // wait 3us
1243
  }
1244
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1245
    i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN
1246
  else
1247
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1248
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1249
  return i; // return
1250
}
1251

    
1252
/**
1253
 * Set the channel the XBee is using.
1254
 *
1255
 * @param channel the channel the XBee will not use,
1256
 * between 0x0B and 0x1A
1257
 *
1258
 * @see xbee_get_channel
1259
 **/
1260
int8_t xbee_set_channel(uint8_t channel)
1261
{
1262
  if (channel < 0x0B || channel > 0x1A)
1263
  {
1264
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1265
    return -1;
1266
  }
1267

    
1268
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1269
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1270
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1271
  
1272
  int16_t i=0;
1273
  // change status to command wait
1274
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1275
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1276
  // wait for up to 30 ms
1277
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1278
    delay_us(1); // wait 3us
1279
  }
1280
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1281
    i = WL_SUCCESS;
1282
  else
1283
    i = WL_ERROR_XBEE_COMMAND; // set error code
1284
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1285
  return (int8_t)i; // return
1286
}
1287

    
1288
/**
1289
 * Returns the channel which the XBee is currently using.
1290
 *
1291
 * @return the channel the XBee is using
1292
 *
1293
 * @see xbee_set_channel
1294
 **/
1295
int8_t xbee_get_channel(void)
1296
{
1297
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1298
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1299
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1300
  
1301
  int16_t i=0;
1302
  // change status to command wait
1303
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1304
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the channel
1305
  // wait for up to 30 ms
1306
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1307
    delay_us(1); // wait 3us
1308
  }
1309
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1310
    i = xbee_command[2]; // get channel
1311
  else
1312
    i = WL_ERROR_XBEE_COMMAND; // set error code
1313
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1314
  return i; // return
1315
}
1316

    
1317
/**
1318
 * Get the 16-bit address of the XBee.
1319
 * This is used to specify who to send messages to
1320
 * and who messages are from.
1321
 *
1322
 * @return the 16-bit address of the XBee.
1323
 **/
1324
uint16_t xbee_get_address(void)
1325
{
1326
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1327
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1328
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1329
  
1330
  uint16_t i=0;
1331
  // change status to command wait
1332
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1333
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1334
  // wait for up to 30 ms
1335
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1336
    delay_us(1); // wait 3us
1337
  }
1338
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y')
1339
    i = (xbee_command[2]<<8)+xbee_command[3]; // get address
1340
  else
1341
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1342
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1343
  WL_DEBUG_PRINT("get MY address, interrupt status=");
1344
  WL_DEBUG_PRINT_INT(step);
1345
  WL_DEBUG_PRINT("\r\n");
1346
  return i; // return
1347
}
1348

    
1349
/**@} **/ // end xbee group
1350