Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / behaviors / Wireless_Speed_test / xbee.c @ 1562

History | View | Annotate | Download (24.6 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
#include "time.h"
38

    
39
//#define ROBOT
40
//#define WL_DEBUG
41
//#define WL_DEBUG_PRINT( s ) usb_puts( s )
42
//#define WL_DEBUG_PRINT_INT( i ) usb_puti(i)
43

    
44
#ifndef ROBOT
45

    
46
#include <fcntl.h>
47
#include <unistd.h>
48
#include <pthread.h>
49
#include <errno.h>
50
#include <termios.h>
51

    
52
#else
53

    
54
#include "serial.h" ////////////////////////
55
#include <avr/interrupt.h>
56

    
57
#endif
58

    
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <string.h>
62

    
63
#define XBEE_FRAME_START 0x7E
64
#define XBEE_GET_PACKET_TIMEOUT 1000
65

    
66
/*Frame Types*/
67
#define XBEE_FRAME_STATUS 0x8A
68
#define XBEE_FRAME_AT_COMMAND 0x08
69
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88
70
#define XBEE_FRAME_TX_REQUEST_64 0x00
71
#define XBEE_FRAME_TX_REQUEST_16 0x01
72
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS
73
#define XBEE_FRAME_RX_64 0x80
74
#define XBEE_FRAME_RX_16 XBEE_RX
75

    
76
/*Internal Function Prototypes*/
77

    
78
/*I/O Functions*/
79
static int xbee_send(char* buf, int size);
80
static int xbee_send_string(char* c);
81

    
82
#ifndef ROBOT
83
static int xbee_read(char* buf, int size);
84
#endif
85

    
86
/*Command Mode Functions
87
 * Called during initialization.
88
 */
89
static int xbee_enter_command_mode(void);
90
static int xbee_exit_command_mode(void);
91
static int xbee_enter_api_mode(void);
92
static int xbee_exit_api_mode(void);
93
static int xbee_wait_for_string(char* s, int len);
94
static int xbee_wait_for_ok(void);
95

    
96
/*API Mode Functions*/
97

    
98
static int xbee_handle_packet(char* packet, int len);
99
static int xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen);
100
static void xbee_handle_status(char status);
101
static int xbee_verify_checksum(char* packet, int len);
102
static char xbee_compute_checksum(char* packet, int len);
103
static int xbee_send_frame(char* buf, int len);
104
int xbee_send_read_at_command(char* command);
105
static int xbee_send_modify_at_command(char* command, char* value);
106

    
107
/*Global Variables*/
108

    
109
#ifndef ROBOT
110
static char* xbee_com_port = XBEE_PORT_DEFAULT;
111
static int xbee_stream;
112
static pthread_t* xbee_listen_thread;
113
#endif
114

    
115
// TODO: is this a good size?
116
#define XBEE_BUFFER_SIZE        128
117
#define PACKET_BUFFER_SIZE        108
118
// a buffer for data received from the XBee
119
char arrival_buf[XBEE_BUFFER_SIZE];
120
// location of last unread byte in buffer
121
volatile int buffer_last = 0;
122
// first unread byte in buffer
123
volatile int buffer_first = 0;
124

    
125

    
126
//used to store packets as they are read
127
static char xbee_buf[PACKET_BUFFER_SIZE];
128
static int currentBufPos = 0;
129

    
130
//XBee status
131
static unsigned int xbee_panID = XBEE_PAN_DEFAULT;
132
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT;
133
static int xbee_channel = XBEE_CHANNEL_DEFAULT;
134
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT;
135
static volatile unsigned int xbee_address = 0;
136

    
137
/*Function Implementations*/
138

    
139
#ifdef ROBOT
140

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

    
175
#else
176

    
177
// Computer code
178

    
179
/**
180
 * Thread that listens to the xbee.
181
 **/
182
static void* listen_to_xbee(void* x)
183
{
184
        char c;
185
        while (1)
186
        {
187
                if (xbee_read(&c, 1) != 0) {
188
                        WL_DEBUG_PRINT("xbee_read failed.\n");
189
                        return NULL;
190
                }
191

    
192
                arrival_buf[buffer_last] = c;
193
                int t = buffer_last + 1;
194
                if (t == XBEE_BUFFER_SIZE)
195
                        t = 0;
196
                if (t == buffer_first)
197
                {
198
                        WL_DEBUG_PRINT("Out of space in buffer.\n");
199
                }
200
                buffer_last = t;
201

    
202
                usleep(1000);
203
        }
204

    
205
        return NULL;
206
}
207

    
208
#endif
209

    
210
/**
211
 * Initializes the XBee library so that other functions may be used.
212
 **/
213
int xbee_lib_init()
214
{
215
  if (xbee_init() != 0) {
216
    usb_puts("xbee_init error");
217
    return -1;
218
  }
219

    
220
        WL_DEBUG_PRINT("in xbee_init\n");
221
#ifdef ROBOT
222

    
223
        //enable the receiving interrupt
224
#ifdef FIREFLY
225
        UCSR0B |= _BV(RXCIE) | _BV(RXEN);
226
#else
227
#ifdef BAYBOARD
228
        UCSR1B |= _BV(RXCIE1);
229
#else
230
        UCSR1B |= _BV(RXCIE);
231
#endif
232
#endif
233
        sei();
234
#else
235
        xbee_stream = open(xbee_com_port, O_RDWR);
236
        if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/)
237
        {
238
                WL_DEBUG_PRINT("Failed to open connection to XBee on port ");
239
                WL_DEBUG_PRINT_INT(xbee_com_port);
240
                WL_DEBUG_PRINT(".\n");
241
                return -1;
242
        } else {
243
          WL_DEBUG_PRINT("Successfully opened connection to XBee on port ");
244
                WL_DEBUG_PRINT_INT(xbee_com_port);
245
                WL_DEBUG_PRINT(".\n");
246
        }
247

    
248
        // set baud rate, etc. correctly
249
        struct termios options;
250

    
251
        tcgetattr(xbee_stream, &options);
252
        cfsetispeed(&options, B9600);
253
        cfsetospeed(&options, B9600);
254
        options.c_iflag &= ~ICRNL;
255
        options.c_oflag &= ~OCRNL;
256
        options.c_cflag |= (CLOCAL | CREAD);
257
        options.c_cflag &= ~PARENB;
258
        options.c_cflag &= ~CSTOPB;
259
        options.c_cflag &= ~CSIZE;
260
        options.c_cflag |= CS8;
261
        options.c_lflag &= ~ICANON;
262
        options.c_cc[VMIN] = 1;
263
        options.c_cc[VTIME] = 50;
264

    
265
        if (tcsetattr(xbee_stream, TCSANOW, &options))
266
        {
267
                WL_DEBUG_PRINT("Error setting attributes.\n");
268
                return -1;
269
        }
270

    
271
        xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t));
272
        if (xbee_listen_thread == NULL)
273
        {
274
                WL_DEBUG_PRINT("Malloc failed.\n");
275
                return -1;
276
        }
277

    
278
        int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL);
279
        if (ret)
280
        {
281
                WL_DEBUG_PRINT("Failed to create listener thread.\n");
282
                return -1;
283
        }
284
#endif
285

    
286
        WL_DEBUG_PRINT("Entering command mode.\r\n");
287

    
288
        if (xbee_enter_command_mode() != 0) {
289
    usb_puts("error entering command mode\r\n");
290
                return -1;
291
        }
292

    
293
        WL_DEBUG_PRINT("Entered command mode.\r\n");
294

    
295
  // reset baud rate
296
  WL_DEBUG_PRINT("Resetting Baud to ");
297
  WL_DEBUG_PRINT(XBEE_BAUD_STR);
298
  WL_DEBUG_PRINT("\r\n");
299
  
300
  // set baud on xbee
301
//#if (XBEE_BAUD == 250000)
302
#if (XBEE_BAUD == 115200)
303
  xbee_send_string("ATBD7\r\n");
304
#elif (XBEE_BAUD == 57600)
305
  xbee_send_string("ATBD6\r\n");
306
#elif (XBEE_BAUD == 38400)
307
  xbee_send_string("ATBD5\r\n");
308
#elif (XBEE_BAUD == 19200)
309
  xbee_send_string("ATBD4\r\n");
310
#elif (XBEE_BAUD == 9600)
311
  // already at this baud rate
312
  //xbee_send_string("ATBD3\r\n");
313
#else
314
  WL_DEBUG_PRINT("undefined baud rate\r\n");
315
#endif  
316
  // exit command mode
317
  xbee_wait_for_ok();
318
  WL_DEBUG_PRINT("got ok from baud reset\r\n");
319
  xbee_send_string("ATCN\r\n");
320
  xbee_wait_for_ok();
321
  WL_DEBUG_PRINT("got ok from exiting command mode\r\n");
322
  
323
  // set UART baud
324
#if (XBEE_BAUD == 250000)
325
  UBRR1H = 0x00;
326
  UBRR1L = 3;
327
  UCSR1A |= _BV(U2X1);
328
#elif (XBEE_BAUD == 115200)
329
  UBRR1H = 0x00;
330
  UBRR1L = 8;
331
  UCSR1A |= _BV(U2X1);
332
#elif (XBEE_BAUD == 57600)
333
  UBRR1H = 0x00;
334
  UBRR1L = 16;
335
  UCSR1A |= _BV(U2X1);
336
#elif (XBEE_BAUD == 38400)
337
  UBRR1H = 0x00;
338
  UBRR1L = 25;
339
  UCSR1A |= _BV(U2X1);
340
#elif (XBEE_BAUD == 19200)
341
  UBRR1H = 0x00;
342
  UBRR1L = 51;
343
  UCSR1A |= _BV(U2X1);
344
#elif (XBEE_BAUD == 9600)
345
  /* this is the default baud rate, so do nothing
346
  UBRR1H = 0x00;
347
  UBRR1L = 103;
348
  UCSR1A |= _BV(U2X1);*/
349
#else //Baud rate is defined in the header file, we should not get here
350
  return 0;
351
#endif
352
  delay_ms(50);
353

    
354
  // enter command mode
355
  WL_DEBUG_PRINT("entering command mode 2\r\n");
356
  xbee_send_string("+++");
357
  xbee_wait_for_ok();
358
  WL_DEBUG_PRINT("entered command mode 2\r\n");
359
  
360
  if (xbee_enter_api_mode() != 0) {
361
    WL_DEBUG_PRINT("can't enter api mode\r\n");
362
                return -1;
363
        }
364

    
365
        WL_DEBUG_PRINT("Entered api mode.\r\n");
366

    
367
        if (xbee_exit_command_mode() != 0) {
368
    WL_DEBUG_PRINT("can't exit command mode\r\n");
369
          return -1;
370
        }
371
        
372
        WL_DEBUG_PRINT("Left command mode.\r\n");
373
  
374
  // get MY address
375
        if (xbee_send_read_at_command("BD")) {
376
    WL_DEBUG_PRINT("can't send BD command\r\n");
377
                return -1;
378
        }
379
        WL_DEBUG_PRINT("Getting ATBD rate.\n");
380
  
381
  // get MY address
382
        if (xbee_send_read_at_command("MY")) {
383
    WL_DEBUG_PRINT("can't send my command\r\n");
384
                return -1;
385
        }
386
        WL_DEBUG_PRINT("Getting ATMY address.\n");
387

    
388
#ifndef ROBOT
389
        int i;
390
        for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) {
391
          ret = xbee_get_packet(NULL);
392

    
393
          usleep(1000);
394
          
395
/*           if (ret == -1) { */
396
/*             WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */
397
/*             return -1; */
398
/*           } */
399
        }
400
#else
401
        //wait to return until the address is set
402
  //TODO: this shouldn't wait indefinitely.  There should be some sort of reasonable timeout
403
  // so if the address is never set right, an error can be returned instead of having the
404
  // robot hang forever
405
        while (xbee_address == 0) {
406
          xbee_get_packet(NULL);
407
        }
408
#endif
409
        WL_DEBUG_PRINT("Got ATMY address.\n");
410

    
411
#ifndef ROBOT
412
        if (i == XBEE_GET_PACKET_TIMEOUT) { // We timed-out.
413

    
414
          WL_DEBUG_PRINT("xbee_get_packet timed out.\n");
415
          return -1;
416
        } else {
417
          return 0;
418
        }
419
#else
420
        return 0;
421
#endif
422
}
423

    
424
/**
425
 * Call when finished using the XBee library. This releases
426
 * all sued resources.
427
 **/
428
void xbee_terminate()
429
{
430
        #ifndef ROBOT
431
        pthread_cancel(*xbee_listen_thread);
432
    pthread_join(*xbee_listen_thread, NULL);
433
        free(xbee_listen_thread);
434
        lockf(xbee_stream, F_ULOCK, 0);
435
        close(xbee_stream);
436
  #else
437
  xbee_exit_api_mode();
438
        #endif
439
}
440

    
441
/**
442
 * Send a buffer buf of size bytes to the XBee.
443
 *
444
 * @param buf the buffer of data to send
445
 * @param size the number of bytes to send
446
 **/
447
static int xbee_send(char* buf, int size)
448
{
449
#ifdef ROBOT
450
        int i;
451
        for (i = 0; i < size; i++) {
452
                xbee_putc(buf[i]);
453
        }
454

    
455
        return 0;
456

    
457
#else
458

    
459
        int ret = write(xbee_stream, buf, size);
460
        //success
461
        if (ret == size)
462
                return 0;
463
        if (ret == -1)
464
        {
465
                //interrupted by system signal, probably timer interrupt.
466
                //just try again
467
                if (errno == 4)
468
                {
469
                        return xbee_send(buf, size);
470
                }
471
                WL_DEBUG_PRINT("Failed to write to xbee\r\n");
472
                return -1;
473
        }
474

    
475
        //write was interrupted after writing ret bytes
476
        return xbee_send(buf + ret, size - ret);
477
#endif
478
}
479

    
480
/**
481
 * Sends a string to the XBee.
482
 *
483
 * @param c the string to send to the XBEE
484
 **/
485
static int xbee_send_string(char* c)
486
{
487
        return xbee_send(c, strlen(c));
488
}
489

    
490
#ifndef ROBOT
491
static int xbee_read(char* buf, int size)
492
{
493
        if (read(xbee_stream, buf, size) == -1) {
494
                WL_DEBUG_PRINT("Failed to read from xbee.\r\n");
495
                return -1;
496
        }
497

    
498
        return 0;
499
}
500
#endif
501

    
502
/**
503
 * Enter into command mode.
504
 **/
505
static int xbee_enter_command_mode()
506
{
507
        if (xbee_send_string("+++") != 0) {
508
                return -1;
509
        }
510

    
511
        if (xbee_wait_for_ok() != 0) {
512
          return -1;
513
        }
514
          return 0;
515
}
516

    
517
/**
518
 * Exit from command mode.
519
 **/
520
static int xbee_exit_command_mode()
521
{
522
        if (xbee_send_string("ATCN\r") != 0) {
523
                return -1;
524
        }
525

    
526
        xbee_wait_for_ok();
527

    
528
        return 0;
529
}
530

    
531
/**
532
 * Enter API mode.
533
 **/
534
static int xbee_enter_api_mode()
535
{
536
        if (xbee_send_string("ATAP 1\r") != 0) {
537
                return -1;
538
        }
539
        xbee_wait_for_ok();
540

    
541
        return 0;
542
}
543

    
544
/**
545
 * Exit API mode.
546
 **/
547
static int xbee_exit_api_mode()
548
{
549
        if (xbee_send_modify_at_command("AP","0") != 0) {
550
                return -1;
551
        }
552

    
553
        return 0;
554
}
555

    
556
/**
557
 * Wait until the string "OK\r" is received from the XBee.
558
 **/
559
static int xbee_wait_for_ok()
560
{
561
        return xbee_wait_for_string("OK\r", 3);
562
}
563

    
564
/**
565
 * Delay until the specified string is received from
566
 * the XBee. Discards all other XBee data.
567
 *
568
 * ********* Robot often hangs here ****************
569
 *
570
 * @param s the string to receive
571
 * @param len the length of the string
572
 **/
573
static int xbee_wait_for_string(char* s, int len)
574
{
575
        char* curr = s;
576
  unsigned int i=0;
577
        while (curr - s < len) {
578
    WL_DEBUG_PRINT("waiting for string\r\n");
579
                // check if buffer is empty
580
                if (buffer_last != buffer_first) {
581
                        char c = arrival_buf[buffer_first++];
582
                        if (buffer_first == XBEE_BUFFER_SIZE) {
583
                                buffer_first = 0;
584
                        }
585
      WL_DEBUG_PRINT("buffer char|");
586
      WL_DEBUG_PRINT_CHAR(c);
587
      WL_DEBUG_PRINT("|\r\n");
588

    
589
                        if (c == *curr) {
590
                                curr++;
591
                        } else {
592
#ifndef ROBOT
593
                          //return -1; // Computer is less forgiving.
594
                          curr = s;
595
#else
596
                          curr = s;
597
#endif
598
                        }
599
                } // else buffer is empty.
600

    
601
#ifndef ROBOT
602
                usleep(100);
603
#endif
604
        }
605
  if (i >= 10000)
606
    return -1;
607

    
608
        return 0;
609
}
610

    
611
/**
612
 * Verifies that the packets checksum is correct.
613
 * (If the checksum is correct, the sum of the bytes
614
 * is 0xFF.)
615
 *
616
 * @param packet the packet received. This includes the first
617
 * three bytes, which are header information from the XBee.
618
 *
619
 * @param len The length of the packet received from the XBee
620
 *
621
 * @return 0 if the checksum is incorrect, nonzero
622
 * otherwise
623
 **/
624
int xbee_verify_checksum(char* packet, int len)
625
{
626
        unsigned char sum = 0;
627
        int i;
628
        for (i = 3; i < len; i++)
629
                sum += (unsigned char)packet[i];
630
        return sum == 0xFF;
631
}
632

    
633
/**
634
 * Returns the checksum of the given packet.
635
 *
636
 * @param buf the data for the packet to send
637
 * @param len the length of the packet in bytes
638
 *
639
 * @return the checksum of the packet, which will
640
 * become the last byte sent in the packet
641
 **/
642
char xbee_compute_checksum(char* buf, int len)
643
{
644
        int i;
645
        unsigned char sum = 0;
646
        for (i = 0; i < len; i++)
647
                sum += (unsigned char)buf[i];
648
        return 0xFF - sum;
649
}
650

    
651
/**
652
 * Adds header information and checksum to the given
653
 * packet and sends it. Header information includes
654
 * XBEE_FRAME_START and the packet length, as two bytes.
655
 *
656
 * @param buf the packet data
657
 * @param len the size in bytes of the packet data
658
 *
659
 **/
660
static int xbee_send_frame(char* buf, int len)
661
{
662
        char prefix[3];
663
        prefix[0] = XBEE_FRAME_START;
664
        prefix[1] = (len & 0xFF00) >> 8;
665
        prefix[2] = len & 0xFF;
666
        char checksum = xbee_compute_checksum(buf, len);
667

    
668
        if (xbee_send(prefix, 3) != 0) {
669
                return -1;
670
        }
671

    
672
        if (xbee_send(buf, len) != 0) {
673
                return -1;
674
        }
675

    
676
        if (xbee_send(&checksum, 1) != 0) {
677
                return -1;
678
        }
679

    
680
        return 0;
681
}
682

    
683
/**
684
 * Sends an AT command to read a parameter.
685
 *
686
 * @param command the AT command to send. For exmaple,
687
 * use ID to read the PAN ID and MY to return the XBee ID.
688
 * See the XBee reference guide for a complete listing.
689
 **/
690
int xbee_send_read_at_command(char* command)
691
{
692
        return xbee_send_modify_at_command(command, NULL);
693
}
694

    
695
/**
696
 * Sends the given AT command.
697
 *
698
 * @param command the AT command to send (e.g., MY, ID)
699
 * @param value the value to pass as a parameter
700
 * (or NULL if there is no parameter)
701
 **/
702
static int xbee_send_modify_at_command(char* command, char* value)
703
{
704
        char buf[16];
705
        int i;
706

    
707
        buf[0] = XBEE_FRAME_AT_COMMAND;
708
        buf[1] = 1;
709
        buf[2] = command[0];
710
        buf[3] = command[1];
711
        int valueLen = 0;
712
        if (value != NULL)
713
        {
714
                valueLen = strlen(value);
715
                if (valueLen > 8)
716
                {
717
                        WL_DEBUG_PRINT("AT Command too large.\r\n");
718
                        return -1;
719
                }
720

    
721
                for (i = 0; i < valueLen; i++) {
722
                        buf[4 + i] = value[i];
723
                }
724
        }
725

    
726
        return xbee_send_frame(buf, 4 + valueLen);
727
}
728

    
729
/**
730
 * Send the specified packet.
731
 *
732
 * @param packet the packet data to send
733
 * @param len the number of bytes in the packet
734
 *
735
 * @param dest the ID of the XBee to send the packet to,
736
 * or XBEE_BROADCAST to send the message to all robots
737
 * in the PAN.
738
 *
739
 * @param options a combination of the flags
740
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and
741
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
742
 *
743
 * @param frame the frame number to associate this packet
744
 * with. This will be used to identify the response when
745
 * the XBee alerts us as to whether or not our message
746
 * was received.
747
 **/
748
int xbee_send_packet(char* packet, int len, int dest, char options, char frame)
749
{
750
        char buf[5];
751
        char prefix[3];
752
        int i;
753
        unsigned char checksum = 0;
754

    
755
        if (len > 100)
756
        {
757
                WL_DEBUG_PRINT("Packet is too large.\r\n");
758
                return -1;
759
        }
760

    
761
        //data for sending request
762
        buf[0] = XBEE_FRAME_TX_REQUEST_16;
763
        buf[1] = frame;
764
        buf[2] = (dest >> 8) & 0xFF;
765
        buf[3] = dest & 0xFF;
766
        buf[4] = options;
767

    
768
        //packet prefix, do this here so we don't need an extra buffer
769
        prefix[0] = XBEE_FRAME_START;
770
        prefix[1] = ((5 + len) & 0xFF00) >> 8;
771
        prefix[2] = (5 + len) & 0xFF;
772

    
773
        for (i = 0; i < 5; i++)
774
                checksum += (unsigned char)buf[i];
775
        for (i = 0; i < len; i++)
776
                checksum += (unsigned char)packet[i];
777
        checksum = 0xFF - checksum;
778

    
779
        if (xbee_send(prefix, 3) != 0) {
780
                return -1;
781
        }
782

    
783
        if (xbee_send(buf, 5) != 0) {
784
                return -1;
785
        }
786

    
787
        if (xbee_send(packet, len) != 0) {
788
                return -1;
789
        }
790

    
791
        if (xbee_send((char*)&checksum, 1) != 0) {
792
                return -1;
793
        }
794

    
795
        return 0;
796
}
797

    
798
/**
799
 * Reads a packet received from the XBee. This function
800
 * is non-blocking. The resulting packet is stored in dest.
801
 * Only returns transmission response packets and
802
 * received packets. The returned packet does not include
803
 * header information or the checksum. This method also
804
 * handles special packets dealt with by the XBee library,
805
 * and so should be called frequently while the XBee is in
806
 * use.<br><br>
807
 *
808
 * The first byte of the packet will be either
809
 * XBEE_TX_STATUS or XBEE_RX to indicated
810
 * a response to a sent message or a received message,
811
 * respectively.<br><br>
812
 *
813
 * For a status response packet:<br>
814
 * The first byte will be XBEE_TX_STATUS.<br>
815
 * The second byte will be the frame number.<br>
816
 * The third byte will be the result. 0 indicates success,
817
 * and nonzero indicates that an error ocurred in
818
 * transmitting the packet.<br><br>
819
 *
820
 * For a received packet:<br>
821
 * The first byte will be XBEE_RX.<br>
822
 * The second and third bytes will be the 16-bit
823
 * address of the packet's sender.<br>
824
 * The fourth byte is the signal strength.<br>
825
 * The fifth byte is 1 if the packet were sent to
826
 * a specific address, and 2 if it is a broadcast packet.<br><br>
827
 *
828
 * @param dest set to the packet data
829
 * @return the length of the packet, or -1 if no packet
830
 * is available
831
 **/
832
int xbee_get_packet(unsigned char* dest)
833
{
834
     int ret;
835
        //start reading a packet with XBEE_FRAME_START
836
        if (currentBufPos == 0)
837
        {
838
                do
839
                {
840
                        if (buffer_first == XBEE_BUFFER_SIZE)
841
                                buffer_first = 0;
842
                        // check if buffer is empty
843
                        if (buffer_first == buffer_last) {
844
        WL_DEBUG_PRINT("buffer empty\r\n");
845
                                return -1;
846
                        }
847
                } while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
848

    
849
                if (buffer_first == XBEE_BUFFER_SIZE) {
850
                        buffer_first = 0;
851
                }
852
                xbee_buf[0] = XBEE_FRAME_START;
853
                currentBufPos++;
854
        }
855

    
856
        int len = -1;
857
        if (currentBufPos >= 3) {
858
                len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
859
        }
860

    
861
        while (len == -1 //packet length has not been read yet
862
                || currentBufPos < len + 4)
863
        {
864
                if (currentBufPos == 3)
865
                {
866
                        len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
867
                        if (len > 120)
868
                        {
869
                                WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\r\n");
870
                                currentBufPos = 0;
871
                                return -1;
872
                        }
873
                }
874

    
875
                // check if buffer is empty
876
                if (buffer_first == buffer_last) {
877
      WL_DEBUG_PRINT("Buffer empty 2\r\n");
878
                        return -1;
879
                }
880
                xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
881
                if (buffer_first == XBEE_BUFFER_SIZE) {
882
                        buffer_first = 0;
883
                }
884
        }
885

    
886
        currentBufPos = 0;
887

    
888
        if (!xbee_verify_checksum(xbee_buf, len + 4))
889
        {
890
                WL_DEBUG_PRINT("XBee checksum failed.\r\n");
891
                return -1;
892
        }
893

    
894
        //we will take care of the packet
895
        
896
        ret = xbee_handle_packet(xbee_buf+3, len);
897
        if (ret == 1) {
898
                return 3;
899
        } else if (ret == -1) {
900
    WL_DEBUG_PRINT("xbee_handle_packet returned -1\r\n");
901
    return -2;
902
  }
903
        
904
        if (dest == NULL) {
905
    WL_DEBUG_PRINT("dest buffer is null\r\n");
906
                return -1;
907
        }
908

    
909
        int i;
910
        for (i = 3; i < len + 3; i++) {
911
                dest[i - 3] = xbee_buf[i];
912
        }
913
        return len;
914
}
915

    
916
/**
917
 * Handles modem status packets.
918
 *
919
 * @param status the type of status packet received.
920
 **/
921
void xbee_handle_status(char status)
922
{
923
        switch (status)
924
        {
925
                case 0:
926
                        WL_DEBUG_PRINT("XBee hardware reset.\r\n");
927
                        break;
928
                case 1:
929
                        WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
930
                        break;
931
                case 2:
932
                        WL_DEBUG_PRINT("Associated.\r\n");
933
                        break;
934
                case 3:
935
                        WL_DEBUG_PRINT("Disassociated.\r\n");
936
                        break;
937
                case 4:
938
                        WL_DEBUG_PRINT("Synchronization lost.\r\n");
939
                        break;
940
                case 5:
941
                        WL_DEBUG_PRINT("Coordinator realignment.\r\n");
942
                        break;
943
                case 6:
944
                        WL_DEBUG_PRINT("Coordinator started.\r\n");
945
                        break;
946
        }
947
}
948

    
949
/**
950
 * Handles AT command response packets.
951
 * @param command the two character AT command, e.g. MY or ID
952
 * @param result 0 for success, 1 for an error
953
 * @param extra the hex value of the requested register
954
 * @param extraLen the length in bytes of extra
955
 **/
956
static int xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen)
957
{
958
        if (result == 1)
959
        {
960
                WL_DEBUG_PRINT("Error with AT");
961
                WL_DEBUG_PRINT(command);
962
                WL_DEBUG_PRINT(" packet. Result = ");
963
    switch(result) {
964
    case 1:
965
      WL_DEBUG_PRINT("ERROR\r\n");
966
      break;
967
    case 2:
968
      WL_DEBUG_PRINT("Invalid Command\r\n");
969
      break;
970
    case 3:
971
      WL_DEBUG_PRINT("Invalid Parameter\r\n");
972
      break;
973
    }
974
    return -1;
975
        }
976
        WL_DEBUG_PRINT("AT");
977
        WL_DEBUG_PRINT(command);
978
        WL_DEBUG_PRINT(" command was successful.\r\n");
979

    
980
        if (command[0] == 'I' && command[1] == 'D')
981
        {
982
                xbee_panID = xbee_pending_panID;
983
                WL_DEBUG_PRINT("PAN ID set to ");
984
                WL_DEBUG_PRINT_INT(xbee_panID);
985
                WL_DEBUG_PRINT(".\r\n");
986
                return 0;
987
        }
988

    
989
        if (command[0] == 'C' && command[1] == 'H')
990
        {
991
                xbee_channel = xbee_pending_channel;
992
                WL_DEBUG_PRINT("Channel set to ");
993
                WL_DEBUG_PRINT_INT(xbee_channel);
994
                WL_DEBUG_PRINT(".\r\n");
995
                return 0;
996
        }
997
  
998
  if (command[0] == 'N' && command[1] == 'D')
999
        {
1000
                WL_DEBUG_PRINT("ND - extra=");
1001
    WL_DEBUG_PRINT(extra);
1002
                WL_DEBUG_PRINT("\r\n");
1003
                return 0;
1004
        }
1005
  
1006
   if (command[0] == 'B' && command[1] == 'D')
1007
        {
1008
                WL_DEBUG_PRINT("BD - extra=");
1009
    WL_DEBUG_PRINT(extra);
1010
                WL_DEBUG_PRINT("\r\n");
1011
                return 0;
1012
        }
1013

    
1014
        if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0)
1015
        {
1016
                xbee_address = 0;
1017
                int i;
1018
                for (i = 0; i < extraLen; i++) {
1019
                        xbee_address = (xbee_address << 8) + extra[i];
1020
                }
1021

    
1022
                WL_DEBUG_PRINT("XBee address is ");
1023
                WL_DEBUG_PRINT_INT(xbee_address);
1024
                WL_DEBUG_PRINT(".\r\n");
1025

    
1026
                if (xbee_address == 0)
1027
                {
1028
                        WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
1029
                        #ifndef ROBOT
1030
                        exit(0);
1031
                        #endif
1032
                }
1033
        }
1034
  return 0;
1035
}
1036

    
1037
/**
1038
 * Attempts to handle the packet if it is dealt with
1039
 * by the library.
1040
 * We will handle the following packet types:
1041
 *    Modem Status
1042
 *    AT Command Response
1043
 *
1044
 * @param packet the packet to handle
1045
 * @param len the length of the packet
1046
 *
1047
 * @return 1 if we have handled the packet, 0 otherwise
1048
 */
1049
static int xbee_handle_packet(char* packet, int len)
1050
{
1051

    
1052
        char command[3] = {1, 2, 3};
1053
        if (len <= 0) //this should not happend
1054
        {
1055
                WL_DEBUG_PRINT("Non-positive packet length.\r\n");
1056
                return 0;
1057
        }
1058

    
1059
        switch ((unsigned char)packet[0]) //packet type
1060
        {
1061
                case XBEE_FRAME_STATUS:
1062
                        xbee_handle_status(packet[1]);
1063
                        return 1;
1064
                case XBEE_FRAME_AT_COMMAND_RESPONSE:
1065
                        command[0] = packet[2];
1066
                        command[1] = packet[3];
1067
                        command[2] = 0;
1068
                        if (xbee_handle_at_command_response(command, packet[4], packet + 5, len - 5) != 0)
1069
        return -1;
1070
      else
1071
        return 1;
1072
        }
1073
        return 0;
1074
}
1075

    
1076
/**
1077
 * Sets the personal area network id.
1078
 *
1079
 * @param id the new personal area network (PAN) id
1080
 **/
1081
int xbee_set_pan_id(int id)
1082
{
1083
        char s[3];
1084
        s[0] = (id >> 8) & 0xFF;
1085
        s[1] = id & 0xFF;
1086
        s[2] = 0;
1087
        xbee_pending_panID = id;
1088
        return xbee_send_modify_at_command("ID", s);
1089
}
1090

    
1091
/**
1092
 * Get the PAN ID for the XBee.
1093
 *
1094
 * @return the personal area network id, or
1095
 * XBEE_PAN_DEFAULT if it has not yet been set.
1096
 **/
1097
unsigned int xbee_get_pan_id()
1098
{
1099
        return xbee_panID;
1100
}
1101

    
1102
/**
1103
 * Set the channel the XBee is using.
1104
 *
1105
 * @param channel the channel the XBee will not use,
1106
 * between 0x0B and 0x1A
1107
 *
1108
 * @see xbee_get_channel
1109
 **/
1110
int xbee_set_channel(int channel)
1111
{
1112
        if (channel < 0x0B || channel > 0x1A)
1113
        {
1114
                WL_DEBUG_PRINT("Channel out of range.\r\n");
1115
                return -1;
1116
        }
1117

    
1118
        char s[3];
1119
        s[0] = channel & 0xFF;
1120
        s[1] = 0;
1121
        xbee_pending_channel = channel;
1122

    
1123
        return xbee_send_modify_at_command("CH", s);
1124
}
1125

    
1126
/**
1127
 * Returns the channel which the XBee is currently using.
1128
 *
1129
 * @return the channel the XBee is using
1130
 *
1131
 * @see xbee_set_channel
1132
 **/
1133
int xbee_get_channel(void)
1134
{
1135
        return xbee_channel;
1136
}
1137

    
1138
/**
1139
 * Get the 16-bit address of the XBee.
1140
 * This is used to specify who to send messages to
1141
 * and who messages are from.
1142
 *
1143
 * @return the 16-bit address of the XBee.
1144
 **/
1145
unsigned int xbee_get_address()
1146
{
1147
        return xbee_address;
1148
}
1149

    
1150
#ifndef ROBOT
1151
void xbee_set_com_port(char* port)
1152
{
1153
        xbee_com_port = port;
1154
}
1155
#endif