Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / libwireless / lib / xbee.c @ 409

History | View | Annotate | Download (19.3 KB)

1 242 bcoltin
/**
2
 * Copyright (c) 2007 Colony Project
3 409 emarinel
 *
4 242 bcoltin
 * 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 409 emarinel
 *
13 242 bcoltin
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15 409 emarinel
 *
16 242 bcoltin
 * 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 Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34
35 17 bcoltin
#include "xbee.h"
36
#include "wl_defs.h"
37
38
#ifndef ROBOT
39
40
#include <fcntl.h>
41
#include <unistd.h>
42
#include <pthread.h>
43
#include <errno.h>
44 309 emarinel
#include <termios.h>
45 17 bcoltin
46
#else
47
48
#include <serial.h>
49
#include <avr/interrupt.h>
50
51
#endif
52
53
#include <stdio.h>
54
#include <stdlib.h>
55
#include <string.h>
56
57
#define XBEE_FRAME_START 0x7E
58
59
/*Frame Types*/
60
#define XBEE_FRAME_STATUS 0x8A
61
#define XBEE_FRAME_AT_COMMAND 0x08
62
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88
63
#define XBEE_FRAME_TX_REQUEST_64 0x00
64
#define XBEE_FRAME_TX_REQUEST_16 0x01
65
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS
66
#define XBEE_FRAME_RX_64 0x80
67
#define XBEE_FRAME_RX_16 XBEE_RX
68
69
/*Internal Function Prototypes*/
70
71
/*I/O Functions*/
72 397 emarinel
static int xbee_send(char* buf, int size);
73
static void xbee_send_string(char* c);
74 17 bcoltin
75
#ifndef ROBOT
76
void xbee_read(char* buf, int size);
77
#endif
78
79
/*Command Mode Functions
80
 * Called during initialization.
81
 */
82 409 emarinel
static void xbee_enter_command_mode(void);
83
static void xbee_exit_command_mode(void);
84
static void xbee_enter_api_mode(void);
85
static void xbee_exit_api_mode(void);
86
static void xbee_wait_for_string(char* s, int len);
87
static void xbee_wait_for_ok(void);
88 17 bcoltin
89
/*API Mode Functions*/
90
91
int xbee_handle_packet(char* packet, int len);
92 397 emarinel
void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen);
93 17 bcoltin
void xbee_handle_status(char status);
94
int xbee_verify_checksum(char* packet, int len);
95
char xbee_compute_checksum(char* packet, int len);
96
void xbee_send_frame(char* buf, int len);
97
void xbee_send_read_at_command(char* command);
98
void xbee_send_modify_at_command(char* command, char* value);
99
100
/*Global Variables*/
101
102
#ifndef ROBOT
103 399 emarinel
static char* xbee_com_port = XBEE_PORT_DEFAULT;
104
static int xbee_stream;
105
static pthread_t* xbee_listen_thread;
106 17 bcoltin
#endif
107
108 336 bcoltin
// TODO: is this a good size?
109
#define XBEE_BUFFER_SIZE        256
110
// a buffer for data received from the XBee
111
char arrival_buf[XBEE_BUFFER_SIZE];
112
// location of last unread byte in buffer
113
volatile int buffer_last = 0;
114
// first unread byte in buffer
115
volatile int buffer_first = 0;
116 17 bcoltin
117 336 bcoltin
118 17 bcoltin
//used to store packets as they are read
119
char xbee_buf[128];
120
int currentBufPos = 0;
121
122
//XBee status
123
unsigned int xbee_panID = XBEE_PAN_DEFAULT;
124
unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
125 60 bcoltin
int xbee_channel = XBEE_CHANNEL_DEFAULT;
126
int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
127 17 bcoltin
unsigned int xbee_address = 0;
128
129
/*Function Implementations*/
130
131
#ifdef ROBOT
132
133
/**
134
 * Interrupt for the robot. Adds bytes received from the xbee
135 336 bcoltin
 * to the buffer.
136 17 bcoltin
 **/
137 86 bcoltin
#ifndef FIREFLY
138 346 bcoltin
ISR(USART1_RX_vect)
139
{
140
        char c = UDR1;
141
        arrival_buf[buffer_last] = c;
142
        int t = buffer_last + 1;
143
        if (t == XBEE_BUFFER_SIZE)
144
                t = 0;
145
        if (t == buffer_first)
146
        {
147
                WL_DEBUG_PRINT("Out of space in buffer.\n");
148
        }
149
        buffer_last = t;
150 17 bcoltin
}
151 86 bcoltin
#else
152 346 bcoltin
SIGNAL(SIG_USART0_RECV)
153
{
154
        char c = UDR0;
155
        arrival_buf[buffer_last] = c;
156
        int t = buffer_last + 1;
157
        if (t == XBEE_BUFFER_SIZE)
158
                t = 0;
159
        if (t == buffer_first)
160
        {
161
                WL_DEBUG_PRINT("Out of space in buffer.\n");
162
        }
163
        buffer_last = t;
164 86 bcoltin
}
165
#endif
166 17 bcoltin
167
#else
168
169
/**
170
 * Thread that listens to the xbee.
171
 **/
172 346 bcoltin
void* listen_to_xbee(void* x)
173
{
174
        char c;
175
        while (1)
176
        {
177
                xbee_read(&c, 1);
178
                arrival_buf[buffer_last] = c;
179
                int t = buffer_last + 1;
180
                if (t == XBEE_BUFFER_SIZE)
181
                        t = 0;
182
                if (t == buffer_first)
183
                {
184
                        WL_DEBUG_PRINT("Out of space in buffer.\n");
185
                }
186
                buffer_last = t;
187 409 emarinel
188
                usleep(1000);
189 346 bcoltin
        }
190
        return 0;
191 17 bcoltin
}
192
193
#endif
194
195
/**
196
 * Initializes the XBee library so that other functions may be used.
197
 **/
198 399 emarinel
int xbee_lib_init()
199 346 bcoltin
{
200
        arrival_buf[0] = 'A';
201
        arrival_buf[1] = 'A';
202
        arrival_buf[2] = 'A';
203
        #ifdef ROBOT
204 17 bcoltin
205 346 bcoltin
        //enable the receiving interrupt
206
        #ifdef FIREFLY
207
        UCSR0B |= _BV(RXCIE) | _BV(RXEN);
208
        #else
209
        UCSR1B |= _BV(RXCIE);
210
        #endif
211
        sei();
212
        #else
213
        printf("Connecting to port %s.\n", xbee_com_port);
214
        xbee_stream = open(xbee_com_port, O_RDWR);
215
        if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/)
216
        {
217
                printf("Failed to open connection to XBee on port %s\r\n", xbee_com_port);
218
                return -1;
219
        }
220 409 emarinel
221 346 bcoltin
        // set baud rate, etc. correctly
222
        struct termios options;
223 309 emarinel
224 346 bcoltin
        tcgetattr(xbee_stream, &options);
225
        cfsetispeed(&options, B9600);
226
        cfsetospeed(&options, B9600);
227
        options.c_iflag &= ~ICRNL;
228
        options.c_oflag &= ~OCRNL;
229
        options.c_cflag |= (CLOCAL | CREAD);
230
        options.c_cflag &= ~PARENB;
231
        options.c_cflag &= ~CSTOPB;
232
        options.c_cflag &= ~CSIZE;
233
        options.c_cflag |= CS8;
234
        options.c_lflag &= ~ICANON;
235
        options.c_cc[VMIN] = 1;
236
        options.c_cc[VTIME] = 50;
237 309 emarinel
238 346 bcoltin
        if (tcsetattr(xbee_stream, TCSANOW, &options))
239
        {
240
                fprintf(stderr, "Error setting attributes.\n");
241
                return -1;
242
        }
243 309 emarinel
244 346 bcoltin
        //lockf(xbee_stream, F_LOCK, 0);
245 409 emarinel
246
        xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t));
247 346 bcoltin
        if (xbee_listen_thread == NULL)
248
        {
249
                fprintf(stderr, "%s: Malloc failed.\n", __FUNCTION__);
250
                return -1;
251
        }
252 409 emarinel
253
        int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL);
254 346 bcoltin
        if (ret)
255
        {
256
                fprintf(stderr, "Failed to create listener thread.\r\n");
257
                return -1;
258
        }
259 409 emarinel
260 346 bcoltin
        #endif
261
        xbee_enter_command_mode();
262
        xbee_enter_api_mode();
263
        xbee_exit_command_mode();
264
        xbee_send_read_at_command("MY");
265 409 emarinel
266 346 bcoltin
        //wait to return until the address is set
267
        while (xbee_address == 0) xbee_get_packet(NULL);
268 309 emarinel
269 346 bcoltin
270
        return 0;
271 17 bcoltin
}
272
273
/**
274
 * Call when finished using the XBee library. This releases
275
 * all sued resources.
276
 **/
277 346 bcoltin
void xbee_terminate()
278
{
279
        #ifndef ROBOT
280
        pthread_cancel(*xbee_listen_thread);
281
        free(xbee_listen_thread);
282
        lockf(xbee_stream, F_ULOCK, 0);
283
        close(xbee_stream);
284
        #endif
285 17 bcoltin
}
286
287
/**
288
 * Send a buffer buf of size bytes to the XBee.
289 409 emarinel
 *
290 17 bcoltin
 * @param buf the buffer of data to send
291
 * @param size the number of bytes to send
292
 **/
293 397 emarinel
int xbee_send(char* buf, int size)
294 346 bcoltin
{
295
        #ifdef ROBOT
296
        int i;
297
        for (i = 0; i < size; i++)
298
                xbee_putc(buf[i]);
299
        #else
300
        int ret = write(xbee_stream, buf, size);
301
        //success
302
        if (ret == size)
303 397 emarinel
                return 0;
304 346 bcoltin
        if (ret == -1)
305
        {
306
                //interrupted by system signal, probably timer interrupt.
307
                //just try again
308
                if (errno == 4)
309
                {
310 397 emarinel
                        return xbee_send(buf, size);
311 346 bcoltin
                }
312
                printf("Failed to write to xbee, error %i.\r\n", errno);
313 397 emarinel
                return -1;
314 346 bcoltin
        }
315 17 bcoltin
316 346 bcoltin
        //write was interrupted after writing ret bytes
317
        xbee_send(buf + ret, size - ret);
318
        #endif
319 397 emarinel
320
        return 0;
321 17 bcoltin
}
322
323
/**
324
 * Sends a string to the XBee.
325
 *
326
 * @param c the string to send to the XBEE
327
 **/
328 346 bcoltin
void xbee_send_string(char* c)
329
{
330
        xbee_send(c, strlen(c));
331 17 bcoltin
}
332
333
#ifndef ROBOT
334 346 bcoltin
void xbee_read(char* buf, int size)
335
{
336
        if (read(xbee_stream, buf, size) == -1)
337
                printf("Failed to read from xbee.\r\n");
338 17 bcoltin
}
339
#endif
340
341
/**
342
 * Enter into command mode.
343
 **/
344 409 emarinel
static void xbee_enter_command_mode()
345 346 bcoltin
{
346
        xbee_send_string("+++");
347
        xbee_wait_for_ok();
348 17 bcoltin
}
349
350
/**
351
 * Exit from command mode.
352
 **/
353 409 emarinel
static void xbee_exit_command_mode()
354 346 bcoltin
{
355
        xbee_send_string("ATCN\r");
356
        xbee_wait_for_ok();
357 17 bcoltin
}
358
359
/**
360
 * Enter API mode.
361
 **/
362 409 emarinel
static void xbee_enter_api_mode()
363 346 bcoltin
{
364
        xbee_send_string("ATAP 1\r");
365
        xbee_wait_for_ok();
366 17 bcoltin
}
367
368
/**
369 309 emarinel
 * Exit API mode. (warning - does not check for response)
370
 **/
371 409 emarinel
static void xbee_exit_api_mode()
372 346 bcoltin
{
373
        xbee_send_string("ATAP 0\r");
374 309 emarinel
}
375
376
/**
377 17 bcoltin
 * Wait until the string "OK\r" is received from the XBee.
378
 **/
379 409 emarinel
static void xbee_wait_for_ok()
380 346 bcoltin
{
381
        xbee_wait_for_string("OK\r", 3);
382 17 bcoltin
}
383
384
/**
385
 * Delay until the specified string is received from
386
 * the XBee. Discards all other XBee data.
387
 *
388
 * @param s the string to receive
389
 * @param len the length of the string
390
 **/
391 409 emarinel
static void xbee_wait_for_string(char* s, int len)
392 346 bcoltin
{
393 409 emarinel
  char* curr = s;
394
  while (curr - s < len) {
395
    // check if buffer is empty
396
    if (buffer_last != buffer_first) {
397
      char c = arrival_buf[buffer_first++];
398
      if (buffer_first == XBEE_BUFFER_SIZE) {
399
        buffer_first = 0;
400
      }
401
402
      if (c == *curr) {
403
        curr++;
404
      } else {
405
        curr = s;
406
      }
407
    }
408
409
    usleep(1000);
410
  }
411 17 bcoltin
}
412
413
/**
414
 * Verifies that the packets checksum is correct.
415
 * (If the checksum is correct, the sum of the bytes
416
 * is 0xFF.)
417
 *
418
 * @param packet the packet received. This includes the first
419
 * three bytes, which are header information from the XBee.
420
 *
421
 * @param len The length of the packet received from the XBee
422
 *
423
 * @return 0 if the checksum is incorrect, nonzero
424
 * otherwise
425
 **/
426 346 bcoltin
int xbee_verify_checksum(char* packet, int len)
427
{
428
        unsigned char sum = 0;
429
        int i;
430
        for (i = 3; i < len; i++)
431
                sum += (unsigned char)packet[i];
432
        return sum == 0xFF;
433 17 bcoltin
}
434
435
/**
436
 * Returns the checksum of the given packet.
437
 *
438
 * @param buf the data for the packet to send
439
 * @param len the length of the packet in bytes
440
 *
441
 * @return the checksum of the packet, which will
442
 * become the last byte sent in the packet
443
 **/
444 346 bcoltin
char xbee_compute_checksum(char* buf, int len)
445
{
446
        int i;
447
        unsigned char sum = 0;
448
        for (i = 0; i < len; i++)
449
                sum += (unsigned char)buf[i];
450
        return 0xFF - sum;
451 17 bcoltin
}
452
453
/**
454
 * Adds header information and checksum to the given
455
 * packet and sends it. Header information includes
456
 * XBEE_FRAME_START and the packet length, as two bytes.
457
 *
458
 * @param buf the packet data
459
 * @param len the size in bytes of the packet data
460
 *
461
 **/
462 346 bcoltin
void xbee_send_frame(char* buf, int len)
463
{
464
        char prefix[3];
465
        prefix[0] = XBEE_FRAME_START;
466
        prefix[1] = (len & 0xFF00) >> 8;
467
        prefix[2] = len & 0xFF;
468
        char checksum = xbee_compute_checksum(buf, len);
469
        xbee_send(prefix, 3);
470
        xbee_send(buf, len);
471
        xbee_send(&checksum, 1);
472 17 bcoltin
}
473
474
/**
475
 * Sends an AT command to read a parameter.
476
 *
477
 * @param command the AT command to send. For exmaple,
478
 * use ID to read the PAN ID and MY to return the XBee ID.
479
 * See the XBee reference guide for a complete listing.
480
 **/
481 346 bcoltin
void xbee_send_read_at_command(char* command)
482
{
483
        xbee_send_modify_at_command(command, NULL);
484 17 bcoltin
}
485
486
/**
487
 * Sends the given AT command.
488
 *
489
 * @param command the AT command to send (e.g., MY, ID)
490
 * @param value the value to pass as a parameter
491
 * (or NULL if there is no parameter)
492
 **/
493 346 bcoltin
void xbee_send_modify_at_command(char* command, char* value)
494
{
495
        char buf[16];
496
        int i;
497 409 emarinel
498 346 bcoltin
        buf[0] = XBEE_FRAME_AT_COMMAND;
499
        buf[1] = 1;
500
        buf[2] = command[0];
501
        buf[3] = command[1];
502
        int valueLen = 0;
503
        if (value != NULL)
504
        {
505
                valueLen = strlen(value);
506
                if (valueLen > 8)
507
                {
508
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
509
                        return;
510
                }
511
                for (i = 0; i < valueLen; i++)
512
                        buf[4 + i] = value[i];
513
        }
514
        xbee_send_frame(buf, 4 + valueLen);
515 17 bcoltin
}
516
517
/**
518
 * Send the specified packet.
519 409 emarinel
 *
520 17 bcoltin
 * @param packet the packet data to send
521
 * @param len the number of bytes in the packet
522 409 emarinel
 *
523 17 bcoltin
 * @param dest the ID of the XBee to send the packet to,
524
 * or XBEE_BROADCAST to send the message to all robots
525
 * in the PAN.
526 409 emarinel
 *
527 17 bcoltin
 * @param options a combination of the flags
528 409 emarinel
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
529 17 bcoltin
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
530
 *
531
 * @param frame the frame number to associate this packet
532
 * with. This will be used to identify the response when
533
 * the XBee alerts us as to whether or not our message
534
 * was received.
535
 **/
536 397 emarinel
int xbee_send_packet(char* packet, int len, int dest, char options, char frame)
537 346 bcoltin
{
538
        char buf[5];
539
        char prefix[3];
540
        int i;
541
        unsigned char checksum = 0;
542 17 bcoltin
543 346 bcoltin
        if (len > 100)
544
        {
545
                WL_DEBUG_PRINT("Packet is too large.\r\n");
546 397 emarinel
                return -1;
547 346 bcoltin
        }
548 17 bcoltin
549 346 bcoltin
        //data for sending request
550
        buf[0] = XBEE_FRAME_TX_REQUEST_16;
551
        buf[1] = frame;
552
        buf[2] = (dest >> 8) & 0xFF;
553
        buf[3] = dest & 0xFF;
554
        buf[4] = options;
555 17 bcoltin
556 346 bcoltin
        //packet prefix, do this here so we don't need an extra buffer
557
        prefix[0] = XBEE_FRAME_START;
558
        prefix[1] = ((5 + len) & 0xFF00) >> 8;
559
        prefix[2] = (5 + len) & 0xFF;
560 17 bcoltin
561 346 bcoltin
        for (i = 0; i < 5; i++)
562
                checksum += (unsigned char)buf[i];
563
        for (i = 0; i < len; i++)
564
                checksum += (unsigned char)packet[i];
565
        checksum = 0xFF - checksum;
566 397 emarinel
567
        if (xbee_send(prefix, 3) != 0) {
568
                return -1;
569
        }
570
571
        if (xbee_send(buf, 5) != 0) {
572
                return -1;
573
        }
574
575
        if (xbee_send(packet, len) != 0) {
576
                return -1;
577
        }
578
579
        if (xbee_send((char*)&checksum, 1) != 0) {
580
                return -1;
581
        }
582
583
        return 0;
584 17 bcoltin
}
585
586
/**
587
 * Reads a packet received from the XBee. This function
588
 * is non-blocking. The resulting packet is stored in dest.
589
 * Only returns transmission response packets and
590
 * received packets. The returned packet does not include
591
 * header information or the checksum. This method also
592
 * handles special packets dealt with by the XBee library,
593
 * and so should be called frequently while the XBee is in
594
 * use.<br><br>
595
 *
596
 * The first byte of the packet will be either
597
 * XBEE_TX_STATUS or XBEE_RX to indicated
598 409 emarinel
 * a response to a sent message or a received message,
599 17 bcoltin
 * respectively.<br><br>
600
 *
601
 * For a status response packet:<br>
602
 * The first byte will be XBEE_TX_STATUS.<br>
603
 * The second byte will be the frame number.<br>
604
 * The third byte will be the result. 0 indicates success,
605 409 emarinel
 * and nonzero indicates that an error ocurred in
606 17 bcoltin
 * transmitting the packet.<br><br>
607
 *
608
 * For a received packet:<br>
609
 * The first byte will be XBEE_RX.<br>
610
 * The second and third bytes will be the 16-bit
611
 * address of the packet's sender.<br>
612
 * The fourth byte is the signal strength.<br>
613
 * The fifth byte is 1 if the packet were sent to
614
 * a specific address, and 2 if it is a broadcast packet.<br><br>
615 409 emarinel
 *
616 17 bcoltin
 * @param dest set to the packet data
617
 * @return the length of the packet, or -1 if no packet
618
 * is available
619
 **/
620 346 bcoltin
int xbee_get_packet(unsigned char* dest)
621
{
622
        //start reading a packet with XBEE_FRAME_START
623
        if (currentBufPos == 0)
624
        {
625
                do
626
                {
627
                        if (buffer_first == XBEE_BUFFER_SIZE)
628
                                buffer_first = 0;
629
                        // check if buffer is empty
630
                        if (buffer_first == buffer_last)
631
                                return -1;
632
                }
633
                while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
634
                if (buffer_first == XBEE_BUFFER_SIZE)
635
                        buffer_first = 0;
636
                xbee_buf[0] = XBEE_FRAME_START;
637
                currentBufPos++;
638
        }
639 17 bcoltin
640 346 bcoltin
        int len = -1;
641
        if (currentBufPos >= 3)
642
                len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
643 409 emarinel
644 346 bcoltin
        while (len == -1 //packet length has not been read yet
645
                        || currentBufPos < len + 4)
646
        {
647
                if (currentBufPos == 3)
648
                {
649
                        len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
650
                        if (len > 120)
651
                        {
652
                                WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
653
                                currentBufPos = 0;
654
                                return -1;
655
                        }
656
                }
657
                // check if buffer is empty
658
                if (buffer_first == buffer_last)
659
                        return -1;
660
                xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
661
                if (buffer_first == XBEE_BUFFER_SIZE)
662
                        buffer_first = 0;
663
        }
664 409 emarinel
665 17 bcoltin
        currentBufPos = 0;
666 409 emarinel
667 346 bcoltin
        if (!xbee_verify_checksum(xbee_buf, len + 4))
668
        {
669
                WL_DEBUG_PRINT("XBee checksum failed.\r\n");
670
                return -1;
671
        }
672 17 bcoltin
673 346 bcoltin
        //we will take care of the packet
674
        if (xbee_handle_packet(xbee_buf + 3, len))
675
                return -1;
676 409 emarinel
677 346 bcoltin
        if (dest == NULL)
678
                return -1;
679 409 emarinel
680 346 bcoltin
        int i;
681
        for (i = 3; i < len + 3; i++)
682
                dest[i - 3] = xbee_buf[i];
683
        return len;
684 17 bcoltin
}
685
686
/**
687
 * Handles modem status packets.
688
 *
689
 * @param status the type of status packet received.
690
 **/
691 346 bcoltin
void xbee_handle_status(char status)
692
{
693
        switch (status)
694
        {
695
                case 0:
696
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
697
                        break;
698
                case 1:
699
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
700
                        break;
701
                case 2:
702
                        WL_DEBUG_PRINT("Associated.\r\n");
703
                        break;
704
                case 3:
705
                        WL_DEBUG_PRINT("Disassociated.\r\n");
706
                        break;
707
                case 4:
708
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
709
                        break;
710
                case 5:
711
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
712
                        break;
713
                case 6:
714
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
715
                        break;
716
        }
717 17 bcoltin
}
718
719
/**
720
 * Handles AT command response packets.
721
 * @param command the two character AT command, e.g. MY or ID
722
 * @param result 0 for success, 1 for an error
723
 * @param extra the hex value of the requested register
724
 * @param extraLen the length in bytes of extra
725
 **/
726
void xbee_handle_at_command_response(char* command, char result,
727 346 bcoltin
        char* extra, int extraLen)
728
{
729
        if (result == 1)
730
        {
731
                WL_DEBUG_PRINT("Error with AT");
732
                WL_DEBUG_PRINT(command);
733
                WL_DEBUG_PRINT(" packet.\r\n");
734
        }
735
        WL_DEBUG_PRINT("AT");
736
        WL_DEBUG_PRINT(command);
737
        WL_DEBUG_PRINT(" command was successful.\r\n");
738 409 emarinel
739 346 bcoltin
        if (command[0] == 'I' && command[1] == 'D')
740
        {
741
                xbee_panID = xbee_pending_panID;
742
                WL_DEBUG_PRINT("PAN ID set to ");
743
                WL_DEBUG_PRINT_INT(xbee_panID);
744
                WL_DEBUG_PRINT(".\r\n");
745
                return;
746
        }
747 60 bcoltin
748 346 bcoltin
        if (command[0] == 'C' && command[1] == 'H')
749
        {
750
                xbee_channel = xbee_pending_channel;
751
                WL_DEBUG_PRINT("Channel set to ");
752
                WL_DEBUG_PRINT_INT(xbee_channel);
753
                WL_DEBUG_PRINT(".\r\n");
754
                return;
755
        }
756 409 emarinel
757 346 bcoltin
        if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
758
        {
759
                xbee_address = 0;
760
                int i;
761
                for (i = 0; i < extraLen; i++)
762
                        xbee_address = (xbee_address << 8) + extra[i];
763 17 bcoltin
764 346 bcoltin
                WL_DEBUG_PRINT("XBee address is ");
765
                WL_DEBUG_PRINT_INT(xbee_address);
766
                WL_DEBUG_PRINT(".\r\n");
767 17 bcoltin
768 346 bcoltin
                if (xbee_address == 0)
769
                {
770
                        WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
771
                        exit(0);
772
                }
773
        }
774 17 bcoltin
}
775
776
/**
777
 * Attempts to handle the packet if it is dealt with
778
 * by the library.
779
 * We will handle the following packet types:
780
 *    Modem Status
781
 *    AT Command Response
782
 *
783
 * @param packet the packet to handle
784
 * @param len the length of the packet
785 409 emarinel
 *
786 17 bcoltin
 * @return 1 if we have handled the packet, 0 otherwise
787
 */
788 346 bcoltin
int xbee_handle_packet(char* packet, int len)
789
{
790
        char command[3] = {1, 2, 3};
791
        if (len <= 0) //this should not happend
792
        {
793
                WL_DEBUG_PRINT("Non-positive packet length.\r\n");
794
                return 0;
795
        }
796 409 emarinel
797 346 bcoltin
        switch ((unsigned char)packet[0]) //packet type
798
        {
799
                case XBEE_FRAME_STATUS:
800
                        xbee_handle_status(packet[1]);
801
                        return 1;
802
                case XBEE_FRAME_AT_COMMAND_RESPONSE:
803
                        command[0] = packet[2];
804
                        command[1] = packet[3];
805
                        command[2] = 0;
806
                        xbee_handle_at_command_response(command,
807
                                packet[4], packet + 5, len - 5);
808
                        return 1;
809
        }
810
        return 0;
811 17 bcoltin
}
812
813
/**
814
 * Sets the personal area network id.
815
 *
816
 * @param id the new personal area network (PAN) id
817
 **/
818 346 bcoltin
void xbee_set_pan_id(int id)
819
{
820
        char s[3];
821
        s[0] = (id >> 8) & 0xFF;
822
        s[1] = id & 0xFF;
823
        s[2] = 0;
824
        xbee_pending_panID = id;
825
        xbee_send_modify_at_command("ID", s);
826 17 bcoltin
}
827
828
/**
829
 * Get the PAN ID for the XBee.
830 409 emarinel
 *
831 17 bcoltin
 * @return the personal area network id, or
832
 * XBEE_PAN_DEFAULT if it has not yet been set.
833
 **/
834 346 bcoltin
unsigned int xbee_get_pan_id()
835
{
836
        return xbee_panID;
837 17 bcoltin
}
838
839
/**
840 60 bcoltin
 * Set the channel the XBee is using.
841
 *
842 409 emarinel
 * @param channel the channel the XBee will not use,
843 60 bcoltin
 * between 0x0B and 0x1A
844
 *
845
 * @see xbee_get_channel
846
 **/
847 346 bcoltin
void xbee_set_channel(int channel)
848
{
849
        if (channel < 0x0B || channel > 0x1A)
850
        {
851
                WL_DEBUG_PRINT("Channel out of range.\r\n");
852
                return;
853
        }
854
        char s[3];
855
        s[0] = channel & 0xFF;
856
        s[1] = 0;
857
        xbee_pending_channel = channel;
858
        xbee_send_modify_at_command("CH", s);
859 60 bcoltin
}
860
861
/**
862
 * Returns the channel which the XBee is currently using.
863
 *
864
 * @return the channel the XBee is using
865
 *
866
 * @see xbee_set_channel
867
 **/
868 346 bcoltin
int xbee_get_channel(void)
869
{
870
        return xbee_channel;
871 60 bcoltin
}
872
873
/**
874 17 bcoltin
 * Get the 16-bit address of the XBee.
875
 * This is used to specify who to send messages to
876
 * and who messages are from.
877
 *
878
 * @return the 16-bit address of the XBee.
879
 **/
880 346 bcoltin
unsigned int xbee_get_address()
881
{
882
        return xbee_address;
883 17 bcoltin
}
884
885 203 justin
#ifndef ROBOT
886 346 bcoltin
void xbee_set_com_port(char* port)
887
{
888
        xbee_com_port = port;
889 203 justin
}
890
#endif