Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (38.7 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
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 = 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
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 = 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
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[8];
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 message[100];
128

    
129

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

    
133
/*Function Implementations*/
134

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

    
394

    
395
/* adds a byte to the basic buffer */
396
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
397
  if (*ptr == basic_buf_first) {
398
    // buffer full
399
    WL_DEBUG_PRINT("basic buffer full\r\n");
400
    return -1;
401
  }
402
  xbee_basic_buf[(*ptr)++] = byte;
403
  if (*ptr == PACKET_BUFFER_SIZE)
404
    *ptr = 0;
405
  return 0;
406
}
407
/* gets a byte from the basic buffer */
408
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
409
  uint8_t byte = xbee_basic_buf[(*ptr)++];
410
  if (*ptr == PACKET_BUFFER_SIZE)
411
    *ptr = 0;
412
  return byte;
413
}
414
/* adds a byte to the other buffer */
415
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
416
  if (*ptr == other_buf_first) {
417
    // buffer full
418
    WL_DEBUG_PRINT("other buffer full\r\n");
419
    return -1;
420
  }
421
  xbee_other_buf[(*ptr)++] = byte;
422
  if (*ptr == PACKET_BUFFER_SIZE)
423
    *ptr = 0;
424
  return 0;
425
}
426

    
427
/**
428
 * Checks if packet is a duplicate
429
 **/
430
int8_t check_last_receive(uint16_t source,uint8_t framenum) {
431
  uint8_t i=0;
432
  for(;i<NUM_LAST_PACKETS;i++) {
433
    if (lastPacket[i].source == source && lastPacket[i].framenum == framenum)
434
      return -1; // duplicate packet, so return error
435
  }
436
  // save packet source and framenum
437
  i=getStatus(LAST_PACKET_MASK);
438
  lastPacket[i].source = source;
439
  lastPacket[i].framenum = framenum;
440
  if (++i>=NUM_LAST_PACKETS)
441
    i = 0;
442
  setStatus(LAST_PACKET_MASK,i);
443
  return WL_SUCCESS;
444
}
445

    
446
/** status functions **/
447
inline uint8_t getStatus(uint8_t mask) { return xbee_status&mask; }
448
void setStatus(uint8_t mask,uint8_t value) { xbee_status = ((xbee_status&(~mask))|value); }
449

    
450

    
451
// test interrupt
452
/*ISR(USART1_RX_vect) {
453
  WL_DEBUG_PRINT("in interrupt|");
454
  char c = UDR1;
455
  WL_DEBUG_PRINT_HEX(c);
456
  WL_DEBUG_PRINT("|in interrupt");
457
}*/
458

    
459

    
460

    
461
/**
462
 * Initializes the XBee library so that other functions may be used.
463
 **/
464
int8_t xbee_init()
465
{
466
  WL_DEBUG_PRINT("in xbee_init\r\n");
467
  
468
  if(getStatus(XBEE_NOT_INITD) != XBEE_NOT_INITD) {
469
    return WL_ERROR_INIT_ALREADY_INITD;
470
  }
471
  
472
  // set status
473
  setStatus(XBEE_NOT_INITD,XBEE_COMMAND_NONE);
474
  
475
  // clear last packet buffer
476
  for(int i=0;i<NUM_LAST_PACKETS;i++)
477
    lastPacket[i].source = lastPacket[i].framenum = 0;
478
  
479
  // Set startup baud rate of 9600
480
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
481
  // Enable receiver and transmitter and the receiving interrupt
482
#ifdef FIREFLY
483
  UBRR0H = 0x00;
484
  UBRR0L = 103;
485
  UCSR0A |= (1<<U2X0);
486
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
487
  UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE); 
488
#else
489
  // Bayboard or robot  
490
  UBRR1H = 0x00; // baud rate
491
  UBRR1L = 103;  // baud rate
492
  UCSR1A |= (1<<U2X1); // double transmit speed 
493
  //Enable receiver and transmitter on USART1
494
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
495
        
496
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
497
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
498
  
499
  UCSR1B |= (1<<RXCIE1);  // enable receive, transmit (1<<RXCIE)
500
#endif
501
  sei();
502
 
503
  // enter command mode
504
  WL_DEBUG_PRINT("entering command mode\r\n");
505
  xbee_send_string((uint8_t*)"+++");
506
  xbee_wait_for_ok();
507
  WL_DEBUG_PRINT("entered command mode\r\n");
508

    
509
  
510
  // set baud on xbee
511
#if (XBEE_BAUD == 115200)
512
  xbee_send_string((uint8_t*)"ATBD7\r");
513
#elif (XBEE_BAUD == 57600)
514
  xbee_send_string((uint8_t*)"ATBD6\r");
515
#elif (XBEE_BAUD == 38400)
516
  xbee_send_string((uint8_t*)"ATBD5\r");
517
#elif (XBEE_BAUD == 19200)
518
  xbee_send_string((uint8_t*)"ATBD4\r");
519
#elif (XBEE_BAUD == 9600)
520
  // already at this baud rate
521
  xbee_send_string("ATBD3\r\n");
522
#else
523
  WL_DEBUG_PRINT("undefined baud rate\r\n");
524
  return WL_ERROR_BAUD;
525
#endif  
526
  // exit command mode
527
  xbee_wait_for_ok();
528
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
529
  xbee_send_string((uint8_t*)"ATCN\r");
530
  xbee_wait_for_ok();
531
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
532
  
533
  // set UART baud
534
#ifdef FIREFLY
535
#if (XBEE_BAUD == 115200)
536
  UBRR0H = 0x00;
537
  UBRR0L = 8;
538
#elif (XBEE_BAUD == 57600)
539
  UBRR0H = 0x00;
540
  UBRR0L = 16;
541
#elif (XBEE_BAUD == 38400)
542
  UBRR0H = 0x00;
543
  UBRR0L = 25;
544
#elif (XBEE_BAUD == 19200)
545
  UBRR0H = 0x00;
546
  UBRR0L = 51;
547
#elif (XBEE_BAUD == 9600)
548
  /* this is the default baud rate, so do nothing
549
  UBRR0H = 0x00;
550
  UBRR0L = 103;*/
551
#else
552
  WL_DEBUG_PRINT("undefined baud rate\r\n");
553
  return WL_ERROR_BUAD;
554
#endif
555
#else // Bayboard or robot
556
#if (XBEE_BAUD == 115200)
557
  UBRR1H = 0x00;
558
  UBRR1L = 8;
559
#elif (XBEE_BAUD == 57600)
560
  UBRR1H = 0x00;
561
  UBRR1L = 16;
562
#elif (XBEE_BAUD == 38400)
563
  UBRR1H = 0x00;
564
  UBRR1L = 25;
565
#elif (XBEE_BAUD == 19200)
566
  UBRR1H = 0x00;
567
  UBRR1L = 51;
568
#elif (XBEE_BAUD == 9600)
569
  /* this is the default baud rate, so do nothing
570
  UBRR1H = 0x00;
571
  UBRR1L = 103;*/
572
#else
573
  WL_DEBUG_PRINT("undefined baud rate\r\n");
574
  return WL_ERROR_BUAD;
575
#endif
576
#endif
577
  // wait half second for the baud change to stabalize
578
  delay_ms(500);
579

    
580
  // enter command mode
581
  WL_DEBUG_PRINT("entering command mode 2\r\n");
582
  xbee_send_string((uint8_t*)"+++");
583
  xbee_wait_for_ok();
584
  WL_DEBUG_PRINT("entered command mode 2\r\n");
585
  
586
  if (xbee_enter_api_mode() != 0) {
587
    WL_DEBUG_PRINT("can't enter api mode\r\n");
588
    return -1;
589
  }
590
  /*xbee_send_string((uint8_t*)"ATAP 1\r");
591
  xbee_wait_for_ok();*/
592
  
593
  /*WL_DEBUG_PRINT("Entered api mode.\r\n");
594

595
  if (xbee_exit_command_mode() != 0) {
596
    WL_DEBUG_PRINT("can't exit command mode\r\n");
597
    return -1;
598
  }
599
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
600
  
601
  WL_DEBUG_PRINT("Left command mode.\r\n");
602
  
603
  WL_DEBUG_PRINT("before status=");
604
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
605
  WL_DEBUG_PRINT("\r\n");
606
  
607
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status to API_ON (API mode 1)*/
608
  
609
#ifdef WL_DEBUG
610
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
611
    WL_DEBUG_PRINT("|API OFF|");
612
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
613
    WL_DEBUG_PRINT("|API ON|");
614
  } else {
615
    WL_DEBUG_PRINT("|API ERROR|");
616
  }
617
#endif
618
  
619
  
620
  // TODO: we should set the MY address to the robot address from eeprom  
621
  uint16_t i=0;
622
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);  
623
  uint8_t newmy = 4;
624
  if (xbee_send_modify_at_command((uint8_t*)"MY",&newmy,1) != WL_SUCCESS) {
625
    WL_DEBUG_PRINT("setting MY address failed\r\n");
626
  }
627
  // wait for up to 30 ms
628
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
629
    delay_us(1); // wait 3us
630
  }  
631
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
632
    WL_DEBUG_PRINT("setting MY address successful\r\n");
633
  } else
634
    WL_DEBUG_PRINT("setting MY address failed\r\n");
635
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
636
  
637
  
638
  uint16_t address = xbee_get_address();
639
  if (address == WL_ERROR_XBEE_COMMAND_16BIT) {
640
    WL_DEBUG_PRINT("getting MY address failed\r\n");
641
  }
642
  WL_DEBUG_PRINT("MY address:");
643
  WL_DEBUG_PRINT_HEX((uint8_t)(address>>8));
644
  WL_DEBUG_PRINT_HEX((uint8_t)(address&0xFF));
645
  WL_DEBUG_PRINT("\r\n");
646
  
647
  return WL_SUCCESS;
648
}
649

    
650
/**
651
 * Call when finished using the XBee library.
652
 **/
653
int8_t xbee_terminate()
654
{
655
  int ret=xbee_exit_api_mode();
656
  if (ret != WL_SUCCESS) {
657
    WL_DEBUG_PRINT("xbee termination failed\r\n");
658
    WL_DEBUG_PRINT_INT(ret);
659
    WL_DEBUG_PRINT("|\r\n");
660
    return WL_ERROR_TERMINATION_FAILED;
661
  }
662
  setStatus(XBEE_NOT_INITD,XBEE_NOT_INITD); // clean initd status
663
  return WL_SUCCESS;
664
}
665

    
666
/**
667
 * Sends a character to the XBee.
668
 *
669
 * @param c the byte to send
670
 * @return 0 for success, nonzero for failure
671
 **/
672
int8_t xbee_putc(uint8_t c) {
673

    
674
  // Wait until buffer is clear for sending
675
  // Then load buffer with your character
676
  
677
  /*WL_DEBUG_PRINT("xbee_putc:");
678
  WL_DEBUG_PRINT_HEX(c);
679
  WL_DEBUG_PRINT("|\r\n");*/
680
  
681
#ifdef FIREFLY
682
  loop_until_bit_is_set(UCSR0A, UDRE0);  
683
  UDR0 = c;
684
#else
685
  loop_until_bit_is_set(UCSR1A, UDRE1);
686
  UDR1 = c;
687
#endif
688
  
689
  return WL_SUCCESS;
690
}
691

    
692
/**
693
 * Returns the first byte in the buffer received from xbee.
694
 * This function blocks execution until a character has been
695
 * received. xbee_init must be called before this function
696
 * may be used.
697
 * 
698
 * @return the first character in the xbee buffer, -1 on error
699
 * 
700
 * @see xbee_init, xbee_getc_nb
701
 **/
702
int16_t xbee_getc(void) {
703
    
704
  // Wait for the receive buffer to be filled
705
  // Then read the receive buffer
706
#ifdef FIREFLY
707
  loop_until_bit_is_set(UCSR0A, RXC0);  
708
  return UDR0;
709
#else
710
  loop_until_bit_is_set(UCSR1A, RXC1);
711
  return UDR1;
712
#endif
713
}
714

    
715
/**
716
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
717
 * it is returned, otherwise -1 is returned immediately. xbee_init
718
 * must be called before this function can be used.
719
 *
720
 * @param c The received byte. This will be set if a byte has been received.
721
 * 
722
 * @return -1 If no byte is available, 0 otherwise, positive for error
723
 *
724
 * @see xbee_getc
725
 **/
726
int8_t xbee_getc_nb(uint8_t *c) {
727

    
728
  // check if the receive buffer is filled
729
#ifdef FIREFLY
730
  if (UCSR0A & (1<<RXC0)) {
731
    (*c) = UDR0;
732
#else
733
  if (UCSR1A & (1<<RXC1)) {
734
    (*c) = UDR1;
735
#endif
736
    return WL_SUCCESS;
737
  }
738
  return -1; // Return empty
739
}
740

    
741
/**
742
 * Send a buffer buf of size bytes to the XBee.
743
 *
744
 * @param buf the buffer of data to send
745
 * @param size the number of bytes to send
746
 **/
747
int8_t xbee_send(uint8_t* buf, uint16_t size)
748
{
749
  uint16_t i=0; // check if we need this variable
750
  while(i<size) {
751
    if (xbee_putc(buf[i++]) != WL_SUCCESS)
752
      return WL_ERROR_SEND;
753
  }
754

    
755
  return WL_SUCCESS;
756
}
757

    
758
/**
759
 * Sends a string to the XBee.
760
 *
761
 * @param c the string to send to the XBEE
762
 **/
763
static int8_t xbee_send_string(uint8_t* c)
764
{
765
  return xbee_send(c, strlen((char*)c));
766
}
767

    
768

    
769
/**
770
 * Enter into command mode.
771
 **/
772
static int8_t xbee_enter_command_mode(void)
773
{
774
  if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
775
    return WL_ERROR_XBEE_COMMAND;
776
  }
777
  WL_DEBUG_PRINT("sent command +++|");
778

    
779
  if (xbee_wait_for_ok() != WL_SUCCESS) {
780
    return WL_ERROR_XBEE_COMMAND;
781
  }
782
  WL_DEBUG_PRINT("got OK\r\n");
783
  
784
  return WL_SUCCESS;
785
}
786

    
787
/**
788
 * Exit from command mode.
789
 **/
790
static int8_t xbee_exit_command_mode()
791
{
792
  if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
793
    return WL_ERROR_SEND;
794
  }
795
  if (xbee_wait_for_ok() != WL_SUCCESS) {
796
    WL_DEBUG_PRINT("failed to exit command mode\r\n");
797
    return WL_ERROR_SEND;
798
  }
799

    
800
  return WL_SUCCESS;
801
}
802

    
803
/**
804
 * Enter API mode.
805
 **/
806
static int8_t xbee_enter_api_mode(void) {
807
  if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
808
    return WL_ERROR_SEND;
809
  }
810
  if (xbee_wait_for_ok() != WL_SUCCESS) {
811
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
812
    return WL_ERROR_SEND;
813
  }
814
  if (xbee_exit_command_mode() != WL_SUCCESS) {
815
    WL_DEBUG_PRINT("failed to enter API mode\r\n");
816
    return WL_ERROR_SEND;
817
  }    
818
  WL_DEBUG_PRINT("got OK after entering API mode\r\n");
819
  
820
  setStatus(XBEE_API_MASK,XBEE_API_ON); // set status
821
  
822
  return WL_SUCCESS;
823
}
824

    
825
/**
826
 * Enter API mode 2.
827
 **/
828
static int8_t xbee_enter_api_mode2(void) {
829
  if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
830
    return WL_ERROR_SEND;
831
  }
832
  if (xbee_wait_for_ok() != WL_SUCCESS) {
833
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
834
    return WL_ERROR_SEND;
835
  }
836
  if (xbee_exit_command_mode() != WL_SUCCESS) {
837
    WL_DEBUG_PRINT("failed to enter API mode2\r\n");
838
    return WL_ERROR_SEND;
839
  }    
840
  WL_DEBUG_PRINT("got OK after entering API mode2\r\n");
841
  
842
  setStatus(XBEE_API_MASK,XBEE_API_ESCAPE); // set status
843
  
844
  return WL_SUCCESS;
845
}
846

    
847
/**
848
 * Exit API mode.
849
 **/
850
static int8_t xbee_exit_api_mode()
851
{
852
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
853
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
854
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
855
  WL_DEBUG_PRINT("now exiting API mode\r\n");
856
  
857
  int16_t i=0;
858
  // change status to command wait
859
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
860
  if (xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)(&i),1) != WL_SUCCESS) { // send command
861
    WL_DEBUG_PRINT("error sending AP 0 command\r\n");
862
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
863
    return WL_ERROR_XBEE_COMMAND;
864
  }
865
  // wait for up to 30 ms
866
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
867
    delay_us(1); // wait 3us
868
  }
869
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
870
    WL_DEBUG_PRINT("done exiting API mode\r\n");
871
    i = WL_SUCCESS;
872
  } else {
873
    WL_DEBUG_PRINT("failed to exit API mode\r\n");
874
    i = WL_ERROR_XBEE_COMMAND; // set error code
875
  }
876
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
877
  setStatus(XBEE_API_MASK,XBEE_API_OFF);
878
  
879
  return (int8_t)i; // return
880
}
881

    
882
/**
883
 * Wait until the string "OK\r" is received from the XBee.
884
 **/
885
static int8_t xbee_wait_for_ok()
886
{
887
  //delay_ms(1000);
888
  //return WL_SUCCESS;
889
  return xbee_wait_for_string((uint8_t*)"OK", 2);
890
}
891

    
892
/**
893
 * Delay until the specified string is received from
894
 * the XBee.
895
 *
896
 * Only works when not in API mode
897
 *
898
 * @param s the string to receive
899
 * @param len the length of the string
900
 **/
901
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
902
{
903
  uint8_t i=0;  
904
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT); // set status flag
905
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
906
    // wait until the response is received (only wait 1 second)
907
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
908
      delay_us(1);
909
    }
910
    // check response
911
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
912
      // bad response
913
      WL_DEBUG_PRINT("Bad response when waiting for string ");
914
      WL_DEBUG_PRINT(s);
915
      WL_DEBUG_PRINT("\r\n");
916
      return -1;
917
    }
918
    
919
    setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear status
920
  }
921
  
922
  WL_DEBUG_PRINT("done waiting for string.\r\n");
923

    
924
  return 0;
925
}
926

    
927
/**
928
 * Delay until we receive a command response.
929
 * Then copy the response to S and set the len
930
 *
931
 * Only works when not in API mode
932
 *
933
 * @param s the string to store the response in
934
 * @param len the length of the string
935
 */
936
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
937
  uint8_t i=0;
938
  if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
939
    // wait until the response is received (only wait 1 second)
940
    while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
941
      delay_us(1);
942
    }
943
    // check response
944
    if (i >= 1000) {
945
      return -1;
946
    } else {
947
      i=strcspn((char*)xbee_basic_buf,"\r");
948
      if (i<PACKET_BUFFER_SIZE) {
949
        memcpy(s,xbee_basic_buf,i);
950
        len = i;
951
        setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // clear response
952
        return 0;
953
      }
954
      else
955
        return -1;      
956
    }
957
  }
958
  // TODO: do something for API mode
959
  
960
  return 0;
961
}
962

    
963
/**  TODO: since we don't use this, do we need it?
964
 *
965
 * Verifies that the packets checksum is correct.
966
 * (If the checksum is correct, the sum of the bytes
967
 * is 0xFF.)
968
 *
969
 * @param packet the packet received. This includes the first
970
 * three bytes, which are header information from the XBee.
971
 *
972
 * @param len The length of the packet received from the XBee
973
 *
974
 * @return 0 if the checksum is incorrect, nonzero
975
 * otherwise
976
 **/
977
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
978
{
979
  uint8_t sum = 0;
980
  while(--len > 0) {
981
    sum += packet[len];
982
  }
983
  sum += packet[0];
984
  return (sum == 0xFF);
985
}
986

    
987
/**
988
 * Returns the checksum of the given packet.
989
 *
990
 * @param buf the data for the packet to send
991
 * @param len the length of the packet in bytes
992
 *
993
 * @return the checksum of the packet, which will
994
 * become the last byte sent in the packet
995
 **/
996
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
997
{
998
  uint8_t sum = 0;
999
  while(--len > 0) {
1000
    sum += buf[len];
1001
  }
1002
  sum += buf[0];
1003
  return 0xFF - sum;
1004
}
1005

    
1006
/**
1007
 * Adds buf to the previous checksum total
1008
 *
1009
 * @param buf a byte buffer to add to the checksum
1010
 * @param len the length of the buffer
1011
 * @param sum the previous sum
1012
 *
1013
 * @return error code
1014
 **/
1015
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
1016
  if (buf == NULL || sum == NULL)
1017
    return WL_ERROR_ARGUMENT;
1018
  while(--len > 0) {
1019
    *sum += buf[len];
1020
  }
1021
  *sum += buf[0];
1022
  return WL_SUCCESS;
1023
}
1024

    
1025

    
1026
/**
1027
 * Sends header information. Header information includes
1028
 * XBEE_FRAME_START and the packet length, as two bytes.
1029
 *
1030
 * @param type the packet type
1031
 * @param len the size in bytes of the packet data
1032
 *
1033
 **/
1034
int8_t xbee_send_header(uint8_t type, uint16_t len)
1035
{  
1036
  //packet prefix
1037
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1038
    return WL_ERROR_SEND;
1039
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
1040
    return WL_ERROR_SEND;
1041
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
1042
    return WL_ERROR_SEND;
1043

    
1044
  return WL_SUCCESS;
1045
}
1046

    
1047
/**
1048
 * Adds header information and checksum to the given
1049
 * packet and sends it. Header information includes
1050
 * XBEE_FRAME_START and the packet length, as two bytes.
1051
 *
1052
 * @param buf the packet data
1053
 * @param len the size in bytes of the packet data
1054
 *
1055
 **/
1056
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
1057
{
1058
  uint8_t checksum = xbee_compute_checksum(buf, len);
1059
  
1060
  //packet prefix
1061
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1062
    return WL_ERROR_SEND;
1063
  if (xbee_putc((uint8_t)(len>>8)) != WL_SUCCESS)
1064
    return WL_ERROR_SEND;
1065
  if (xbee_putc((uint8_t)(len&0xFF)) != WL_SUCCESS)
1066
    return WL_ERROR_SEND;
1067

    
1068
  if (xbee_send(buf, len) != WL_SUCCESS)
1069
    return WL_ERROR_SEND;
1070
  
1071
  if (xbee_putc(checksum) != WL_SUCCESS)
1072
    return WL_ERROR_SEND;
1073
  
1074
  return WL_SUCCESS;
1075
}
1076

    
1077
/**
1078
 * Sends an AT command to read a parameter.
1079
 *
1080
 * @param command the AT command to send. For exmaple,
1081
 * use ID to read the PAN ID and MY to return the XBee ID.
1082
 * See the XBee reference guide for a complete listing.
1083
 **/
1084
int8_t xbee_send_read_at_command(uint8_t* command)
1085
{
1086
  return xbee_send_modify_at_command(command, NULL, 0);
1087
}
1088

    
1089
/**
1090
 * Sends the given AT command.
1091
 *
1092
 * @param command the AT command to send (e.g., MY, ID)
1093
 * @param value the value to pass as a parameter
1094
 * (or NULL if there is no parameter)
1095
 **/
1096
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
1097
{
1098
  uint8_t buf[12];
1099

    
1100
  buf[0] = XBEE_FRAME_AT_COMMAND;
1101
  buf[1] = 1;
1102
  buf[2] = command[0];
1103
  buf[3] = command[1];
1104
  if (value != NULL)
1105
  {
1106
    if (len > 8)
1107
    {
1108
      WL_DEBUG_PRINT("AT Command too large.\r\n");
1109
      return WL_ERROR_ARGUMENT;
1110
    }
1111
    memcpy(buf+4,value,len);
1112
  }
1113

    
1114
  return xbee_send_frame(buf, 4 + len);
1115
}
1116

    
1117
/**
1118
 * Send the specified packet.
1119
 *
1120
 * @param packet the packet data to send
1121
 * @param len the number of bytes in the packet
1122
 *
1123
 * @param dest the ID of the XBee to send the packet to,
1124
 * or XBEE_BROADCAST to send the message to all robots
1125
 * in the PAN.
1126
 *
1127
 * @param options a combination of the flags
1128
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
1129
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
1130
 *
1131
 * @param frame the frame number to associate this packet
1132
 * with. This will be used to identify the response when
1133
 * the XBee alerts us as to whether or not our message
1134
 * was received.
1135
 **/
1136
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
1137
{
1138
  uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
1139
  uint8_t i = 0;
1140

    
1141
  if (len > 100)
1142
  {
1143
    WL_DEBUG_PRINT("Packet is too large.\r\n");
1144
    return WL_ERROR_ARGUMENT;
1145
  }
1146
  
1147
  // calculate checksum
1148
  for(;i<len;i++)
1149
    sum += packet[len];
1150
  sum += frame;
1151
  sum += (dest&0xFF00) >> 8;
1152
  sum += dest&0x00FF;
1153
  sum += options;
1154
  sum = 0xFF - sum;
1155

    
1156
  //packet prefix
1157
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
1158
    return WL_ERROR_SEND;
1159
  if (xbee_putc(0x00) != WL_SUCCESS)
1160
    return WL_ERROR_SEND;
1161
  if (xbee_putc(len+5) != WL_SUCCESS)
1162
    return WL_ERROR_SEND;
1163
    
1164
  //send header for TX request
1165
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
1166
    return WL_ERROR_SEND;
1167
  if (xbee_putc(frame) != WL_SUCCESS)
1168
    return WL_ERROR_SEND;
1169
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
1170
    return WL_ERROR_SEND;
1171
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
1172
    return WL_ERROR_SEND;
1173
  if (xbee_putc(options) != WL_SUCCESS)
1174
    return WL_ERROR_SEND;
1175

    
1176
  // send packet
1177
  if (xbee_send(packet, len) != WL_SUCCESS)
1178
    return WL_ERROR_SEND;
1179

    
1180
  // send checksum
1181
  if (xbee_putc(sum) != WL_SUCCESS)
1182
    return WL_ERROR_SEND;
1183

    
1184
  return WL_SUCCESS;
1185
}
1186

    
1187
/**
1188
 * Handles modem status packets.
1189
 *
1190
 * @param status the type of status packet received.
1191
 **/
1192
void xbee_handle_status(uint8_t status)
1193
{
1194
  switch (status)
1195
  {
1196
    case 0:
1197
      WL_DEBUG_PRINT("XBee hardware reset.\r\n");
1198
      break;
1199
    case 1:
1200
      WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
1201
      break;
1202
    case 2:
1203
      WL_DEBUG_PRINT("Associated.\r\n");
1204
      break;
1205
    case 3:
1206
      WL_DEBUG_PRINT("Disassociated.\r\n");
1207
      break;
1208
    case 4:
1209
      WL_DEBUG_PRINT("Synchronization lost.\r\n");
1210
      break;
1211
    case 5:
1212
      WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1213
      break;
1214
    case 6:
1215
      WL_DEBUG_PRINT("Coordinator started.\r\n");
1216
      break;
1217
  }
1218
}
1219

    
1220
/**
1221
 * Handles AT command response packets.
1222
 * @param command the two character AT command, e.g. MY or ID
1223
 * @param result 0 for success, 1 for an error
1224
 * @param len the length in bytes of extra
1225
 **/
1226
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t status, uint8_t len)
1227
{
1228
  WL_DEBUG_PRINT("HANDLE AT COMMAND\r\n");
1229
  if (status != 0)
1230
  {
1231
    WL_DEBUG_PRINT("Error with AT");
1232
    WL_DEBUG_PRINT(command);
1233
    WL_DEBUG_PRINT(" packet. Result = ");
1234
    switch(status) {
1235
    case 1:
1236
      WL_DEBUG_PRINT("ERROR\r\n");
1237
      break;
1238
    case 2:
1239
      WL_DEBUG_PRINT("Invalid Command\r\n");
1240
      break;
1241
    case 3:
1242
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
1243
      break;
1244
    }
1245
    return WL_SUCCESS;
1246
  }
1247
  WL_DEBUG_PRINT("AT");
1248
  WL_DEBUG_PRINT_CHAR((uint8_t)(command>>8));
1249
  WL_DEBUG_PRINT_CHAR((uint8_t)(command));
1250
  WL_DEBUG_PRINT(" command is being handled\r\n");
1251
  
1252
  // TODO: program more command responses here (ND, etc)
1253
  switch(command) {
1254
  case ('I'<<8)+'D': // PAN
1255
  case ('C'<<8)+'H': // channel
1256
  case ('M'<<8)+'Y': // address
1257
  case ('A'<<8)+'P': // api mode
1258
    // copy command to handler
1259
    xbee_command[0] = (command&0xFF00)>>8;
1260
    xbee_command[1] = command&0x00FF;
1261
    uint8_t ptr = basic_buf_last;
1262
    for(command=2;command<len+2;command++) {
1263
      xbee_command[command] = xbee_basic_buf_get(&ptr);
1264
      if (xbee_command[command] == '\r')
1265
        break; // done with command
1266
      WL_DEBUG_PRINT_HEX(xbee_command[command]);
1267
    }
1268
    xbee_command[command] = '\0';
1269
    WL_DEBUG_PRINT("len=");
1270
    WL_DEBUG_PRINT_INT(len);
1271
    WL_DEBUG_PRINT("ID,CH,or MY command result:");
1272
    WL_DEBUG_PRINT(xbee_command);
1273
    WL_DEBUG_PRINT("\r\n");
1274
    break;
1275
  default:
1276
    WL_DEBUG_PRINT("unknown AT command");
1277
  }
1278
  
1279
  // signal handler that command response is done
1280
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_RESPONSE);
1281

    
1282
  return WL_SUCCESS;
1283
}
1284

    
1285
/**
1286
 * Sets the personal area network id.
1287
 *
1288
 * @param id the new personal area network (PAN) id
1289
 **/
1290
int8_t xbee_set_pan_id(uint16_t id)
1291
{
1292
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1293
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1294
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1295
  
1296
  int16_t i=0;
1297
  // change status to command wait
1298
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1299
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1300
  // wait for up to 30 ms
1301
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1302
    delay_us(1); // wait 3us
1303
  }
1304
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1305
    i = WL_SUCCESS;
1306
  else
1307
    i = WL_ERROR_XBEE_COMMAND; // set error code
1308
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1309
  return (int8_t)i; // return
1310
}
1311

    
1312
/**
1313
 * Get the PAN ID for the XBee.
1314
 *
1315
 * @return the personal area network id, or
1316
 * XBEE_PAN_DEFAULT if it has not yet been set.
1317
 **/
1318
uint16_t xbee_get_pan_id()
1319
{
1320
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1321
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1322
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1323
  
1324
  uint16_t i=0;
1325
  // change status to command wait
1326
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1327
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1328
  // wait for up to 30 ms
1329
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1330
    delay_us(1); // wait 3us
1331
  }
1332
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1333
    i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN
1334
  else
1335
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1336
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1337
  return i; // return
1338
}
1339

    
1340
/**
1341
 * Set the channel the XBee is using.
1342
 *
1343
 * @param channel the channel the XBee will not use,
1344
 * between 0x0B and 0x1A
1345
 *
1346
 * @see xbee_get_channel
1347
 **/
1348
int8_t xbee_set_channel(uint8_t channel)
1349
{
1350
  if (channel < 0x0B || channel > 0x1A)
1351
  {
1352
    WL_DEBUG_PRINT("Channel out of range.\r\n");
1353
    return -1;
1354
  }
1355

    
1356
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1357
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1358
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1359
  
1360
  int16_t i=0;
1361
  // change status to command wait
1362
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1363
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1364
  // wait for up to 30 ms
1365
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1366
    delay_us(1); // wait 3us
1367
  }
1368
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1369
    i = WL_SUCCESS;
1370
  else
1371
    i = WL_ERROR_XBEE_COMMAND; // set error code
1372
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1373
  return (int8_t)i; // return
1374
}
1375

    
1376
/**
1377
 * Returns the channel which the XBee is currently using.
1378
 *
1379
 * @return the channel the XBee is using
1380
 *
1381
 * @see xbee_set_channel
1382
 **/
1383
int8_t xbee_get_channel(void)
1384
{
1385
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1386
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1387
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1388
  
1389
  int16_t i=0;
1390
  // change status to command wait
1391
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);
1392
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the channel
1393
  // wait for up to 30 ms
1394
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1395
    delay_us(1); // wait 3us
1396
  }
1397
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1398
    i = xbee_command[2]; // get channel
1399
  else
1400
    i = WL_ERROR_XBEE_COMMAND; // set error code
1401
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1402
  return i; // return
1403
}
1404

    
1405
/**
1406
 * Get the 16-bit address of the XBee.
1407
 * This is used to specify who to send messages to
1408
 * and who messages are from.
1409
 *
1410
 * @return the 16-bit address of the XBee.
1411
 **/
1412
uint16_t xbee_get_address(void)
1413
{
1414
  if (getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_WAIT
1415
    || getStatus(XBEE_COMMAND_MASK) == XBEE_COMMAND_RESPONSE)
1416
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1417
  
1418
  uint16_t i=0;
1419
  // change status to command wait  
1420
  /*WL_DEBUG_PRINT("\r\nbefore status=");
1421
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
1422
  WL_DEBUG_PRINT("\r\n");*/
1423
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_WAIT);  
1424
  /*if (getStatus(XBEE_API_MASK) == XBEE_API_OFF) {
1425
    WL_DEBUG_PRINT("|API OFF|");
1426
  } else if (getStatus(XBEE_API_MASK) == XBEE_API_ON) {
1427
    WL_DEBUG_PRINT("|API ON|");
1428
  } else {
1429
    WL_DEBUG_PRINT("|API ERROR|");
1430
  }
1431
  WL_DEBUG_PRINT("after status=");
1432
  WL_DEBUG_PRINT_HEX(getStatus(0xFF));
1433
  WL_DEBUG_PRINT("\r\n");*/
1434
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1435
  // wait for up to 30 ms
1436
  while(getStatus(XBEE_COMMAND_MASK) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1437
    delay_us(1); // wait 3us
1438
  }
1439
  
1440
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') {
1441
    i = (xbee_command[2]<<8) | (xbee_command[3]);
1442
  } else
1443
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1444
  setStatus(XBEE_COMMAND_MASK,XBEE_COMMAND_NONE); // reset status
1445
  WL_DEBUG_PRINT("get MY address\r\n");
1446
  return i; // return
1447
}
1448

    
1449
/**@} **/ // end xbee group
1450