Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (31 KB)

1 1576 dsschult
/**
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
35 1601 dsschult
#include <string.h>
36
#include <avr/interrupt.h>
37 1576 dsschult
#include <time.h>
38 1601 dsschult
#include "wl_defs.h"
39 1611 dsschult
#include "wireless.h"
40 1601 dsschult
#include "xbee.h"
41 1576 dsschult
42
43 1601 dsschult
/* Internal Function Prototypes */
44 1576 dsschult
45
// TODO: convert all int references to int16_t syntax (see stdint.h)
46
47 1601 dsschult
/* I/O Functions */
48 1611 dsschult
static int8_t xbee_send_string(uint8_t* c);
49 1576 dsschult
50 1601 dsschult
/* Command Mode Functions */
51 1611 dsschult
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 1576 dsschult
58 1601 dsschult
/* API Mode Functions */
59 1611 dsschult
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 int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
62 1609 dsschult
static void xbee_handle_status(uint8_t status);
63 1611 dsschult
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 1576 dsschult
69 1601 dsschult
/* 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 1576 dsschult
74
75 1601 dsschult
/*Global Variables*/
76 1576 dsschult
77 1591 dsschult
// array for basic packets
78 1589 alevkoy
static uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE];
79 1591 dsschult
80
// beginning of first packet in basic buffer
81
static uint8_t basic_buf_first = 0;
82
83
// byte after end of last packet in basic buffer (only access < basic_buf_last)
84
// aka, the first free byte in basic buffer
85
static uint8_t basic_buf_last = 0;
86
87
// array for other packets
88 1589 alevkoy
static uint8_t xbee_other_buf[PACKET_BUFFER_SIZE];
89 1576 dsschult
90 1591 dsschult
// beginning of first packet in other buffer
91
static uint8_t other_buf_first = 0;
92
93
// byte after end of last packet in other buffer (only access < other_buf_last)
94
// aka, the first free byte in other buffer
95
static uint8_t other_buf_last = 0;
96
97 1600 dsschult
// xbee status
98
#define XBEE_API_OFF 0x0
99
#define XBEE_API_ON 0x1
100
#define XBEE_API_ESCAPE 0x2
101
#define XBEE_NORMAL 0x00
102
#define XBEE_COMMAND_WAIT 0x80
103
#define XBEE_COMMAND_RESPONSE 0xC0
104 1604 dsschult
#define XBEE_INITD 0x08
105 1600 dsschult
static uint8_t xbee_status = XBEE_API_OFF|XBEE_NORMAL;
106
107
// xbee command response (for PAN, channel, address, etc)
108
static uint8_t xbee_command[4];
109
110 1591 dsschult
// external ack handler (wireless_send.c)
111
extern void ackhandle(uint8_t num,uint8_t val);
112
113 1601 dsschult
114 1587 dsschult
/**@addtogroup xbee
115
 * @{ **/
116
117 1576 dsschult
/*Function Implementations*/
118
119
/**
120
 * Interrupt for the robot. Adds bytes received from the xbee
121
 * to the buffer.
122
 **/
123
#ifndef FIREFLY
124 1591 dsschult
#define PORT UDR1
125
#define FLAG RXC1
126 1576 dsschult
ISR(USART1_RX_vect)
127
#else
128 1591 dsschult
#define PORT UDR0
129
#define FLAG RXC0
130 1576 dsschult
SIGNAL(SIG_USART0_RECV)
131 1591 dsschult
#endif
132 1576 dsschult
{
133 1591 dsschult
  // start of frame
134
        uint8_t apitype = PORT; // get frame start byte
135
  uint16_t i=0;
136
  uint16_t len=0;
137 1600 dsschult
138
  // check that we're in API mode
139 1609 dsschult
  if ((xbee_status&0x03) == XBEE_API_OFF || apitype != XBEE_FRAME_START) {
140 1600 dsschult
    // not in API mode
141 1609 dsschult
    if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT) {
142 1600 dsschult
      // get rest of command and put in basic buf
143
      xbee_basic_buf[0] = apitype;
144
      if (xbee_basic_buf[i] != '\r') {
145
        while(i < PACKET_BUFFER_SIZE) {
146
          if (FLAG) {
147
            xbee_basic_buf[i] = PORT;
148
            if (xbee_basic_buf[i] == '\r')
149
              break;
150
          }
151
        }
152
      }
153
      // signal handler that command response is done
154 1601 dsschult
      xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_RESPONSE;
155 1600 dsschult
    }
156
    return;
157
  }
158
159 1591 dsschult
  // get length and type
160
  while(i<3) {
161
    if (FLAG) {
162
      if (i==0)
163
        len |= PORT<<8;
164
      else if (i==1)
165
        len |= PORT;
166
      else if (i==2)
167
        apitype = PORT;
168
      i++;
169
    }
170
  }
171
172
  // do something based on the type
173
  i=1;
174
  switch(apitype) {
175 1611 dsschult
  case XBEE_FRAME_AT_COMMAND_RESPONSE: {
176 1591 dsschult
    // AT command response
177 1609 dsschult
    if ((xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
178 1600 dsschult
      return; // we're currently processing a command, so drop the incoming one
179 1591 dsschult
    uint16_t atcommand=0;
180
    uint8_t ptr=basic_buf_last;
181
    while(i<len) {
182
      if (FLAG) {
183
        if (i==1)
184
          apitype = PORT; // get frame id, but ignore it
185
        else if (i==2)
186
          atcommand |= PORT<<8; // get command char1
187
        else if (i==3)
188
          atcommand |= PORT; // get command char2
189
        else if (i==4)
190
          apitype = PORT; // get status
191
        else {
192
          // put the command response on the basic buf temporarily
193 1600 dsschult
          if (xbee_basic_buf_add(&ptr,PORT) != 0)
194 1591 dsschult
            break;
195
        }
196
        i++;
197
      }
198 1600 dsschult
    }
199
    // handle AT command
200
    xbee_handle_at_command_response(atcommand,apitype,i-5); // TODO: rewrite function
201 1611 dsschult
    break; }
202
  case XBEE_FRAME_TX_STATUS: {
203 1591 dsschult
    // TX status
204 1609 dsschult
    uint8_t frame_id = 0;
205 1591 dsschult
    while(i<len) {
206
      if (FLAG) {
207
        if (i==1)
208 1609 dsschult
          frame_id = PORT;
209 1591 dsschult
        else {
210 1609 dsschult
          ackhandle(frame_id,PORT); // handle the status
211 1591 dsschult
          break;
212
        }
213
        i++;
214
      }
215
    }
216 1611 dsschult
    break; }
217
  case XBEE_FRAME_RX_64: {
218 1591 dsschult
    // receive a packet with 64bit address
219 1611 dsschult
    break; } // TODO: implement this (even if we don't use it)
220
  case XBEE_FRAME_RX_16: {
221 1591 dsschult
    // receive a packet with 16bit address
222
    uint16_t source = 0;
223
    uint8_t framenum = 0;
224
    uint8_t group = 0;
225
    uint8_t ptr=basic_buf_last;
226
    while(i<len) {
227
      if (FLAG) {
228
        if (i==1)
229
          source |= PORT<<8; // get source hi byte
230
        else if (i==2)
231
          source |= PORT; // get source lo byte
232
        else if (i==3)
233
          apitype = PORT; // get RSSI, and ignore
234
        else if (i==4)
235
          apitype = PORT; // get options, and ignore
236
        else if (i==5) {
237
          framenum = PORT; // get the frame number
238
          if (check_last_receive(source,framenum) != 0) {  // TODO: write function
239
            // we've already received this frame
240
            ptr = 0xFF; // signal to skip processing
241
            break;
242
          }
243
        }
244
        else if (i==6) {
245
          group = PORT; // get group number
246
          if (group == 0) {
247
            ptr = basic_buf_last+1;
248
            // add source to buffer
249 1600 dsschult
            if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
250 1591 dsschult
              break;
251 1600 dsschult
            if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
252 1591 dsschult
              break;
253
          } else {
254
            ptr = other_buf_last+1;
255 1600 dsschult
            // add source and group to buffer
256
            if (xbee_other_buf_add(&ptr,group) != 0)
257 1591 dsschult
              break;
258 1600 dsschult
            if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0)
259 1591 dsschult
              break;
260 1600 dsschult
            if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0)
261 1591 dsschult
              break;
262
          }
263
        }
264 1600 dsschult
        else { // TODO: handle escaped characters supported by APIv2
265 1591 dsschult
          // put packet data on the correct buffer
266 1600 dsschult
          if (group == 0 && xbee_basic_buf_add(&ptr,PORT) != 0)
267
            break;
268
          else if (xbee_other_buf_add(&ptr,PORT) != 0)
269
            break;
270 1591 dsschult
        }
271
        i++;
272
      }
273
    }
274 1600 dsschult
    if (ptr != 0xFF && i > 6) {
275 1591 dsschult
      if (group == 0) {
276
        xbee_basic_buf[basic_buf_last] = i-6; // set length
277
        basic_buf_last = ptr;
278
      }
279
      else {
280
        xbee_other_buf[other_buf_last] = i-6; // set length
281
        // check if we have a high priority group
282
        for(;;)
283
          if (HIGH_PRIORITY) {
284
            // handle receive now
285
            ptr = 0xFF;
286
            break;
287
          }
288
        if (ptr != 0xFF) {
289
          // handle receive later
290
          other_buf_last = ptr;
291
        }
292
      }
293
    }
294 1611 dsschult
    break; }
295 1600 dsschult
  } // end of switch statement
296
  while (1) {
297
    if (FLAG) {
298
      apitype = PORT; // get checksum, and ignore
299
      break;
300
    }
301 1591 dsschult
  }
302
} // end of interrupt
303 1576 dsschult
304
305 1600 dsschult
/* adds a byte to the basic buffer */
306
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) {
307
  if (*ptr == basic_buf_first) {
308
    // buffer full
309
    WL_DEBUG_PRINT("basic buffer full\r\n");
310
    return -1;
311
  }
312 1611 dsschult
  xbee_basic_buf[(*ptr)++] = byte;
313 1600 dsschult
  if (*ptr == PACKET_BUFFER_SIZE)
314
    *ptr = 0;
315
  return 0;
316
}
317 1601 dsschult
/* gets a byte from the basic buffer */
318
uint8_t xbee_basic_buf_get(uint8_t *ptr) {
319
  uint8_t byte = xbee_basic_buf[(*ptr)++];
320
  if (*ptr == PACKET_BUFFER_SIZE)
321
    *ptr = 0;
322
  return byte;
323
}
324 1600 dsschult
/* adds a byte to the other buffer */
325
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) {
326
  if (*ptr == other_buf_first) {
327
    // buffer full
328
    WL_DEBUG_PRINT("other buffer full\r\n");
329
    return -1;
330
  }
331
  xbee_other_buf[(*ptr)++] = byte;
332 1611 dsschult
  if (*ptr == PACKET_BUFFER_SIZE)
333 1600 dsschult
    *ptr = 0;
334
  return 0;
335
}
336
337
338 1576 dsschult
/**
339
 * Initializes the XBee library so that other functions may be used.
340
 **/
341 1604 dsschult
int8_t xbee_init()
342 1576 dsschult
{
343 1604 dsschult
        WL_DEBUG_PRINT("in xbee_init\n");
344
345 1611 dsschult
  if((xbee_status&0x08) == XBEE_INITD) {
346 1604 dsschult
    return WL_ERROR_INIT_ALREADY_INITD;
347 1576 dsschult
  }
348 1604 dsschult
349
  // Set startup baud rate of 9600
350
        // Set frame format: 8data, 1stop bit, asynchronous normal mode
351
  // Enable receiver and transmitter and the receiving interrupt
352 1576 dsschult
#ifdef FIREFLY
353 1604 dsschult
  UCSR0A |= (1<<U2X0);
354
  UBRR0H = 0x00;
355
  UBRR0L = 103;
356
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
357
        UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
358 1576 dsschult
#else
359 1604 dsschult
  // Bayboard or robot
360
  UCSR1A |= (1<<U2X1);
361
  UBRR1H = 0x00;
362
  UBRR1L = 103;
363
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
364
        UCSR1B |= (1<<RXEN1) | (1<<TXEN1) | (1<<RXCIE1);
365 1576 dsschult
#endif
366
        sei();
367
368
        WL_DEBUG_PRINT("Entering command mode.\r\n");
369
        if (xbee_enter_command_mode() != 0) {
370 1611 dsschult
    WL_DEBUG_PRINT("error entering command mode\r\n");
371 1576 dsschult
                return -1;
372
        }
373
        WL_DEBUG_PRINT("Entered command mode.\r\n");
374
375
  // reset baud rate
376
  WL_DEBUG_PRINT("Resetting Baud to ");
377
  WL_DEBUG_PRINT(XBEE_BAUD_STR);
378
  WL_DEBUG_PRINT("\r\n");
379
380
  // set baud on xbee
381
#if (XBEE_BAUD == 115200)
382 1611 dsschult
  xbee_send_string((uint8_t*)"ATBD7\r");
383
  xbee_send_string((uint8_t*)"ATBD7\r");
384 1576 dsschult
#elif (XBEE_BAUD == 57600)
385 1611 dsschult
  xbee_send_string((uint8_t*)"ATBD6\r");
386 1576 dsschult
#elif (XBEE_BAUD == 38400)
387 1611 dsschult
  xbee_send_string((uint8_t*)"ATBD5\r");
388 1576 dsschult
#elif (XBEE_BAUD == 19200)
389 1611 dsschult
  xbee_send_string((uint8_t*)"ATBD4\r");
390 1576 dsschult
#elif (XBEE_BAUD == 9600)
391
  // already at this baud rate
392
  //xbee_send_string("ATBD3\r\n");
393
#else
394
  WL_DEBUG_PRINT("undefined baud rate\r\n");
395 1601 dsschult
  return WL_ERROR_BAUD;
396 1576 dsschult
#endif
397
  // exit command mode
398
  xbee_wait_for_ok();
399
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
400 1611 dsschult
  xbee_send_string((uint8_t*)"ATCN\r");
401 1576 dsschult
  xbee_wait_for_ok();
402
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
403
404
  // set UART baud
405 1604 dsschult
#ifdef FIREFLY
406 1601 dsschult
#if (XBEE_BAUD == 115200)
407 1604 dsschult
  UBRR0H = 0x00;
408
  UBRR0L = 8;
409
#elif (XBEE_BAUD == 57600)
410
  UBRR0H = 0x00;
411
  UBRR0L = 16;
412
#elif (XBEE_BAUD == 38400)
413
  UBRR0H = 0x00;
414
  UBRR0L = 25;
415
#elif (XBEE_BAUD == 19200)
416
  UBRR0H = 0x00;
417
  UBRR0L = 51;
418
#elif (XBEE_BAUD == 9600)
419
  /* this is the default baud rate, so do nothing
420
  UBRR0H = 0x00;
421
  UBRR0L = 103;*/
422
#else
423
  WL_DEBUG_PRINT("undefined baud rate\r\n");
424
  return WL_ERROR_BUAD;
425
#endif
426
#else // Bayboard or robot
427
#if (XBEE_BAUD == 115200)
428 1576 dsschult
  UBRR1H = 0x00;
429
  UBRR1L = 8;
430
#elif (XBEE_BAUD == 57600)
431
  UBRR1H = 0x00;
432
  UBRR1L = 16;
433
#elif (XBEE_BAUD == 38400)
434
  UBRR1H = 0x00;
435
  UBRR1L = 25;
436
#elif (XBEE_BAUD == 19200)
437
  UBRR1H = 0x00;
438
  UBRR1L = 51;
439
#elif (XBEE_BAUD == 9600)
440
  /* this is the default baud rate, so do nothing
441
  UBRR1H = 0x00;
442 1604 dsschult
  UBRR1L = 103;*/
443 1601 dsschult
#else
444
  WL_DEBUG_PRINT("undefined baud rate\r\n");
445
  return WL_ERROR_BUAD;
446 1576 dsschult
#endif
447 1604 dsschult
#endif
448 1576 dsschult
  delay_ms(50);
449
450
  // enter command mode
451
  WL_DEBUG_PRINT("entering command mode 2\r\n");
452 1611 dsschult
  xbee_send_string((uint8_t*)"+++");
453 1576 dsschult
  xbee_wait_for_ok();
454
  WL_DEBUG_PRINT("entered command mode 2\r\n");
455
456
  if (xbee_enter_api_mode() != 0) {
457
    WL_DEBUG_PRINT("can't enter api mode\r\n");
458
                return -1;
459
        }
460
461
        WL_DEBUG_PRINT("Entered api mode.\r\n");
462
463
        if (xbee_exit_command_mode() != 0) {
464
    WL_DEBUG_PRINT("can't exit command mode\r\n");
465
          return -1;
466
        }
467
468
        WL_DEBUG_PRINT("Left command mode.\r\n");
469
470 1601 dsschult
  // TODO: we should set the MY address to the robot address from eeprom
471 1576 dsschult
472 1604 dsschult
473
  // set status
474
  xbee_status |= XBEE_INITD;
475
476 1601 dsschult
        return WL_SUCCESS;
477 1576 dsschult
}
478
479
/**
480 1601 dsschult
 * Call when finished using the XBee library.
481 1576 dsschult
 **/
482 1604 dsschult
int8_t xbee_terminate()
483 1576 dsschult
{
484 1604 dsschult
  if (xbee_exit_api_mode() != WL_SUCCESS) {
485
    WL_DEBUG_PRINT("xbee termination failed\r\n");
486
    return WL_ERROR_TERMINATION_FAILED;
487
  }
488
  xbee_status = xbee_status&0xF7; // clean initd status
489
  return WL_SUCCESS;
490 1576 dsschult
}
491
492
/**
493 1604 dsschult
 * Sends a character to the XBee.
494
 *
495
 * @param c the byte to send
496
 * @return 0 for success, nonzero for failure
497
 **/
498 1611 dsschult
int8_t xbee_putc(uint8_t c) {
499 1604 dsschult
  if(!(xbee_status&XBEE_INITD))
500
    return WL_ERROR_LIBRARY_NOT_INITD;
501
502
  // Wait until buffer is clear for sending
503
  // Then load buffer with your character
504
#ifdef FIREFLY
505
  loop_until_bit_is_set(UCSR0A, UDRE0);
506
  UDR0 = c;
507
#else
508
  loop_until_bit_is_set(UCSR1A, UDRE1);
509
  UDR1 = c;
510
#endif
511
512
  return WL_SUCCESS;
513
}
514
515
/**
516
 * Returns the first byte in the buffer received from xbee.
517
 * This function blocks execution until a character has been
518
 * received. xbee_init must be called before this function
519
 * may be used.
520
 *
521
 * @return the first character in the xbee buffer, -1 on error
522
 *
523
 * @see xbee_init, xbee_getc_nb
524
 **/
525
int16_t xbee_getc(void) {
526
  if(!(xbee_status&XBEE_INITD))
527
    return WL_ERROR_LIBRARY_NOT_INITD;
528
529
  // Wait for the receive buffer to be filled
530
  // Then read the receive buffer
531
#ifdef FIREFLY
532
  loop_until_bit_is_set(UCSR0A, RXC0);
533
  return UDR0;
534
#else
535
  loop_until_bit_is_set(UCSR1A, RXC1);
536
  return UDR1;
537
#endif
538
}
539
540
/**
541
 * Non blocking version of xbee_getc. If a byte is present in the buffer,
542
 * it is returned, otherwise -1 is returned immediately. xbee_init
543
 * must be called before this function can be used.
544
 *
545
 * @param c The received byte. This will be set if a byte has been received.
546
 *
547
 * @return -1 If no byte is available, 0 otherwise, positive for error
548
 *
549
 * @see xbee_getc
550
 **/
551
int8_t xbee_getc_nb(uint8_t *c) {
552
  if(!(xbee_status&XBEE_INITD))
553
    return WL_ERROR_LIBRARY_NOT_INITD;
554
555
  // check if the receive buffer is filled
556
#ifdef FIREFLY
557
  if (UCSR0A & (1<<RXC0)) {
558
    (*c) = UDR0;
559
#else
560
  if (UCSR1A & (1<<RXC1)) {
561
    (*c) = UDR1;
562
#endif
563
    return WL_SUCCESS;
564
  }
565
  return -1; // Return empty
566
}
567
568
/**
569 1576 dsschult
 * Send a buffer buf of size bytes to the XBee.
570
 *
571
 * @param buf the buffer of data to send
572
 * @param size the number of bytes to send
573
 **/
574 1600 dsschult
static int8_t xbee_send(uint8_t* buf, uint16_t size)
575 1576 dsschult
{
576 1611 dsschult
  uint16_t i=0; // check if we need this variable
577
        while(i<size) {
578
                if (xbee_putc(buf[i++]) != WL_SUCCESS)
579 1600 dsschult
      return WL_ERROR_SEND;
580
        }
581
  if (xbee_putc(buf[0]) != WL_SUCCESS)
582
    return WL_ERROR_SEND;
583 1576 dsschult
584 1600 dsschult
        return WL_SUCCESS;
585 1576 dsschult
}
586
587
/**
588
 * Sends a string to the XBee.
589
 *
590
 * @param c the string to send to the XBEE
591
 **/
592 1611 dsschult
static int8_t xbee_send_string(uint8_t* c)
593 1576 dsschult
{
594 1611 dsschult
        return xbee_send(c, strlen((char*)c));
595 1576 dsschult
}
596
597
598
/**
599
 * Enter into command mode.
600
 **/
601 1611 dsschult
static int8_t xbee_enter_command_mode(void)
602 1576 dsschult
{
603 1611 dsschult
        if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
604 1601 dsschult
                return WL_ERROR_XBEE_COMMAND;
605 1576 dsschult
        }
606
607 1601 dsschult
        if (xbee_wait_for_ok() != WL_SUCCESS) {
608
          return WL_ERROR_XBEE_COMMAND;
609 1576 dsschult
        }
610 1601 dsschult
611
        return WL_SUCCESS;
612 1576 dsschult
}
613
614
/**
615
 * Exit from command mode.
616
 **/
617 1600 dsschult
static int8_t xbee_exit_command_mode()
618 1576 dsschult
{
619 1611 dsschult
        if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
620 1604 dsschult
                return WL_ERROR_SEND;
621 1576 dsschult
        }
622
        xbee_wait_for_ok();
623
624 1604 dsschult
        return WL_SUCCESS;
625 1576 dsschult
}
626
627
/**
628
 * Enter API mode.
629
 **/
630 1611 dsschult
static int8_t xbee_enter_api_mode(void) {
631
        if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) {
632 1604 dsschult
                return WL_ERROR_SEND;
633 1576 dsschult
        }
634
        xbee_wait_for_ok();
635 1600 dsschult
636
  xbee_status = (xbee_status&0xFC)|XBEE_API_ON;
637 1576 dsschult
638 1604 dsschult
        return WL_SUCCESS;
639 1576 dsschult
}
640
641
/**
642 1600 dsschult
 * Enter API mode 2.
643
 **/
644 1611 dsschult
static int8_t xbee_enter_api_mode2(void) {
645
        if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) {
646 1604 dsschult
                return WL_ERROR_SEND;
647 1600 dsschult
        }
648
        xbee_wait_for_ok();
649
650
  xbee_status = (xbee_status&0xFC)|XBEE_API_ESCAPE;
651
652 1604 dsschult
        return WL_SUCCESS;
653 1600 dsschult
}
654
655
/**
656 1576 dsschult
 * Exit API mode.
657
 **/
658 1604 dsschult
static int8_t xbee_exit_api_mode()
659 1576 dsschult
{
660 1611 dsschult
        if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
661
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
662 1604 dsschult
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
663 1600 dsschult
664 1604 dsschult
  int16_t i=0;
665
  // change status to command wait
666
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
667 1611 dsschult
  xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)"0",1); // send command
668 1604 dsschult
  // wait for up to 30 ms
669 1611 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
670 1604 dsschult
    delay_us(1); // wait 3us
671
  }
672 1611 dsschult
  if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P')
673 1604 dsschult
    i = WL_SUCCESS;
674
  else
675
    i = WL_ERROR_XBEE_COMMAND; // set error code
676
  xbee_status = (xbee_status&0x3C)|XBEE_API_OFF; // reset status
677
        return (int8_t)i; // return
678 1576 dsschult
}
679
680
/**
681
 * Wait until the string "OK\r" is received from the XBee.
682
 **/
683 1611 dsschult
static int8_t xbee_wait_for_ok()
684 1576 dsschult
{
685 1611 dsschult
        return xbee_wait_for_string((uint8_t*)"OK\r", 3);
686 1576 dsschult
}
687
688
/**
689
 * Delay until the specified string is received from
690 1604 dsschult
 * the XBee.
691 1576 dsschult
 *
692 1604 dsschult
 * Only works when not in API mode
693 1576 dsschult
 *
694
 * @param s the string to receive
695
 * @param len the length of the string
696
 **/
697 1611 dsschult
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
698 1576 dsschult
{
699 1600 dsschult
  uint8_t i=0;
700 1611 dsschult
  if ((xbee_status&0x03) == XBEE_API_OFF) {
701 1600 dsschult
    // wait until the response is received (only wait 1 second)
702 1611 dsschult
    while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
703 1600 dsschult
      delay_us(1);
704
    }
705
    // check response
706
    if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) {
707
      // bad response
708
      WL_DEBUG_PRINT("Bad response when waiting for string ");
709
      WL_DEBUG_PRINT(s);
710
      WL_DEBUG_PRINT("\r\n");
711
      return -1;
712
    }
713 1601 dsschult
714
    // clear response
715
    xbee_status = xbee_status&0x3F;
716 1600 dsschult
  }
717 1576 dsschult
718
        return 0;
719
}
720
721
/**
722 1600 dsschult
 * Delay until we receive a command response.
723
 * (either OK\r or some actual value)
724
 *
725
 * Only works when not in API mode
726
 *
727
 * @param s the string to store the response in
728
 * @param len the length of the string
729
 */
730 1611 dsschult
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
731 1600 dsschult
  uint8_t i=0;
732 1611 dsschult
  if ((xbee_status&0x03) == XBEE_API_OFF) {
733 1600 dsschult
    // wait until the response is received (only wait 1 second)
734 1611 dsschult
    while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
735 1600 dsschult
      delay_us(1);
736
    }
737
    // check response
738 1611 dsschult
    if (i >= 1000) {
739 1600 dsschult
      return -1;
740
    } else {
741 1611 dsschult
      i=strcspn((char*)xbee_basic_buf,"\r");
742 1600 dsschult
      if (i<PACKET_BUFFER_SIZE) {
743
        memcpy(s,xbee_basic_buf,i);
744 1601 dsschult
        xbee_status = xbee_status&0x3F; // clear response
745 1600 dsschult
        return 0;
746
      }
747
      else
748
        return -1;
749
    }
750
  }
751
  // TODO: do something for API mode
752
753
  return 0;
754
}
755
756 1601 dsschult
/**  TODO: since we don't use this, do we need it?
757
 *
758 1576 dsschult
 * Verifies that the packets checksum is correct.
759
 * (If the checksum is correct, the sum of the bytes
760
 * is 0xFF.)
761
 *
762
 * @param packet the packet received. This includes the first
763
 * three bytes, which are header information from the XBee.
764
 *
765
 * @param len The length of the packet received from the XBee
766
 *
767
 * @return 0 if the checksum is incorrect, nonzero
768
 * otherwise
769
 **/
770 1611 dsschult
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
771 1576 dsschult
{
772 1601 dsschult
        uint8_t sum = 0;
773
        while(--len > 0) {
774
                sum += packet[len];
775
  }
776
  sum += packet[0];
777
        return (sum == 0xFF);
778 1576 dsschult
}
779
780
/**
781
 * Returns the checksum of the given packet.
782
 *
783
 * @param buf the data for the packet to send
784
 * @param len the length of the packet in bytes
785
 *
786
 * @return the checksum of the packet, which will
787
 * become the last byte sent in the packet
788
 **/
789 1604 dsschult
uint8_t xbee_compute_checksum(uint8_t* buf, uint16_t len)
790 1576 dsschult
{
791 1600 dsschult
        uint8_t sum = 0;
792
        while(--len > 0) {
793
                sum += buf[len];
794
  }
795
  sum += buf[0];
796 1576 dsschult
        return 0xFF - sum;
797
}
798
799
/**
800 1604 dsschult
 * Adds buf to the previous checksum total
801
 *
802
 * @param buf a byte buffer to add to the checksum
803
 * @param len the length of the buffer
804
 * @param sum the previous sum
805
 *
806
 * @return error code
807
 **/
808
static int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum) {
809
  if (buf == NULL || sum == NULL)
810
    return WL_ERROR_ARGUMENT;
811
  while(--len > 0) {
812
                *sum += buf[len];
813
  }
814
  *sum += buf[0];
815
}
816
817
818
/**
819
 * Sends header information. Header information includes
820
 * XBEE_FRAME_START and the packet length, as two bytes.
821
 *
822
 * @param type the packet type
823
 * @param len the size in bytes of the packet data
824
 *
825
 **/
826
static int8_t xbee_send_header(uint8_t type, uint16_t len)
827
{
828
  //packet prefix
829
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
830
    return WL_ERROR_SEND;
831
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
832
    return WL_ERROR_SEND;
833
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
834
    return WL_ERROR_SEND;
835
836
        return WL_SUCCESS;
837
}
838
839
/**
840 1576 dsschult
 * Adds header information and checksum to the given
841
 * packet and sends it. Header information includes
842
 * XBEE_FRAME_START and the packet length, as two bytes.
843
 *
844
 * @param buf the packet data
845
 * @param len the size in bytes of the packet data
846
 *
847
 **/
848 1600 dsschult
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
849 1576 dsschult
{
850 1600 dsschult
        uint8_t checksum = xbee_compute_checksum(buf, len);
851 1604 dsschult
852
  //packet prefix
853
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
854
    return WL_ERROR_SEND;
855
  if (xbee_putc((uint8_t)((len & 0xFF00) >> 8)) != WL_SUCCESS)
856
    return WL_ERROR_SEND;
857
  if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS)
858
    return WL_ERROR_SEND;
859 1576 dsschult
860 1604 dsschult
        if (xbee_send(buf, len) != WL_SUCCESS)
861 1600 dsschult
                return WL_ERROR_SEND;
862 1604 dsschult
863
        if (xbee_putc(checksum) != WL_SUCCESS)
864 1600 dsschult
                return WL_ERROR_SEND;
865 1604 dsschult
866 1600 dsschult
        return WL_SUCCESS;
867 1576 dsschult
}
868
869
/**
870
 * Sends an AT command to read a parameter.
871
 *
872
 * @param command the AT command to send. For exmaple,
873
 * use ID to read the PAN ID and MY to return the XBee ID.
874
 * See the XBee reference guide for a complete listing.
875
 **/
876 1600 dsschult
int8_t xbee_send_read_at_command(uint8_t* command)
877 1576 dsschult
{
878 1600 dsschult
        return xbee_send_modify_at_command(command, NULL, 0);
879 1576 dsschult
}
880
881
/**
882
 * Sends the given AT command.
883
 *
884
 * @param command the AT command to send (e.g., MY, ID)
885
 * @param value the value to pass as a parameter
886
 * (or NULL if there is no parameter)
887
 **/
888 1600 dsschult
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
889 1576 dsschult
{
890 1600 dsschult
        uint8_t buf[12];
891 1576 dsschult
892
        buf[0] = XBEE_FRAME_AT_COMMAND;
893
        buf[1] = 1;
894
        buf[2] = command[0];
895
        buf[3] = command[1];
896
        if (value != NULL)
897
        {
898 1600 dsschult
                if (len > 8)
899 1576 dsschult
                {
900
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
901 1600 dsschult
                        return WL_ERROR_ARGUMENT;
902 1576 dsschult
                }
903 1600 dsschult
    memcpy(buf+4,value,len);
904 1576 dsschult
        }
905
906 1600 dsschult
        return xbee_send_frame(buf, 4 + len);
907 1576 dsschult
}
908
909
/**
910
 * Send the specified packet.
911
 *
912
 * @param packet the packet data to send
913
 * @param len the number of bytes in the packet
914
 *
915
 * @param dest the ID of the XBee to send the packet to,
916
 * or XBEE_BROADCAST to send the message to all robots
917
 * in the PAN.
918
 *
919
 * @param options a combination of the flags
920
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
921
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
922
 *
923
 * @param frame the frame number to associate this packet
924
 * with. This will be used to identify the response when
925
 * the XBee alerts us as to whether or not our message
926
 * was received.
927
 **/
928 1604 dsschult
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame)
929 1576 dsschult
{
930 1604 dsschult
        uint8_t sum = XBEE_FRAME_TX_REQUEST_16;
931
  uint8_t i = 0;
932 1576 dsschult
933
        if (len > 100)
934
        {
935
                WL_DEBUG_PRINT("Packet is too large.\r\n");
936 1604 dsschult
                return WL_ERROR_ARGUMENT;
937 1576 dsschult
        }
938 1604 dsschult
939
  // calculate checksum
940
        for(;i<len;i++)
941
                sum += packet[len];
942
  sum += frame;
943
  sum += (dest&0xFF00) >> 8;
944
  sum += dest&0x00FF;
945
  sum += options;
946
        sum = 0xFF - sum;
947 1576 dsschult
948 1604 dsschult
        //packet prefix
949
  if (xbee_putc(XBEE_FRAME_START) != WL_SUCCESS)
950
    return WL_ERROR_SEND;
951
  if (xbee_putc(0x00) != WL_SUCCESS)
952
    return WL_ERROR_SEND;
953
  if (xbee_putc(len+5) != WL_SUCCESS)
954
    return WL_ERROR_SEND;
955
956
        //send header for TX request
957
  if (xbee_putc(XBEE_FRAME_TX_REQUEST_16) != WL_SUCCESS)
958
    return WL_ERROR_SEND;
959
  if (xbee_putc(frame) != WL_SUCCESS)
960
    return WL_ERROR_SEND;
961
  if (xbee_putc((uint8_t)((dest&0xFF00) >> 8)) != WL_SUCCESS)
962
    return WL_ERROR_SEND;
963
  if (xbee_putc((uint8_t)(dest&0x00FF)) != WL_SUCCESS)
964
    return WL_ERROR_SEND;
965
  if (xbee_putc(options) != WL_SUCCESS)
966
    return WL_ERROR_SEND;
967 1576 dsschult
968 1604 dsschult
  // send packet
969
        if (xbee_send(packet, len) != WL_SUCCESS)
970
                return WL_ERROR_SEND;
971 1576 dsschult
972 1604 dsschult
  // send checksum
973
        if (xbee_putc(sum) != WL_SUCCESS)
974
                return WL_ERROR_SEND;
975 1576 dsschult
976 1604 dsschult
        return WL_SUCCESS;
977 1576 dsschult
}
978
979
/**
980
 * Handles modem status packets.
981
 *
982
 * @param status the type of status packet received.
983
 **/
984 1611 dsschult
void xbee_handle_status(uint8_t status)
985 1576 dsschult
{
986
        switch (status)
987
        {
988
                case 0:
989
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
990
                        break;
991
                case 1:
992
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
993
                        break;
994
                case 2:
995
                        WL_DEBUG_PRINT("Associated.\r\n");
996
                        break;
997
                case 3:
998
                        WL_DEBUG_PRINT("Disassociated.\r\n");
999
                        break;
1000
                case 4:
1001
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
1002
                        break;
1003
                case 5:
1004
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
1005
                        break;
1006
                case 6:
1007
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
1008
                        break;
1009
        }
1010
}
1011
1012
/**
1013
 * Handles AT command response packets.
1014
 * @param command the two character AT command, e.g. MY or ID
1015
 * @param result 0 for success, 1 for an error
1016 1601 dsschult
 * @param len the length in bytes of extra
1017 1576 dsschult
 **/
1018 1601 dsschult
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len)
1019 1576 dsschult
{
1020
        if (result == 1)
1021
        {
1022
                WL_DEBUG_PRINT("Error with AT");
1023
                WL_DEBUG_PRINT(command);
1024
                WL_DEBUG_PRINT(" packet. Result = ");
1025
    switch(result) {
1026
    case 1:
1027
      WL_DEBUG_PRINT("ERROR\r\n");
1028
      break;
1029
    case 2:
1030
      WL_DEBUG_PRINT("Invalid Command\r\n");
1031
      break;
1032
    case 3:
1033
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
1034
      break;
1035
    }
1036 1601 dsschult
    return WL_SUCCESS;
1037 1576 dsschult
        }
1038
        WL_DEBUG_PRINT("AT");
1039
        WL_DEBUG_PRINT(command);
1040
        WL_DEBUG_PRINT(" command was successful.\r\n");
1041
1042 1601 dsschult
  // TODO: program more command responses here (ND, etc)
1043
  switch(command) {
1044
  case ('I'<<8)+'D': // PAN
1045
  case ('C'<<8)+'H': // channel
1046
  case ('M'<<8)+'Y': // address
1047
    // copy command to handler
1048
    xbee_command[0] = (command&0xFF00)>>8;
1049
    xbee_command[1] = command&0x00FF;
1050
    result = basic_buf_last;
1051
    for(command=2;command<len+2;command++)
1052
      xbee_command[command] = xbee_basic_buf_get(&result);
1053
    break;
1054
  default:
1055
    WL_DEBUG_PRINT("unknown AT command");
1056
  }
1057 1576 dsschult
1058 1601 dsschult
  // signal handler that command response is done
1059
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_RESPONSE;
1060 1576 dsschult
1061 1601 dsschult
  return WL_SUCCESS;
1062 1576 dsschult
}
1063
1064
/**
1065
 * Sets the personal area network id.
1066
 *
1067
 * @param id the new personal area network (PAN) id
1068
 **/
1069 1600 dsschult
int8_t xbee_set_pan_id(uint16_t id)
1070 1576 dsschult
{
1071 1611 dsschult
        if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
1072
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
1073 1600 dsschult
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1074
1075
  int16_t i=0;
1076
  // change status to command wait
1077
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
1078 1611 dsschult
  xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
1079 1600 dsschult
  // wait for up to 30 ms
1080 1611 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1081 1600 dsschult
    delay_us(1); // wait 3us
1082
  }
1083 1611 dsschult
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1084 1600 dsschult
    i = WL_SUCCESS;
1085
  else
1086
    i = WL_ERROR_XBEE_COMMAND; // set error code
1087
  xbee_status = xbee_status&0x3F; // reset status
1088
        return (int8_t)i; // return
1089 1576 dsschult
}
1090
1091
/**
1092
 * Get the PAN ID for the XBee.
1093
 *
1094
 * @return the personal area network id, or
1095
 * XBEE_PAN_DEFAULT if it has not yet been set.
1096
 **/
1097 1600 dsschult
uint16_t xbee_get_pan_id()
1098 1576 dsschult
{
1099 1611 dsschult
  if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
1100
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
1101 1600 dsschult
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1102
1103
  uint16_t i=0;
1104
  // change status to command wait
1105
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
1106 1611 dsschult
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
1107 1600 dsschult
  // wait for up to 30 ms
1108 1611 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1109 1600 dsschult
    delay_us(1); // wait 3us
1110
  }
1111 1611 dsschult
  if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D')
1112 1600 dsschult
    i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN
1113
  else
1114
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1115
  xbee_status = xbee_status&0x3F; // reset status
1116
        return i; // return
1117 1576 dsschult
}
1118
1119
/**
1120
 * Set the channel the XBee is using.
1121
 *
1122
 * @param channel the channel the XBee will not use,
1123
 * between 0x0B and 0x1A
1124
 *
1125
 * @see xbee_get_channel
1126
 **/
1127 1600 dsschult
int8_t xbee_set_channel(uint8_t channel)
1128 1576 dsschult
{
1129
        if (channel < 0x0B || channel > 0x1A)
1130
        {
1131
                WL_DEBUG_PRINT("Channel out of range.\r\n");
1132
                return -1;
1133
        }
1134
1135 1611 dsschult
        if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
1136
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
1137 1600 dsschult
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1138
1139
  int16_t i=0;
1140
  // change status to command wait
1141
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
1142 1611 dsschult
  xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
1143 1600 dsschult
  // wait for up to 30 ms
1144 1609 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1145 1600 dsschult
    delay_us(1); // wait 3us
1146
  }
1147 1609 dsschult
  if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K')
1148 1600 dsschult
    i = WL_SUCCESS;
1149
  else
1150
    i = WL_ERROR_XBEE_COMMAND; // set error code
1151
  xbee_status = xbee_status&0x3F; // reset status
1152
        return (int8_t)i; // return
1153 1576 dsschult
}
1154
1155
/**
1156
 * Returns the channel which the XBee is currently using.
1157
 *
1158
 * @return the channel the XBee is using
1159
 *
1160
 * @see xbee_set_channel
1161
 **/
1162 1600 dsschult
int8_t xbee_get_channel(void)
1163 1576 dsschult
{
1164 1609 dsschult
  if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
1165
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
1166 1600 dsschult
    return WL_ERROR_XBEE_COMMAND; // can't do command right now
1167
1168
  int16_t i=0;
1169
  // change status to command wait
1170
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
1171 1611 dsschult
  xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the channel
1172 1600 dsschult
  // wait for up to 30 ms
1173 1609 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1174 1600 dsschult
    delay_us(1); // wait 3us
1175
  }
1176 1609 dsschult
  if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H')
1177 1600 dsschult
    i = xbee_command[2]; // get channel
1178
  else
1179
    i = WL_ERROR_XBEE_COMMAND; // set error code
1180
  xbee_status = xbee_status&0x3F; // reset status
1181
        return i; // return
1182 1576 dsschult
}
1183
1184
/**
1185
 * Get the 16-bit address of the XBee.
1186
 * This is used to specify who to send messages to
1187
 * and who messages are from.
1188
 *
1189
 * @return the 16-bit address of the XBee.
1190
 **/
1191 1601 dsschult
uint16_t xbee_get_address(void)
1192 1576 dsschult
{
1193 1609 dsschult
  if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
1194
    || (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
1195 1600 dsschult
    return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now
1196
1197
  uint16_t i=0;
1198
  // change status to command wait
1199
  xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT;
1200 1611 dsschult
  xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
1201 1600 dsschult
  // wait for up to 30 ms
1202 1609 dsschult
  while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
1203 1600 dsschult
    delay_us(1); // wait 3us
1204
  }
1205 1609 dsschult
  if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y')
1206 1600 dsschult
    i = (xbee_command[2]<<8)+xbee_command[3]; // get address
1207
  else
1208
    i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code
1209
  xbee_status = xbee_status&0x3F; // reset status
1210
        return i; // return
1211 1576 dsschult
}
1212
1213 1581 dsschult
/**@} **/ // end xbee group