Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (19.4 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
  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
    WL_DEBUG_PRINT("Out of space in buffer.\n");
147
  }
148
  buffer_last = t;
149
}
150
#else
151
SIGNAL(SIG_USART0_RECV) {
152
  char c = UDR0;
153
  arrival_buf[buffer_last] = c;
154
  int t = buffer_last + 1;
155
  if (t == XBEE_BUFFER_SIZE)
156
    t = 0;
157
  if (t == buffer_first) {
158
    WL_DEBUG_PRINT("Out of space in buffer.\n");
159
  }
160
  buffer_last = t;
161
}
162
#endif
163

    
164
#else
165

    
166
/**
167
 * Thread that listens to the xbee.
168
 **/
169
void* listen_to_xbee(void* x) {
170
  char c;
171
  while (1) {
172
    xbee_read(&c, 1);
173
    arrival_buf[buffer_last] = c;
174
    int t = buffer_last + 1;
175
    if (t == XBEE_BUFFER_SIZE)
176
      t = 0;
177
    if (t == buffer_first) {
178
      WL_DEBUG_PRINT("Out of space in buffer.\n");
179
    }
180
    buffer_last = t;
181
  }
182
  return 0;
183
}
184

    
185
#endif
186

    
187
/**
188
 * Initializes the XBee library so that other functions may be used.
189
 **/
190
int xbee_lib_init(void) {
191
  arrival_buf[0] = 'A';
192
  arrival_buf[1] = 'A';
193
  arrival_buf[2] = 'A';
194
#ifdef ROBOT
195

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

    
214
  tcgetattr(xbee_stream, &options);
215
  cfsetispeed(&options, B9600);
216
  cfsetospeed(&options, B9600);
217
  options.c_iflag &= ~ICRNL;
218
  options.c_oflag &= ~OCRNL;
219
  options.c_cflag |= (CLOCAL | CREAD);
220
  options.c_cflag &= ~PARENB;
221
  options.c_cflag &= ~CSTOPB;
222
  options.c_cflag &= ~CSIZE;
223
  options.c_cflag |= CS8;
224
  options.c_lflag &= ~ICANON;
225
  options.c_cc[VMIN] = 1;
226
  options.c_cc[VTIME] = 50;
227

    
228
  if (tcsetattr(xbee_stream, TCSANOW, &options)) {
229
    fprintf(stderr, "Error setting attributes.\n");
230
    return -1;
231
  }
232

    
233
  //lockf(xbee_stream, F_LOCK, 0);
234
        
235
  xbee_listen_thread =
236
    (pthread_t*)malloc(sizeof(pthread_t));
237
  if (xbee_listen_thread == NULL) {
238
    fprintf(stderr, "%s: Malloc failed.\n", __FUNCTION__);
239
    return -1;
240
  }
241
        
242
  int ret = pthread_create(xbee_listen_thread, NULL,
243
                           listen_to_xbee, NULL);
244
  if (ret) {
245
    fprintf(stderr, "Failed to create listener thread.\r\n");
246
    return -1;
247
  }
248
        
249
#endif
250
  xbee_enter_command_mode();
251
  xbee_enter_api_mode();
252
  xbee_exit_command_mode();
253
  xbee_send_read_at_command("MY");
254
        
255
  //wait to return until the address is set
256
  while (xbee_address == 0) xbee_get_packet(NULL);
257

    
258
  return 0;
259
}
260

    
261
/**
262
 * Call when finished using the XBee library. This releases
263
 * all sued resources.
264
 **/
265
void xbee_terminate() {
266
#ifndef ROBOT
267
  pthread_cancel(*xbee_listen_thread);
268
  free(xbee_listen_thread);
269
  lockf(xbee_stream, F_ULOCK, 0);
270
  close(xbee_stream);
271
#endif
272
}
273

    
274
/**
275
 * Send a buffer buf of size bytes to the XBee.
276
 * 
277
 * @param buf the buffer of data to send
278
 * @param size the number of bytes to send
279
 **/
280
void xbee_send(char* buf, int size) {
281
#ifdef ROBOT
282
  int i;
283
  for (i = 0; i < size; i++)
284
    xbee_putc(buf[i]);
285
#else
286
  int ret = write(xbee_stream, buf, size);
287
  //success
288
  if (ret == size)
289
    return;
290
  if (ret == -1) {
291
    //interrupted by system signal, probably timer interrupt.
292
    //just try again
293
    if (errno == 4) {
294
      xbee_send(buf, size);
295
      return;
296
    }
297
    printf("Failed to write to xbee, error %i.\r\n", errno);
298
    return;
299
  }
300

    
301
  //write was interrupted after writing ret bytes
302
  xbee_send(buf + ret, size - ret);
303
#endif
304
}
305

    
306
/**
307
 * Sends a string to the XBee.
308
 *
309
 * @param c the string to send to the XBEE
310
 **/
311
void xbee_send_string(char* c) {
312
  xbee_send(c, strlen(c));
313
}
314

    
315
#ifndef ROBOT
316
void xbee_read(char* buf, int size) {
317
  if (read(xbee_stream, buf, size) == -1)
318
    printf("Failed to read from xbee.\r\n");
319
}
320
#endif
321

    
322
/**
323
 * Enter into command mode.
324
 **/
325
void xbee_enter_command_mode() {
326
  xbee_send_string("+++");
327
  xbee_wait_for_ok();
328
}
329

    
330
/**
331
 * Exit from command mode.
332
 **/
333
void xbee_exit_command_mode() {
334
  xbee_send_string("ATCN\r");
335
  xbee_wait_for_ok();
336
}
337

    
338
/**
339
 * Enter API mode.
340
 **/
341
void xbee_enter_api_mode() {
342
  xbee_send_string("ATAP 1\r");
343
  xbee_wait_for_ok();
344
}
345

    
346
/**
347
 * Exit API mode. (warning - does not check for response)
348
 **/
349
void xbee_exit_api_mode() {
350
  xbee_send_string("ATAP 0\r");
351
}
352

    
353
/**
354
 * Wait until the string "OK\r" is received from the XBee.
355
 **/
356
void xbee_wait_for_ok() {
357
  xbee_wait_for_string("OK\r", 3);
358
}
359

    
360
/**
361
 * Delay until the specified string is received from
362
 * the XBee. Discards all other XBee data.
363
 *
364
 * @param s the string to receive
365
 * @param len the length of the string
366
 **/
367
void xbee_wait_for_string(char* s, int len) {
368
  char* curr = s;
369
  while (curr - s < len) {
370
    // check if buffer is empty
371
    if (buffer_last == buffer_first)
372
      continue;
373
    char c = arrival_buf[buffer_first++];
374
    if (buffer_first == XBEE_BUFFER_SIZE)
375
      buffer_first = 0;
376
    if (c == *curr)
377
      curr++;
378
    else
379
      curr = s;
380
  }
381
}
382

    
383
/**
384
 * Verifies that the packets checksum is correct.
385
 * (If the checksum is correct, the sum of the bytes
386
 * is 0xFF.)
387
 *
388
 * @param packet the packet received. This includes the first
389
 * three bytes, which are header information from the XBee.
390
 *
391
 * @param len The length of the packet received from the XBee
392
 *
393
 * @return 0 if the checksum is incorrect, nonzero
394
 * otherwise
395
 **/
396
int xbee_verify_checksum(char* packet, int len) {
397
  unsigned char sum = 0;
398
  int i;
399
  for (i = 3; i < len; i++)
400
    sum += (unsigned char)packet[i];
401
  return sum == 0xFF;
402
}
403

    
404
/**
405
 * Returns the checksum of the given packet.
406
 *
407
 * @param buf the data for the packet to send
408
 * @param len the length of the packet in bytes
409
 *
410
 * @return the checksum of the packet, which will
411
 * become the last byte sent in the packet
412
 **/
413
char xbee_compute_checksum(char* buf, int len) {
414
  int i;
415
  unsigned char sum = 0;
416
  for (i = 0; i < len; i++)
417
    sum += (unsigned char)buf[i];
418
  return 0xFF - sum;
419
}
420

    
421
/**
422
 * Adds header information and checksum to the given
423
 * packet and sends it. Header information includes
424
 * XBEE_FRAME_START and the packet length, as two bytes.
425
 *
426
 * @param buf the packet data
427
 * @param len the size in bytes of the packet data
428
 *
429
 **/
430
void xbee_send_frame(char* buf, int len) {
431
  char prefix[3];
432
  prefix[0] = XBEE_FRAME_START;
433
  prefix[1] = (len & 0xFF00) >> 8;
434
  prefix[2] = len & 0xFF;
435
  char checksum = xbee_compute_checksum(buf, len);
436
  xbee_send(prefix, 3);
437
  xbee_send(buf, len);
438
  xbee_send(&checksum, 1);
439
}
440

    
441
/**
442
 * Sends an AT command to read a parameter.
443
 *
444
 * @param command the AT command to send. For exmaple,
445
 * use ID to read the PAN ID and MY to return the XBee ID.
446
 * See the XBee reference guide for a complete listing.
447
 **/
448
void xbee_send_read_at_command(char* command) {
449
  xbee_send_modify_at_command(command, NULL);
450
}
451

    
452
/**
453
 * Sends the given AT command.
454
 *
455
 * @param command the AT command to send (e.g., MY, ID)
456
 * @param value the value to pass as a parameter
457
 * (or NULL if there is no parameter)
458
 **/
459
void xbee_send_modify_at_command(char* command, char* value) {
460
  char buf[16];
461
  int i;
462
        
463
  buf[0] = XBEE_FRAME_AT_COMMAND;
464
  buf[1] = 1;
465
  buf[2] = command[0];
466
  buf[3] = command[1];
467
  int valueLen = 0;
468
  if (value != NULL) {
469
    valueLen = strlen(value);
470
    if (valueLen > 8) {
471
      WL_DEBUG_PRINT("AT Command too large.\r\n");
472
      return;
473
    }
474
    for (i = 0; i < valueLen; i++)
475
      buf[4 + i] = value[i];
476
  }
477
  xbee_send_frame(buf, 4 + valueLen);
478
}
479

    
480
/**
481
 * Send the specified packet.
482
 * 
483
 * @param packet the packet data to send
484
 * @param len the number of bytes in the packet
485
 * 
486
 * @param dest the ID of the XBee to send the packet to,
487
 * or XBEE_BROADCAST to send the message to all robots
488
 * in the PAN.
489
 * 
490
 * @param options a combination of the flags
491
 * XBEE_OPTIONS_NONE, XBEE_OPTIONS_DISABLE_RESPONSE and 
492
 * XBEE_OPTIONS_BROADCAST_ALL_PANS
493
 *
494
 * @param frame the frame number to associate this packet
495
 * with. This will be used to identify the response when
496
 * the XBee alerts us as to whether or not our message
497
 * was received.
498
 **/
499
void xbee_send_packet(char* packet, int len, int dest,
500
                      char options, char frame) {
501
  char buf[5];
502
  char prefix[3];
503
  int i;
504
  unsigned char checksum = 0;
505

    
506
  if (len > 100) {
507
    WL_DEBUG_PRINT("Packet is too large.\r\n");
508
    return;
509
  }
510

    
511
  //data for sending request
512
  buf[0] = XBEE_FRAME_TX_REQUEST_16;
513
  buf[1] = frame;
514
  buf[2] = (dest >> 8) & 0xFF;
515
  buf[3] = dest & 0xFF;
516
  buf[4] = options;
517

    
518
  //packet prefix, do this here so we don't need an extra buffer
519
  prefix[0] = XBEE_FRAME_START;
520
  prefix[1] = ((5 + len) & 0xFF00) >> 8;
521
  prefix[2] = (5 + len) & 0xFF;
522

    
523
  for (i = 0; i < 5; i++)
524
    checksum += (unsigned char)buf[i];
525
  for (i = 0; i < len; i++)
526
    checksum += (unsigned char)packet[i];
527
  checksum = 0xFF - checksum;
528
  xbee_send(prefix, 3);
529
  xbee_send(buf, 5);
530
  xbee_send(packet, len);
531
  xbee_send((char*)&checksum, 1);
532
}
533

    
534
/**
535
 * Reads a packet received from the XBee. This function
536
 * is non-blocking. The resulting packet is stored in dest.
537
 * Only returns transmission response packets and
538
 * received packets. The returned packet does not include
539
 * header information or the checksum. This method also
540
 * handles special packets dealt with by the XBee library,
541
 * and so should be called frequently while the XBee is in
542
 * use.<br><br>
543
 *
544
 * The first byte of the packet will be either
545
 * XBEE_TX_STATUS or XBEE_RX to indicated
546
 * a response to a sent message or a received message, 
547
 * respectively.<br><br>
548
 *
549
 * For a status response packet:<br>
550
 * The first byte will be XBEE_TX_STATUS.<br>
551
 * The second byte will be the frame number.<br>
552
 * The third byte will be the result. 0 indicates success,
553
 * and nonzero indicates that an error ocurred in 
554
 * transmitting the packet.<br><br>
555
 *
556
 * For a received packet:<br>
557
 * The first byte will be XBEE_RX.<br>
558
 * The second and third bytes will be the 16-bit
559
 * address of the packet's sender.<br>
560
 * The fourth byte is the signal strength.<br>
561
 * The fifth byte is 1 if the packet were sent to
562
 * a specific address, and 2 if it is a broadcast packet.<br><br>
563
 * 
564
 * @param dest set to the packet data
565
 * @return the length of the packet, or -1 if no packet
566
 * is available
567
 **/
568
int xbee_get_packet(unsigned char* dest) {
569
  //start reading a packet with XBEE_FRAME_START
570
  if (currentBufPos == 0) {
571
    do {
572
      if (buffer_first == XBEE_BUFFER_SIZE)
573
        buffer_first = 0;
574
      // check if buffer is empty
575
      if (buffer_first == buffer_last)
576
        return -1;
577
    }
578
    while (arrival_buf[buffer_first++] != XBEE_FRAME_START);
579
    if (buffer_first == XBEE_BUFFER_SIZE)
580
      buffer_first = 0;
581
    xbee_buf[0] = XBEE_FRAME_START;
582
    currentBufPos++;
583
  }
584

    
585
  int len = -1;
586
  if (currentBufPos >= 3)
587
    len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
588
                
589
  while (len == -1 //packet length has not been read yet
590
         || currentBufPos < len + 4) {
591
    if (currentBufPos == 3) {
592
      len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8);
593
      if (len > 120) {
594
        WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n");
595
        currentBufPos = 0;
596
        return -1;
597
      }
598
    }
599
    // check if buffer is empty
600
    if (buffer_first == buffer_last)
601
      return -1;
602
    xbee_buf[currentBufPos++] = arrival_buf[buffer_first++];
603
    if (buffer_first == XBEE_BUFFER_SIZE)
604
      buffer_first = 0;
605
  }
606
        
607
  currentBufPos = 0;
608
        
609
  if (!xbee_verify_checksum(xbee_buf, len + 4)) {
610
    WL_DEBUG_PRINT("XBee checksum failed.\r\n");
611
    return -1;
612
  }
613

    
614
  //we will take care of the packet
615
  if (xbee_handle_packet(xbee_buf + 3, len))
616
    return -1;
617
        
618
  if (dest == NULL)
619
    return -1;
620
        
621
  int i;
622
  for (i = 3; i < len + 3; i++)
623
    dest[i - 3] = xbee_buf[i];
624
  return len;
625
}
626

    
627
/**
628
 * Handles modem status packets.
629
 *
630
 * @param status the type of status packet received.
631
 **/
632
void xbee_handle_status(char status) {
633
  switch (status) {
634
  case 0:
635
    WL_DEBUG_PRINT("XBee hardware reset.\r\n");
636
    break;
637
  case 1:
638
    WL_DEBUG_PRINT("Watchdog timer reset.\r\n");
639
    break;
640
  case 2:
641
    WL_DEBUG_PRINT("Associated.\r\n");
642
    break;
643
  case 3:
644
    WL_DEBUG_PRINT("Disassociated.\r\n");
645
    break;
646
  case 4:
647
    WL_DEBUG_PRINT("Synchronization lost.\r\n");
648
    break;
649
  case 5:
650
    WL_DEBUG_PRINT("Coordinator realignment.\r\n");
651
    break;
652
  case 6:
653
    WL_DEBUG_PRINT("Coordinator started.\r\n");
654
    break;
655
  }
656
}
657

    
658
/**
659
 * Handles AT command response packets.
660
 * @param command the two character AT command, e.g. MY or ID
661
 * @param result 0 for success, 1 for an error
662
 * @param extra the hex value of the requested register
663
 * @param extraLen the length in bytes of extra
664
 **/
665
void xbee_handle_at_command_response(char* command, char result,
666
                                     char* extra, int extraLen) {
667
  if (result == 1) {
668
    WL_DEBUG_PRINT("Error with AT");
669
    WL_DEBUG_PRINT(command);
670
    WL_DEBUG_PRINT(" packet.\r\n");
671
  }
672
  WL_DEBUG_PRINT("AT");
673
  WL_DEBUG_PRINT(command);
674
  WL_DEBUG_PRINT(" command was successful.\r\n");
675
                
676
  if (command[0] == 'I' && command[1] == 'D') {
677
    xbee_panID = xbee_pending_panID;
678
    WL_DEBUG_PRINT("PAN ID set to ");
679
    WL_DEBUG_PRINT_INT(xbee_panID);
680
    WL_DEBUG_PRINT(".\r\n");
681
    return;
682
  }
683

    
684
  if (command[0] == 'C' && command[1] == 'H') {
685
    xbee_channel = xbee_pending_channel;
686
    WL_DEBUG_PRINT("Channel set to ");
687
    WL_DEBUG_PRINT_INT(xbee_channel);
688
    WL_DEBUG_PRINT(".\r\n");
689
    return;
690
  }
691
        
692
  if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0) {
693
    xbee_address = 0;
694
    int i;
695
    for (i = 0; i < extraLen; i++)
696
      xbee_address = (xbee_address << 8) + extra[i];
697

    
698
    WL_DEBUG_PRINT("XBee address is ");
699
    WL_DEBUG_PRINT_INT(xbee_address);
700
    WL_DEBUG_PRINT(".\r\n");
701

    
702
    if (xbee_address == 0) {
703
      WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n");
704
      exit(0);
705
    }
706
  }
707
}
708

    
709
/**
710
 * Attempts to handle the packet if it is dealt with
711
 * by the library.
712
 * We will handle the following packet types:
713
 *    Modem Status
714
 *    AT Command Response
715
 *
716
 * @param packet the packet to handle
717
 * @param len the length of the packet
718
 * 
719
 * @return 1 if we have handled the packet, 0 otherwise
720
 */
721
int xbee_handle_packet(char* packet, int len) {
722
  char command[3] = {1, 2, 3};
723
  if (len <= 0) {
724
    //this should not happend
725
    WL_DEBUG_PRINT("Non-positive packet length.\r\n");
726
    return 0;
727
  }
728
        
729
  //packet type
730
  switch ((unsigned char)packet[0]) {
731
  case XBEE_FRAME_STATUS:
732
    xbee_handle_status(packet[1]);
733
    return 1;
734
  case XBEE_FRAME_AT_COMMAND_RESPONSE:
735
    command[0] = packet[2];
736
    command[1] = packet[3];
737
    command[2] = 0;
738
    xbee_handle_at_command_response(command,
739
                                    packet[4], packet + 5, len - 5);
740
    return 1;
741
  }
742
  return 0;
743
}
744

    
745
/**
746
 * Sets the personal area network id.
747
 *
748
 * @param id the new personal area network (PAN) id
749
 **/
750
void xbee_set_pan_id(int id) {
751
  char s[3];
752
  s[0] = (id >> 8) & 0xFF;
753
  s[1] = id & 0xFF;
754
  s[2] = 0;
755
  xbee_pending_panID = id;
756
  xbee_send_modify_at_command("ID", s);
757
}
758

    
759
/**
760
 * Get the PAN ID for the XBee.
761
 * 
762
 * @return the personal area network id, or
763
 * XBEE_PAN_DEFAULT if it has not yet been set.
764
 **/
765
unsigned int xbee_get_pan_id() {
766
  return xbee_panID;
767
}
768

    
769
/**
770
 * Set the channel the XBee is using.
771
 *
772
 * @param channel the channel the XBee will not use, 
773
 * between 0x0B and 0x1A
774
 *
775
 * @see xbee_get_channel
776
 **/
777
void xbee_set_channel(int channel) {
778
  if (channel < 0x0B || channel > 0x1A) {
779
    WL_DEBUG_PRINT("Channel out of range.\r\n");
780
    return;
781
  }
782
  char s[3];
783
  s[0] = channel & 0xFF;
784
  s[1] = 0;
785
  xbee_pending_channel = channel;
786
  xbee_send_modify_at_command("CH", s);
787
}
788

    
789
/**
790
 * Returns the channel which the XBee is currently using.
791
 *
792
 * @return the channel the XBee is using
793
 *
794
 * @see xbee_set_channel
795
 **/
796
int xbee_get_channel(void) {
797
  return xbee_channel;
798
}
799

    
800
/**
801
 * Get the 16-bit address of the XBee.
802
 * This is used to specify who to send messages to
803
 * and who messages are from.
804
 *
805
 * @return the 16-bit address of the XBee.
806
 **/
807
unsigned int xbee_get_address() {
808
  return xbee_address;
809
}
810

    
811
#ifndef ROBOT
812
void xbee_set_com_port(char* port) {
813
  xbee_com_port = port;
814
}
815
#endif
816