Project

General

Profile

Statistics
| Revision:

root / branches / autonomous_recharging / code / projects / autonomous_recharging / charging_station / xbee.c @ 337

History | View | Annotate | Download (19 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
void xbee_send(char* buf, int size);
73
void xbee_send_string(char* c);
74

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

    
79
/*Command Mode Functions
80
 * Called during initialization.
81
 */
82
void xbee_enter_command_mode(void);
83
void xbee_exit_command_mode(void);
84
void xbee_enter_api_mode(void);
85
void xbee_exit_api_mode(void);
86
void xbee_wait_for_string(char* s, int len);
87
void xbee_wait_for_ok(void);
88

    
89
/*API Mode Functions*/
90

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

    
101
/*Global Variables*/
102

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

    
109
// TODO: is this a good size?
110
#define XBEE_BUFFER_SIZE        256
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
char xbee_buf[128];
121
int currentBufPos = 0;
122

    
123
//XBee status
124
unsigned int xbee_panID = XBEE_PAN_DEFAULT;
125
unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
126
int xbee_channel = XBEE_CHANNEL_DEFAULT;
127
int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
128
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("Out 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
/**
171
 * Thread that listens to the xbee.
172
 **/
173
void* listen_to_xbee(void* x)
174
{
175
        char c;
176
        while (1)
177
        {
178
                xbee_read(&c, 1);
179
                arrival_buf[buffer_last] = c;
180
                int t = buffer_last + 1;
181
                if (t == XBEE_BUFFER_SIZE)
182
                        t = 0;
183
                if (t == buffer_first)
184
                {
185
                        WL_DEBUG_PRINT("Out of space in buffer.\n");
186
                }
187
                buffer_last = t;
188
        }
189
        return 0;
190
}
191

    
192
#endif
193

    
194
/**
195
 * Initializes the XBee library so that other functions may be used.
196
 **/
197
int xbee_lib_init(void)
198
{
199
        arrival_buf[0] = 'A';
200
        arrival_buf[1] = 'A';
201
        arrival_buf[2] = 'A';
202
        #ifdef ROBOT
203

    
204
        //enable the receiving interrupt
205
        #ifdef FIREFLY
206
        UCSR0B |= _BV(RXCIE) | _BV(RXEN);
207
        #else
208
        UCSR1B |= _BV(RXCIE);
209
        #endif
210
        sei();
211
        #else
212
        printf("Connecting to port %s.\n", xbee_com_port);
213
        xbee_stream = open(xbee_com_port, O_RDWR);
214
        if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/)
215
        {
216
                printf("Failed to open connection to XBee on port %s\r\n", xbee_com_port);
217
                return -1;
218
        }
219
        
220
        // set baud rate, etc. correctly
221
        struct termios options;
222

    
223
        tcgetattr(xbee_stream, &options);
224
        cfsetispeed(&options, B9600);
225
        cfsetospeed(&options, B9600);
226
        options.c_iflag &= ~ICRNL;
227
        options.c_oflag &= ~OCRNL;
228
        options.c_cflag |= (CLOCAL | CREAD);
229
        options.c_cflag &= ~PARENB;
230
        options.c_cflag &= ~CSTOPB;
231
        options.c_cflag &= ~CSIZE;
232
        options.c_cflag |= CS8;
233
        options.c_lflag &= ~ICANON;
234
        options.c_cc[VMIN] = 1;
235
        options.c_cc[VTIME] = 50;
236

    
237
        if (tcsetattr(xbee_stream, TCSANOW, &options))
238
        {
239
                fprintf(stderr, "Error setting attributes.\n");
240
                return -1;
241
        }
242

    
243
        //lockf(xbee_stream, F_LOCK, 0);
244
        
245
        xbee_listen_thread =
246
                (pthread_t*)malloc(sizeof(pthread_t));
247
        if (xbee_listen_thread == NULL)
248
        {
249
                fprintf(stderr, "%s: Malloc failed.\n", __FUNCTION__);
250
                return -1;
251
        }
252
        
253
        int ret = pthread_create(xbee_listen_thread, NULL,
254
                listen_to_xbee, NULL);
255
        if (ret)
256
        {
257
                fprintf(stderr, "Failed to create listener thread.\r\n");
258
                return -1;
259
        }
260
        
261
        #endif
262
        xbee_enter_command_mode();
263
        xbee_enter_api_mode();
264
        xbee_exit_command_mode();
265
        xbee_send_read_at_command("MY");
266
        
267
        //wait to return until the address is set
268
        while (xbee_address == 0) xbee_get_packet(NULL);
269

    
270

    
271
        return 0;
272
}
273

    
274
/**
275
 * Call when finished using the XBee library. This releases
276
 * all sued resources.
277
 **/
278
void xbee_terminate()
279
{
280
        #ifndef ROBOT
281
        pthread_cancel(*xbee_listen_thread);
282
        free(xbee_listen_thread);
283
        lockf(xbee_stream, F_ULOCK, 0);
284
        close(xbee_stream);
285
        #endif
286
}
287

    
288
/**
289
 * Send a buffer buf of size bytes to the XBee.
290
 * 
291
 * @param buf the buffer of data to send
292
 * @param size the number of bytes to send
293
 **/
294
void xbee_send(char* buf, int size)
295
{
296
        #ifdef ROBOT
297
        int i;
298
        for (i = 0; i < size; i++)
299
                xbee_putc(buf[i]);
300
        #else
301
        int ret = write(xbee_stream, buf, size);
302
        //success
303
        if (ret == size)
304
                return;
305
        if (ret == -1)
306
        {
307
                //interrupted by system signal, probably timer interrupt.
308
                //just try again
309
                if (errno == 4)
310
                {
311
                        xbee_send(buf, size);
312
                        return;
313
                }
314
                printf("Failed to write to xbee, error %i.\r\n", errno);
315
                return;
316
        }
317

    
318
        //write was interrupted after writing ret bytes
319
        xbee_send(buf + ret, size - ret);
320
        #endif
321
}
322

    
323
/**
324
 * Sends a string to the XBee.
325
 *
326
 * @param c the string to send to the XBEE
327
 **/
328
void xbee_send_string(char* c)
329
{
330
        xbee_send(c, strlen(c));
331
}
332

    
333
#ifndef ROBOT
334
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
}
339
#endif
340

    
341
/**
342
 * Enter into command mode.
343
 **/
344
void xbee_enter_command_mode()
345
{
346
        xbee_send_string("+++");
347
        xbee_wait_for_ok();
348
}
349

    
350
/**
351
 * Exit from command mode.
352
 **/
353
void xbee_exit_command_mode()
354
{
355
        xbee_send_string("ATCN\r");
356
        xbee_wait_for_ok();
357
}
358

    
359
/**
360
 * Enter API mode.
361
 **/
362
void xbee_enter_api_mode()
363
{
364
        xbee_send_string("ATAP 1\r");
365
        xbee_wait_for_ok();
366
}
367

    
368
/**
369
 * Exit API mode. (warning - does not check for response)
370
 **/
371
void xbee_exit_api_mode()
372
{
373
        xbee_send_string("ATAP 0\r");
374
}
375

    
376
/**
377
 * Wait until the string "OK\r" is received from the XBee.
378
 **/
379
void xbee_wait_for_ok()
380
{
381
        xbee_wait_for_string("OK\r", 3);
382
}
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
void xbee_wait_for_string(char* s, int len)
392
{
393
        char* curr = s;
394
        while (curr - s < len)
395
        {
396
                // check if buffer is empty
397
                if (buffer_last == buffer_first)
398
                        continue;
399
                char c = arrival_buf[buffer_first++];
400
                if (buffer_first == XBEE_BUFFER_SIZE)
401
                        buffer_first = 0;
402
                if (c == *curr)
403
                        curr++;
404
                else
405
                        curr = s;
406
        }
407
}
408

    
409
/**
410
 * Verifies that the packets checksum is correct.
411
 * (If the checksum is correct, the sum of the bytes
412
 * is 0xFF.)
413
 *
414
 * @param packet the packet received. This includes the first
415
 * three bytes, which are header information from the XBee.
416
 *
417
 * @param len The length of the packet received from the XBee
418
 *
419
 * @return 0 if the checksum is incorrect, nonzero
420
 * otherwise
421
 **/
422
int xbee_verify_checksum(char* packet, int len)
423
{
424
        unsigned char sum = 0;
425
        int i;
426
        for (i = 3; i < len; i++)
427
                sum += (unsigned char)packet[i];
428
        return sum == 0xFF;
429
}
430

    
431
/**
432
 * Returns the checksum of the given packet.
433
 *
434
 * @param buf the data for the packet to send
435
 * @param len the length of the packet in bytes
436
 *
437
 * @return the checksum of the packet, which will
438
 * become the last byte sent in the packet
439
 **/
440
char xbee_compute_checksum(char* buf, int len)
441
{
442
        int i;
443
        unsigned char sum = 0;
444
        for (i = 0; i < len; i++)
445
                sum += (unsigned char)buf[i];
446
        return 0xFF - sum;
447
}
448

    
449
/**
450
 * Adds header information and checksum to the given
451
 * packet and sends it. Header information includes
452
 * XBEE_FRAME_START and the packet length, as two bytes.
453
 *
454
 * @param buf the packet data
455
 * @param len the size in bytes of the packet data
456
 *
457
 **/
458
void xbee_send_frame(char* buf, int len)
459
{
460
        char prefix[3];
461
        prefix[0] = XBEE_FRAME_START;
462
        prefix[1] = (len & 0xFF00) >> 8;
463
        prefix[2] = len & 0xFF;
464
        char checksum = xbee_compute_checksum(buf, len);
465
        xbee_send(prefix, 3);
466
        xbee_send(buf, len);
467
        xbee_send(&checksum, 1);
468
}
469

    
470
/**
471
 * Sends an AT command to read a parameter.
472
 *
473
 * @param command the AT command to send. For exmaple,
474
 * use ID to read the PAN ID and MY to return the XBee ID.
475
 * See the XBee reference guide for a complete listing.
476
 **/
477
void xbee_send_read_at_command(char* command)
478
{
479
        xbee_send_modify_at_command(command, NULL);
480
}
481

    
482
/**
483
 * Sends the given AT command.
484
 *
485
 * @param command the AT command to send (e.g., MY, ID)
486
 * @param value the value to pass as a parameter
487
 * (or NULL if there is no parameter)
488
 **/
489
void xbee_send_modify_at_command(char* command, char* value)
490
{
491
        char buf[16];
492
        int i;
493
        
494
        buf[0] = XBEE_FRAME_AT_COMMAND;
495
        buf[1] = 1;
496
        buf[2] = command[0];
497
        buf[3] = command[1];
498
        int valueLen = 0;
499
        if (value != NULL)
500
        {
501
                valueLen = strlen(value);
502
                if (valueLen > 8)
503
                {
504
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
505
                        return;
506
                }
507
                for (i = 0; i < valueLen; i++)
508
                        buf[4 + i] = value[i];
509
        }
510
        xbee_send_frame(buf, 4 + valueLen);
511
}
512

    
513
/**
514
 * Send the specified packet.
515
 * 
516
 * @param packet the packet data to send
517
 * @param len the number of bytes in the packet
518
 * 
519
 * @param dest the ID of the XBee to send the packet to,
520
 * or XBEE_BROADCAST to send the message to all robots
521
 * in the PAN.
522
 * 
523
 * @param options a combination of the flags
524
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and 
525
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
526
 *
527
 * @param frame the frame number to associate this packet
528
 * with. This will be used to identify the response when
529
 * the XBee alerts us as to whether or not our message
530
 * was received.
531
 **/
532
void xbee_send_packet(char* packet, int len, int dest,
533
        char options, char frame)
534
{
535
        char buf[5];
536
        char prefix[3];
537
        int i;
538
        unsigned char checksum = 0;
539

    
540
        if (len > 100)
541
        {
542
                WL_DEBUG_PRINT("Packet is too large.\r\n");
543
                return;
544
        }
545

    
546
        //data for sending request
547
        buf[0] = XBEE_FRAME_TX_REQUEST_16;
548
        buf[1] = frame;
549
        buf[2] = (dest >> 8) & 0xFF;
550
        buf[3] = dest & 0xFF;
551
        buf[4] = options;
552

    
553
        //packet prefix, do this here so we don't need an extra buffer
554
        prefix[0] = XBEE_FRAME_START;
555
        prefix[1] = ((5 + len) & 0xFF00) >> 8;
556
        prefix[2] = (5 + len) & 0xFF;
557

    
558
        for (i = 0; i < 5; i++)
559
                checksum += (unsigned char)buf[i];
560
        for (i = 0; i < len; i++)
561
                checksum += (unsigned char)packet[i];
562
        checksum = 0xFF - checksum;
563
        xbee_send(prefix, 3);
564
        xbee_send(buf, 5);
565
        xbee_send(packet, len);
566
        xbee_send((char*)&checksum, 1);
567
}
568

    
569
/**
570
 * Reads a packet received from the XBee. This function
571
 * is non-blocking. The resulting packet is stored in dest.
572
 * Only returns transmission response packets and
573
 * received packets. The returned packet does not include
574
 * header information or the checksum. This method also
575
 * handles special packets dealt with by the XBee library,
576
 * and so should be called frequently while the XBee is in
577
 * use.<br><br>
578
 *
579
 * The first byte of the packet will be either
580
 * XBEE_TX_STATUS or XBEE_RX to indicated
581
 * a response to a sent message or a received message, 
582
 * respectively.<br><br>
583
 *
584
 * For a status response packet:<br>
585
 * The first byte will be XBEE_TX_STATUS.<br>
586
 * The second byte will be the frame number.<br>
587
 * The third byte will be the result. 0 indicates success,
588
 * and nonzero indicates that an error ocurred in 
589
 * transmitting the packet.<br><br>
590
 *
591
 * For a received packet:<br>
592
 * The first byte will be XBEE_RX.<br>
593
 * The second and third bytes will be the 16-bit
594
 * address of the packet's sender.<br>
595
 * The fourth byte is the signal strength.<br>
596
 * The fifth byte is 1 if the packet were sent to
597
 * a specific address, and 2 if it is a broadcast packet.<br><br>
598
 * 
599
 * @param dest set to the packet data
600
 * @return the length of the packet, or -1 if no packet
601
 * is available
602
 **/
603
int xbee_get_packet(unsigned char* dest)
604
{
605
        //start reading a packet with XBEE_FRAME_START
606
        if (currentBufPos == 0)
607
        {
608
                do
609
                {
610
                        if (buffer_first == XBEE_BUFFER_SIZE)
611
                                buffer_first = 0;
612
                        // check if buffer is empty
613
                        if (buffer_first == buffer_last)
614
                                return -1;
615
                }
616
                while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
617
                if (buffer_first == XBEE_BUFFER_SIZE)
618
                        buffer_first = 0;
619
                xbee_buf[0] = XBEE_FRAME_START;
620
                currentBufPos++;
621
        }
622

    
623
        int len = -1;
624
        if (currentBufPos >= 3)
625
                len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
626
                
627
        while (len == -1 //packet length has not been read yet
628
                        || currentBufPos < len + 4)
629
        {
630
                if (currentBufPos == 3)
631
                {
632
                        len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
633
                        if (len > 120)
634
                        {
635
                                WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
636
                                currentBufPos = 0;
637
                                return -1;
638
                        }
639
                }
640
                // check if buffer is empty
641
                if (buffer_first == buffer_last)
642
                        return -1;
643
                xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
644
                if (buffer_first == XBEE_BUFFER_SIZE)
645
                        buffer_first = 0;
646
        }
647
        
648
        currentBufPos = 0;
649
        
650
        if (!xbee_verify_checksum(xbee_buf, len + 4))
651
        {
652
                WL_DEBUG_PRINT("XBee checksum failed.\r\n");
653
                return -1;
654
        }
655

    
656
        //we will take care of the packet
657
        if (xbee_handle_packet(xbee_buf + 3, len))
658
                return -1;
659
        
660
        if (dest == NULL)
661
                return -1;
662
        
663
        int i;
664
        for (i = 3; i < len + 3; i++)
665
                dest[i - 3] = xbee_buf[i];
666
        return len;
667
}
668

    
669
/**
670
 * Handles modem status packets.
671
 *
672
 * @param status the type of status packet received.
673
 **/
674
void xbee_handle_status(char status)
675
{
676
        switch (status)
677
        {
678
                case 0:
679
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
680
                        break;
681
                case 1:
682
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
683
                        break;
684
                case 2:
685
                        WL_DEBUG_PRINT("Associated.\r\n");
686
                        break;
687
                case 3:
688
                        WL_DEBUG_PRINT("Disassociated.\r\n");
689
                        break;
690
                case 4:
691
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
692
                        break;
693
                case 5:
694
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
695
                        break;
696
                case 6:
697
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
698
                        break;
699
        }
700
}
701

    
702
/**
703
 * Handles AT command response packets.
704
 * @param command the two character AT command, e.g. MY or ID
705
 * @param result 0 for success, 1 for an error
706
 * @param extra the hex value of the requested register
707
 * @param extraLen the length in bytes of extra
708
 **/
709
void xbee_handle_at_command_response(char* command, char result,
710
        char* extra, int extraLen)
711
{
712
        if (result == 1)
713
        {
714
                WL_DEBUG_PRINT("Error with AT");
715
                WL_DEBUG_PRINT(command);
716
                WL_DEBUG_PRINT(" packet.\r\n");
717
        }
718
        WL_DEBUG_PRINT("AT");
719
        WL_DEBUG_PRINT(command);
720
        WL_DEBUG_PRINT(" command was successful.\r\n");
721
                
722
        if (command[0] == 'I' && command[1] == 'D')
723
        {
724
                xbee_panID = xbee_pending_panID;
725
                WL_DEBUG_PRINT("PAN ID set to ");
726
                WL_DEBUG_PRINT_INT(xbee_panID);
727
                WL_DEBUG_PRINT(".\r\n");
728
                return;
729
        }
730

    
731
        if (command[0] == 'C' && command[1] == 'H')
732
        {
733
                xbee_channel = xbee_pending_channel;
734
                WL_DEBUG_PRINT("Channel set to ");
735
                WL_DEBUG_PRINT_INT(xbee_channel);
736
                WL_DEBUG_PRINT(".\r\n");
737
                return;
738
        }
739
        
740
        if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
741
        {
742
                xbee_address = 0;
743
                int i;
744
                for (i = 0; i < extraLen; i++)
745
                        xbee_address = (xbee_address << 8) + extra[i];
746

    
747
                WL_DEBUG_PRINT("XBee address is ");
748
                WL_DEBUG_PRINT_INT(xbee_address);
749
                WL_DEBUG_PRINT(".\r\n");
750

    
751
                if (xbee_address == 0)
752
                {
753
                        WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
754
                        exit(0);
755
                }
756
        }
757
}
758

    
759
/**
760
 * Attempts to handle the packet if it is dealt with
761
 * by the library.
762
 * We will handle the following packet types:
763
 *    Modem Status
764
 *    AT Command Response
765
 *
766
 * @param packet the packet to handle
767
 * @param len the length of the packet
768
 * 
769
 * @return 1 if we have handled the packet, 0 otherwise
770
 */
771
int xbee_handle_packet(char* packet, int len)
772
{
773
        char command[3] = {1, 2, 3};
774
        if (len <= 0) //this should not happend
775
        {
776
                WL_DEBUG_PRINT("Non-positive packet length.\r\n");
777
                return 0;
778
        }
779
        
780
        switch ((unsigned char)packet[0]) //packet type
781
        {
782
                case XBEE_FRAME_STATUS:
783
                        xbee_handle_status(packet[1]);
784
                        return 1;
785
                case XBEE_FRAME_AT_COMMAND_RESPONSE:
786
                        command[0] = packet[2];
787
                        command[1] = packet[3];
788
                        command[2] = 0;
789
                        xbee_handle_at_command_response(command,
790
                                packet[4], packet + 5, len - 5);
791
                        return 1;
792
        }
793
        return 0;
794
}
795

    
796
/**
797
 * Sets the personal area network id.
798
 *
799
 * @param id the new personal area network (PAN) id
800
 **/
801
void xbee_set_pan_id(int id)
802
{
803
        char s[3];
804
        s[0] = (id >> 8) & 0xFF;
805
        s[1] = id & 0xFF;
806
        s[2] = 0;
807
        xbee_pending_panID = id;
808
        xbee_send_modify_at_command("ID", s);
809
}
810

    
811
/**
812
 * Get the PAN ID for the XBee.
813
 * 
814
 * @return the personal area network id, or
815
 * XBEE_PAN_DEFAULT if it has not yet been set.
816
 **/
817
unsigned int xbee_get_pan_id()
818
{
819
        return xbee_panID;
820
}
821

    
822
/**
823
 * Set the channel the XBee is using.
824
 *
825
 * @param channel the channel the XBee will not use, 
826
 * between 0x0B and 0x1A
827
 *
828
 * @see xbee_get_channel
829
 **/
830
void xbee_set_channel(int channel)
831
{
832
        if (channel < 0x0B || channel > 0x1A)
833
        {
834
                WL_DEBUG_PRINT("Channel out of range.\r\n");
835
                return;
836
        }
837
        char s[3];
838
        s[0] = channel & 0xFF;
839
        s[1] = 0;
840
        xbee_pending_channel = channel;
841
        xbee_send_modify_at_command("CH", s);
842
}
843

    
844
/**
845
 * Returns the channel which the XBee is currently using.
846
 *
847
 * @return the channel the XBee is using
848
 *
849
 * @see xbee_set_channel
850
 **/
851
int xbee_get_channel(void)
852
{
853
        return xbee_channel;
854
}
855

    
856
/**
857
 * Get the 16-bit address of the XBee.
858
 * This is used to specify who to send messages to
859
 * and who messages are from.
860
 *
861
 * @return the 16-bit address of the XBee.
862
 **/
863
unsigned int xbee_get_address()
864
{
865
        return xbee_address;
866
}
867

    
868
#ifndef ROBOT
869
void xbee_set_com_port(char* port)
870
{
871
        xbee_com_port = port;
872
}
873
#endif
874