Project

General

Profile

Statistics
| Revision:

root / branches / wl_dev / code / projects / libwireless / lib / xbee.c @ 735

History | View | Annotate | Download (19.9 KB)

1
/**
2
 * Copyright (c) 2007 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 Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34

    
35
#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
#include <termios.h>
45

    
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
static int xbee_send(char* buf, int size);
73
static int xbee_send_string(char* c);
74

    
75
#ifndef ROBOT
76
static int xbee_read(char* buf, int size);
77
#endif
78

    
79
/*Command Mode Functions
80
 * Called during initialization.
81
 */
82
static int xbee_enter_command_mode(void);
83
static int xbee_exit_command_mode(void);
84
static int xbee_enter_api_mode(void);
85
static int 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

    
89
/*API Mode Functions*/
90

    
91
static int xbee_handle_packet(char* packet, int len);
92
static void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen);
93
static void xbee_handle_status(char status);
94
static int xbee_verify_checksum(char* packet, int len);
95
static char xbee_compute_checksum(char* packet, int len);
96
static int xbee_send_frame(char* buf, int len);
97
static int xbee_send_read_at_command(char* command);
98
static int xbee_send_modify_at_command(char* command, char* value);
99

    
100
/*Global Variables*/
101

    
102
#ifndef ROBOT
103
static char* xbee_com_port = XBEE_PORT_DEFAULT;
104
static int xbee_stream;
105
static pthread_t* xbee_listen_thread;
106
#endif
107

    
108
// TODO: is this a good size?
109
#define XBEE_BUFFER_SIZE        128
110
#define PACKET_BUFFER_SIZE        108
111
// a buffer for data received from the XBee
112
char arrival_buf[XBEE_BUFFER_SIZE];
113
// location of last unread byte in buffer
114
volatile int buffer_last = 0;
115
// first unread byte in buffer
116
volatile int buffer_first = 0;
117

    
118

    
119
//used to store packets as they are read
120
static char xbee_buf[PACKET_BUFFER_SIZE];
121
static int currentBufPos = 0;
122

    
123
//XBee status
124
static unsigned int xbee_panID = XBEE_PAN_DEFAULT;
125
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
126
static int xbee_channel = XBEE_CHANNEL_DEFAULT;
127
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
128
static unsigned int xbee_address = 0;
129

    
130
/*Function Implementations*/
131

    
132
#ifdef ROBOT
133

    
134
/**
135
 * Interrupt for the robot. Adds bytes received from the xbee
136
 * to the buffer.
137
 **/
138
#ifndef FIREFLY
139
ISR(USART1_RX_vect)
140
{
141
        char c = UDR1;
142
        arrival_buf[buffer_last] = c;
143
        int t = buffer_last + 1;
144
        if (t == XBEE_BUFFER_SIZE)
145
                t = 0;
146
        if (t == buffer_first)
147
        {
148
                WL_DEBUG_PRINT("\nOut of space in buffer.\n");
149
        }
150
        buffer_last = t;
151
}
152
#else
153
SIGNAL(SIG_USART0_RECV)
154
{
155
        char c = UDR0;
156
        arrival_buf[buffer_last] = c;
157
        int t = buffer_last + 1;
158
        if (t == XBEE_BUFFER_SIZE)
159
                t = 0;
160
        if (t == buffer_first)
161
        {
162
                WL_DEBUG_PRINT("Out of space in buffer.\n");
163
        }
164
        buffer_last = t;
165
}
166
#endif
167

    
168
#else
169

    
170
// Computer code
171

    
172
/**
173
 * Thread that listens to the xbee.
174
 **/
175
static void* listen_to_xbee(void* x)
176
{
177
        char c;
178
        while (1)
179
        {
180
                if (xbee_read(&c, 1) != 0) {
181
                        WL_DEBUG_PRINT("xbee_read failed.\n");
182
                        return NULL;
183
                }
184

    
185
                arrival_buf[buffer_last] = c;
186
                int t = buffer_last + 1;
187
                if (t == XBEE_BUFFER_SIZE)
188
                        t = 0;
189
                if (t == buffer_first)
190
                {
191
                        WL_DEBUG_PRINT("Out of space in buffer.\n");
192
                }
193
                buffer_last = t;
194

    
195
                usleep(1000);
196
        }
197

    
198
        return NULL;
199
}
200

    
201
#endif
202

    
203
/**
204
 * Initializes the XBee library so that other functions may be used.
205
 **/
206
int xbee_lib_init()
207
{
208
        #ifdef ROBOT
209

    
210
        //enable the receiving interrupt
211
#ifdef FIREFLY
212
        UCSR0B |= _BV(RXCIE) | _BV(RXEN);
213
#else
214
        UCSR1B |= _BV(RXCIE);
215
#endif
216
        sei();
217
#else
218
        printf("Connecting to port %s.\n", xbee_com_port);
219
        xbee_stream = open(xbee_com_port, O_RDWR);
220
        if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/)
221
        {
222
                printf("Failed to open connection to XBee on port %s\r\n", xbee_com_port);
223
                return -1;
224
        }
225

    
226
        // set baud rate, etc. correctly
227
        struct termios options;
228

    
229
        tcgetattr(xbee_stream, &options);
230
        cfsetispeed(&options, B9600);
231
        cfsetospeed(&options, B9600);
232
        options.c_iflag &= ~ICRNL;
233
        options.c_oflag &= ~OCRNL;
234
        options.c_cflag |= (CLOCAL | CREAD);
235
        options.c_cflag &= ~PARENB;
236
        options.c_cflag &= ~CSTOPB;
237
        options.c_cflag &= ~CSIZE;
238
        options.c_cflag |= CS8;
239
        options.c_lflag &= ~ICANON;
240
        options.c_cc[VMIN] = 1;
241
        options.c_cc[VTIME] = 50;
242

    
243
        if (tcsetattr(xbee_stream, TCSANOW, &options))
244
        {
245
                fprintf(stderr, "Error setting attributes.\n");
246
                return -1;
247
        }
248

    
249
        //lockf(xbee_stream, F_LOCK, 0);
250

    
251
        xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t));
252
        if (xbee_listen_thread == NULL)
253
        {
254
                fprintf(stderr, "%s: Malloc failed.\n", __FUNCTION__);
255
                return -1;
256
        }
257

    
258
        int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL);
259
        if (ret)
260
        {
261
                fprintf(stderr, "Failed to create listener thread.\r\n");
262
                return -1;
263
        }
264
#endif
265

    
266
        if (xbee_enter_command_mode() != 0) {
267
                return -1;
268
        }
269

    
270
        if (xbee_enter_api_mode() != 0) {
271
                return -1;
272
        }
273

    
274
        if (xbee_exit_command_mode() != 0) {
275
                return -1;
276
        }
277

    
278
        if (xbee_send_read_at_command("MY")) {
279
                return -1;
280
        }
281

    
282
        //wait to return until the address is set
283
        while (xbee_address == 0) xbee_get_packet(NULL);
284

    
285
        return 0;
286
}
287

    
288
/**
289
 * Call when finished using the XBee library. This releases
290
 * all sued resources.
291
 **/
292
void xbee_terminate()
293
{
294
        #ifndef ROBOT
295
        pthread_cancel(*xbee_listen_thread);
296
        free(xbee_listen_thread);
297
        lockf(xbee_stream, F_ULOCK, 0);
298
        close(xbee_stream);
299
        #endif
300
}
301

    
302
/**
303
 * Send a buffer buf of size bytes to the XBee.
304
 *
305
 * @param buf the buffer of data to send
306
 * @param size the number of bytes to send
307
 **/
308
static int xbee_send(char* buf, int size)
309
{
310
#ifdef ROBOT
311
        int i;
312
        for (i = 0; i < size; i++) {
313
                xbee_putc(buf[i]);
314
        }
315

    
316
        return 0;
317

    
318
#else
319

    
320
        int ret = write(xbee_stream, buf, size);
321
        //success
322
        if (ret == size)
323
                return 0;
324
        if (ret == -1)
325
        {
326
                //interrupted by system signal, probably timer interrupt.
327
                //just try again
328
                if (errno == 4)
329
                {
330
                        return xbee_send(buf, size);
331
                }
332
                printf("Failed to write to xbee, error %i.\r\n", errno);
333
                return -1;
334
        }
335

    
336
        //write was interrupted after writing ret bytes
337
        return xbee_send(buf + ret, size - ret);
338
#endif
339
}
340

    
341
/**
342
 * Sends a string to the XBee.
343
 *
344
 * @param c the string to send to the XBEE
345
 **/
346
static int xbee_send_string(char* c)
347
{
348
        return xbee_send(c, strlen(c));
349
}
350

    
351
#ifndef ROBOT
352
static int xbee_read(char* buf, int size)
353
{
354
        if (read(xbee_stream, buf, size) == -1) {
355
                printf("Failed to read from xbee.\r\n");
356
                return -1;
357
        }
358

    
359
        return 0;
360
}
361
#endif
362

    
363
/**
364
 * Enter into command mode.
365
 **/
366
static int xbee_enter_command_mode()
367
{
368
        if (xbee_send_string("+++") != 0) {
369
                return -1;
370
        }
371

    
372
        xbee_wait_for_ok();
373

    
374
        return 0;
375
}
376

    
377
/**
378
 * Exit from command mode.
379
 **/
380
static int xbee_exit_command_mode()
381
{
382
        if (xbee_send_string("ATCN\r") != 0) {
383
                return -1;
384
        }
385

    
386
        xbee_wait_for_ok();
387

    
388
        return 0;
389
}
390

    
391
/**
392
 * Enter API mode.
393
 **/
394
static int xbee_enter_api_mode()
395
{
396
        if (xbee_send_string("ATAP 1\r") != 0) {
397
                return -1;
398
        }
399
        xbee_wait_for_ok();
400

    
401
        return 0;
402
}
403

    
404
/**
405
 * Wait until the string "OK\r" is received from the XBee.
406
 **/
407
static void xbee_wait_for_ok()
408
{
409
        xbee_wait_for_string("OK\r", 3);
410
}
411

    
412
/**
413
 * Delay until the specified string is received from
414
 * the XBee. Discards all other XBee data.
415
 *
416
 * @param s the string to receive
417
 * @param len the length of the string
418
 **/
419
static void xbee_wait_for_string(char* s, int len)
420
{
421
        char* curr = s;
422
        while (curr - s < len) {
423
                // check if buffer is empty
424
                if (buffer_last != buffer_first) {
425
                        char c = arrival_buf[buffer_first++];
426
                        if (buffer_first == XBEE_BUFFER_SIZE) {
427
                                buffer_first = 0;
428
                        }
429

    
430
                        if (c == *curr) {
431
                                curr++;
432
                        } else {
433
                                curr = s;
434
                        }
435
                }
436

    
437
#ifndef ROBOT
438
                usleep(1000);
439
#endif
440
        }
441
}
442

    
443
/**
444
 * Verifies that the packets checksum is correct.
445
 * (If the checksum is correct, the sum of the bytes
446
 * is 0xFF.)
447
 *
448
 * @param packet the packet received. This includes the first
449
 * three bytes, which are header information from the XBee.
450
 *
451
 * @param len The length of the packet received from the XBee
452
 *
453
 * @return 0 if the checksum is incorrect, nonzero
454
 * otherwise
455
 **/
456
int xbee_verify_checksum(char* packet, int len)
457
{
458
        unsigned char sum = 0;
459
        int i;
460
        for (i = 3; i < len; i++)
461
                sum += (unsigned char)packet[i];
462
        return sum == 0xFF;
463
}
464

    
465
/**
466
 * Returns the checksum of the given packet.
467
 *
468
 * @param buf the data for the packet to send
469
 * @param len the length of the packet in bytes
470
 *
471
 * @return the checksum of the packet, which will
472
 * become the last byte sent in the packet
473
 **/
474
char xbee_compute_checksum(char* buf, int len)
475
{
476
        int i;
477
        unsigned char sum = 0;
478
        for (i = 0; i < len; i++)
479
                sum += (unsigned char)buf[i];
480
        return 0xFF - sum;
481
}
482

    
483
/**
484
 * Adds header information and checksum to the given
485
 * packet and sends it. Header information includes
486
 * XBEE_FRAME_START and the packet length, as two bytes.
487
 *
488
 * @param buf the packet data
489
 * @param len the size in bytes of the packet data
490
 *
491
 **/
492
static int xbee_send_frame(char* buf, int len)
493
{
494
        char prefix[3];
495
        prefix[0] = XBEE_FRAME_START;
496
        prefix[1] = (len & 0xFF00) >> 8;
497
        prefix[2] = len & 0xFF;
498
        char checksum = xbee_compute_checksum(buf, len);
499

    
500
        if (xbee_send(prefix, 3) != 0) {
501
                return -1;
502
        }
503
        
504
        if (xbee_send(buf, len) != 0) {
505
                return -1;
506
        }
507

    
508
        if (xbee_send(&checksum, 1) != 0) {
509
                return -1;
510
        }
511

    
512
        return 0;
513
}
514

    
515
/**
516
 * Sends an AT command to read a parameter.
517
 *
518
 * @param command the AT command to send. For exmaple,
519
 * use ID to read the PAN ID and MY to return the XBee ID.
520
 * See the XBee reference guide for a complete listing.
521
 **/
522
static int xbee_send_read_at_command(char* command)
523
{
524
        return xbee_send_modify_at_command(command, NULL);
525
}
526

    
527
/**
528
 * Sends the given AT command.
529
 *
530
 * @param command the AT command to send (e.g., MY, ID)
531
 * @param value the value to pass as a parameter
532
 * (or NULL if there is no parameter)
533
 **/
534
static int xbee_send_modify_at_command(char* command, char* value)
535
{
536
        char buf[16];
537
        int i;
538

    
539
        buf[0] = XBEE_FRAME_AT_COMMAND;
540
        buf[1] = 1;
541
        buf[2] = command[0];
542
        buf[3] = command[1];
543
        int valueLen = 0;
544
        if (value != NULL)
545
        {
546
                valueLen = strlen(value);
547
                if (valueLen > 8)
548
                {
549
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
550
                        return -1;
551
                }
552

    
553
                for (i = 0; i < valueLen; i++) {
554
                        buf[4 + i] = value[i];
555
                }
556
        }
557

    
558
        return xbee_send_frame(buf, 4 + valueLen);
559
}
560

    
561
/**
562
 * Send the specified packet.
563
 *
564
 * @param packet the packet data to send
565
 * @param len the number of bytes in the packet
566
 *
567
 * @param dest the ID of the XBee to send the packet to,
568
 * or XBEE_BROADCAST to send the message to all robots
569
 * in the PAN.
570
 *
571
 * @param options a combination of the flags
572
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
573
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
574
 *
575
 * @param frame the frame number to associate this packet
576
 * with. This will be used to identify the response when
577
 * the XBee alerts us as to whether or not our message
578
 * was received.
579
 **/
580
int xbee_send_packet(char* packet, int len, int dest, char options, char frame)
581
{
582
        char buf[5];
583
        char prefix[3];
584
        int i;
585
        unsigned char checksum = 0;
586

    
587
        if (len > 100)
588
        {
589
                WL_DEBUG_PRINT("Packet is too large.\r\n");
590
                return -1;
591
        }
592

    
593
        //data for sending request
594
        buf[0] = XBEE_FRAME_TX_REQUEST_16;
595
        buf[1] = frame;
596
        buf[2] = (dest >> 8) & 0xFF;
597
        buf[3] = dest & 0xFF;
598
        buf[4] = options;
599

    
600
        //packet prefix, do this here so we don't need an extra buffer
601
        prefix[0] = XBEE_FRAME_START;
602
        prefix[1] = ((5 + len) & 0xFF00) >> 8;
603
        prefix[2] = (5 + len) & 0xFF;
604

    
605
        for (i = 0; i < 5; i++)
606
                checksum += (unsigned char)buf[i];
607
        for (i = 0; i < len; i++)
608
                checksum += (unsigned char)packet[i];
609
        checksum = 0xFF - checksum;
610

    
611
        if (xbee_send(prefix, 3) != 0) {
612
                return -1;
613
        }
614

    
615
        if (xbee_send(buf, 5) != 0) {
616
                return -1;
617
        }
618

    
619
        if (xbee_send(packet, len) != 0) {
620
                return -1;
621
        }
622

    
623
        if (xbee_send((char*)&checksum, 1) != 0) {
624
                return -1;
625
        }
626

    
627
        return 0;
628
}
629

    
630
/**
631
 * Reads a packet received from the XBee. This function
632
 * is non-blocking. The resulting packet is stored in dest.
633
 * Only returns transmission response packets and
634
 * received packets. The returned packet does not include
635
 * header information or the checksum. This method also
636
 * handles special packets dealt with by the XBee library,
637
 * and so should be called frequently while the XBee is in
638
 * use.<br><br>
639
 *
640
 * The first byte of the packet will be either
641
 * XBEE_TX_STATUS or XBEE_RX to indicated
642
 * a response to a sent message or a received message,
643
 * respectively.<br><br>
644
 *
645
 * For a status response packet:<br>
646
 * The first byte will be XBEE_TX_STATUS.<br>
647
 * The second byte will be the frame number.<br>
648
 * The third byte will be the result. 0 indicates success,
649
 * and nonzero indicates that an error ocurred in
650
 * transmitting the packet.<br><br>
651
 *
652
 * For a received packet:<br>
653
 * The first byte will be XBEE_RX.<br>
654
 * The second and third bytes will be the 16-bit
655
 * address of the packet's sender.<br>
656
 * The fourth byte is the signal strength.<br>
657
 * The fifth byte is 1 if the packet were sent to
658
 * a specific address, and 2 if it is a broadcast packet.<br><br>
659
 *
660
 * @param dest set to the packet data
661
 * @return the length of the packet, or -1 if no packet
662
 * is available
663
 **/
664
int xbee_get_packet(unsigned char* dest)
665
{
666
        //start reading a packet with XBEE_FRAME_START
667
        if (currentBufPos == 0)
668
        {
669
                do
670
                {
671
                        if (buffer_first == XBEE_BUFFER_SIZE)
672
                                buffer_first = 0;
673
                        // check if buffer is empty
674
                        if (buffer_first == buffer_last)
675
                                return -1;
676
                } while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
677

    
678
                if (buffer_first == XBEE_BUFFER_SIZE) {
679
                        buffer_first = 0;
680
                }
681
                xbee_buf[0] = XBEE_FRAME_START;
682
                currentBufPos++;
683
        }
684

    
685
        int len = -1;
686
        if (currentBufPos >= 3) {
687
                len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
688
        }
689

    
690
        while (len == -1 //packet length has not been read yet
691
                || currentBufPos < len + 4)
692
        {
693
                if (currentBufPos == 3)
694
                {
695
                        len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
696
                        if (len > 120)
697
                        {
698
                                WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
699
                                currentBufPos = 0;
700
                                return -1;
701
                        }
702
                }
703

    
704
                // check if buffer is empty
705
                if (buffer_first == buffer_last) {
706
                        return -1;
707
                }
708
                xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
709
                if (buffer_first == XBEE_BUFFER_SIZE) {
710
                        buffer_first = 0;
711
                }
712
        }
713

    
714
        currentBufPos = 0;
715

    
716
        if (!xbee_verify_checksum(xbee_buf, len + 4))
717
        {
718
                WL_DEBUG_PRINT("XBee checksum failed.\r\n");
719
                return -1;
720
        }
721

    
722
        //we will take care of the packet
723
        if (xbee_handle_packet(xbee_buf + 3, len)) {
724
                return -1;
725
        }
726

    
727
        if (dest == NULL) {
728
                return -1;
729
        }
730

    
731
        int i;
732
        for (i = 3; i < len + 3; i++) {
733
                dest[i - 3] = xbee_buf[i];
734
        }
735

    
736
        return len;
737
}
738

    
739
/**
740
 * Handles modem status packets.
741
 *
742
 * @param status the type of status packet received.
743
 **/
744
void xbee_handle_status(char status)
745
{
746
        switch (status)
747
        {
748
                case 0:
749
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
750
                        break;
751
                case 1:
752
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
753
                        break;
754
                case 2:
755
                        WL_DEBUG_PRINT("Associated.\r\n");
756
                        break;
757
                case 3:
758
                        WL_DEBUG_PRINT("Disassociated.\r\n");
759
                        break;
760
                case 4:
761
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
762
                        break;
763
                case 5:
764
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
765
                        break;
766
                case 6:
767
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
768
                        break;
769
        }
770
}
771

    
772
/**
773
 * Handles AT command response packets.
774
 * @param command the two character AT command, e.g. MY or ID
775
 * @param result 0 for success, 1 for an error
776
 * @param extra the hex value of the requested register
777
 * @param extraLen the length in bytes of extra
778
 **/
779
static void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen)
780
{
781
        if (result == 1)
782
        {
783
                WL_DEBUG_PRINT("Error with AT");
784
                WL_DEBUG_PRINT(command);
785
                WL_DEBUG_PRINT(" packet.\r\n");
786
        }
787
        WL_DEBUG_PRINT("AT");
788
        WL_DEBUG_PRINT(command);
789
        WL_DEBUG_PRINT(" command was successful.\r\n");
790

    
791
        if (command[0] == 'I' && command[1] == 'D')
792
        {
793
                xbee_panID = xbee_pending_panID;
794
                WL_DEBUG_PRINT("PAN ID set to ");
795
                WL_DEBUG_PRINT_INT(xbee_panID);
796
                WL_DEBUG_PRINT(".\r\n");
797
                return;
798
        }
799

    
800
        if (command[0] == 'C' && command[1] == 'H')
801
        {
802
                xbee_channel = xbee_pending_channel;
803
                WL_DEBUG_PRINT("Channel set to ");
804
                WL_DEBUG_PRINT_INT(xbee_channel);
805
                WL_DEBUG_PRINT(".\r\n");
806
                return;
807
        }
808

    
809
        if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
810
        {
811
//                                                        printf("reading xbee_address\n");
812
                
813
                xbee_address = 0;
814
                int i;
815
                for (i = 0; i < extraLen; i++) {
816
                        xbee_address = (xbee_address << 8) + extra[i];
817
                }
818
//                                                        printf("xbee address is: %d\n", xbee_address);
819

    
820
                WL_DEBUG_PRINT("XBee address is ");
821
                WL_DEBUG_PRINT_INT(xbee_address);
822
                WL_DEBUG_PRINT(".\r\n");
823

    
824
                if (xbee_address == 0)
825
                {
826
                        WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
827
                        exit(0);
828
                }
829
        }
830
}
831

    
832
/**
833
 * Attempts to handle the packet if it is dealt with
834
 * by the library.
835
 * We will handle the following packet types:
836
 *    Modem Status
837
 *    AT Command Response
838
 *
839
 * @param packet the packet to handle
840
 * @param len the length of the packet
841
 *
842
 * @return 1 if we have handled the packet, 0 otherwise
843
 */
844
static int xbee_handle_packet(char* packet, int len)
845
{
846
        char command[3] = {1, 2, 3};
847
        if (len <= 0) //this should not happend
848
        {
849
                WL_DEBUG_PRINT("Non-positive packet length.\r\n");
850
                return 0;
851
        }
852

    
853
        switch ((unsigned char)packet[0]) //packet type
854
        {
855
                case XBEE_FRAME_STATUS:
856
                        xbee_handle_status(packet[1]);
857
                        return 1;
858
                case XBEE_FRAME_AT_COMMAND_RESPONSE:
859
                        command[0] = packet[2];
860
                        command[1] = packet[3];
861
                        command[2] = 0;
862
                        xbee_handle_at_command_response(command, packet[4], packet + 5, len - 5);
863
                        return 1;
864
        }
865
        return 0;
866
}
867

    
868
/**
869
 * Sets the personal area network id.
870
 *
871
 * @param id the new personal area network (PAN) id
872
 **/
873
int xbee_set_pan_id(int id)
874
{
875
        char s[3];
876
        s[0] = (id >> 8) & 0xFF;
877
        s[1] = id & 0xFF;
878
        s[2] = 0;
879
        xbee_pending_panID = id;
880
        return xbee_send_modify_at_command("ID", s);
881
}
882

    
883
/**
884
 * Get the PAN ID for the XBee.
885
 *
886
 * @return the personal area network id, or
887
 * XBEE_PAN_DEFAULT if it has not yet been set.
888
 **/
889
unsigned int xbee_get_pan_id()
890
{
891
        return xbee_panID;
892
}
893

    
894
/**
895
 * Set the channel the XBee is using.
896
 *
897
 * @param channel the channel the XBee will not use,
898
 * between 0x0B and 0x1A
899
 *
900
 * @see xbee_get_channel
901
 **/
902
int xbee_set_channel(int channel)
903
{
904
        if (channel < 0x0B || channel > 0x1A)
905
        {
906
                WL_DEBUG_PRINT("Channel out of range.\r\n");
907
                return -1;
908
        }
909

    
910
        char s[3];
911
        s[0] = channel & 0xFF;
912
        s[1] = 0;
913
        xbee_pending_channel = channel;
914

    
915
        return xbee_send_modify_at_command("CH", s);
916
}
917

    
918
/**
919
 * Returns the channel which the XBee is currently using.
920
 *
921
 * @return the channel the XBee is using
922
 *
923
 * @see xbee_set_channel
924
 **/
925
int xbee_get_channel(void)
926
{
927
        return xbee_channel;
928
}
929

    
930
/**
931
 * Get the 16-bit address of the XBee.
932
 * This is used to specify who to send messages to
933
 * and who messages are from.
934
 *
935
 * @return the 16-bit address of the XBee.
936
 **/
937
unsigned int xbee_get_address()
938
{
939
        return xbee_address;
940
}
941

    
942
#ifndef ROBOT
943
void xbee_set_com_port(char* port)
944
{
945
        xbee_com_port = port;
946
}
947
#endif
948