Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (35 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 "xbee.h"
43

    
44

    
45
/* Internal Function Prototypes */
46

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

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

    
58
/* API Mode Functions */
59
//TODO: does this exist?  static int8_t xbee_handle_packet(uint8_t* packet, uint16_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
  step=0;
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[i] = 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
          i++;
179
        }
180
      }
181
      WL_DEBUG_PRINT("got packet, len=");
182
      WL_DEBUG_PRINT_INT(i);
183
      WL_DEBUG_PRINT("str=");
184
      WL_DEBUG_PRINT(xbee_basic_buf);
185
      step=2;
186
      // signal handler that command response is done
187
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
188
    }
189
    WL_DEBUG_PRINT("return\r\n");
190
    step=3;
191
    return;
192
  }  
193
  WL_DEBUG_PRINT("|API ON");
194
  step=10;
195
    
196
  // get length and type
197
  while(i<3) {
198
    if (FLAG) {
199
      if (i==0)
200
        len |= PORT<<8;
201
      else if (i==1)
202
        len |= PORT;
203
      else if (i==2)
204
        apitype = PORT;
205
      i++;
206
    }
207
  }
208
  WL_DEBUG_PRINT("|len=");
209
  WL_DEBUG_PRINT_INT(len);
210
  WL_DEBUG_PRINT("|apitype=");
211
  WL_DEBUG_PRINT_HEX(apitype);
212
  WL_DEBUG_PRINT("\r\n");
213
  step=11;
214
  
215
  // do something based on the type
216
  i=1;
217
  switch(apitype) {
218
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
219
    // AT command response
220
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
221
      return; // we're currently processing a command, so drop the incoming one
222
    uint16_t atcommand=0;
223
    uint8_t ptr=basic_buf_last;
224
    while(i<len) {
225
      if (FLAG) {
226
        if (i==1)
227
          apitype = PORT; // get frame id, but ignore it
228
        else if (i==2)
229
          atcommand |= PORT<<8; // get command char1
230
        else if (i==3)
231
          atcommand |= PORT; // get command char2
232
        else if (i==4)
233
          apitype = PORT; // get status
234
        else {
235
          // put the command response on the basic buf temporarily
236
          if (xbee_basic_buf_add(&ptr,PORT) != 0)
237
            break;
238
        }
239
        i++;
240
      }
241
    }  
242
    // handle AT command  
243
    xbee_handle_at_command_response(atcommand,apitype,i-5); // TODO: rewrite function
244
    break; }
245
  case XBEE_FRAME_TX_STATUS: {
246
    // TX status
247
    uint8_t frame_id = 0;
248
    while(i<len) {
249
      if (FLAG) {
250
        if (i==1)
251
          frame_id = PORT;
252
        else {
253
          ackhandle(frame_id,PORT); // handle the status
254
          break;
255
        }
256
        i++;
257
      }
258
    }
259
    break; }
260
  case XBEE_FRAME_RX_64: {
261
    // receive a packet with 64bit address
262
    break; } // TODO: implement this (even if we don't use it)
263
  case XBEE_FRAME_RX_16: {
264
    // receive a packet with 16bit address
265
    uint16_t source = 0;
266
    uint8_t framenum = 0;
267
    uint8_t group = 0;
268
    uint8_t ptr=basic_buf_last;
269
    while(i<len) {
270
      if (FLAG) {
271
        if (i==1)
272
          source |= PORT<<8; // get source hi byte
273
        else if (i==2)
274
          source |= PORT; // get source lo byte
275
        else if (i==3)
276
          apitype = PORT; // get RSSI, and ignore
277
        else if (i==4)
278
          apitype = PORT; // get options, and ignore
279
        else if (i==5) {
280
          framenum = PORT; // get the frame number
281
          if (check_last_receive(source,framenum) != WL_SUCCESS) {
282
            // we've already received this frame
283
            ptr = 0xFF; // signal to skip processing
284
            break;
285
          }
286
        }
287
        else if (i==6) {
288
          group = PORT; // get group number
289
          if (group == 0) {
290
            ptr = basic_buf_last+1;
291
            // add source to buffer
292
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
293
              break;
294
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
295
              break;
296
          } else {
297
            ptr = other_buf_last+1;
298
            // add source and group to buffer
299
            if (xbee_other_buf_add(&ptr,group) != 0)
300
              break;
301
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
302
              break;
303
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
304
              break;
305
          }
306
        }
307
        else { // TODO: handle escaped characters supported by APIv2
308
          // put packet data on the correct buffer
309
          if (group == 0 && xbee_basic_buf_add(&ptr,PORT) != 0)
310
            break;
311
          else if (xbee_other_buf_add(&ptr,PORT) != 0)
312
            break;
313
        }
314
        i++;
315
      }
316
    }
317
    if (ptr != 0xFF && i > 6) {
318
      if (group == 0) {
319
        xbee_basic_buf[basic_buf_last] = i-6; // set length
320
        basic_buf_last = ptr;
321
      }
322
      else {        
323
        xbee_other_buf[other_buf_last] = i-6; // set length
324
        // check if we have a high priority group
325
        for(;;)
326
          if (HIGH_PRIORITY) {
327
            // handle receive now
328
            ptr = 0xFF;
329
            break;
330
          }        
331
        if (ptr != 0xFF) {
332
          // handle receive later
333
          other_buf_last = ptr;
334
        }
335
      }
336
    }
337
    break; }
338
  } // end of switch statement
339
  while (1) {
340
    if (FLAG) {
341
      apitype = PORT; // get checksum, and ignore
342
      break;
343
    }
344
  }
345
  WL_DEBUG_PRINT("return\r\n");
346
  step=255;
347
} // end of interrupt 
348

    
349

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

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

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

    
405

    
406
// test interrupt
407
/*ISR(USART1_RX_vect) {
408
  WL_DEBUG_PRINT("in interrupt|");
409
  char c = UDR1;
410
  WL_DEBUG_PRINT_HEX(c);
411
  WL_DEBUG_PRINT("|in interrupt");
412
}*/
413

    
414

    
415

    
416
/**
417
 * Initializes the XBee library so that other functions may be used.
418
 **/
419
int8_t xbee_init()
420
{
421
  WL_DEBUG_PRINT("in xbee_init\r\n");
422
  
423
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
424
    return WL_ERROR_INIT_ALREADY_INITD;
425
  }
426
  
427
  // clear last packet buffer
428
  for(int i=0;i<NUM_LAST_PACKETS;i++)
429
    lastPacket[i].source = lastPacket[i].framenum = 0;
430
  
431
  // Set startup baud rate of 9600
432
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
433
  // Enable receiver and transmitter and the receiving interrupt
434
/*#ifdef FIREFLY
435
  UCSR0A |= (1<<U2X0);
436
  UBRR0H = 0x00;
437
  UBRR0L = 103;
438
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
439
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
440
#else*/
441
  // Bayboard or robot
442
  
443
  UBRR1H = 0x00; // baud rate
444
  UBRR1L = 103;  // baud rate
445
  UCSR1A |= (1<<U2X1); // double transmit speed 
446
  //Enable receiver and transmitter on USART1
447
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
448
        
449
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
450
  //UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
451
  
452
  //UCSR1C |= (1<<UMSEL1) | (1<<UCSZ10) | (1<<UCSZ11);   
453
  //UCSR1C |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
454
  UCSR1B |= (1<<RXCIE1);  // enable receive, transmit (1<<RXCIE)
455
  WL_DEBUG_PRINT("receive interrupt flag=");
456
  WL_DEBUG_PRINT_HEX(UCSR1B&(1<<RXCIE1));
457
  WL_DEBUG_PRINT("|\r\n");
458
  sei();
459
 
460
  /*xbee_putc('+');
461
  xbee_putc('+');
462
  xbee_putc('+');
463
  delay_ms(1000);*/
464
  
465
  
466
  WL_DEBUG_PRINT("entering command mode\r\n");
467
  xbee_send_string((uint8_t*)"+++");
468
  xbee_wait_for_ok();
469
  WL_DEBUG_PRINT("entered command mode\r\n");
470

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

    
541
  // enter command mode
542
  WL_DEBUG_PRINT("entering command mode 2\r\n");
543
  xbee_send_string((uint8_t*)"+++");
544
  xbee_wait_for_ok();
545
  WL_DEBUG_PRINT("entered command mode 2\r\n");
546
  
547
  if (xbee_enter_api_mode() != 0) {
548
    WL_DEBUG_PRINT("can't enter api mode\r\n");
549
    return -1;
550
  }
551
  
552
  
553

    
554
  WL_DEBUG_PRINT("Entered api mode.\r\n");
555

    
556
  if (xbee_exit_command_mode() != 0) {
557
    WL_DEBUG_PRINT("can't exit command mode\r\n");
558
    return -1;
559
  }
560
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
561
  
562
  WL_DEBUG_PRINT("Left command mode.\r\n");
563
  
564
  // TODO: we should set the MY address to the robot address from eeprom
565
  
566
  if (xbee_get_address() == WL_ERROR_XBEE_COMMAND_16BIT) {
567
    WL_DEBUG_PRINT("getting MY address failed\r\n");
568
  }
569
  WL_DEBUG_PRINT("MY address successful\r\n");
570
  
571
  // set status
572
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
573
  
574
  return WL_SUCCESS;
575
}
576

    
577
/**
578
 * Call when finished using the XBee library.
579
 **/
580
int8_t xbee_terminate()
581
{
582
  int ret=xbee_exit_api_mode();
583
  if (ret != WL_SUCCESS) {
584
    WL_DEBUG_PRINT("xbee termination failed\r\n");
585
    WL_DEBUG_PRINT_INT(ret);
586
    WL_DEBUG_PRINT("|\r\n");
587
    return WL_ERROR_TERMINATION_FAILED;
588
  }
589
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
590
  return WL_SUCCESS;
591
}
592

    
593
/**
594
 * Sends a character to the XBee.
595
 *
596
 * @param c the byte to send
597
 * @return 0 for success, nonzero for failure
598
 **/
599
int8_t xbee_putc(uint8_t c) {
600

    
601
  // Wait until buffer is clear for sending
602
  // Then load buffer with your character
603
  
604
  WL_DEBUG_PRINT("xbee_putc:");
605
  WL_DEBUG_PRINT_HEX(c);
606
  WL_DEBUG_PRINT("|\r\n");
607
  
608
/*#ifdef FIREFLY
609
  loop_until_bit_is_set(UCSR0A, UDRE0);  
610
  UDR0 = c;
611
#else*/
612
  loop_until_bit_is_set(UCSR1A, UDRE1);
613
  WL_DEBUG_PRINT_HEX(UCSR1A&TXC1);
614
  UDR1 = c;
615
//#endif
616
  
617
  return WL_SUCCESS;
618
}
619

    
620
/**
621
 * Returns the first byte in the buffer received from xbee.
622
 * This function blocks execution until a character has been
623
 * received. xbee_init must be called before this function
624
 * may be used.
625
 * 
626
 * @return the first character in the xbee buffer, -1 on error
627
 * 
628
 * @see xbee_init, xbee_getc_nb
629
 **/
630
int16_t xbee_getc(void) {
631
    
632
  // Wait for the receive buffer to be filled
633
  // Then read the receive buffer
634
#ifdef FIREFLY
635
  loop_until_bit_is_set(UCSR0A, RXC0);  
636
  return UDR0;
637
#else
638
  loop_until_bit_is_set(UCSR1A, RXC1);
639
  return UDR1;
640
#endif
641
}
642

    
643
/**
644
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
645
 * it is returned, otherwise -1 is returned immediately. xbee_init
646
 * must be called before this function can be used.
647
 *
648
 * @param c The received byte. This will be set if a byte has been received.
649
 * 
650
 * @return -1 If no byte is available, 0 otherwise, positive for error
651
 *
652
 * @see xbee_getc
653
 **/
654
int8_t xbee_getc_nb(uint8_t *c) {
655

    
656
  // check if the receive buffer is filled
657
#ifdef FIREFLY
658
  if (UCSR0A & (1<<RXC0)) {
659
    (*c) = UDR0;
660
#else
661
  if (UCSR1A & (1<<RXC1)) {
662
    (*c) = UDR1;
663
#endif
664
    return WL_SUCCESS;
665
  }
666
  return -1; // Return empty
667
}
668

    
669
/**
670
 * Send a buffer buf of size bytes to the XBee.
671
 *
672
 * @param buf the buffer of data to send
673
 * @param size the number of bytes to send
674
 **/
675
int8_t xbee_send(uint8_t* buf, uint16_t size)
676
{
677
  uint16_t i=0; // check if we need this variable
678
  while(i<size) {
679
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
680
      return WL_ERROR_SEND;
681
  }
682

    
683
  return WL_SUCCESS;
684
}
685

    
686
/**
687
 * Sends a string to the XBee.
688
 *
689
 * @param c the string to send to the XBEE
690
 **/
691
static int8_t xbee_send_string(uint8_t* c)
692
{
693
  return xbee_send(c, strlen((char*)c));
694
}
695

    
696

    
697
/**
698
 * Enter into command mode.
699
 **/
700
static int8_t xbee_enter_command_mode(void)
701
{
702
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
703
    return WL_ERROR_XBEE_COMMAND;
704
  }
705
  WL_DEBUG_PRINT("sent command +++|");
706

    
707
  if (xbee_wait_for_ok() != WL_SUCCESS) {
708
    return WL_ERROR_XBEE_COMMAND;
709
  }
710
  WL_DEBUG_PRINT("got OK\r\n");
711
  
712
  return WL_SUCCESS;
713
}
714

    
715
/**
716
 * Exit from command mode.
717
 **/
718
static int8_t xbee_exit_command_mode()
719
{
720
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
721
    return WL_ERROR_SEND;
722
  }
723
  xbee_wait_for_ok();
724

    
725
  return WL_SUCCESS;
726
}
727

    
728
/**
729
 * Enter API mode.
730
 **/
731
static int8_t xbee_enter_api_mode(void) {
732
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
733
    return WL_ERROR_SEND;
734
  }
735
  if (xbee_wait_for_ok() != 0) {
736
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
737
    return WL_ERROR_SEND;
738
  }
739
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
740
  
741
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
742

    
743
  return WL_SUCCESS;
744
}
745

    
746
/**
747
 * Enter API mode 2.
748
 **/
749
static int8_t xbee_enter_api_mode2(void) {
750
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
751
    return WL_ERROR_SEND;
752
  }
753
  if (xbee_wait_for_ok() != 0) {
754
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
755
    return WL_ERROR_SEND;
756
  }
757
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
758
  
759
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
760
  
761
  return WL_SUCCESS;
762
}
763

    
764
/**
765
 * Exit API mode.
766
 **/
767
static int8_t xbee_exit_api_mode()
768
{
769
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
770
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
771
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
772
  WL_DEBUG_PRINT("now exiting API mode\r\n");
773
  
774
  int16_t i=0;
775
  // change status to command wait
776
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
777
  xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)"0",1); // send command
778
  // wait for up to 30 ms
779
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
780
    delay_us(1); // wait 3us
781
  }
782
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
783
    WL_DEBUG_PRINT("done exiting API mode\r\n");
784
    i = WL_SUCCESS;
785
  } else {
786
    WL_DEBUG_PRINT("failed to exit API mode\r\n");
787
    i = WL_ERROR_XBEE_COMMAND; // set error code
788
  }
789
  setStatus(XBEE_API_MASK,XBEE_API_OFF); // reset status
790
  return (int8_t)i; // return
791
}
792

    
793
/**
794
 * Wait until the string "OK\r" is received from the XBee.
795
 **/
796
static int8_t xbee_wait_for_ok()
797
{
798
  return xbee_wait_for_string((uint8_t*)"OK\r", 3);
799
}
800

    
801
/**
802
 * Delay until the specified string is received from
803
 * the XBee.
804
 *
805
 * Only works when not in API mode
806
 *
807
 * @param s the string to receive
808
 * @param len the length of the string
809
 **/
810
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
811
{
812
  uint8_t i=0;  
813
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
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 || memcmp(s,xbee_basic_buf,len) != 0) {
821
      // bad response
822
      WL_DEBUG_PRINT("Bad response when waiting for string ");
823
      WL_DEBUG_PRINT(s);
824
      WL_DEBUG_PRINT("\r\n");
825
      return -1;
826
    }
827
    
828
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
829
  }
830
  
831
  WL_DEBUG_PRINT("|\r\ndone waiting for string. interrupt status=");
832
  WL_DEBUG_PRINT_INT(step);
833
  WL_DEBUG_PRINT("\r\n");
834

    
835
  return 0;
836
}
837

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

    
873
/**  TODO: since we don't use this, do we need it?
874
 *
875
 * Verifies that the packets checksum is correct.
876
 * (If the checksum is correct, the sum of the bytes
877
 * is 0xFF.)
878
 *
879
 * @param packet the packet received. This includes the first
880
 * three bytes, which are header information from the XBee.
881
 *
882
 * @param len The length of the packet received from the XBee
883
 *
884
 * @return 0 if the checksum is incorrect, nonzero
885
 * otherwise
886
 **/
887
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
888
{
889
  uint8_t sum = 0;
890
  while(--len > 0) {
891
    sum += packet[len];
892
  }
893
  sum += packet[0];
894
  return (sum == 0xFF);
895
}
896

    
897
/**
898
 * Returns the checksum of the given packet.
899
 *
900
 * @param buf the data for the packet to send
901
 * @param len the length of the packet in bytes
902
 *
903
 * @return the checksum of the packet, which will
904
 * become the last byte sent in the packet
905
 **/
906
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
907
{
908
  uint8_t sum = 0;
909
  while(--len > 0) {
910
    sum += buf[len];
911
  }
912
  sum += buf[0];
913
  return 0xFF - sum;
914
}
915

    
916
/**
917
 * Adds buf to the previous checksum total
918
 *
919
 * @param buf a byte buffer to add to the checksum
920
 * @param len the length of the buffer
921
 * @param sum the previous sum
922
 *
923
 * @return error code
924
 **/
925
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
926
  if (buf == NULL || sum == NULL)
927
    return WL_ERROR_ARGUMENT;
928
  while(--len > 0) {
929
    *sum += buf[len];
930
  }
931
  *sum += buf[0];
932
  return WL_SUCCESS;
933
}
934

    
935

    
936
/**
937
 * Sends header information. Header information includes
938
 * XBEE_FRAME_START and the packet length, as two bytes.
939
 *
940
 * @param type the packet type
941
 * @param len the size in bytes of the packet data
942
 *
943
 **/
944
int8_t xbee_send_header(uint8_t type, uint16_t len)
945
{  
946
  //packet prefix
947
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
948
    return WL_ERROR_SEND;
949
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
950
    return WL_ERROR_SEND;
951
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
952
    return WL_ERROR_SEND;
953

    
954
  return WL_SUCCESS;
955
}
956

    
957
/**
958
 * Adds header information and checksum to the given
959
 * packet and sends it. Header information includes
960
 * XBEE_FRAME_START and the packet length, as two bytes.
961
 *
962
 * @param buf the packet data
963
 * @param len the size in bytes of the packet data
964
 *
965
 **/
966
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
967
{
968
  uint8_t checksum = xbee_compute_checksum(buf, len);
969
  
970
  //packet prefix
971
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
972
    return WL_ERROR_SEND;
973
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
974
    return WL_ERROR_SEND;
975
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
976
    return WL_ERROR_SEND;
977

    
978
  if (xbee_send(buf, len) != WL_SUCCESS)
979
    return WL_ERROR_SEND;
980
  
981
  if (xbee_putc(checksum) != WL_SUCCESS)
982
    return WL_ERROR_SEND;
983
  
984
  return WL_SUCCESS;
985
}
986

    
987
/**
988
 * Sends an AT command to read a parameter.
989
 *
990
 * @param command the AT command to send. For exmaple,
991
 * use ID to read the PAN ID and MY to return the XBee ID.
992
 * See the XBee reference guide for a complete listing.
993
 **/
994
int8_t xbee_send_read_at_command(uint8_t* command)
995
{
996
  return xbee_send_modify_at_command(command, NULL, 0);
997
}
998

    
999
/**
1000
 * Sends the given AT command.
1001
 *
1002
 * @param command the AT command to send (e.g., MY, ID)
1003
 * @param value the value to pass as a parameter
1004
 * (or NULL if there is no parameter)
1005
 **/
1006
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1007
{
1008
  uint8_t buf[12];
1009

    
1010
  buf[0] = XBEE_FRAME_AT_COMMAND;
1011
  buf[1] = 1;
1012
  buf[2] = command[0];
1013
  buf[3] = command[1];
1014
  if (value != NULL)
1015
  {
1016
    if (len > 8)
1017
    {
1018
      WL_DEBUG_PRINT("AT Command too large.\r\n");
1019
      return WL_ERROR_ARGUMENT;
1020
    }
1021
    memcpy(buf+4,value,len);
1022
  }
1023

    
1024
  return xbee_send_frame(buf, 4 + len);
1025
}
1026

    
1027
/**
1028
 * Send the specified packet.
1029
 *
1030
 * @param packet the packet data to send
1031
 * @param len the number of bytes in the packet
1032
 *
1033
 * @param dest the ID of the XBee to send the packet to,
1034
 * or XBEE_BROADCAST to send the message to all robots
1035
 * in the PAN.
1036
 *
1037
 * @param options a combination of the flags
1038
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1039
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1040
 *
1041
 * @param frame the frame number to associate this packet
1042
 * with. This will be used to identify the response when
1043
 * the XBee alerts us as to whether or not our message
1044
 * was received.
1045
 **/
1046
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1047
{
1048
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1049
  uint8_t i = 0;
1050

    
1051
  if (len > 100)
1052
  {
1053
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1054
    return WL_ERROR_ARGUMENT;
1055
  }
1056
  
1057
  // calculate checksum
1058
  for(;i<len;i++)
1059
    sum += packet[len];
1060
  sum += frame;
1061
  sum += (dest&0xFF00) >> 8;
1062
  sum += dest&0x00FF;
1063
  sum += options;
1064
  sum = 0xFF - sum;
1065

    
1066
  //packet prefix
1067
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1068
    return WL_ERROR_SEND;
1069
  if (xbee_putc(0x00) != WL_SUCCESS)
1070
    return WL_ERROR_SEND;
1071
  if (xbee_putc(len+5) != WL_SUCCESS)
1072
    return WL_ERROR_SEND;
1073
    
1074
  //send header for TX request
1075
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1076
    return WL_ERROR_SEND;
1077
  if (xbee_putc(frame) != WL_SUCCESS)
1078
    return WL_ERROR_SEND;
1079
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1080
    return WL_ERROR_SEND;
1081
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1082
    return WL_ERROR_SEND;
1083
  if (xbee_putc(options) != WL_SUCCESS)
1084
    return WL_ERROR_SEND;
1085

    
1086
  // send packet
1087
  if (xbee_send(packet, len) != WL_SUCCESS)
1088
    return WL_ERROR_SEND;
1089

    
1090
  // send checksum
1091
  if (xbee_putc(sum) != WL_SUCCESS)
1092
    return WL_ERROR_SEND;
1093

    
1094
  return WL_SUCCESS;
1095
}
1096

    
1097
/**
1098
 * Handles modem status packets.
1099
 *
1100
 * @param status the type of status packet received.
1101
 **/
1102
void xbee_handle_status(uint8_t status)
1103
{
1104
  switch (status)
1105
  {
1106
    case 0:
1107
      WL_DEBUG_PRINT("XBee hardware reset.\r\n");
1108
      break;
1109
    case 1:
1110
      WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
1111
      break;
1112
    case 2:
1113
      WL_DEBUG_PRINT("Associated.\r\n");
1114
      break;
1115
    case 3:
1116
      WL_DEBUG_PRINT("Disassociated.\r\n");
1117
      break;
1118
    case 4:
1119
      WL_DEBUG_PRINT("Synchronization lost.\r\n");
1120
      break;
1121
    case 5:
1122
      WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1123
      break;
1124
    case 6:
1125
      WL_DEBUG_PRINT("Coordinator started.\r\n");
1126
      break;
1127
  }
1128
}
1129

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

    
1182
  return WL_SUCCESS;
1183
}
1184

    
1185
/**
1186
 * Sets the personal area network id.
1187
 *
1188
 * @param id the new personal area network (PAN) id
1189
 **/
1190
int8_t xbee_set_pan_id(uint16_t id)
1191
{
1192
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1193
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1194
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1195
  
1196
  int16_t i=0;
1197
  // change status to command wait
1198
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1199
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1200
  // wait for up to 30 ms
1201
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1202
    delay_us(1); // wait 3us
1203
  }
1204
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1205
    i = WL_SUCCESS;
1206
  else
1207
    i = WL_ERROR_XBEE_COMMAND; // set error code
1208
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1209
  return (int8_t)i; // return
1210
}
1211

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

    
1240
/**
1241
 * Set the channel the XBee is using.
1242
 *
1243
 * @param channel the channel the XBee will not use,
1244
 * between 0x0B and 0x1A
1245
 *
1246
 * @see xbee_get_channel
1247
 **/
1248
int8_t xbee_set_channel(uint8_t channel)
1249
{
1250
  if (channel < 0x0B || channel > 0x1A)
1251
  {
1252
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1253
    return -1;
1254
  }
1255

    
1256
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1257
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1258
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1259
  
1260
  int16_t i=0;
1261
  // change status to command wait
1262
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1263
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1264
  // wait for up to 30 ms
1265
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1266
    delay_us(1); // wait 3us
1267
  }
1268
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1269
    i = WL_SUCCESS;
1270
  else
1271
    i = WL_ERROR_XBEE_COMMAND; // set error code
1272
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1273
  return (int8_t)i; // return
1274
}
1275

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

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

    
1337
/**@} **/ // end xbee group
1338