Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (37.4 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 <eeprom.h>
43
#include "xbee.h"
44

    
45

    
46
/* Internal Function Prototypes */
47

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

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

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

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

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

    
79
/*Global Variables*/
80

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

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

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

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

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

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

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

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

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

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

    
127

    
128

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

    
132
/*Function Implementations*/
133

    
134
/**
135
 * Interrupt for the robot. Adds bytes received from the xbee
136
 * to the buffer.
137
 **/
138
 
139
 
140
#ifndef FIREFLY
141
#define PORT UDR1
142
#define FLAG (UCSR1A & (1<<RXC1))
143
ISR(USART1_RX_vect) {
144
#else
145
#define PORT UDR0
146
#define FLAG (UCSR0A & (1<<RXC0))
147
SIGNAL(SIG_USART0_RECV)
148
#endif
149
  // start of frame
150
  uint8_t apitype = PORT; // get frame start byte
151
  uint16_t i=0;
152
  uint16_t len=0;
153
  
154
  // check that we're in API mode
155
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
156
    // not in API mode
157
    WL_DEBUG_PRINT_P("|api off branch");
158
    
159
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT) {
160
      // get rest of command and put in basic buf
161
      xbee_basic_buf[i] = apitype;
162
      if (xbee_basic_buf[i++] != '\r') {
163
        while(i < PACKET_BUFFER_SIZE) {
164
          if (FLAG) {
165
            xbee_basic_buf[i] = PORT;
166
            if (xbee_basic_buf[i] == '\r')
167
              break;
168
            i++;
169
          }
170
        }
171
      }
172
      WL_DEBUG_PRINT_P("got packet, len=");
173
      WL_DEBUG_PRINT_INT(i);
174
      WL_DEBUG_PRINT_P("str=");
175
      WL_DEBUG_PRINT(xbee_basic_buf);
176
      // signal handler that command response is done
177
      setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
178
    }
179
    WL_DEBUG_PRINT_P("return\r\n");
180
    return;
181
  }  
182
  //WL_DEBUG_PRINT_P("|api on branch");
183
    
184
  // get length and type
185
  while(i<3) {
186
    if (FLAG) {
187
      if (i==0) {
188
        len |= PORT<<8;       
189
      } else if (i==1) {
190
        len |= PORT;
191
      } else if (i==2) {      
192
        apitype = PORT;
193
      }
194
      i++;
195
    }
196
  }
197
  
198
  // do something based on the type
199
  i=1;
200
  switch(apitype) {
201
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
202
    // AT command response
203
    if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
204
      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 ****
205
    uint16_t atcommand=0;
206
    uint8_t ptr=basic_buf_last;
207
    while(i<len) {
208
      if (FLAG) {
209
        if (i==1)
210
          apitype = PORT; // get frame id, but ignore it
211
        else if (i==2)
212
          atcommand |= PORT<<8; // get command char1
213
        else if (i==3)
214
          atcommand |= PORT; // get command char2
215
        else if (i==4)
216
          apitype = PORT; // get status
217
        else {
218
          // put the command response on the basic buf temporarily
219
          if (xbee_basic_buf_add(&ptr,PORT) != 0)
220
            break;
221
        }
222
        i++;
223
      }
224
    }
225
    // handle AT command    
226
    WL_DEBUG_PRINT_P("|XBEE_FRAME_AT_COMMAND_RESPONSE");
227
    WL_DEBUG_PRINT_P("|i=");
228
    WL_DEBUG_PRINT_INT(i);
229
    WL_DEBUG_PRINT_P("|len=");
230
    WL_DEBUG_PRINT_INT(len);
231
    WL_DEBUG_PRINT_P("|status:");
232
    WL_DEBUG_PRINT_INT(apitype);
233
    WL_DEBUG_PRINT_P("|atcommand:");
234
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand>>8));
235
    WL_DEBUG_PRINT_CHAR((uint8_t)(atcommand&0xFF));
236
    WL_DEBUG_PRINT_P("|buf=");
237
    uint8_t ptr2 = basic_buf_last;
238
    for(uint8_t j=0;j<i;j++)
239
      WL_DEBUG_PRINT_HEX(xbee_basic_buf_get(&ptr2));
240
    WL_DEBUG_PRINT_P("|\r\n");
241
    xbee_handle_at_command_response(atcommand,apitype,len-5); // TODO: rewrite function
242
    break; }
243
  case XBEE_FRAME_TX_STATUS: {
244
    // TX status
245
    uint8_t frame_id = 0;
246
    while(i<len) {
247
      if (FLAG) {
248
        if (i==1)
249
          frame_id = PORT;
250
        else {
251
          ackhandle(frame_id,PORT); // handle the status
252
          break;
253
        }
254
        i++;
255
      }
256
    }
257
    WL_DEBUG_PRINT_P("|XBEE_FRAME_TX_STATUS");
258
    break; }
259
  case XBEE_FRAME_RX_64: {
260
    // receive a packet with 64bit address
261
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_64");
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
    WL_DEBUG_PRINT_P("|XBEE_FRAME_RX_16|len=");
338
    WL_DEBUG_PRINT_INT(len);
339
    WL_DEBUG_PRINT_P("|source=");
340
    WL_DEBUG_PRINT_INT(source);
341
    WL_DEBUG_PRINT_P("|framenum=");
342
    WL_DEBUG_PRINT_INT(framenum);
343
    WL_DEBUG_PRINT_P("group=");
344
    WL_DEBUG_PRINT_INT(group);
345
    WL_DEBUG_PRINT_P("\r\n");
346
    break; }
347
    default:
348
      WL_DEBUG_PRINT_P("|BAD APITYPE");
349
  } // end of switch statement
350
  while (1) {
351
    if (FLAG) {
352
      apitype = PORT; // get checksum, and ignore
353
      break;
354
    }
355
  }
356
  WL_DEBUG_PRINT_P("|interrupt - return\r\n");
357
} // end of interrupt 
358

    
359

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

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

    
411
/** status functions **/
412
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
413
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
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_P("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
  // set status
428
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
429
  
430
  // clear last packet buffer
431
  for(int i=0;i<NUM_LAST_PACKETS;i++)
432
    lastPacket[i].source = lastPacket[i].framenum = 0;
433
  
434
  // Set startup baud rate of 9600
435
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
436
  // Enable receiver and transmitter and the receiving interrupt
437
#ifdef FIREFLY
438
  UBRR0H = 0x00;
439
  UBRR0L = 103;
440
  UCSR0A |= (1<<U2X0);
441
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
442
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
443
#else
444
  // Bayboard or robot  
445
  UBRR1H = 0x00; // baud rate
446
  UBRR1L = 103;  // baud rate
447
  UCSR1A |= (1<<U2X1); // double transmit speed 
448
  //Enable receiver and transmitter on USART1
449
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
450
        
451
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
452
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
453
  
454
  UCSR1B |= (1<<RXCIE1);  // enable receive, transmit (1<<RXCIE)
455
#endif
456
  sei();
457
 
458
  // enter command mode
459
  WL_DEBUG_PRINT_P("entering command mode\r\n");
460
  xbee_send_string((uint8_t*)"+++");
461
  xbee_wait_for_ok();
462
  WL_DEBUG_PRINT_P("entered command mode\r\n");
463

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

    
535
  // enter command mode
536
  WL_DEBUG_PRINT_P("entering command mode 2\r\n");
537
  xbee_send_string((uint8_t*)"+++");
538
  xbee_wait_for_ok();
539
  WL_DEBUG_PRINT_P("entered command mode 2\r\n");
540
  
541
  if (xbee_enter_api_mode() != 0) {
542
    WL_DEBUG_PRINT_P("can't enter api mode\r\n");
543
    return -1;
544
  }
545
  
546
#ifdef WL_DEBUG
547
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
548
    WL_DEBUG_PRINT_P("|API OFF|");
549
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
550
    WL_DEBUG_PRINT_P("|API ON|");
551
  } else {
552
    WL_DEBUG_PRINT_P("|API ERROR|");
553
  }
554
#endif
555
  
556
  // set MY address
557
  uint8_t newmy = (uint8_t)get_robotid();
558
  if (newmy == 0xFF) {
559
    WL_DEBUG_PRINT_P("can't get MY address from EEPROM\r\n");
560
  } else {
561
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); 
562
    if (xbee_send_modify_at_command((uint8_t*)"MY",&newmy,1) != WL_SUCCESS) {
563
      WL_DEBUG_PRINT_P("setting MY address failed\r\n");
564
    }
565
    // wait for up to 30 ms
566
    newmy = 0;
567
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && newmy++ < 10000) {
568
      delay_us(1); // wait 3us
569
    }  
570
    if (newmy < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
571
      WL_DEBUG_PRINT_P("setting MY address successful\r\n");
572
    } else
573
      WL_DEBUG_PRINT_P("setting MY address failed\r\n");
574
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
575
  }
576
    
577
  // get MY address
578
  uint16_t address = xbee_get_address();
579
  if (address == WL_ERROR_XBEE_COMMAND_16BIT) {
580
    WL_DEBUG_PRINT_P("getting MY address failed\r\n");
581
  }
582
  WL_DEBUG_PRINT_P("MY address:");
583
  WL_DEBUG_PRINT_HEX((uint8_t)(address>>8));
584
  WL_DEBUG_PRINT_HEX((uint8_t)(address&0xFF));
585
  WL_DEBUG_PRINT_P("\r\n");
586
  
587
  // set PAN
588
  xbee_set_pan(0);
589
  
590
  return WL_SUCCESS;
591
}
592

    
593
/**
594
 * Call when finished using the XBee library.
595
 **/
596
int8_t xbee_terminate()
597
{
598
  int ret=xbee_exit_api_mode();
599
  if (ret != WL_SUCCESS) {
600
    WL_DEBUG_PRINT_P("xbee termination failed\r\n");
601
    WL_DEBUG_PRINT_INT(ret);
602
    WL_DEBUG_PRINT_P("|\r\n");
603
    return WL_ERROR_TERMINATION_FAILED;
604
  }
605
  delay_ms(1000);
606
  // reset baud to defaults
607
  xbee_enter_command_mode();
608
  xbee_send_string((uint8_t*)"ATBD 3\r");
609
  xbee_wait_for_ok();
610
  xbee_exit_command_mode();
611
  UBRR1H = 0x00;
612
  UBRR1L = 103;
613
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
614
  return WL_SUCCESS;
615
}
616

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

    
625
  // Wait until buffer is clear for sending
626
  // Then load buffer with your character
627
  
628
  /*WL_DEBUG_PRINT_P("xbee_putc:");
629
  WL_DEBUG_PRINT_HEX(c);
630
  WL_DEBUG_PRINT_P("|\r\n");*/
631
  
632
#ifdef FIREFLY
633
  loop_until_bit_is_set(UCSR0A, UDRE0);  
634
  UDR0 = c;
635
#else
636
  loop_until_bit_is_set(UCSR1A, UDRE1);
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_P("sent command +++|");
729

    
730
  if (xbee_wait_for_ok() != WL_SUCCESS) {
731
    return WL_ERROR_XBEE_COMMAND;
732
  }
733
  WL_DEBUG_PRINT_P("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
  if (xbee_wait_for_ok() != WL_SUCCESS) {
747
    WL_DEBUG_PRINT_P("failed to exit command mode\r\n");
748
    return WL_ERROR_SEND;
749
  }
750

    
751
  return WL_SUCCESS;
752
}
753

    
754
/**
755
 * Enter API mode.
756
 **/
757
static int8_t xbee_enter_api_mode(void) {
758
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
759
    return WL_ERROR_SEND;
760
  }
761
  if (xbee_wait_for_ok() != WL_SUCCESS) {
762
    WL_DEBUG_PRINT_P("failed to enter API mode\r\n");
763
    return WL_ERROR_SEND;
764
  }
765
  if (xbee_exit_command_mode() != WL_SUCCESS) {
766
    WL_DEBUG_PRINT_P("failed to enter API mode\r\n");
767
    return WL_ERROR_SEND;
768
  }    
769
  WL_DEBUG_PRINT_P("got OK after entering API mode\r\n");
770
  
771
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
772
  
773
  return WL_SUCCESS;
774
}
775

    
776
/**
777
 * Enter API mode 2.
778
 **/
779
static int8_t xbee_enter_api_mode2(void) {
780
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
781
    return WL_ERROR_SEND;
782
  }
783
  if (xbee_wait_for_ok() != WL_SUCCESS) {
784
    WL_DEBUG_PRINT_P("failed to enter API mode2\r\n");
785
    return WL_ERROR_SEND;
786
  }
787
  if (xbee_exit_command_mode() != WL_SUCCESS) {
788
    WL_DEBUG_PRINT_P("failed to enter API mode2\r\n");
789
    return WL_ERROR_SEND;
790
  }    
791
  WL_DEBUG_PRINT_P("got OK after entering API mode2\r\n");
792
  
793
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
794
  
795
  return WL_SUCCESS;
796
}
797

    
798
/**
799
 * Exit API mode.
800
 **/
801
static int8_t xbee_exit_api_mode()
802
{
803
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
804
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
805
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
806
  WL_DEBUG_PRINT_P("now exiting API mode\r\n");
807
  
808
  int16_t i=0;
809
  // change status to command wait
810
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
811
  if (xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)(&i),1) != WL_SUCCESS) { // send command
812
    WL_DEBUG_PRINT_P("error sending AP 0 command\r\n");
813
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
814
    return WL_ERROR_XBEE_COMMAND;
815
  }
816
  // wait for up to 30 ms
817
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
818
    delay_us(1); // wait 3us
819
  }
820
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
821
    WL_DEBUG_PRINT_P("done exiting API mode\r\n");
822
    i = WL_SUCCESS;
823
  } else {
824
    WL_DEBUG_PRINT_P("failed to exit API mode\r\n");
825
    i = WL_ERROR_XBEE_COMMAND; // set error code
826
  }
827
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
828
  setStatus(XBEE_API_MASK,XBEE_API_OFF);
829
  
830
  return (int8_t)i; // return
831
}
832

    
833
/**
834
 * Wait until the string "OK\r" is received from the XBee.
835
 **/
836
static int8_t xbee_wait_for_ok()
837
{
838
  //delay_ms(1000);
839
  //return WL_SUCCESS;
840
  return xbee_wait_for_string((uint8_t*)"OK", 2);
841
}
842

    
843
/**
844
 * Delay until the specified string is received from
845
 * the XBee.
846
 *
847
 * Only works when not in API mode
848
 *
849
 * @param s the string to receive
850
 * @param len the length of the string
851
 **/
852
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
853
{
854
  uint8_t i=0;  
855
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
856
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
857
    // wait until the response is received (only wait 1 second)
858
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
859
      delay_us(1);
860
    }
861
    // check response
862
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
863
      // bad response
864
      WL_DEBUG_PRINT_P("Bad response when waiting for string ");
865
      WL_DEBUG_PRINT(s);
866
      WL_DEBUG_PRINT_P("\r\n");
867
      return -1;
868
    }
869
    
870
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
871
  }
872
  
873
  WL_DEBUG_PRINT_P("done waiting for string.\r\n");
874

    
875
  return 0;
876
}
877

    
878
/**
879
 * Delay until we receive a command response.
880
 * Then copy the response to S and set the len
881
 *
882
 * Only works when not in API mode
883
 *
884
 * @param s the string to store the response in
885
 * @param len the length of the string
886
 */
887
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
888
  uint8_t i=0;
889
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
890
    // wait until the response is received (only wait 1 second)
891
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
892
      delay_us(1);
893
    }
894
    // check response
895
    if (i >= 1000) {
896
      return -1;
897
    } else {
898
      i=strcspn((char*)xbee_basic_buf,"\r");
899
      if (i<PACKET_BUFFER_SIZE) {
900
        memcpy(s,xbee_basic_buf,i);
901
        len = i;
902
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
903
        return 0;
904
      }
905
      else
906
        return -1;      
907
    }
908
  }
909
  // TODO: do something for API mode
910
  
911
  return 0;
912
}
913

    
914
/**  TODO: since we don't use this, do we need it?
915
 *
916
 * Verifies that the packets checksum is correct.
917
 * (If the checksum is correct, the sum of the bytes
918
 * is 0xFF.)
919
 *
920
 * @param packet the packet received. This includes the first
921
 * three bytes, which are header information from the XBee.
922
 *
923
 * @param len The length of the packet received from the XBee
924
 *
925
 * @return 0 if the checksum is incorrect, nonzero
926
 * otherwise
927
 **/
928
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
929
{
930
  uint8_t sum = 0;
931
  while(--len > 0) {
932
    sum += packet[len];
933
  }
934
  sum += packet[0];
935
  return (sum == 0xFF);
936
}
937

    
938
/**
939
 * Returns the checksum of the given packet.
940
 *
941
 * @param buf the data for the packet to send
942
 * @param len the length of the packet in bytes
943
 *
944
 * @return the checksum of the packet, which will
945
 * become the last byte sent in the packet
946
 **/
947
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
948
{
949
  uint8_t sum = 0;
950
  while(--len > 0) {
951
    sum += buf[len];
952
  }
953
  sum += buf[0];
954
  return 0xFF - sum;
955
}
956

    
957
/**
958
 * Adds buf to the previous checksum total
959
 *
960
 * @param buf a byte buffer to add to the checksum
961
 * @param len the length of the buffer
962
 * @param sum the previous sum
963
 *
964
 * @return error code
965
 **/
966
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
967
  if (buf == NULL || sum == NULL)
968
    return WL_ERROR_ARGUMENT;
969
  while(--len > 0) {
970
    *sum += buf[len];
971
  }
972
  *sum += buf[0];
973
  return WL_SUCCESS;
974
}
975

    
976

    
977
/**
978
 * Sends header information. Header information includes
979
 * XBEE_FRAME_START and the packet length, as two bytes.
980
 *
981
 * @param type the packet type
982
 * @param len the size in bytes of the packet data
983
 *
984
 **/
985
int8_t xbee_send_header(uint16_t len)
986
{  
987
  //packet prefix
988
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
989
    return WL_ERROR_SEND;
990
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
991
    return WL_ERROR_SEND;
992
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
993
    return WL_ERROR_SEND;
994

    
995
  return WL_SUCCESS;
996
}
997

    
998
/**
999
 * Adds header information and checksum to the given
1000
 * packet and sends it. Header information includes
1001
 * XBEE_FRAME_START and the packet length, as two bytes.
1002
 *
1003
 * @param buf the packet data
1004
 * @param len the size in bytes of the packet data
1005
 *
1006
 **/
1007
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
1008
{
1009
  uint8_t checksum = xbee_compute_checksum(buf, len);
1010
  
1011
  //packet prefix
1012
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1013
    return WL_ERROR_SEND;
1014
  if (xbee_putc((uint8_t)(len>>8)) != WL_SUCCESS)
1015
    return WL_ERROR_SEND;
1016
  if (xbee_putc((uint8_t)(len&0xFF)) != WL_SUCCESS)
1017
    return WL_ERROR_SEND;
1018

    
1019
  if (xbee_send(buf, len) != WL_SUCCESS)
1020
    return WL_ERROR_SEND;
1021
  
1022
  if (xbee_putc(checksum) != WL_SUCCESS)
1023
    return WL_ERROR_SEND;
1024
  
1025
  return WL_SUCCESS;
1026
}
1027

    
1028
/**
1029
 * Sends an AT command to read a parameter.
1030
 *
1031
 * @param command the AT command to send. For exmaple,
1032
 * use ID to read the PAN ID and MY to return the XBee ID.
1033
 * See the XBee reference guide for a complete listing.
1034
 **/
1035
int8_t xbee_send_read_at_command(uint8_t* command)
1036
{
1037
  return xbee_send_modify_at_command(command, NULL, 0);
1038
}
1039

    
1040
/**
1041
 * Sends the given AT command.
1042
 *
1043
 * @param command the AT command to send (e.g., MY, ID)
1044
 * @param value the value to pass as a parameter
1045
 * (or NULL if there is no parameter)
1046
 **/
1047
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1048
{
1049
  uint8_t buf[12];
1050

    
1051
  buf[0] = XBEE_FRAME_AT_COMMAND;
1052
  buf[1] = 1;
1053
  buf[2] = command[0];
1054
  buf[3] = command[1];
1055
  if (value != NULL)
1056
  {
1057
    if (len > 8)
1058
    {
1059
      WL_DEBUG_PRINT_P("AT Command too large.\r\n");
1060
      return WL_ERROR_ARGUMENT;
1061
    }
1062
    memcpy(buf+4,value,len);
1063
  }
1064

    
1065
  return xbee_send_frame(buf, 4 + len);
1066
}
1067

    
1068
/**
1069
 * Send the specified packet.
1070
 *
1071
 * @param packet the packet data to send
1072
 * @param len the number of bytes in the packet
1073
 *
1074
 * @param dest the ID of the XBee to send the packet to,
1075
 * or XBEE_BROADCAST to send the message to all robots
1076
 * in the PAN.
1077
 *
1078
 * @param options a combination of the flags
1079
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1080
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1081
 *
1082
 * @param frame the frame number to associate this packet
1083
 * with. This will be used to identify the response when
1084
 * the XBee alerts us as to whether or not our message
1085
 * was received.
1086
 **/
1087
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1088
{
1089
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1090
  uint8_t i = 0;
1091

    
1092
  if (len > 100)
1093
  {
1094
    WL_DEBUG_PRINT_P("Packet is too large.\r\n");
1095
    return WL_ERROR_ARGUMENT;
1096
  }
1097
  
1098
  // calculate checksum
1099
  for(;i<len;i++)
1100
    sum += packet[len];
1101
  sum += frame;
1102
  sum += (dest&0xFF00) >> 8;
1103
  sum += dest&0x00FF;
1104
  sum += options;
1105
  sum = 0xFF - sum;
1106

    
1107
  //packet prefix
1108
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1109
    return WL_ERROR_SEND;
1110
  if (xbee_putc(0x00) != WL_SUCCESS)
1111
    return WL_ERROR_SEND;
1112
  if (xbee_putc(len+5) != WL_SUCCESS)
1113
    return WL_ERROR_SEND;
1114
    
1115
  //send header for TX request
1116
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1117
    return WL_ERROR_SEND;
1118
  if (xbee_putc(frame) != WL_SUCCESS)
1119
    return WL_ERROR_SEND;
1120
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1121
    return WL_ERROR_SEND;
1122
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1123
    return WL_ERROR_SEND;
1124
  if (xbee_putc(options) != WL_SUCCESS)
1125
    return WL_ERROR_SEND;
1126

    
1127
  // send packet
1128
  if (xbee_send(packet, len) != WL_SUCCESS)
1129
    return WL_ERROR_SEND;
1130

    
1131
  // send checksum
1132
  if (xbee_putc(sum) != WL_SUCCESS)
1133
    return WL_ERROR_SEND;
1134

    
1135
  return WL_SUCCESS;
1136
}
1137

    
1138
/**
1139
 * Handles modem status packets.
1140
 *
1141
 * @param status the type of status packet received.
1142
 **/
1143
void xbee_handle_status(uint8_t status)
1144
{
1145
  switch (status)
1146
  {
1147
    case 0:
1148
      WL_DEBUG_PRINT_P("XBee hardware reset.\r\n");
1149
      break;
1150
    case 1:
1151
      WL_DEBUG_PRINT_P("Watchdog timer reset.\r\n");
1152
      break;
1153
    case 2:
1154
      WL_DEBUG_PRINT_P("Associated.\r\n");
1155
      break;
1156
    case 3:
1157
      WL_DEBUG_PRINT_P("Disassociated.\r\n");
1158
      break;
1159
    case 4:
1160
      WL_DEBUG_PRINT_P("Synchronization lost.\r\n");
1161
      break;
1162
    case 5:
1163
      WL_DEBUG_PRINT_P("Coordinator realignment.\r\n");
1164
      break;
1165
    case 6:
1166
      WL_DEBUG_PRINT_P("Coordinator started.\r\n");
1167
      break;
1168
  }
1169
}
1170

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

    
1233
  return WL_SUCCESS;
1234
}
1235

    
1236
/**
1237
 * Sets the personal area network id.
1238
 *
1239
 * @param id the new personal area network (PAN) id
1240
 **/
1241
int8_t xbee_set_pan(uint16_t id)
1242
{
1243
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1244
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1245
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1246
  
1247
  int16_t i=(id&0xFF)|(id>>8);
1248
  // change status to command wait
1249
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1250
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&i),2); // send command to set the channel
1251
  // wait for up to 30 ms
1252
  i=0;
1253
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1254
    delay_us(1); // wait 3us
1255
  }
1256
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1257
    i = WL_SUCCESS;
1258
  else
1259
    i = WL_ERROR_XBEE_COMMAND; // set error code
1260
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1261
  return (int8_t)i; // return
1262
}
1263

    
1264
/**
1265
 * Get the PAN ID for the XBee.
1266
 *
1267
 * @return the personal area network id, or
1268
 * XBEE_PAN_DEFAULT if it has not yet been set.
1269
 **/
1270
uint16_t xbee_get_pan()
1271
{
1272
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1273
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1274
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1275
  
1276
  uint16_t i=0;
1277
  // change status to command wait
1278
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1279
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1280
  // wait for up to 30 ms
1281
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1282
    delay_us(1); // wait 3us
1283
  }
1284
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1285
    i = (xbee_command[2]<<8)|xbee_command[3]; // do ntoh16 coversion
1286
  else
1287
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1288
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1289
  return i; // return
1290
}
1291

    
1292
/**
1293
 * Set the channel the XBee is using.
1294
 *
1295
 * @param channel the channel the XBee will not use,
1296
 * between 0x0B and 0x1A
1297
 *
1298
 * @see xbee_get_channel
1299
 **/
1300
int8_t xbee_set_channel(uint8_t channel)
1301
{
1302
  if (channel < 0x0B || channel > 0x1A)
1303
  {
1304
    WL_DEBUG_PRINT_P("Channel out of range.\r\n");
1305
    return WL_ERROR_ARGUMENT;
1306
  }
1307

    
1308
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1309
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1310
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1311
  
1312
  int16_t i=0;
1313
  // change status to command wait
1314
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1315
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1316
  // wait for up to 30 ms
1317
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1318
    delay_us(1); // wait 3us
1319
  }
1320
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1321
    i = WL_SUCCESS;
1322
  else
1323
    i = WL_ERROR_XBEE_COMMAND; // set error code
1324
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1325
  return (int8_t)i; // return
1326
}
1327

    
1328
/**
1329
 * Returns the channel which the XBee is currently using.
1330
 *
1331
 * @return the channel the XBee is using
1332
 *
1333
 * @see xbee_set_channel
1334
 **/
1335
int8_t xbee_get_channel(void)
1336
{
1337
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1338
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1339
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1340
  
1341
  int16_t i=0;
1342
  // change status to command wait
1343
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1344
  xbee_send_read_at_command((uint8_t*)"CH"); // send command to get the channel
1345
  // wait for up to 30 ms
1346
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1347
    delay_us(1); // wait 3us
1348
  }
1349
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1350
    i = (int8_t)xbee_command[2]; // get channel
1351
  else
1352
    i = WL_ERROR_XBEE_COMMAND; // set error code
1353
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1354
  return i; // return
1355
}
1356

    
1357
/**
1358
 * Get the 16-bit address of the XBee.
1359
 * This is used to specify who to send messages to
1360
 * and who messages are from.
1361
 *
1362
 * @return the 16-bit address of the XBee.
1363
 **/
1364
uint16_t xbee_get_address(void)
1365
{
1366
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1367
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1368
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1369
  
1370
  uint16_t i=0;
1371
  // change status to command wait 
1372
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1373
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1374
  // wait for up to 30 ms
1375
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1376
    delay_us(1); // wait 3us
1377
  }
1378
  
1379
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
1380
    i = (xbee_command[2]<<8)|xbee_command[3]; // do ntoh16 coversion
1381
  } else
1382
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1383
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1384
  WL_DEBUG_PRINT_P("get MY address\r\n");
1385
  return i; // return
1386
}
1387

    
1388
/**@} **/ // end xbee group
1389