Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (38 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 status, 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
uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE];
89

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

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

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

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

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

    
107
// 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[8];
122

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

    
126

    
127

    
128
/**@addtogroup xbee
129
 * @{ **/
130

    
131
/*Function Implementations*/
132

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

    
362

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

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

    
414
/** status functions **/
415
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
416
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
417

    
418

    
419
// test interrupt
420
/*ISR(USART1_RX_vect) {
421
  WL_DEBUG_PRINT("in interrupt|");
422
  char c = UDR1;
423
  WL_DEBUG_PRINT_HEX(c);
424
  WL_DEBUG_PRINT("|in interrupt");
425
}*/
426

    
427

    
428

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

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

    
548
  // enter command mode
549
  WL_DEBUG_PRINT("entering command mode 2\r\n");
550
  xbee_send_string((uint8_t*)"+++");
551
  xbee_wait_for_ok();
552
  WL_DEBUG_PRINT("entered command mode 2\r\n");
553
  
554
  if (xbee_enter_api_mode() != 0) {
555
    WL_DEBUG_PRINT("can't enter api mode\r\n");
556
    return -1;
557
  }
558
  /*xbee_send_string((uint8_t*)"ATAP 1\r");
559
  xbee_wait_for_ok();*/
560
  
561
  /*WL_DEBUG_PRINT("Entered api mode.\r\n");
562

563
  if (xbee_exit_command_mode() != 0) {
564
    WL_DEBUG_PRINT("can't exit command mode\r\n");
565
    return -1;
566
  }
567
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
568
  
569
  WL_DEBUG_PRINT("Left command mode.\r\n");
570
  
571
  WL_DEBUG_PRINT("before status=");
572
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
573
  WL_DEBUG_PRINT("\r\n");
574
  
575
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status to API_ON (API mode 1)*/
576
  
577
#ifdef WL_DEBUG
578
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
579
    WL_DEBUG_PRINT("|API OFF|");
580
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
581
    WL_DEBUG_PRINT("|API ON|");
582
  } else {
583
    WL_DEBUG_PRINT("|API ERROR|");
584
  }
585
#endif
586
  
587
  
588
  // TODO: we should set the MY address to the robot address from eeprom  
589
  uint16_t i=0;
590
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);  
591
  uint16_t newmy = 0x9876;
592
  if (xbee_send_modify_at_command((uint8_t*)"MY",&newmy,2) != WL_SUCCESS) {
593
    WL_DEBUG_PRINT("setting MY address failed\r\n");
594
  }
595
  // wait for up to 30 ms
596
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
597
    delay_us(1); // wait 3us
598
  }  
599
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
600
    WL_DEBUG_PRINT("setting MY address successful\r\n");
601
  } else
602
    WL_DEBUG_PRINT("setting MY address failed\r\n");
603
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
604
  
605
  
606
  uint16_t address = xbee_get_address();
607
  if (address == WL_ERROR_XBEE_COMMAND_16BIT) {
608
    WL_DEBUG_PRINT("getting MY address failed\r\n");
609
  }
610
  WL_DEBUG_PRINT("MY address:");
611
  WL_DEBUG_PRINT_HEX((uint8_t)(address>>8));
612
  WL_DEBUG_PRINT_HEX((uint8_t)(address&0xFF));
613
  WL_DEBUG_PRINT("\r\n");
614
  
615
  return WL_SUCCESS;
616
}
617

    
618
/**
619
 * Call when finished using the XBee library.
620
 **/
621
int8_t xbee_terminate()
622
{
623
  int ret=xbee_exit_api_mode();
624
  if (ret != WL_SUCCESS) {
625
    WL_DEBUG_PRINT("xbee termination failed\r\n");
626
    WL_DEBUG_PRINT_INT(ret);
627
    WL_DEBUG_PRINT("|\r\n");
628
    return WL_ERROR_TERMINATION_FAILED;
629
  }
630
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
631
  return WL_SUCCESS;
632
}
633

    
634
/**
635
 * Sends a character to the XBee.
636
 *
637
 * @param c the byte to send
638
 * @return 0 for success, nonzero for failure
639
 **/
640
int8_t xbee_putc(uint8_t c) {
641

    
642
  // Wait until buffer is clear for sending
643
  // Then load buffer with your character
644
  
645
  /*WL_DEBUG_PRINT("xbee_putc:");
646
  WL_DEBUG_PRINT_HEX(c);
647
  WL_DEBUG_PRINT("|\r\n");*/
648
  
649
#ifdef FIREFLY
650
  loop_until_bit_is_set(UCSR0A, UDRE0);  
651
  UDR0 = c;
652
#else
653
  loop_until_bit_is_set(UCSR1A, UDRE1);
654
  UDR1 = c;
655
#endif
656
  
657
  return WL_SUCCESS;
658
}
659

    
660
/**
661
 * Returns the first byte in the buffer received from xbee.
662
 * This function blocks execution until a character has been
663
 * received. xbee_init must be called before this function
664
 * may be used.
665
 * 
666
 * @return the first character in the xbee buffer, -1 on error
667
 * 
668
 * @see xbee_init, xbee_getc_nb
669
 **/
670
int16_t xbee_getc(void) {
671
    
672
  // Wait for the receive buffer to be filled
673
  // Then read the receive buffer
674
#ifdef FIREFLY
675
  loop_until_bit_is_set(UCSR0A, RXC0);  
676
  return UDR0;
677
#else
678
  loop_until_bit_is_set(UCSR1A, RXC1);
679
  return UDR1;
680
#endif
681
}
682

    
683
/**
684
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
685
 * it is returned, otherwise -1 is returned immediately. xbee_init
686
 * must be called before this function can be used.
687
 *
688
 * @param c The received byte. This will be set if a byte has been received.
689
 * 
690
 * @return -1 If no byte is available, 0 otherwise, positive for error
691
 *
692
 * @see xbee_getc
693
 **/
694
int8_t xbee_getc_nb(uint8_t *c) {
695

    
696
  // check if the receive buffer is filled
697
#ifdef FIREFLY
698
  if (UCSR0A & (1<<RXC0)) {
699
    (*c) = UDR0;
700
#else
701
  if (UCSR1A & (1<<RXC1)) {
702
    (*c) = UDR1;
703
#endif
704
    return WL_SUCCESS;
705
  }
706
  return -1; // Return empty
707
}
708

    
709
/**
710
 * Send a buffer buf of size bytes to the XBee.
711
 *
712
 * @param buf the buffer of data to send
713
 * @param size the number of bytes to send
714
 **/
715
int8_t xbee_send(uint8_t* buf, uint16_t size)
716
{
717
  uint16_t i=0; // check if we need this variable
718
  while(i<size) {
719
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
720
      return WL_ERROR_SEND;
721
  }
722

    
723
  return WL_SUCCESS;
724
}
725

    
726
/**
727
 * Sends a string to the XBee.
728
 *
729
 * @param c the string to send to the XBEE
730
 **/
731
static int8_t xbee_send_string(uint8_t* c)
732
{
733
  return xbee_send(c, strlen((char*)c));
734
}
735

    
736

    
737
/**
738
 * Enter into command mode.
739
 **/
740
static int8_t xbee_enter_command_mode(void)
741
{
742
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
743
    return WL_ERROR_XBEE_COMMAND;
744
  }
745
  WL_DEBUG_PRINT("sent command +++|");
746

    
747
  if (xbee_wait_for_ok() != WL_SUCCESS) {
748
    return WL_ERROR_XBEE_COMMAND;
749
  }
750
  WL_DEBUG_PRINT("got OK\r\n");
751
  
752
  return WL_SUCCESS;
753
}
754

    
755
/**
756
 * Exit from command mode.
757
 **/
758
static int8_t xbee_exit_command_mode()
759
{
760
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
761
    return WL_ERROR_SEND;
762
  }
763
  if (xbee_wait_for_ok() != WL_SUCCESS) {
764
    WL_DEBUG_PRINT("failed to exit command mode\r\n");
765
    return WL_ERROR_SEND;
766
  }
767

    
768
  return WL_SUCCESS;
769
}
770

    
771
/**
772
 * Enter API mode.
773
 **/
774
static int8_t xbee_enter_api_mode(void) {
775
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
776
    return WL_ERROR_SEND;
777
  }
778
  if (xbee_wait_for_ok() != WL_SUCCESS) {
779
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
780
    return WL_ERROR_SEND;
781
  }
782
  if (xbee_exit_command_mode() != WL_SUCCESS) {
783
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
784
    return WL_ERROR_SEND;
785
  }    
786
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
787
  
788
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
789
  
790
  return WL_SUCCESS;
791
}
792

    
793
/**
794
 * Enter API mode 2.
795
 **/
796
static int8_t xbee_enter_api_mode2(void) {
797
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
798
    return WL_ERROR_SEND;
799
  }
800
  if (xbee_wait_for_ok() != WL_SUCCESS) {
801
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
802
    return WL_ERROR_SEND;
803
  }
804
  if (xbee_exit_command_mode() != WL_SUCCESS) {
805
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
806
    return WL_ERROR_SEND;
807
  }    
808
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
809
  
810
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
811
  
812
  return WL_SUCCESS;
813
}
814

    
815
/**
816
 * Exit API mode.
817
 **/
818
static int8_t xbee_exit_api_mode()
819
{
820
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
821
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
822
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
823
  WL_DEBUG_PRINT("now exiting API mode\r\n");
824
  
825
  int16_t i=0;
826
  // change status to command wait
827
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
828
  if (xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)(&i),1) != WL_SUCCESS) { // send command
829
    WL_DEBUG_PRINT("error sending AP 0 command\r\n");
830
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
831
    return WL_ERROR_XBEE_COMMAND;
832
  }
833
  // wait for up to 30 ms
834
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
835
    delay_us(1); // wait 3us
836
  }
837
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
838
    WL_DEBUG_PRINT("done exiting API mode\r\n");
839
    i = WL_SUCCESS;
840
  } else {
841
    WL_DEBUG_PRINT("failed to exit API mode\r\n");
842
    i = WL_ERROR_XBEE_COMMAND; // set error code
843
  }
844
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
845
  setStatus(XBEE_API_MASK,XBEE_API_OFF);
846
  
847
  return (int8_t)i; // return
848
}
849

    
850
/**
851
 * Wait until the string "OK\r" is received from the XBee.
852
 **/
853
static int8_t xbee_wait_for_ok()
854
{
855
  //delay_ms(1000);
856
  //return WL_SUCCESS;
857
  return xbee_wait_for_string((uint8_t*)"OK", 2);
858
}
859

    
860
/**
861
 * Delay until the specified string is received from
862
 * the XBee.
863
 *
864
 * Only works when not in API mode
865
 *
866
 * @param s the string to receive
867
 * @param len the length of the string
868
 **/
869
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
870
{
871
  uint8_t i=0;  
872
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
873
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
874
    // wait until the response is received (only wait 1 second)
875
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
876
      delay_us(1);
877
    }
878
    // check response
879
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
880
      // bad response
881
      WL_DEBUG_PRINT("Bad response when waiting for string ");
882
      WL_DEBUG_PRINT(s);
883
      WL_DEBUG_PRINT("\r\n");
884
      return -1;
885
    }
886
    
887
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
888
  }
889
  
890
  WL_DEBUG_PRINT("done waiting for string.\r\n");
891

    
892
  return 0;
893
}
894

    
895
/**
896
 * Delay until we receive a command response.
897
 * Then copy the response to S and set the len
898
 *
899
 * Only works when not in API mode
900
 *
901
 * @param s the string to store the response in
902
 * @param len the length of the string
903
 */
904
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
905
  uint8_t i=0;
906
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
907
    // wait until the response is received (only wait 1 second)
908
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
909
      delay_us(1);
910
    }
911
    // check response
912
    if (i >= 1000) {
913
      return -1;
914
    } else {
915
      i=strcspn((char*)xbee_basic_buf,"\r");
916
      if (i<PACKET_BUFFER_SIZE) {
917
        memcpy(s,xbee_basic_buf,i);
918
        len = i;
919
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
920
        return 0;
921
      }
922
      else
923
        return -1;      
924
    }
925
  }
926
  // TODO: do something for API mode
927
  
928
  return 0;
929
}
930

    
931
/**  TODO: since we don't use this, do we need it?
932
 *
933
 * Verifies that the packets checksum is correct.
934
 * (If the checksum is correct, the sum of the bytes
935
 * is 0xFF.)
936
 *
937
 * @param packet the packet received. This includes the first
938
 * three bytes, which are header information from the XBee.
939
 *
940
 * @param len The length of the packet received from the XBee
941
 *
942
 * @return 0 if the checksum is incorrect, nonzero
943
 * otherwise
944
 **/
945
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
946
{
947
  uint8_t sum = 0;
948
  while(--len > 0) {
949
    sum += packet[len];
950
  }
951
  sum += packet[0];
952
  return (sum == 0xFF);
953
}
954

    
955
/**
956
 * Returns the checksum of the given packet.
957
 *
958
 * @param buf the data for the packet to send
959
 * @param len the length of the packet in bytes
960
 *
961
 * @return the checksum of the packet, which will
962
 * become the last byte sent in the packet
963
 **/
964
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
965
{
966
  uint8_t sum = 0;
967
  while(--len > 0) {
968
    sum += buf[len];
969
  }
970
  sum += buf[0];
971
  return 0xFF - sum;
972
}
973

    
974
/**
975
 * Adds buf to the previous checksum total
976
 *
977
 * @param buf a byte buffer to add to the checksum
978
 * @param len the length of the buffer
979
 * @param sum the previous sum
980
 *
981
 * @return error code
982
 **/
983
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
984
  if (buf == NULL || sum == NULL)
985
    return WL_ERROR_ARGUMENT;
986
  while(--len > 0) {
987
    *sum += buf[len];
988
  }
989
  *sum += buf[0];
990
  return WL_SUCCESS;
991
}
992

    
993

    
994
/**
995
 * Sends header information. Header information includes
996
 * XBEE_FRAME_START and the packet length, as two bytes.
997
 *
998
 * @param type the packet type
999
 * @param len the size in bytes of the packet data
1000
 *
1001
 **/
1002
int8_t xbee_send_header(uint16_t len)
1003
{  
1004
  //packet prefix
1005
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1006
    return WL_ERROR_SEND;
1007
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
1008
    return WL_ERROR_SEND;
1009
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
1010
    return WL_ERROR_SEND;
1011

    
1012
  return WL_SUCCESS;
1013
}
1014

    
1015
/**
1016
 * Adds header information and checksum to the given
1017
 * packet and sends it. Header information includes
1018
 * XBEE_FRAME_START and the packet length, as two bytes.
1019
 *
1020
 * @param buf the packet data
1021
 * @param len the size in bytes of the packet data
1022
 *
1023
 **/
1024
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
1025
{
1026
  uint8_t checksum = xbee_compute_checksum(buf, len);
1027
  
1028
  //packet prefix
1029
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1030
    return WL_ERROR_SEND;
1031
  if (xbee_putc((uint8_t)(len>>8)) != WL_SUCCESS)
1032
    return WL_ERROR_SEND;
1033
  if (xbee_putc((uint8_t)(len&0xFF)) != WL_SUCCESS)
1034
    return WL_ERROR_SEND;
1035

    
1036
  if (xbee_send(buf, len) != WL_SUCCESS)
1037
    return WL_ERROR_SEND;
1038
  
1039
  if (xbee_putc(checksum) != WL_SUCCESS)
1040
    return WL_ERROR_SEND;
1041
  
1042
  return WL_SUCCESS;
1043
}
1044

    
1045
/**
1046
 * Sends an AT command to read a parameter.
1047
 *
1048
 * @param command the AT command to send. For exmaple,
1049
 * use ID to read the PAN ID and MY to return the XBee ID.
1050
 * See the XBee reference guide for a complete listing.
1051
 **/
1052
int8_t xbee_send_read_at_command(uint8_t* command)
1053
{
1054
  return xbee_send_modify_at_command(command, NULL, 0);
1055
}
1056

    
1057
/**
1058
 * Sends the given AT command.
1059
 *
1060
 * @param command the AT command to send (e.g., MY, ID)
1061
 * @param value the value to pass as a parameter
1062
 * (or NULL if there is no parameter)
1063
 **/
1064
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1065
{
1066
  uint8_t buf[12];
1067

    
1068
  buf[0] = XBEE_FRAME_AT_COMMAND;
1069
  buf[1] = 1;
1070
  buf[2] = command[0];
1071
  buf[3] = command[1];
1072
  if (value != NULL)
1073
  {
1074
    if (len > 8)
1075
    {
1076
      WL_DEBUG_PRINT("AT Command too large.\r\n");
1077
      return WL_ERROR_ARGUMENT;
1078
    }
1079
    memcpy(buf+4,value,len);
1080
  }
1081

    
1082
  return xbee_send_frame(buf, 4 + len);
1083
}
1084

    
1085
/**
1086
 * Send the specified packet.
1087
 *
1088
 * @param packet the packet data to send
1089
 * @param len the number of bytes in the packet
1090
 *
1091
 * @param dest the ID of the XBee to send the packet to,
1092
 * or XBEE_BROADCAST to send the message to all robots
1093
 * in the PAN.
1094
 *
1095
 * @param options a combination of the flags
1096
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1097
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1098
 *
1099
 * @param frame the frame number to associate this packet
1100
 * with. This will be used to identify the response when
1101
 * the XBee alerts us as to whether or not our message
1102
 * was received.
1103
 **/
1104
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1105
{
1106
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1107
  uint8_t i = 0;
1108

    
1109
  if (len > 100)
1110
  {
1111
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1112
    return WL_ERROR_ARGUMENT;
1113
  }
1114
  
1115
  // calculate checksum
1116
  for(;i<len;i++)
1117
    sum += packet[len];
1118
  sum += frame;
1119
  sum += (dest&0xFF00) >> 8;
1120
  sum += dest&0x00FF;
1121
  sum += options;
1122
  sum = 0xFF - sum;
1123

    
1124
  //packet prefix
1125
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1126
    return WL_ERROR_SEND;
1127
  if (xbee_putc(0x00) != WL_SUCCESS)
1128
    return WL_ERROR_SEND;
1129
  if (xbee_putc(len+5) != WL_SUCCESS)
1130
    return WL_ERROR_SEND;
1131
    
1132
  //send header for TX request
1133
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1134
    return WL_ERROR_SEND;
1135
  if (xbee_putc(frame) != WL_SUCCESS)
1136
    return WL_ERROR_SEND;
1137
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1138
    return WL_ERROR_SEND;
1139
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1140
    return WL_ERROR_SEND;
1141
  if (xbee_putc(options) != WL_SUCCESS)
1142
    return WL_ERROR_SEND;
1143

    
1144
  // send packet
1145
  if (xbee_send(packet, len) != WL_SUCCESS)
1146
    return WL_ERROR_SEND;
1147

    
1148
  // send checksum
1149
  if (xbee_putc(sum) != WL_SUCCESS)
1150
    return WL_ERROR_SEND;
1151

    
1152
  return WL_SUCCESS;
1153
}
1154

    
1155
/**
1156
 * Handles modem status packets.
1157
 *
1158
 * @param status the type of status packet received.
1159
 **/
1160
void xbee_handle_status(uint8_t status)
1161
{
1162
  switch (status)
1163
  {
1164
    case 0:
1165
      WL_DEBUG_PRINT("XBee hardware reset.\r\n");
1166
      break;
1167
    case 1:
1168
      WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
1169
      break;
1170
    case 2:
1171
      WL_DEBUG_PRINT("Associated.\r\n");
1172
      break;
1173
    case 3:
1174
      WL_DEBUG_PRINT("Disassociated.\r\n");
1175
      break;
1176
    case 4:
1177
      WL_DEBUG_PRINT("Synchronization lost.\r\n");
1178
      break;
1179
    case 5:
1180
      WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1181
      break;
1182
    case 6:
1183
      WL_DEBUG_PRINT("Coordinator started.\r\n");
1184
      break;
1185
  }
1186
}
1187

    
1188
/**
1189
 * Handles AT command response packets.
1190
 * @param command the two character AT command, e.g. MY or ID
1191
 * @param result 0 for success, 1 for an error
1192
 * @param len the length in bytes of extra
1193
 **/
1194
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t status, uint8_t len)
1195
{
1196
  WL_DEBUG_PRINT("HANDLE AT COMMAND\r\n");
1197
  if (status != 0)
1198
  {
1199
    WL_DEBUG_PRINT("Error with AT");
1200
    WL_DEBUG_PRINT(command);
1201
    WL_DEBUG_PRINT(" packet. Result = ");
1202
    switch(status) {
1203
    case 1:
1204
      WL_DEBUG_PRINT("ERROR\r\n");
1205
      break;
1206
    case 2:
1207
      WL_DEBUG_PRINT("Invalid Command\r\n");
1208
      break;
1209
    case 3:
1210
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
1211
      break;
1212
    }
1213
    return WL_SUCCESS;
1214
  }
1215
  WL_DEBUG_PRINT("AT");
1216
  WL_DEBUG_PRINT_CHAR((uint8_t)(command>>8));
1217
  WL_DEBUG_PRINT_CHAR((uint8_t)(command));
1218
  WL_DEBUG_PRINT(" command is being handled\r\n");
1219
  
1220
  // TODO: program more command responses here (ND, etc)
1221
  switch(command) {
1222
  case ('I'<<8)+'D': // PAN
1223
  case ('C'<<8)+'H': // channel
1224
  case ('M'<<8)+'Y': // address
1225
  case ('A'<<8)+'P': // api mode
1226
    // copy command to handler
1227
    xbee_command[0] = (command&0xFF00)>>8;
1228
    xbee_command[1] = command&0x00FF;
1229
    uint8_t ptr = basic_buf_last;
1230
    for(command=2;command<len+2;command++) {
1231
      xbee_command[command] = xbee_basic_buf_get(&ptr);
1232
      if (xbee_command[command] == '\r')
1233
        break; // done with command
1234
      WL_DEBUG_PRINT_HEX(xbee_command[command]);
1235
    }
1236
    xbee_command[command] = '\0';
1237
    WL_DEBUG_PRINT("len=");
1238
    WL_DEBUG_PRINT_INT(len);
1239
    WL_DEBUG_PRINT("ID,CH,or MY command result:");
1240
    WL_DEBUG_PRINT(xbee_command);
1241
    WL_DEBUG_PRINT("\r\n");
1242
    break;
1243
  default:
1244
    WL_DEBUG_PRINT("unknown AT command");
1245
  }
1246
  
1247
  // signal handler that command response is done
1248
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
1249

    
1250
  return WL_SUCCESS;
1251
}
1252

    
1253
/**
1254
 * Sets the personal area network id.
1255
 *
1256
 * @param id the new personal area network (PAN) id
1257
 **/
1258
int8_t xbee_set_pan(uint16_t id)
1259
{
1260
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1261
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1262
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1263
  
1264
  int16_t i=0;
1265
  // change status to command wait
1266
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1267
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1268
  // wait for up to 30 ms
1269
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1270
    delay_us(1); // wait 3us
1271
  }
1272
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1273
    i = WL_SUCCESS;
1274
  else
1275
    i = WL_ERROR_XBEE_COMMAND; // set error code
1276
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1277
  return (int8_t)i; // return
1278
}
1279

    
1280
/**
1281
 * Get the PAN ID for the XBee.
1282
 *
1283
 * @return the personal area network id, or
1284
 * XBEE_PAN_DEFAULT if it has not yet been set.
1285
 **/
1286
uint16_t xbee_get_pan()
1287
{
1288
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1289
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1290
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1291
  
1292
  uint16_t i=0;
1293
  // change status to command wait
1294
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1295
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1296
  // wait for up to 30 ms
1297
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1298
    delay_us(1); // wait 3us
1299
  }
1300
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1301
    i = xbee_command[2]|(xbee_command[3]<<8); // do ntoh16 coversion
1302
  else
1303
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1304
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1305
  return i; // return
1306
}
1307

    
1308
/**
1309
 * Set the channel the XBee is using.
1310
 *
1311
 * @param channel the channel the XBee will not use,
1312
 * between 0x0B and 0x1A
1313
 *
1314
 * @see xbee_get_channel
1315
 **/
1316
int8_t xbee_set_channel(uint8_t channel)
1317
{
1318
  if (channel < 0x0B || channel > 0x1A)
1319
  {
1320
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1321
    return WL_ERROR_ARGUMENT;
1322
  }
1323

    
1324
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1325
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1326
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1327
  
1328
  int16_t i=0;
1329
  // change status to command wait
1330
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1331
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1332
  // wait for up to 30 ms
1333
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1334
    delay_us(1); // wait 3us
1335
  }
1336
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1337
    i = WL_SUCCESS;
1338
  else
1339
    i = WL_ERROR_XBEE_COMMAND; // set error code
1340
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1341
  return (int8_t)i; // return
1342
}
1343

    
1344
/**
1345
 * Returns the channel which the XBee is currently using.
1346
 *
1347
 * @return the channel the XBee is using
1348
 *
1349
 * @see xbee_set_channel
1350
 **/
1351
int8_t xbee_get_channel(void)
1352
{
1353
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1354
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1355
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1356
  
1357
  int16_t i=0;
1358
  // change status to command wait
1359
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1360
  xbee_send_read_at_command((uint8_t*)"CH"); // send command to get the channel
1361
  // wait for up to 30 ms
1362
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1363
    delay_us(1); // wait 3us
1364
  }
1365
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1366
    i = (int8_t)xbee_command[2]; // get channel
1367
  else
1368
    i = WL_ERROR_XBEE_COMMAND; // set error code
1369
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1370
  return i; // return
1371
}
1372

    
1373
/**
1374
 * Get the 16-bit address of the XBee.
1375
 * This is used to specify who to send messages to
1376
 * and who messages are from.
1377
 *
1378
 * @return the 16-bit address of the XBee.
1379
 **/
1380
uint16_t xbee_get_address(void)
1381
{
1382
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1383
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1384
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1385
  
1386
  uint16_t i=0;
1387
  // change status to command wait  
1388
  /*WL_DEBUG_PRINT("\r\nbefore status=");
1389
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
1390
  WL_DEBUG_PRINT("\r\n");*/
1391
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);  
1392
  /*if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
1393
    WL_DEBUG_PRINT("|API OFF|");
1394
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
1395
    WL_DEBUG_PRINT("|API ON|");
1396
  } else {
1397
    WL_DEBUG_PRINT("|API ERROR|");
1398
  }
1399
  WL_DEBUG_PRINT("after status=");
1400
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
1401
  WL_DEBUG_PRINT("\r\n");*/
1402
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1403
  // wait for up to 30 ms
1404
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1405
    delay_us(1); // wait 3us
1406
  }
1407
  
1408
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
1409
    i = xbee_command[2]|(xbee_command[3]<<8); // do ntoh16 coversion
1410
  } else
1411
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1412
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1413
  WL_DEBUG_PRINT("get MY address\r\n");
1414
  return i; // return
1415
}
1416

    
1417
/**@} **/ // end xbee group
1418