Project

General

Profile

Statistics
| Revision:

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

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

    
356

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

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

    
408
/** status functions **/
409
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
410
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
411

    
412

    
413
// test interrupt
414
/*ISR(USART1_RX_vect) {
415
  WL_DEBUG_PRINT("in interrupt|");
416
  char c = UDR1;
417
  WL_DEBUG_PRINT_HEX(c);
418
  WL_DEBUG_PRINT("|in interrupt");
419
}*/
420

    
421

    
422

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

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

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

    
562
  if (xbee_exit_command_mode() != 0) {
563
    WL_DEBUG_PRINT("can't exit command mode\r\n");
564
    return -1;
565
  }
566
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
567
  
568
  WL_DEBUG_PRINT("Left command mode.\r\n");
569
  
570
    // wait one second for the baud change to stabalize
571
  delay_ms(1000);
572

    
573
  // enter command mode
574
  WL_DEBUG_PRINT("entering command mode 2\r\n");
575
  xbee_send_string((uint8_t*)"+++");
576
  xbee_wait_for_ok();
577
  WL_DEBUG_PRINT("entered command mode 2\r\n");
578
    
579
  WL_DEBUG_PRINT("before status=");
580
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
581
  WL_DEBUG_PRINT("\r\n");
582
  
583
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
584
  
585
  WL_DEBUG_PRINT("after status=");
586
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
587
  WL_DEBUG_PRINT("\r\n");
588
  
589
  // TODO: we should set the MY address to the robot address from eeprom
590
  
591
  if (xbee_get_address() == WL_ERROR_XBEE_COMMAND_16BIT) {
592
    WL_DEBUG_PRINT("getting MY address failed\r\n");
593
  }
594
  WL_DEBUG_PRINT("MY address successful\r\n");
595
  
596
  
597
  return WL_SUCCESS;
598
}
599

    
600
/**
601
 * Call when finished using the XBee library.
602
 **/
603
int8_t xbee_terminate()
604
{
605
  int ret=xbee_exit_api_mode();
606
  if (ret != WL_SUCCESS) {
607
    WL_DEBUG_PRINT("xbee termination failed\r\n");
608
    WL_DEBUG_PRINT_INT(ret);
609
    WL_DEBUG_PRINT("|\r\n");
610
    return WL_ERROR_TERMINATION_FAILED;
611
  }
612
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
613
  return WL_SUCCESS;
614
}
615

    
616
/**
617
 * Sends a character to the XBee.
618
 *
619
 * @param c the byte to send
620
 * @return 0 for success, nonzero for failure
621
 **/
622
int8_t xbee_putc(uint8_t c) {
623

    
624
  // Wait until buffer is clear for sending
625
  // Then load buffer with your character
626
  
627
  WL_DEBUG_PRINT("xbee_putc:");
628
  WL_DEBUG_PRINT_HEX(c);
629
  WL_DEBUG_PRINT("|\r\n");
630
  
631
/*#ifdef FIREFLY
632
  loop_until_bit_is_set(UCSR0A, UDRE0);  
633
  UDR0 = c;
634
#else*/
635
  loop_until_bit_is_set(UCSR1A, UDRE1);
636
  WL_DEBUG_PRINT_HEX(UCSR1A&TXC1);
637
  UDR1 = c;
638
//#endif
639
  
640
  return WL_SUCCESS;
641
}
642

    
643
/**
644
 * Returns the first byte in the buffer received from xbee.
645
 * This function blocks execution until a character has been
646
 * received. xbee_init must be called before this function
647
 * may be used.
648
 * 
649
 * @return the first character in the xbee buffer, -1 on error
650
 * 
651
 * @see xbee_init, xbee_getc_nb
652
 **/
653
int16_t xbee_getc(void) {
654
    
655
  // Wait for the receive buffer to be filled
656
  // Then read the receive buffer
657
#ifdef FIREFLY
658
  loop_until_bit_is_set(UCSR0A, RXC0);  
659
  return UDR0;
660
#else
661
  loop_until_bit_is_set(UCSR1A, RXC1);
662
  return UDR1;
663
#endif
664
}
665

    
666
/**
667
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
668
 * it is returned, otherwise -1 is returned immediately. xbee_init
669
 * must be called before this function can be used.
670
 *
671
 * @param c The received byte. This will be set if a byte has been received.
672
 * 
673
 * @return -1 If no byte is available, 0 otherwise, positive for error
674
 *
675
 * @see xbee_getc
676
 **/
677
int8_t xbee_getc_nb(uint8_t *c) {
678

    
679
  // check if the receive buffer is filled
680
#ifdef FIREFLY
681
  if (UCSR0A & (1<<RXC0)) {
682
    (*c) = UDR0;
683
#else
684
  if (UCSR1A & (1<<RXC1)) {
685
    (*c) = UDR1;
686
#endif
687
    return WL_SUCCESS;
688
  }
689
  return -1; // Return empty
690
}
691

    
692
/**
693
 * Send a buffer buf of size bytes to the XBee.
694
 *
695
 * @param buf the buffer of data to send
696
 * @param size the number of bytes to send
697
 **/
698
int8_t xbee_send(uint8_t* buf, uint16_t size)
699
{
700
  uint16_t i=0; // check if we need this variable
701
  while(i<size) {
702
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
703
      return WL_ERROR_SEND;
704
  }
705

    
706
  return WL_SUCCESS;
707
}
708

    
709
/**
710
 * Sends a string to the XBee.
711
 *
712
 * @param c the string to send to the XBEE
713
 **/
714
static int8_t xbee_send_string(uint8_t* c)
715
{
716
  return xbee_send(c, strlen((char*)c));
717
}
718

    
719

    
720
/**
721
 * Enter into command mode.
722
 **/
723
static int8_t xbee_enter_command_mode(void)
724
{
725
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
726
    return WL_ERROR_XBEE_COMMAND;
727
  }
728
  WL_DEBUG_PRINT("sent command +++|");
729

    
730
  if (xbee_wait_for_ok() != WL_SUCCESS) {
731
    return WL_ERROR_XBEE_COMMAND;
732
  }
733
  WL_DEBUG_PRINT("got OK\r\n");
734
  
735
  return WL_SUCCESS;
736
}
737

    
738
/**
739
 * Exit from command mode.
740
 **/
741
static int8_t xbee_exit_command_mode()
742
{
743
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
744
    return WL_ERROR_SEND;
745
  }
746
  xbee_wait_for_ok();
747

    
748
  return WL_SUCCESS;
749
}
750

    
751
/**
752
 * Enter API mode.
753
 **/
754
static int8_t xbee_enter_api_mode(void) {
755
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
756
    return WL_ERROR_SEND;
757
  }
758
  if (xbee_wait_for_ok() != 0) {
759
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
760
    return WL_ERROR_SEND;
761
  }
762
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
763
  
764
  return WL_SUCCESS;
765
}
766

    
767
/**
768
 * Enter API mode 2.
769
 **/
770
static int8_t xbee_enter_api_mode2(void) {
771
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
772
    return WL_ERROR_SEND;
773
  }
774
  if (xbee_wait_for_ok() != 0) {
775
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
776
    return WL_ERROR_SEND;
777
  }
778
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
779
  
780
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
781
  
782
  return WL_SUCCESS;
783
}
784

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

    
814
/**
815
 * Wait until the string "OK\r" is received from the XBee.
816
 **/
817
static int8_t xbee_wait_for_ok()
818
{
819
  return xbee_wait_for_string((uint8_t*)"OK\r", 3);
820
}
821

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

    
856
  return 0;
857
}
858

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

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

    
918
/**
919
 * Returns the checksum of the given packet.
920
 *
921
 * @param buf the data for the packet to send
922
 * @param len the length of the packet in bytes
923
 *
924
 * @return the checksum of the packet, which will
925
 * become the last byte sent in the packet
926
 **/
927
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
928
{
929
  uint8_t sum = 0;
930
  while(--len > 0) {
931
    sum += buf[len];
932
  }
933
  sum += buf[0];
934
  return 0xFF - sum;
935
}
936

    
937
/**
938
 * Adds buf to the previous checksum total
939
 *
940
 * @param buf a byte buffer to add to the checksum
941
 * @param len the length of the buffer
942
 * @param sum the previous sum
943
 *
944
 * @return error code
945
 **/
946
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
947
  if (buf == NULL || sum == NULL)
948
    return WL_ERROR_ARGUMENT;
949
  while(--len > 0) {
950
    *sum += buf[len];
951
  }
952
  *sum += buf[0];
953
  return WL_SUCCESS;
954
}
955

    
956

    
957
/**
958
 * Sends header information. Header information includes
959
 * XBEE_FRAME_START and the packet length, as two bytes.
960
 *
961
 * @param type the packet type
962
 * @param len the size in bytes of the packet data
963
 *
964
 **/
965
int8_t xbee_send_header(uint8_t type, uint16_t len)
966
{  
967
  //packet prefix
968
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
969
    return WL_ERROR_SEND;
970
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
971
    return WL_ERROR_SEND;
972
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
973
    return WL_ERROR_SEND;
974

    
975
  return WL_SUCCESS;
976
}
977

    
978
/**
979
 * Adds header information and checksum to the given
980
 * packet and sends it. Header information includes
981
 * XBEE_FRAME_START and the packet length, as two bytes.
982
 *
983
 * @param buf the packet data
984
 * @param len the size in bytes of the packet data
985
 *
986
 **/
987
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
988
{
989
  uint8_t checksum = xbee_compute_checksum(buf, len);
990
  
991
  //packet prefix
992
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
993
    return WL_ERROR_SEND;
994
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
995
    return WL_ERROR_SEND;
996
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
997
    return WL_ERROR_SEND;
998

    
999
  if (xbee_send(buf, len) != WL_SUCCESS)
1000
    return WL_ERROR_SEND;
1001
  
1002
  if (xbee_putc(checksum) != WL_SUCCESS)
1003
    return WL_ERROR_SEND;
1004
  
1005
  return WL_SUCCESS;
1006
}
1007

    
1008
/**
1009
 * Sends an AT command to read a parameter.
1010
 *
1011
 * @param command the AT command to send. For exmaple,
1012
 * use ID to read the PAN ID and MY to return the XBee ID.
1013
 * See the XBee reference guide for a complete listing.
1014
 **/
1015
int8_t xbee_send_read_at_command(uint8_t* command)
1016
{
1017
  return xbee_send_modify_at_command(command, NULL, 0);
1018
}
1019

    
1020
/**
1021
 * Sends the given AT command.
1022
 *
1023
 * @param command the AT command to send (e.g., MY, ID)
1024
 * @param value the value to pass as a parameter
1025
 * (or NULL if there is no parameter)
1026
 **/
1027
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1028
{
1029
  uint8_t buf[12];
1030

    
1031
  buf[0] = XBEE_FRAME_AT_COMMAND;
1032
  buf[1] = 1;
1033
  buf[2] = command[0];
1034
  buf[3] = command[1];
1035
  if (value != NULL)
1036
  {
1037
    if (len > 8)
1038
    {
1039
      WL_DEBUG_PRINT("AT Command too large.\r\n");
1040
      return WL_ERROR_ARGUMENT;
1041
    }
1042
    memcpy(buf+4,value,len);
1043
  }
1044

    
1045
  return xbee_send_frame(buf, 4 + len);
1046
}
1047

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

    
1072
  if (len > 100)
1073
  {
1074
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1075
    return WL_ERROR_ARGUMENT;
1076
  }
1077
  
1078
  // calculate checksum
1079
  for(;i<len;i++)
1080
    sum += packet[len];
1081
  sum += frame;
1082
  sum += (dest&0xFF00) >> 8;
1083
  sum += dest&0x00FF;
1084
  sum += options;
1085
  sum = 0xFF - sum;
1086

    
1087
  //packet prefix
1088
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1089
    return WL_ERROR_SEND;
1090
  if (xbee_putc(0x00) != WL_SUCCESS)
1091
    return WL_ERROR_SEND;
1092
  if (xbee_putc(len+5) != WL_SUCCESS)
1093
    return WL_ERROR_SEND;
1094
    
1095
  //send header for TX request
1096
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1097
    return WL_ERROR_SEND;
1098
  if (xbee_putc(frame) != WL_SUCCESS)
1099
    return WL_ERROR_SEND;
1100
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1101
    return WL_ERROR_SEND;
1102
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1103
    return WL_ERROR_SEND;
1104
  if (xbee_putc(options) != WL_SUCCESS)
1105
    return WL_ERROR_SEND;
1106

    
1107
  // send packet
1108
  if (xbee_send(packet, len) != WL_SUCCESS)
1109
    return WL_ERROR_SEND;
1110

    
1111
  // send checksum
1112
  if (xbee_putc(sum) != WL_SUCCESS)
1113
    return WL_ERROR_SEND;
1114

    
1115
  return WL_SUCCESS;
1116
}
1117

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

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

    
1203
  return WL_SUCCESS;
1204
}
1205

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

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

    
1261
/**
1262
 * Set the channel the XBee is using.
1263
 *
1264
 * @param channel the channel the XBee will not use,
1265
 * between 0x0B and 0x1A
1266
 *
1267
 * @see xbee_get_channel
1268
 **/
1269
int8_t xbee_set_channel(uint8_t channel)
1270
{
1271
  if (channel < 0x0B || channel > 0x1A)
1272
  {
1273
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1274
    return -1;
1275
  }
1276

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

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

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

    
1364
/**@} **/ // end xbee group
1365