Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (20.1 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        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

    
117

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

    
122
//XBee status
123
static unsigned int xbee_panID = XBEE_PAN_DEFAULT;
124
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
125
static int xbee_channel = XBEE_CHANNEL_DEFAULT;
126
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
127
static 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
 * to the buffer.
136
 **/
137
#ifndef FIREFLY
138
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
}
151
#else
152
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
}
165
#endif
166

    
167
#else
168

    
169
// Computer code
170

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

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

    
194
                usleep(1000);
195
        }
196

    
197
        return NULL;
198
}
199

    
200
#endif
201

    
202
/**
203
 * Initializes the XBee library so that other functions may be used.
204
 **/
205
int xbee_lib_init()
206
{
207
        arrival_buf[0] = 'A';
208
        arrival_buf[1] = 'A';
209
        arrival_buf[2] = 'A';
210
        #ifdef ROBOT
211

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

    
228
        // set baud rate, etc. correctly
229
        struct termios options;
230

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

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

    
251
        //lockf(xbee_stream, F_LOCK, 0);
252

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

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

    
268
        if (xbee_enter_command_mode() != 0) {
269
                return -1;
270
        }
271

    
272
        if (xbee_enter_api_mode() != 0) {
273
                return -1;
274
        }
275

    
276
        if (xbee_exit_command_mode() != 0) {
277
                return -1;
278
        }
279

    
280
        if (xbee_send_read_at_command("MY")) {
281
                return -1;
282
        }
283

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

    
287
        return 0;
288
}
289

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

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

    
318
        return 0;
319

    
320
#else
321

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

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

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

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

    
361
        return 0;
362
}
363
#endif
364

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

    
374
        xbee_wait_for_ok();
375

    
376
        return 0;
377
}
378

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

    
388
        xbee_wait_for_ok();
389

    
390
        return 0;
391
}
392

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

    
403
        return 0;
404
}
405

    
406
/**
407
 * Exit API mode. (warning - does not check for response)
408
 **/
409
static int xbee_exit_api_mode()
410
{
411
        return xbee_send_string("ATAP 0\r");
412
}
413

    
414
/**
415
 * Wait until the string "OK\r" is received from the XBee.
416
 **/
417
static void xbee_wait_for_ok()
418
{
419
        xbee_wait_for_string("OK\r", 3);
420
}
421

    
422
/**
423
 * Delay until the specified string is received from
424
 * the XBee. Discards all other XBee data.
425
 *
426
 * @param s the string to receive
427
 * @param len the length of the string
428
 **/
429
static void xbee_wait_for_string(char* s, int len)
430
{
431
        char* curr = s;
432
        while (curr - s < len) {
433
                // check if buffer is empty
434
                if (buffer_last != buffer_first) {
435
                        char c = arrival_buf[buffer_first++];
436
                        if (buffer_first == XBEE_BUFFER_SIZE) {
437
                                buffer_first = 0;
438
                        }
439

    
440
                        if (c == *curr) {
441
                                curr++;
442
                        } else {
443
                                curr = s;
444
                        }
445
                }
446

    
447
#ifndef ROBOT
448
                usleep(1000);
449
#endif
450
        }
451
}
452

    
453
/**
454
 * Verifies that the packets checksum is correct.
455
 * (If the checksum is correct, the sum of the bytes
456
 * is 0xFF.)
457
 *
458
 * @param packet the packet received. This includes the first
459
 * three bytes, which are header information from the XBee.
460
 *
461
 * @param len The length of the packet received from the XBee
462
 *
463
 * @return 0 if the checksum is incorrect, nonzero
464
 * otherwise
465
 **/
466
int xbee_verify_checksum(char* packet, int len)
467
{
468
        unsigned char sum = 0;
469
        int i;
470
        for (i = 3; i < len; i++)
471
                sum += (unsigned char)packet[i];
472
        return sum == 0xFF;
473
}
474

    
475
/**
476
 * Returns the checksum of the given packet.
477
 *
478
 * @param buf the data for the packet to send
479
 * @param len the length of the packet in bytes
480
 *
481
 * @return the checksum of the packet, which will
482
 * become the last byte sent in the packet
483
 **/
484
char xbee_compute_checksum(char* buf, int len)
485
{
486
        int i;
487
        unsigned char sum = 0;
488
        for (i = 0; i < len; i++)
489
                sum += (unsigned char)buf[i];
490
        return 0xFF - sum;
491
}
492

    
493
/**
494
 * Adds header information and checksum to the given
495
 * packet and sends it. Header information includes
496
 * XBEE_FRAME_START and the packet length, as two bytes.
497
 *
498
 * @param buf the packet data
499
 * @param len the size in bytes of the packet data
500
 *
501
 **/
502
static int xbee_send_frame(char* buf, int len)
503
{
504
        char prefix[3];
505
        prefix[0] = XBEE_FRAME_START;
506
        prefix[1] = (len & 0xFF00) >> 8;
507
        prefix[2] = len & 0xFF;
508
        char checksum = xbee_compute_checksum(buf, len);
509

    
510
        if (xbee_send(prefix, 3) != 0) {
511
                return -1;
512
        }
513
        
514
        if (xbee_send(buf, len) != 0) {
515
                return -1;
516
        }
517

    
518
        if (xbee_send(&checksum, 1) != 0) {
519
                return -1;
520
        }
521

    
522
        return 0;
523
}
524

    
525
/**
526
 * Sends an AT command to read a parameter.
527
 *
528
 * @param command the AT command to send. For exmaple,
529
 * use ID to read the PAN ID and MY to return the XBee ID.
530
 * See the XBee reference guide for a complete listing.
531
 **/
532
static int xbee_send_read_at_command(char* command)
533
{
534
        return xbee_send_modify_at_command(command, NULL);
535
}
536

    
537
/**
538
 * Sends the given AT command.
539
 *
540
 * @param command the AT command to send (e.g., MY, ID)
541
 * @param value the value to pass as a parameter
542
 * (or NULL if there is no parameter)
543
 **/
544
static int xbee_send_modify_at_command(char* command, char* value)
545
{
546
        char buf[16];
547
        int i;
548

    
549
        buf[0] = XBEE_FRAME_AT_COMMAND;
550
        buf[1] = 1;
551
        buf[2] = command[0];
552
        buf[3] = command[1];
553
        int valueLen = 0;
554
        if (value != NULL)
555
        {
556
                valueLen = strlen(value);
557
                if (valueLen > 8)
558
                {
559
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
560
                        return -1;
561
                }
562

    
563
                for (i = 0; i < valueLen; i++) {
564
                        buf[4 + i] = value[i];
565
                }
566
        }
567

    
568
        return xbee_send_frame(buf, 4 + valueLen);
569
}
570

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

    
597
        if (len > 100)
598
        {
599
                WL_DEBUG_PRINT("Packet is too large.\r\n");
600
                return -1;
601
        }
602

    
603
        //data for sending request
604
        buf[0] = XBEE_FRAME_TX_REQUEST_16;
605
        buf[1] = frame;
606
        buf[2] = (dest >> 8) & 0xFF;
607
        buf[3] = dest & 0xFF;
608
        buf[4] = options;
609

    
610
        //packet prefix, do this here so we don't need an extra buffer
611
        prefix[0] = XBEE_FRAME_START;
612
        prefix[1] = ((5 + len) & 0xFF00) >> 8;
613
        prefix[2] = (5 + len) & 0xFF;
614

    
615
        for (i = 0; i < 5; i++)
616
                checksum += (unsigned char)buf[i];
617
        for (i = 0; i < len; i++)
618
                checksum += (unsigned char)packet[i];
619
        checksum = 0xFF - checksum;
620

    
621
        if (xbee_send(prefix, 3) != 0) {
622
                return -1;
623
        }
624

    
625
        if (xbee_send(buf, 5) != 0) {
626
                return -1;
627
        }
628

    
629
        if (xbee_send(packet, len) != 0) {
630
                return -1;
631
        }
632

    
633
        if (xbee_send((char*)&checksum, 1) != 0) {
634
                return -1;
635
        }
636

    
637
        return 0;
638
}
639

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

    
688
                if (buffer_first == XBEE_BUFFER_SIZE) {
689
                        buffer_first = 0;
690
                }
691
                xbee_buf[0] = XBEE_FRAME_START;
692
                currentBufPos++;
693
        }
694

    
695
        int len = -1;
696
        if (currentBufPos >= 3) {
697
                len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
698
        }
699

    
700
        while (len == -1 //packet length has not been read yet
701
                || currentBufPos < len + 4)
702
        {
703
                if (currentBufPos == 3)
704
                {
705
                        len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
706
                        if (len > 120)
707
                        {
708
                                WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
709
                                currentBufPos = 0;
710
                                return -1;
711
                        }
712
                }
713

    
714
                // check if buffer is empty
715
                if (buffer_first == buffer_last) {
716
                        return -1;
717
                }
718
                xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
719
                if (buffer_first == XBEE_BUFFER_SIZE) {
720
                        buffer_first = 0;
721
                }
722
        }
723

    
724
        currentBufPos = 0;
725

    
726
        if (!xbee_verify_checksum(xbee_buf, len + 4))
727
        {
728
                WL_DEBUG_PRINT("XBee checksum failed.\r\n");
729
                return -1;
730
        }
731

    
732
        //we will take care of the packet
733
        if (xbee_handle_packet(xbee_buf + 3, len)) {
734
                return -1;
735
        }
736

    
737
        if (dest == NULL) {
738
                return -1;
739
        }
740

    
741
        int i;
742
        for (i = 3; i < len + 3; i++) {
743
                dest[i - 3] = xbee_buf[i];
744
        }
745

    
746
        return len;
747
}
748

    
749
/**
750
 * Handles modem status packets.
751
 *
752
 * @param status the type of status packet received.
753
 **/
754
void xbee_handle_status(char status)
755
{
756
        switch (status)
757
        {
758
                case 0:
759
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
760
                        break;
761
                case 1:
762
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
763
                        break;
764
                case 2:
765
                        WL_DEBUG_PRINT("Associated.\r\n");
766
                        break;
767
                case 3:
768
                        WL_DEBUG_PRINT("Disassociated.\r\n");
769
                        break;
770
                case 4:
771
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
772
                        break;
773
                case 5:
774
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
775
                        break;
776
                case 6:
777
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
778
                        break;
779
        }
780
}
781

    
782
/**
783
 * Handles AT command response packets.
784
 * @param command the two character AT command, e.g. MY or ID
785
 * @param result 0 for success, 1 for an error
786
 * @param extra the hex value of the requested register
787
 * @param extraLen the length in bytes of extra
788
 **/
789
static void xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen)
790
{
791
        if (result == 1)
792
        {
793
                WL_DEBUG_PRINT("Error with AT");
794
                WL_DEBUG_PRINT(command);
795
                WL_DEBUG_PRINT(" packet.\r\n");
796
        }
797
        WL_DEBUG_PRINT("AT");
798
        WL_DEBUG_PRINT(command);
799
        WL_DEBUG_PRINT(" command was successful.\r\n");
800

    
801
        if (command[0] == 'I' && command[1] == 'D')
802
        {
803
                xbee_panID = xbee_pending_panID;
804
                WL_DEBUG_PRINT("PAN ID set to ");
805
                WL_DEBUG_PRINT_INT(xbee_panID);
806
                WL_DEBUG_PRINT(".\r\n");
807
                return;
808
        }
809

    
810
        if (command[0] == 'C' && command[1] == 'H')
811
        {
812
                xbee_channel = xbee_pending_channel;
813
                WL_DEBUG_PRINT("Channel set to ");
814
                WL_DEBUG_PRINT_INT(xbee_channel);
815
                WL_DEBUG_PRINT(".\r\n");
816
                return;
817
        }
818

    
819
        if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
820
        {
821
//                                                        printf("reading xbee_address\n");
822
                
823
                xbee_address = 0;
824
                int i;
825
                for (i = 0; i < extraLen; i++) {
826
                        xbee_address = (xbee_address << 8) + extra[i];
827
                }
828
//                                                        printf("xbee address is: %d\n", xbee_address);
829

    
830
                WL_DEBUG_PRINT("XBee address is ");
831
                WL_DEBUG_PRINT_INT(xbee_address);
832
                WL_DEBUG_PRINT(".\r\n");
833

    
834
                if (xbee_address == 0)
835
                {
836
                        WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
837
                        exit(0);
838
                }
839
        }
840
}
841

    
842
/**
843
 * Attempts to handle the packet if it is dealt with
844
 * by the library.
845
 * We will handle the following packet types:
846
 *    Modem Status
847
 *    AT Command Response
848
 *
849
 * @param packet the packet to handle
850
 * @param len the length of the packet
851
 *
852
 * @return 1 if we have handled the packet, 0 otherwise
853
 */
854
static int xbee_handle_packet(char* packet, int len)
855
{
856
        char command[3] = {1, 2, 3};
857
        if (len <= 0) //this should not happend
858
        {
859
                WL_DEBUG_PRINT("Non-positive packet length.\r\n");
860
                return 0;
861
        }
862

    
863
        switch ((unsigned char)packet[0]) //packet type
864
        {
865
                case XBEE_FRAME_STATUS:
866
                        xbee_handle_status(packet[1]);
867
                        return 1;
868
                case XBEE_FRAME_AT_COMMAND_RESPONSE:
869
                        command[0] = packet[2];
870
                        command[1] = packet[3];
871
                        command[2] = 0;
872
                        xbee_handle_at_command_response(command, packet[4], packet + 5, len - 5);
873
                        return 1;
874
        }
875
        return 0;
876
}
877

    
878
/**
879
 * Sets the personal area network id.
880
 *
881
 * @param id the new personal area network (PAN) id
882
 **/
883
int xbee_set_pan_id(int id)
884
{
885
        char s[3];
886
        s[0] = (id >> 8) & 0xFF;
887
        s[1] = id & 0xFF;
888
        s[2] = 0;
889
        xbee_pending_panID = id;
890
        return xbee_send_modify_at_command("ID", s);
891
}
892

    
893
/**
894
 * Get the PAN ID for the XBee.
895
 *
896
 * @return the personal area network id, or
897
 * XBEE_PAN_DEFAULT if it has not yet been set.
898
 **/
899
unsigned int xbee_get_pan_id()
900
{
901
        return xbee_panID;
902
}
903

    
904
/**
905
 * Set the channel the XBee is using.
906
 *
907
 * @param channel the channel the XBee will not use,
908
 * between 0x0B and 0x1A
909
 *
910
 * @see xbee_get_channel
911
 **/
912
int xbee_set_channel(int channel)
913
{
914
        if (channel < 0x0B || channel > 0x1A)
915
        {
916
                WL_DEBUG_PRINT("Channel out of range.\r\n");
917
                return -1;
918
        }
919

    
920
        char s[3];
921
        s[0] = channel & 0xFF;
922
        s[1] = 0;
923
        xbee_pending_channel = channel;
924

    
925
        return xbee_send_modify_at_command("CH", s);
926
}
927

    
928
/**
929
 * Returns the channel which the XBee is currently using.
930
 *
931
 * @return the channel the XBee is using
932
 *
933
 * @see xbee_set_channel
934
 **/
935
int xbee_get_channel(void)
936
{
937
        return xbee_channel;
938
}
939

    
940
/**
941
 * Get the 16-bit address of the XBee.
942
 * This is used to specify who to send messages to
943
 * and who messages are from.
944
 *
945
 * @return the 16-bit address of the XBee.
946
 **/
947
unsigned int xbee_get_address()
948
{
949
        return xbee_address;
950
}
951

    
952
#ifndef ROBOT
953
void xbee_set_com_port(char* port)
954
{
955
        xbee_com_port = port;
956
}
957
#endif
958