Revision 1601
wireless: more xbee.c updates
xbee.c | ||
---|---|---|
32 | 32 |
* @author Colony Project, CMU Robotics Club |
33 | 33 |
**/ |
34 | 34 |
|
35 |
#include "xbee.h"
|
|
36 |
#include "wl_defs.h"
|
|
35 |
#include <string.h>
|
|
36 |
#include <avr/interrupt.h>
|
|
37 | 37 |
#include <time.h> |
38 |
|
|
39 |
// TODO: separate robot and computer code into two xbee.c files |
|
40 |
|
|
41 |
#ifndef ROBOT |
|
42 |
|
|
43 |
#include <fcntl.h> |
|
44 |
#include <unistd.h> |
|
45 |
#include <pthread.h> |
|
46 |
#include <errno.h> |
|
47 |
#include <termios.h> |
|
48 |
|
|
49 |
#else |
|
50 |
|
|
51 | 38 |
#include <serial.h> // TODO: integrate serial xbee functions into this file |
52 |
#include <avr/interrupt.h> |
|
39 |
#include "wl_defs.h" |
|
40 |
#include "xbee.h" |
|
53 | 41 |
|
54 |
#endif |
|
55 | 42 |
|
56 |
// TODO: do we really need stdio and stdlib in the robot code? |
|
57 |
#include <stdio.h> |
|
58 |
#include <stdlib.h> |
|
59 |
#include <string.h> |
|
43 |
/* Internal Function Prototypes */ |
|
60 | 44 |
|
61 |
|
|
62 |
/*Internal Function Prototypes*/ |
|
63 |
|
|
64 | 45 |
// TODO: convert all int references to int16_t syntax (see stdint.h) |
65 | 46 |
|
66 |
/*I/O Functions*/
|
|
67 |
static int xbee_send(char* buf, int size);
|
|
68 |
static int xbee_send_string(char* c);
|
|
47 |
/* I/O Functions */
|
|
48 |
static int8_t xbee_send(uint8_t* buf, uint16_t size);
|
|
49 |
static int8_t xbee_send_string(unsigned char* c);
|
|
69 | 50 |
|
70 |
#ifndef ROBOT |
|
71 |
static int xbee_read(char* buf, int size); |
|
72 |
#endif |
|
73 |
|
|
74 |
/*Command Mode Functions |
|
75 |
* Called during initialization. |
|
76 |
*/ |
|
51 |
/* Command Mode Functions */ |
|
77 | 52 |
static int xbee_enter_command_mode(void); |
78 | 53 |
static int xbee_exit_command_mode(void); |
79 | 54 |
static int xbee_enter_api_mode(void); |
... | ... | |
81 | 56 |
static int xbee_wait_for_string(char* s, int len); |
82 | 57 |
static int xbee_wait_for_ok(void); |
83 | 58 |
|
84 |
/*API Mode Functions*/
|
|
85 |
|
|
86 |
static int xbee_handle_packet(char* packet, int len);
|
|
87 |
static int xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen);
|
|
59 |
/* API Mode Functions */
|
|
60 |
static int xbee_handle_packet(uint8_t* packet, uint16_t len); |
|
61 |
static int xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
|
|
62 |
static int xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
|
|
88 | 63 |
static void xbee_handle_status(char status); |
89 | 64 |
static int xbee_verify_checksum(char* packet, int len); |
90 | 65 |
static char xbee_compute_checksum(char* packet, int len); |
... | ... | |
92 | 67 |
int xbee_send_read_at_command(char* command); |
93 | 68 |
static int xbee_send_modify_at_command(char* command, char* value); |
94 | 69 |
|
95 |
/*Global Variables*/ |
|
70 |
/* Buffer Manipulation Functions */ |
|
71 |
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte); |
|
72 |
uint8_t xbee_basic_buf_get(uint8_t *ptr); |
|
73 |
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte); |
|
96 | 74 |
|
97 |
#ifndef ROBOT |
|
98 |
static char* xbee_com_port = XBEE_PORT_DEFAULT; |
|
99 |
static int xbee_stream; |
|
100 |
static pthread_t* xbee_listen_thread; |
|
101 |
#endif |
|
102 | 75 |
|
76 |
/*Global Variables*/ |
|
103 | 77 |
|
104 | 78 |
// array for basic packets |
105 | 79 |
static uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE]; |
... | ... | |
122 | 96 |
static uint8_t other_buf_last = 0; |
123 | 97 |
|
124 | 98 |
|
125 |
// TODO: do we need these? |
|
126 |
static uint16_t xbee_panID = XBEE_PAN_DEFAULT; |
|
127 |
static uint8_t xbee_channel = XBEE_CHANNEL_DEFAULT; |
|
128 |
static uint16_t xbee_address = 0; |
|
129 |
|
|
130 |
|
|
131 | 99 |
// xbee status |
132 | 100 |
#define XBEE_API_OFF 0x0 |
133 | 101 |
#define XBEE_API_ON 0x1 |
... | ... | |
143 | 111 |
// external ack handler (wireless_send.c) |
144 | 112 |
extern void ackhandle(uint8_t num,uint8_t val); |
145 | 113 |
|
114 |
|
|
146 | 115 |
/**@addtogroup xbee |
147 | 116 |
* @{ **/ |
148 | 117 |
|
149 | 118 |
/*Function Implementations*/ |
150 | 119 |
|
151 |
#ifdef ROBOT |
|
152 |
|
|
153 | 120 |
/** |
154 | 121 |
* Interrupt for the robot. Adds bytes received from the xbee |
155 | 122 |
* to the buffer. |
... | ... | |
185 | 152 |
} |
186 | 153 |
} |
187 | 154 |
// signal handler that command response is done |
188 |
xbee_status |= XBEE_COMMAND_RESPONSE;
|
|
155 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_RESPONSE;
|
|
189 | 156 |
} |
190 | 157 |
return; |
191 | 158 |
} |
... | ... | |
335 | 302 |
} |
336 | 303 |
} // end of interrupt |
337 | 304 |
|
338 |
#else |
|
339 | 305 |
|
340 |
// Computer code |
|
341 | 306 |
|
342 |
/** |
|
343 |
* Thread that listens to the xbee. |
|
344 |
**/ |
|
345 |
static void* listen_to_xbee(void* x) |
|
346 |
{ |
|
347 |
char c; |
|
348 |
while (1) |
|
349 |
{ |
|
350 |
if (xbee_read(&c, 1) != 0) { |
|
351 |
WL_DEBUG_PRINT("xbee_read failed.\n"); |
|
352 |
return NULL; |
|
353 |
} |
|
354 |
|
|
355 |
arrival_buf[buffer_last] = c; |
|
356 |
int t = buffer_last + 1; |
|
357 |
if (t == XBEE_BUFFER_SIZE) |
|
358 |
t = 0; |
|
359 |
if (t == buffer_first) |
|
360 |
{ |
|
361 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
362 |
} |
|
363 |
buffer_last = t; |
|
364 |
|
|
365 |
usleep(1000); |
|
366 |
} |
|
367 |
|
|
368 |
return NULL; |
|
369 |
} |
|
370 |
|
|
371 |
#endif |
|
372 |
|
|
373 | 307 |
/* adds a byte to the basic buffer */ |
374 | 308 |
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) { |
375 | 309 |
if (*ptr == basic_buf_first) { |
... | ... | |
382 | 316 |
*ptr = 0; |
383 | 317 |
return 0; |
384 | 318 |
} |
319 |
/* gets a byte from the basic buffer */ |
|
320 |
uint8_t xbee_basic_buf_get(uint8_t *ptr) { |
|
321 |
uint8_t byte = xbee_basic_buf[(*ptr)++]; |
|
322 |
if (*ptr == PACKET_BUFFER_SIZE) |
|
323 |
*ptr = 0; |
|
324 |
return byte; |
|
325 |
} |
|
385 | 326 |
/* adds a byte to the other buffer */ |
386 | 327 |
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) { |
387 | 328 |
if (*ptr == other_buf_first) { |
... | ... | |
408 | 349 |
} |
409 | 350 |
|
410 | 351 |
WL_DEBUG_PRINT("in xbee_init\n"); |
411 |
#ifdef ROBOT |
|
412 | 352 |
|
413 | 353 |
//enable the receiving interrupt |
414 | 354 |
#ifdef FIREFLY |
... | ... | |
421 | 361 |
#endif |
422 | 362 |
#endif |
423 | 363 |
sei(); |
424 |
#else |
|
425 |
xbee_stream = open(xbee_com_port, O_RDWR); |
|
426 |
if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/) |
|
427 |
{ |
|
428 |
WL_DEBUG_PRINT("Failed to open connection to XBee on port "); |
|
429 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
430 |
WL_DEBUG_PRINT(".\n"); |
|
431 |
return -1; |
|
432 |
} else { |
|
433 |
WL_DEBUG_PRINT("Successfully opened connection to XBee on port "); |
|
434 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
435 |
WL_DEBUG_PRINT(".\n"); |
|
436 |
} |
|
437 | 364 |
|
438 |
// set baud rate, etc. correctly |
|
439 |
struct termios options; |
|
440 |
|
|
441 |
tcgetattr(xbee_stream, &options); |
|
442 |
cfsetispeed(&options, B9600); |
|
443 |
cfsetospeed(&options, B9600); |
|
444 |
options.c_iflag &= ~ICRNL; |
|
445 |
options.c_oflag &= ~OCRNL; |
|
446 |
options.c_cflag |= (CLOCAL | CREAD); |
|
447 |
options.c_cflag &= ~PARENB; |
|
448 |
options.c_cflag &= ~CSTOPB; |
|
449 |
options.c_cflag &= ~CSIZE; |
|
450 |
options.c_cflag |= CS8; |
|
451 |
options.c_lflag &= ~ICANON; |
|
452 |
options.c_cc[VMIN] = 1; |
|
453 |
options.c_cc[VTIME] = 50; |
|
454 |
|
|
455 |
if (tcsetattr(xbee_stream, TCSANOW, &options)) |
|
456 |
{ |
|
457 |
WL_DEBUG_PRINT("Error setting attributes.\n"); |
|
458 |
return -1; |
|
459 |
} |
|
460 |
|
|
461 |
xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t)); |
|
462 |
if (xbee_listen_thread == NULL) |
|
463 |
{ |
|
464 |
WL_DEBUG_PRINT("Malloc failed.\n"); |
|
465 |
return -1; |
|
466 |
} |
|
467 |
|
|
468 |
int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL); |
|
469 |
if (ret) |
|
470 |
{ |
|
471 |
WL_DEBUG_PRINT("Failed to create listener thread.\n"); |
|
472 |
return -1; |
|
473 |
} |
|
474 |
#endif |
|
475 |
|
|
476 | 365 |
WL_DEBUG_PRINT("Entering command mode.\r\n"); |
477 |
|
|
478 | 366 |
if (xbee_enter_command_mode() != 0) { |
479 | 367 |
usb_puts("error entering command mode\r\n"); |
480 | 368 |
return -1; |
481 | 369 |
} |
482 |
|
|
483 | 370 |
WL_DEBUG_PRINT("Entered command mode.\r\n"); |
484 | 371 |
|
485 | 372 |
// reset baud rate |
... | ... | |
488 | 375 |
WL_DEBUG_PRINT("\r\n"); |
489 | 376 |
|
490 | 377 |
// set baud on xbee |
491 |
//#if (XBEE_BAUD == 250000) |
|
492 | 378 |
#if (XBEE_BAUD == 115200) |
493 |
xbee_send_string("ATBD7\r\n");
|
|
379 |
xbee_send_string("ATBD7\r"); |
|
494 | 380 |
#elif (XBEE_BAUD == 57600) |
495 |
xbee_send_string("ATBD6\r\n");
|
|
381 |
xbee_send_string("ATBD6\r"); |
|
496 | 382 |
#elif (XBEE_BAUD == 38400) |
497 |
xbee_send_string("ATBD5\r\n");
|
|
383 |
xbee_send_string("ATBD5\r"); |
|
498 | 384 |
#elif (XBEE_BAUD == 19200) |
499 |
xbee_send_string("ATBD4\r\n");
|
|
385 |
xbee_send_string("ATBD4\r"); |
|
500 | 386 |
#elif (XBEE_BAUD == 9600) |
501 | 387 |
// already at this baud rate |
502 | 388 |
//xbee_send_string("ATBD3\r\n"); |
503 | 389 |
#else |
504 | 390 |
WL_DEBUG_PRINT("undefined baud rate\r\n"); |
391 |
return WL_ERROR_BAUD; |
|
505 | 392 |
#endif |
506 | 393 |
// exit command mode |
507 | 394 |
xbee_wait_for_ok(); |
508 | 395 |
WL_DEBUG_PRINT("got ok from baud reset\r\n"); |
509 |
xbee_send_string("ATCN\r\n");
|
|
396 |
xbee_send_string("ATCN\r"); |
|
510 | 397 |
xbee_wait_for_ok(); |
511 | 398 |
WL_DEBUG_PRINT("got ok from exiting command mode\r\n"); |
512 | 399 |
|
513 | 400 |
// set UART baud |
514 |
#if (XBEE_BAUD == 250000)
|
|
401 |
#if (XBEE_BAUD == 115200)
|
|
515 | 402 |
UBRR1H = 0x00; |
516 |
UBRR1L = 3; |
|
517 |
UCSR1A |= _BV(U2X1); |
|
518 |
#elif (XBEE_BAUD == 115200) |
|
519 |
UBRR1H = 0x00; |
|
520 | 403 |
UBRR1L = 8; |
521 | 404 |
UCSR1A |= _BV(U2X1); |
522 | 405 |
#elif (XBEE_BAUD == 57600) |
... | ... | |
536 | 419 |
UBRR1H = 0x00; |
537 | 420 |
UBRR1L = 103; |
538 | 421 |
UCSR1A |= _BV(U2X1);*/ |
539 |
#else //Baud rate is defined in the header file, we should not get here |
|
540 |
return 0; |
|
422 |
#else |
|
423 |
WL_DEBUG_PRINT("undefined baud rate\r\n"); |
|
424 |
return WL_ERROR_BUAD; |
|
541 | 425 |
#endif |
542 | 426 |
delay_ms(50); |
543 | 427 |
|
... | ... | |
561 | 445 |
|
562 | 446 |
WL_DEBUG_PRINT("Left command mode.\r\n"); |
563 | 447 |
|
564 |
// get baud rate |
|
565 |
if (xbee_send_read_at_command("BD")) { |
|
566 |
WL_DEBUG_PRINT("can't send BD command\r\n"); |
|
567 |
return -1; |
|
568 |
} |
|
569 |
WL_DEBUG_PRINT("Getting ATBD rate.\n"); |
|
448 |
// TODO: we should set the MY address to the robot address from eeprom |
|
570 | 449 |
|
571 |
// get MY address |
|
572 |
if (xbee_send_read_at_command("MY")) { |
|
573 |
WL_DEBUG_PRINT("can't send my command\r\n"); |
|
574 |
return -1; |
|
575 |
} |
|
576 |
WL_DEBUG_PRINT("Getting ATMY address.\n"); |
|
577 |
|
|
578 |
#ifndef ROBOT |
|
579 |
int i; |
|
580 |
for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) { |
|
581 |
ret = xbee_get_packet(NULL); |
|
582 |
|
|
583 |
usleep(1000); |
|
584 |
|
|
585 |
/* if (ret == -1) { */ |
|
586 |
/* WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */ |
|
587 |
/* return -1; */ |
|
588 |
/* } */ |
|
589 |
} |
|
590 |
#else |
|
591 |
//wait to return until the address is set |
|
592 |
//TODO: this shouldn't wait indefinitely. There should be some sort of reasonable timeout |
|
593 |
// so if the address is never set right, an error can be returned instead of having the |
|
594 |
// robot hang forever |
|
595 |
while (xbee_address == 0) { |
|
596 |
xbee_get_packet(NULL); |
|
597 |
} |
|
598 |
#endif |
|
599 |
WL_DEBUG_PRINT("Got ATMY address.\n"); |
|
600 |
|
|
601 |
#ifndef ROBOT |
|
602 |
if (i == XBEE_GET_PACKET_TIMEOUT) { // We timed-out. |
|
603 |
|
|
604 |
WL_DEBUG_PRINT("xbee_get_packet timed out.\n"); |
|
605 |
return -1; |
|
606 |
} else { |
|
607 |
return 0; |
|
608 |
} |
|
609 |
#else |
|
610 |
return 0; |
|
611 |
#endif |
|
450 |
return WL_SUCCESS; |
|
612 | 451 |
} |
613 | 452 |
|
614 | 453 |
/** |
615 |
* Call when finished using the XBee library. This releases |
|
616 |
* all sued resources. |
|
454 |
* Call when finished using the XBee library. |
|
617 | 455 |
**/ |
618 | 456 |
void xbee_terminate() |
619 | 457 |
{ |
620 |
#ifndef ROBOT |
|
621 |
pthread_cancel(*xbee_listen_thread); |
|
622 |
pthread_join(*xbee_listen_thread, NULL); |
|
623 |
free(xbee_listen_thread); |
|
624 |
lockf(xbee_stream, F_ULOCK, 0); |
|
625 |
close(xbee_stream); |
|
626 |
#else |
|
627 | 458 |
xbee_exit_api_mode(); |
628 |
#endif |
|
629 | 459 |
} |
630 | 460 |
|
631 | 461 |
/** |
... | ... | |
662 | 492 |
**/ |
663 | 493 |
static int8_t xbee_enter_command_mode() |
664 | 494 |
{ |
665 |
if (xbee_send_string("+++") != 0) {
|
|
666 |
return -1;
|
|
495 |
if (xbee_send_string("+++") != WL_SUCCESS) {
|
|
496 |
return WL_ERROR_XBEE_COMMAND;
|
|
667 | 497 |
} |
668 | 498 |
|
669 |
if (xbee_wait_for_ok() != 0) {
|
|
670 |
return -1;
|
|
499 |
if (xbee_wait_for_ok() != WL_SUCCESS) {
|
|
500 |
return WL_ERROR_XBEE_COMMAND;
|
|
671 | 501 |
} |
672 |
return 0; |
|
502 |
|
|
503 |
return WL_SUCCESS; |
|
673 | 504 |
} |
674 | 505 |
|
675 | 506 |
/** |
... | ... | |
763 | 594 |
WL_DEBUG_PRINT("\r\n"); |
764 | 595 |
return -1; |
765 | 596 |
} |
597 |
|
|
598 |
// clear response |
|
599 |
xbee_status = xbee_status&0x3F; |
|
766 | 600 |
} |
767 | 601 |
|
768 | 602 |
return 0; |
... | ... | |
791 | 625 |
i=strcspn(xbee_basic_buf,"\r"); |
792 | 626 |
if (i<PACKET_BUFFER_SIZE) { |
793 | 627 |
memcpy(s,xbee_basic_buf,i); |
628 |
xbee_status = xbee_status&0x3F; // clear response |
|
794 | 629 |
return 0; |
795 | 630 |
} |
796 | 631 |
else |
... | ... | |
802 | 637 |
return 0; |
803 | 638 |
} |
804 | 639 |
|
805 |
/** |
|
640 |
/** TODO: since we don't use this, do we need it? |
|
641 |
* |
|
806 | 642 |
* Verifies that the packets checksum is correct. |
807 | 643 |
* (If the checksum is correct, the sum of the bytes |
808 | 644 |
* is 0xFF.) |
... | ... | |
815 | 651 |
* @return 0 if the checksum is incorrect, nonzero |
816 | 652 |
* otherwise |
817 | 653 |
**/ |
818 |
int xbee_verify_checksum(char* packet, int len)
|
|
654 |
uint8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
|
|
819 | 655 |
{ |
820 |
unsigned char sum = 0; |
|
821 |
int i; |
|
822 |
for (i = 3; i < len; i++) |
|
823 |
sum += (unsigned char)packet[i]; |
|
824 |
return sum == 0xFF; |
|
656 |
uint8_t sum = 0; |
|
657 |
while(--len > 0) { |
|
658 |
sum += packet[len]; |
|
659 |
} |
|
660 |
sum += packet[0]; |
|
661 |
return (sum == 0xFF); |
|
825 | 662 |
} |
826 | 663 |
|
827 | 664 |
/** |
... | ... | |
985 | 822 |
} |
986 | 823 |
|
987 | 824 |
/** |
988 |
* Reads a packet received from the XBee. This function |
|
989 |
* is non-blocking. The resulting packet is stored in dest. |
|
990 |
* Only returns transmission response packets and |
|
991 |
* received packets. The returned packet does not include |
|
992 |
* header information or the checksum. This method also |
|
993 |
* handles special packets dealt with by the XBee library, |
|
994 |
* and so should be called frequently while the XBee is in |
|
995 |
* use.<br><br> |
|
996 |
* |
|
997 |
* The first byte of the packet will be either |
|
998 |
* XBEE_TX_STATUS or XBEE_RX to indicated |
|
999 |
* a response to a sent message or a received message, |
|
1000 |
* respectively.<br><br> |
|
1001 |
* |
|
1002 |
* For a status response packet:<br> |
|
1003 |
* The first byte will be XBEE_TX_STATUS.<br> |
|
1004 |
* The second byte will be the frame number.<br> |
|
1005 |
* The third byte will be the result. 0 indicates success, |
|
1006 |
* and nonzero indicates that an error ocurred in |
|
1007 |
* transmitting the packet.<br><br> |
|
1008 |
* |
|
1009 |
* For a received packet:<br> |
|
1010 |
* The first byte will be XBEE_RX.<br> |
|
1011 |
* The second and third bytes will be the 16-bit |
|
1012 |
* address of the packet's sender.<br> |
|
1013 |
* The fourth byte is the signal strength.<br> |
|
1014 |
* The fifth byte is 1 if the packet were sent to |
|
1015 |
* a specific address, and 2 if it is a broadcast packet.<br><br> |
|
1016 |
* |
|
1017 |
* @param dest set to the packet data |
|
1018 |
* @return the length of the packet, or -1 if no packet |
|
1019 |
* is available |
|
1020 |
**/ |
|
1021 |
int xbee_get_packet(unsigned char* dest) |
|
1022 |
{ |
|
1023 |
int ret; |
|
1024 |
//start reading a packet with XBEE_FRAME_START |
|
1025 |
if (currentBufPos == 0) |
|
1026 |
{ |
|
1027 |
do |
|
1028 |
{ |
|
1029 |
if (buffer_first == XBEE_BUFFER_SIZE) |
|
1030 |
buffer_first = 0; |
|
1031 |
// check if buffer is empty |
|
1032 |
if (buffer_first == buffer_last) { |
|
1033 |
WL_DEBUG_PRINT("buffer empty\r\n"); |
|
1034 |
return -1; |
|
1035 |
} |
|
1036 |
} while (arrival_buf[buffer_first++] != XBEE_FRAME_START); |
|
1037 |
|
|
1038 |
if (buffer_first == XBEE_BUFFER_SIZE) { |
|
1039 |
buffer_first = 0; |
|
1040 |
} |
|
1041 |
xbee_buf[0] = XBEE_FRAME_START; |
|
1042 |
currentBufPos++; |
|
1043 |
} |
|
1044 |
|
|
1045 |
int len = -1; |
|
1046 |
if (currentBufPos >= 3) { |
|
1047 |
len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8); |
|
1048 |
} |
|
1049 |
|
|
1050 |
while (len == -1 //packet length has not been read yet |
|
1051 |
|| currentBufPos < len + 4) |
|
1052 |
{ |
|
1053 |
if (currentBufPos == 3) |
|
1054 |
{ |
|
1055 |
len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8); |
|
1056 |
if (len > 120) |
|
1057 |
{ |
|
1058 |
WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\r\n"); |
|
1059 |
currentBufPos = 0; |
|
1060 |
return -1; |
|
1061 |
} |
|
1062 |
} |
|
1063 |
|
|
1064 |
// check if buffer is empty |
|
1065 |
if (buffer_first == buffer_last) { |
|
1066 |
WL_DEBUG_PRINT("Buffer empty 2\r\n"); |
|
1067 |
return -1; |
|
1068 |
} |
|
1069 |
xbee_buf[currentBufPos++] = arrival_buf[buffer_first++]; |
|
1070 |
if (buffer_first == XBEE_BUFFER_SIZE) { |
|
1071 |
buffer_first = 0; |
|
1072 |
} |
|
1073 |
} |
|
1074 |
|
|
1075 |
currentBufPos = 0; |
|
1076 |
|
|
1077 |
if (!xbee_verify_checksum(xbee_buf, len + 4)) |
|
1078 |
{ |
|
1079 |
WL_DEBUG_PRINT("XBee checksum failed.\r\n"); |
|
1080 |
return -1; |
|
1081 |
} |
|
1082 |
|
|
1083 |
//we will take care of the packet |
|
1084 |
|
|
1085 |
ret = xbee_handle_packet(xbee_buf+3, len); |
|
1086 |
if (ret == 1) { |
|
1087 |
return 3; |
|
1088 |
} else if (ret == -1) { |
|
1089 |
WL_DEBUG_PRINT("xbee_handle_packet returned -1\r\n"); |
|
1090 |
return -2; |
|
1091 |
} |
|
1092 |
|
|
1093 |
if (dest == NULL) { |
|
1094 |
WL_DEBUG_PRINT("dest buffer is null\r\n"); |
|
1095 |
return -1; |
|
1096 |
} |
|
1097 |
|
|
1098 |
int i; |
|
1099 |
for (i = 3; i < len + 3; i++) { |
|
1100 |
dest[i - 3] = xbee_buf[i]; |
|
1101 |
} |
|
1102 |
return len; |
|
1103 |
} |
|
1104 |
|
|
1105 |
/** |
|
1106 | 825 |
* Handles modem status packets. |
1107 | 826 |
* |
1108 | 827 |
* @param status the type of status packet received. |
... | ... | |
1139 | 858 |
* Handles AT command response packets. |
1140 | 859 |
* @param command the two character AT command, e.g. MY or ID |
1141 | 860 |
* @param result 0 for success, 1 for an error |
1142 |
* @param extra the hex value of the requested register |
|
1143 |
* @param extraLen the length in bytes of extra |
|
861 |
* @param len the length in bytes of extra |
|
1144 | 862 |
**/ |
1145 |
static int xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen)
|
|
863 |
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len)
|
|
1146 | 864 |
{ |
1147 | 865 |
if (result == 1) |
1148 | 866 |
{ |
... | ... | |
1160 | 878 |
WL_DEBUG_PRINT("Invalid Parameter\r\n"); |
1161 | 879 |
break; |
1162 | 880 |
} |
1163 |
return -1;
|
|
881 |
return WL_SUCCESS;
|
|
1164 | 882 |
} |
1165 | 883 |
WL_DEBUG_PRINT("AT"); |
1166 | 884 |
WL_DEBUG_PRINT(command); |
1167 | 885 |
WL_DEBUG_PRINT(" command was successful.\r\n"); |
1168 |
|
|
1169 |
if (command[0] == 'I' && command[1] == 'D') |
|
1170 |
{ |
|
1171 |
xbee_panID = xbee_pending_panID; |
|
1172 |
WL_DEBUG_PRINT("PAN ID set to "); |
|
1173 |
WL_DEBUG_PRINT_INT(xbee_panID); |
|
1174 |
WL_DEBUG_PRINT(".\r\n"); |
|
1175 |
return 0; |
|
1176 |
} |
|
1177 |
|
|
1178 |
if (command[0] == 'C' && command[1] == 'H') |
|
1179 |
{ |
|
1180 |
xbee_channel = xbee_pending_channel; |
|
1181 |
WL_DEBUG_PRINT("Channel set to "); |
|
1182 |
WL_DEBUG_PRINT_INT(xbee_channel); |
|
1183 |
WL_DEBUG_PRINT(".\r\n"); |
|
1184 |
return 0; |
|
1185 |
} |
|
1186 | 886 |
|
1187 |
if (command[0] == 'N' && command[1] == 'D') |
|
1188 |
{ |
|
1189 |
WL_DEBUG_PRINT("ND - extra="); |
|
1190 |
WL_DEBUG_PRINT(extra); |
|
1191 |
WL_DEBUG_PRINT("\r\n"); |
|
1192 |
return 0; |
|
1193 |
} |
|
887 |
// TODO: program more command responses here (ND, etc) |
|
888 |
switch(command) { |
|
889 |
case ('I'<<8)+'D': // PAN |
|
890 |
case ('C'<<8)+'H': // channel |
|
891 |
case ('M'<<8)+'Y': // address |
|
892 |
// copy command to handler |
|
893 |
xbee_command[0] = (command&0xFF00)>>8; |
|
894 |
xbee_command[1] = command&0x00FF; |
|
895 |
result = basic_buf_last; |
|
896 |
for(command=2;command<len+2;command++) |
|
897 |
xbee_command[command] = xbee_basic_buf_get(&result); |
|
898 |
break; |
|
899 |
default: |
|
900 |
WL_DEBUG_PRINT("unknown AT command"); |
|
901 |
} |
|
1194 | 902 |
|
1195 |
if (command[0] == 'B' && command[1] == 'D') |
|
1196 |
{ |
|
1197 |
WL_DEBUG_PRINT("BD - extra="); |
|
1198 |
WL_DEBUG_PRINT(extra); |
|
1199 |
WL_DEBUG_PRINT("\r\n"); |
|
1200 |
return 0; |
|
1201 |
} |
|
903 |
// signal handler that command response is done |
|
904 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_RESPONSE; |
|
1202 | 905 |
|
1203 |
if (command[0] == 'M' && command[1] == 'Y' && extraLen != 0) |
|
1204 |
{ |
|
1205 |
xbee_address = 0; |
|
1206 |
int i; |
|
1207 |
for (i = 0; i < extraLen; i++) { |
|
1208 |
xbee_address = (xbee_address << 8) + extra[i]; |
|
1209 |
} |
|
1210 |
|
|
1211 |
WL_DEBUG_PRINT("XBee address is "); |
|
1212 |
WL_DEBUG_PRINT_INT(xbee_address); |
|
1213 |
WL_DEBUG_PRINT(".\r\n"); |
|
1214 |
|
|
1215 |
if (xbee_address == 0) |
|
1216 |
{ |
|
1217 |
WL_DEBUG_PRINT("XBee 16-bit address must be set using ATMY.\r\n"); |
|
1218 |
#ifndef ROBOT |
|
1219 |
exit(0); |
|
1220 |
#endif |
|
1221 |
} |
|
1222 |
} |
|
1223 |
return 0; |
|
906 |
return WL_SUCCESS; |
|
1224 | 907 |
} |
1225 | 908 |
|
1226 | 909 |
/** |
... | ... | |
1248 | 931 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
1249 | 932 |
xbee_status = xbee_status&0x3F; // reset status |
1250 | 933 |
return (int8_t)i; // return |
1251 |
/* old version |
|
1252 |
char s[3]; |
|
1253 |
s[0] = (id >> 8) & 0xFF; |
|
1254 |
s[1] = id & 0xFF; |
|
1255 |
s[2] = 0; |
|
1256 |
xbee_pending_panID = id; |
|
1257 |
return xbee_send_modify_at_command("ID", s); */ |
|
1258 | 934 |
} |
1259 | 935 |
|
1260 | 936 |
/** |
... | ... | |
1357 | 1033 |
* |
1358 | 1034 |
* @return the 16-bit address of the XBee. |
1359 | 1035 |
**/ |
1360 |
uint16_t xbee_get_address() |
|
1036 |
uint16_t xbee_get_address(void)
|
|
1361 | 1037 |
{ |
1362 | 1038 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
1363 | 1039 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
Also available in: Unified diff