Revision 1600
wireless: xbee update. still not finished, but the major changes are in here. Also added a function for microsecond delays to time.c
xbee.c | ||
---|---|---|
100 | 100 |
static pthread_t* xbee_listen_thread; |
101 | 101 |
#endif |
102 | 102 |
|
103 |
// TODO: clarify buffers, what they're used for, etc |
|
104 | 103 |
|
105 |
// a buffer for data received from the XBee |
|
106 |
char arrival_buf[XBEE_BUFFER_SIZE]; |
|
107 |
// location of last unread byte in buffer |
|
108 |
volatile int buffer_last = 0; |
|
109 |
// first unread byte in buffer |
|
110 |
volatile int buffer_first = 0; |
|
111 |
|
|
112 |
|
|
113 |
// old xbee buf |
|
114 |
static char xbee_buf[PACKET_BUFFER_SIZE]; |
|
115 |
static int currentBufPos = 0; |
|
116 |
|
|
117 | 104 |
// array for basic packets |
118 | 105 |
static uint8_t xbee_basic_buf[PACKET_BUFFER_SIZE]; |
119 | 106 |
|
... | ... | |
134 | 121 |
// aka, the first free byte in other buffer |
135 | 122 |
static uint8_t other_buf_last = 0; |
136 | 123 |
|
137 |
//XBee status |
|
138 |
static unsigned int xbee_panID = XBEE_PAN_DEFAULT; |
|
139 |
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT; |
|
140 |
static int xbee_channel = XBEE_CHANNEL_DEFAULT; |
|
141 |
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT; |
|
142 |
static volatile unsigned int xbee_address = 0; |
|
143 | 124 |
|
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; |
|
144 | 129 |
|
130 |
|
|
131 |
// xbee status |
|
132 |
#define XBEE_API_OFF 0x0 |
|
133 |
#define XBEE_API_ON 0x1 |
|
134 |
#define XBEE_API_ESCAPE 0x2 |
|
135 |
#define XBEE_NORMAL 0x00 |
|
136 |
#define XBEE_COMMAND_WAIT 0x80 |
|
137 |
#define XBEE_COMMAND_RESPONSE 0xC0 |
|
138 |
static uint8_t xbee_status = XBEE_API_OFF|XBEE_NORMAL; |
|
139 |
|
|
140 |
// xbee command response (for PAN, channel, address, etc) |
|
141 |
static uint8_t xbee_command[4]; |
|
142 |
|
|
145 | 143 |
// external ack handler (wireless_send.c) |
146 | 144 |
extern void ackhandle(uint8_t num,uint8_t val); |
147 | 145 |
|
148 | 146 |
/**@addtogroup xbee |
149 | 147 |
* @{ **/ |
150 | 148 |
|
151 |
|
|
152 | 149 |
/*Function Implementations*/ |
153 | 150 |
|
154 | 151 |
#ifdef ROBOT |
... | ... | |
171 | 168 |
uint8_t apitype = PORT; // get frame start byte |
172 | 169 |
uint16_t i=0; |
173 | 170 |
uint16_t len=0; |
171 |
|
|
172 |
// check that we're in API mode |
|
173 |
if (xbee_status&0x03 == XBEE_API_OFF || apitype != XBEE_FRAME_START) { |
|
174 |
// not in API mode |
|
175 |
if (xbee_status&0xC0) == XBEE_COMMAND_WAIT) { |
|
176 |
// get rest of command and put in basic buf |
|
177 |
xbee_basic_buf[0] = apitype; |
|
178 |
if (xbee_basic_buf[i] != '\r') { |
|
179 |
while(i < PACKET_BUFFER_SIZE) { |
|
180 |
if (FLAG) { |
|
181 |
xbee_basic_buf[i] = PORT; |
|
182 |
if (xbee_basic_buf[i] == '\r') |
|
183 |
break; |
|
184 |
} |
|
185 |
} |
|
186 |
} |
|
187 |
// signal handler that command response is done |
|
188 |
xbee_status |= XBEE_COMMAND_RESPONSE; |
|
189 |
} |
|
190 |
return; |
|
191 |
} |
|
192 |
|
|
174 | 193 |
// get length and type |
175 | 194 |
while(i<3) { |
176 | 195 |
if (FLAG) { |
... | ... | |
187 | 206 |
// do something based on the type |
188 | 207 |
i=1; |
189 | 208 |
switch(apitype) { |
190 |
case 0x88:
|
|
209 |
case XBEE_FRAME_AT_COMMAND_RESPONSE:
|
|
191 | 210 |
// AT command response |
211 |
if (xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
212 |
return; // we're currently processing a command, so drop the incoming one |
|
192 | 213 |
uint16_t atcommand=0; |
193 | 214 |
uint8_t ptr=basic_buf_last; |
194 | 215 |
while(i<len) { |
... | ... | |
203 | 224 |
apitype = PORT; // get status |
204 | 225 |
else { |
205 | 226 |
// put the command response on the basic buf temporarily |
206 |
if (ptr == basic_buf_first) { |
|
207 |
// buffer full |
|
208 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
|
227 |
if (xbee_basic_buf_add(&ptr,PORT) != 0) |
|
209 | 228 |
break; |
210 |
} |
|
211 |
xbee_basic_buf[ptr++]=PORT; |
|
212 |
if (ptr == PACKET_BUFFER_SIZE) |
|
213 |
ptr = 0; |
|
214 | 229 |
} |
215 | 230 |
i++; |
216 | 231 |
} |
217 |
} |
|
218 |
// handle AT command |
|
219 |
xbee_handle_at_command_response(atcommand,apitype,xbee_basic_buf+basic_buf_last,len-5);
|
|
232 |
}
|
|
233 |
// handle AT command
|
|
234 |
xbee_handle_at_command_response(atcommand,apitype,i-5); // TODO: rewrite function
|
|
220 | 235 |
break; |
221 |
case 0x89:
|
|
236 |
case XBEE_FRAME_TX_STATUS:
|
|
222 | 237 |
// TX status |
223 | 238 |
uint8_t frameid=0; |
224 | 239 |
while(i<len) { |
... | ... | |
233 | 248 |
} |
234 | 249 |
} |
235 | 250 |
break; |
236 |
case 0x80:
|
|
251 |
case XBEE_FRAME_RX_64:
|
|
237 | 252 |
// receive a packet with 64bit address |
238 |
break; // not implemented yet
|
|
239 |
case 0x81:
|
|
253 |
break; // TODO: implement this (even if we don't use it)
|
|
254 |
case XBEE_FRAME_RX_16:
|
|
240 | 255 |
// receive a packet with 16bit address |
241 | 256 |
uint16_t source = 0; |
242 | 257 |
uint8_t framenum = 0; |
... | ... | |
265 | 280 |
if (group == 0) { |
266 | 281 |
ptr = basic_buf_last+1; |
267 | 282 |
// add source to buffer |
268 |
if (ptr == basic_buf_first) { |
|
269 |
// buffer full |
|
270 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
|
283 |
if (xbee_basic_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) |
|
271 | 284 |
break; |
272 |
} |
|
273 |
xbee_basic_buf[ptr++] = (uint8_t)((source&0xFF00)>>8); |
|
274 |
if (ptr == PACKET_BUFFER_SIZE) |
|
275 |
ptr = 0; |
|
276 |
if (ptr == basic_buf_first) { |
|
277 |
// buffer full |
|
278 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
|
285 |
if (xbee_basic_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) |
|
279 | 286 |
break; |
280 |
} |
|
281 |
xbee_basic_buf[ptr++] = (uint8_t)(source&0x00FF); |
|
282 |
if (ptr == PACKET_BUFFER_SIZE) |
|
283 |
ptr = 0; |
|
284 | 287 |
} else { |
285 | 288 |
ptr = other_buf_last+1; |
286 |
// add source and group to buffer |
|
287 |
if (ptr == other_buf_first) { |
|
288 |
// buffer full |
|
289 |
WL_DEBUG_PRINT("other buffer full\r\n"); |
|
289 |
// add source and group to buffer |
|
290 |
if (xbee_other_buf_add(&ptr,group) != 0) |
|
290 | 291 |
break; |
291 |
} |
|
292 |
xbee_other_buf[ptr++] = group; |
|
293 |
if (ptr == PACKET_BUFFER_SIZE) |
|
294 |
ptr = 0; |
|
295 |
if (ptr == other_buf_first) { |
|
296 |
// buffer full |
|
297 |
WL_DEBUG_PRINT("other buffer full\r\n"); |
|
292 |
if (xbee_other_buf_add(&ptr,(uint8_t)((source&0xFF00)>>8)) != 0) |
|
298 | 293 |
break; |
299 |
} |
|
300 |
xbee_other_buf[ptr++] = (uint8_t)((source&0xFF00)>>8); |
|
301 |
if (ptr == PACKET_BUFFER_SIZE) |
|
302 |
ptr = 0; |
|
303 |
if (ptr == other_buf_first) { |
|
304 |
// buffer full |
|
305 |
WL_DEBUG_PRINT("other buffer full\r\n"); |
|
294 |
if (xbee_other_buf_add(&ptr,(uint8_t)(source&0x00FF)) != 0) |
|
306 | 295 |
break; |
307 |
} |
|
308 |
xbee_other_buf[ptr++] = (uint8_t)(source&0x00FF); |
|
309 |
if (ptr == PACKET_BUFFER_SIZE) |
|
310 |
ptr = 0; |
|
311 | 296 |
} |
312 | 297 |
} |
313 |
else { |
|
298 |
else { // TODO: handle escaped characters supported by APIv2
|
|
314 | 299 |
// put packet data on the correct buffer |
315 |
if (group == 0) { |
|
316 |
if (ptr == basic_buf_first) { |
|
317 |
// buffer full |
|
318 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
|
319 |
break; |
|
320 |
} |
|
321 |
xbee_basic_buf[ptr++]=PORT; |
|
322 |
if (ptr == PACKET_BUFFER_SIZE) |
|
323 |
ptr = 0; |
|
324 |
} else { |
|
325 |
if (ptr == other_buf_first) { |
|
326 |
// buffer full |
|
327 |
WL_DEBUG_PRINT("other buffer full\r\n"); |
|
328 |
break; |
|
329 |
} |
|
330 |
xbee_other_buf[ptr++]=PORT; |
|
331 |
if (ptr == PACKET_BUFFER_SIZE) |
|
332 |
ptr = 0; |
|
333 |
} |
|
300 |
if (group == 0 && xbee_basic_buf_add(&ptr,PORT) != 0) |
|
301 |
break; |
|
302 |
else if (xbee_other_buf_add(&ptr,PORT) != 0) |
|
303 |
break; |
|
334 | 304 |
} |
335 | 305 |
i++; |
336 | 306 |
} |
337 | 307 |
} |
338 |
if (ptr != 0xFF) { |
|
308 |
if (ptr != 0xFF && i > 6) {
|
|
339 | 309 |
if (group == 0) { |
340 | 310 |
xbee_basic_buf[basic_buf_last] = i-6; // set length |
341 | 311 |
basic_buf_last = ptr; |
... | ... | |
356 | 326 |
} |
357 | 327 |
} |
358 | 328 |
break; |
329 |
} // end of switch statement |
|
330 |
while (1) { |
|
331 |
if (FLAG) { |
|
332 |
apitype = PORT; // get checksum, and ignore |
|
333 |
break; |
|
334 |
} |
|
359 | 335 |
} |
360 | 336 |
} // end of interrupt |
361 | 337 |
|
... | ... | |
394 | 370 |
|
395 | 371 |
#endif |
396 | 372 |
|
373 |
/* adds a byte to the basic buffer */ |
|
374 |
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte) { |
|
375 |
if (*ptr == basic_buf_first) { |
|
376 |
// buffer full |
|
377 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
|
378 |
return -1; |
|
379 |
} |
|
380 |
xbee_basic_buf[(*ptr)++] = byte); |
|
381 |
if (*ptr == PACKET_BUFFER_SIZE) |
|
382 |
*ptr = 0; |
|
383 |
return 0; |
|
384 |
} |
|
385 |
/* adds a byte to the other buffer */ |
|
386 |
int8_t xbee_other_buf_add(uint8_t *ptr, uint8_t byte) { |
|
387 |
if (*ptr == other_buf_first) { |
|
388 |
// buffer full |
|
389 |
WL_DEBUG_PRINT("other buffer full\r\n"); |
|
390 |
return -1; |
|
391 |
} |
|
392 |
xbee_other_buf[(*ptr)++] = byte; |
|
393 |
if (ptr == PACKET_BUFFER_SIZE) |
|
394 |
*ptr = 0; |
|
395 |
return 0; |
|
396 |
} |
|
397 |
|
|
398 |
|
|
397 | 399 |
/** |
398 | 400 |
* Initializes the XBee library so that other functions may be used. |
399 | 401 |
**/ |
400 |
int xbee_lib_init() |
|
402 |
int8_t xbee_lib_init()
|
|
401 | 403 |
{ |
404 |
// do serial.c xbee init TODO: merge this into xbee.c |
|
402 | 405 |
if (xbee_init() != 0) { |
403 | 406 |
usb_puts("xbee_init error"); |
404 |
return -1;
|
|
407 |
return WL_ERROR_INIT_FAILED;
|
|
405 | 408 |
} |
406 | 409 |
|
407 | 410 |
WL_DEBUG_PRINT("in xbee_init\n"); |
... | ... | |
558 | 561 |
|
559 | 562 |
WL_DEBUG_PRINT("Left command mode.\r\n"); |
560 | 563 |
|
561 |
// get MY address
|
|
564 |
// get baud rate
|
|
562 | 565 |
if (xbee_send_read_at_command("BD")) { |
563 | 566 |
WL_DEBUG_PRINT("can't send BD command\r\n"); |
564 | 567 |
return -1; |
... | ... | |
631 | 634 |
* @param buf the buffer of data to send |
632 | 635 |
* @param size the number of bytes to send |
633 | 636 |
**/ |
634 |
static int xbee_send(char* buf, int size)
|
|
637 |
static int8_t xbee_send(uint8_t* buf, uint16_t size)
|
|
635 | 638 |
{ |
636 |
#ifdef ROBOT |
|
637 |
int i; |
|
638 |
for (i = 0; i < size; i++) { |
|
639 |
xbee_putc(buf[i]); |
|
640 |
} |
|
639 |
while(--size > 0) |
|
640 |
if (xbee_putc(buf[i]) != WL_SUCCESS) |
|
641 |
return WL_ERROR_SEND; |
|
642 |
} |
|
643 |
if (xbee_putc(buf[0]) != WL_SUCCESS) |
|
644 |
return WL_ERROR_SEND; |
|
641 | 645 |
|
642 |
return 0; |
|
643 |
|
|
644 |
#else |
|
645 |
|
|
646 |
int ret = write(xbee_stream, buf, size); |
|
647 |
//success |
|
648 |
if (ret == size) |
|
649 |
return 0; |
|
650 |
if (ret == -1) |
|
651 |
{ |
|
652 |
//interrupted by system signal, probably timer interrupt. |
|
653 |
//just try again |
|
654 |
if (errno == 4) |
|
655 |
{ |
|
656 |
return xbee_send(buf, size); |
|
657 |
} |
|
658 |
WL_DEBUG_PRINT("Failed to write to xbee\r\n"); |
|
659 |
return -1; |
|
660 |
} |
|
661 |
|
|
662 |
//write was interrupted after writing ret bytes |
|
663 |
return xbee_send(buf + ret, size - ret); |
|
664 |
#endif |
|
646 |
return WL_SUCCESS; |
|
665 | 647 |
} |
666 | 648 |
|
667 | 649 |
/** |
... | ... | |
669 | 651 |
* |
670 | 652 |
* @param c the string to send to the XBEE |
671 | 653 |
**/ |
672 |
static int xbee_send_string(char* c)
|
|
654 |
static int8_t xbee_send_string(unsigned char* c)
|
|
673 | 655 |
{ |
674 | 656 |
return xbee_send(c, strlen(c)); |
675 | 657 |
} |
676 | 658 |
|
677 |
#ifndef ROBOT |
|
678 |
static int xbee_read(char* buf, int size) |
|
679 |
{ |
|
680 |
if (read(xbee_stream, buf, size) == -1) { |
|
681 |
WL_DEBUG_PRINT("Failed to read from xbee.\r\n"); |
|
682 |
return -1; |
|
683 |
} |
|
684 | 659 |
|
685 |
return 0; |
|
686 |
} |
|
687 |
#endif |
|
688 |
|
|
689 | 660 |
/** |
690 | 661 |
* Enter into command mode. |
691 | 662 |
**/ |
692 |
static int xbee_enter_command_mode() |
|
663 |
static int8_t xbee_enter_command_mode()
|
|
693 | 664 |
{ |
694 | 665 |
if (xbee_send_string("+++") != 0) { |
695 | 666 |
return -1; |
... | ... | |
704 | 675 |
/** |
705 | 676 |
* Exit from command mode. |
706 | 677 |
**/ |
707 |
static int xbee_exit_command_mode() |
|
678 |
static int8_t xbee_exit_command_mode()
|
|
708 | 679 |
{ |
709 | 680 |
if (xbee_send_string("ATCN\r") != 0) { |
710 | 681 |
return -1; |
... | ... | |
724 | 695 |
return -1; |
725 | 696 |
} |
726 | 697 |
xbee_wait_for_ok(); |
698 |
|
|
699 |
xbee_status = (xbee_status&0xFC)|XBEE_API_ON; |
|
727 | 700 |
|
728 | 701 |
return 0; |
729 | 702 |
} |
730 | 703 |
|
731 | 704 |
/** |
705 |
* Enter API mode 2. |
|
706 |
**/ |
|
707 |
static int xbee_enter_api_mode2() |
|
708 |
{ |
|
709 |
if (xbee_send_string("ATAP 2\r") != 0) { |
|
710 |
return -1; |
|
711 |
} |
|
712 |
xbee_wait_for_ok(); |
|
713 |
|
|
714 |
xbee_status = (xbee_status&0xFC)|XBEE_API_ESCAPE; |
|
715 |
|
|
716 |
return 0; |
|
717 |
} |
|
718 |
|
|
719 |
/** |
|
732 | 720 |
* Exit API mode. |
733 | 721 |
**/ |
734 | 722 |
static int xbee_exit_api_mode() |
... | ... | |
736 | 724 |
if (xbee_send_modify_at_command("AP","0") != 0) { |
737 | 725 |
return -1; |
738 | 726 |
} |
727 |
|
|
728 |
xbee_status = (xbee_status&0xFC)|XBEE_API_OFF; |
|
739 | 729 |
|
740 | 730 |
return 0; |
741 | 731 |
} |
... | ... | |
757 | 747 |
* @param s the string to receive |
758 | 748 |
* @param len the length of the string |
759 | 749 |
**/ |
760 |
static int xbee_wait_for_string(char* s, int len) |
|
750 |
static int8_t xbee_wait_for_string(char* s, int len)
|
|
761 | 751 |
{ |
762 |
char* curr = s; |
|
763 |
unsigned int i=0; |
|
764 |
while (curr - s < len) { |
|
765 |
WL_DEBUG_PRINT("waiting for string\r\n"); |
|
766 |
// check if buffer is empty |
|
767 |
if (buffer_last != buffer_first) { |
|
768 |
char c = arrival_buf[buffer_first++]; |
|
769 |
if (buffer_first == XBEE_BUFFER_SIZE) { |
|
770 |
buffer_first = 0; |
|
771 |
} |
|
772 |
WL_DEBUG_PRINT("buffer char|"); |
|
773 |
WL_DEBUG_PRINT_CHAR(c); |
|
774 |
WL_DEBUG_PRINT("|\r\n"); |
|
752 |
uint8_t i=0; |
|
753 |
if (xbee_status&0x03 == XBEE_API_OFF) { |
|
754 |
// wait until the response is received (only wait 1 second) |
|
755 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 1000) { |
|
756 |
delay_us(1); |
|
757 |
} |
|
758 |
// check response |
|
759 |
if (i >= 1000 || memcmp(s,xbee_basic_buf,len) != 0) { |
|
760 |
// bad response |
|
761 |
WL_DEBUG_PRINT("Bad response when waiting for string "); |
|
762 |
WL_DEBUG_PRINT(s); |
|
763 |
WL_DEBUG_PRINT("\r\n"); |
|
764 |
return -1; |
|
765 |
} |
|
766 |
} |
|
775 | 767 |
|
776 |
if (c == *curr) { |
|
777 |
curr++; |
|
778 |
} else { |
|
779 |
#ifndef ROBOT |
|
780 |
//return -1; // Computer is less forgiving. |
|
781 |
curr = s; |
|
782 |
#else |
|
783 |
curr = s; |
|
784 |
#endif |
|
785 |
} |
|
786 |
} // else buffer is empty. |
|
787 |
|
|
788 |
#ifndef ROBOT |
|
789 |
usleep(100); |
|
790 |
#endif |
|
791 |
} |
|
792 |
if (i >= 10000) |
|
793 |
return -1; |
|
794 |
|
|
795 | 768 |
return 0; |
796 | 769 |
} |
797 | 770 |
|
798 | 771 |
/** |
772 |
* Delay until we receive a command response. |
|
773 |
* (either OK\r or some actual value) |
|
774 |
* |
|
775 |
* Only works when not in API mode |
|
776 |
* |
|
777 |
* @param s the string to store the response in |
|
778 |
* @param len the length of the string |
|
779 |
*/ |
|
780 |
static int8_t xbee_wait_for_response(char* s, int len) { |
|
781 |
uint8_t i=0; |
|
782 |
if (xbee_status&0x03 == XBEE_API_OFF) { |
|
783 |
// wait until the response is received (only wait 1 second) |
|
784 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 1000) { |
|
785 |
delay_us(1); |
|
786 |
} |
|
787 |
// check response |
|
788 |
if (i >= 1000) |
|
789 |
return -1; |
|
790 |
} else { |
|
791 |
i=strcspn(xbee_basic_buf,"\r"); |
|
792 |
if (i<PACKET_BUFFER_SIZE) { |
|
793 |
memcpy(s,xbee_basic_buf,i); |
|
794 |
return 0; |
|
795 |
} |
|
796 |
else |
|
797 |
return -1; |
|
798 |
} |
|
799 |
} |
|
800 |
// TODO: do something for API mode |
|
801 |
|
|
802 |
return 0; |
|
803 |
} |
|
804 |
|
|
805 |
/** |
|
799 | 806 |
* Verifies that the packets checksum is correct. |
800 | 807 |
* (If the checksum is correct, the sum of the bytes |
801 | 808 |
* is 0xFF.) |
... | ... | |
826 | 833 |
* @return the checksum of the packet, which will |
827 | 834 |
* become the last byte sent in the packet |
828 | 835 |
**/ |
829 |
char xbee_compute_checksum(char* buf, int len)
|
|
836 |
char xbee_compute_checksum(uint8_t* buf, uint16_t len)
|
|
830 | 837 |
{ |
831 |
int i; |
|
832 |
unsigned char sum = 0; |
|
833 |
for (i = 0; i < len; i++) |
|
834 |
sum += (unsigned char)buf[i]; |
|
838 |
uint8_t sum = 0; |
|
839 |
while(--len > 0) { |
|
840 |
sum += buf[len]; |
|
841 |
} |
|
842 |
sum += buf[0]; |
|
835 | 843 |
return 0xFF - sum; |
836 | 844 |
} |
837 | 845 |
|
... | ... | |
844 | 852 |
* @param len the size in bytes of the packet data |
845 | 853 |
* |
846 | 854 |
**/ |
847 |
static int xbee_send_frame(char* buf, int len)
|
|
855 |
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len)
|
|
848 | 856 |
{ |
849 |
char prefix[3];
|
|
857 |
uint8_t prefix[3];
|
|
850 | 858 |
prefix[0] = XBEE_FRAME_START; |
851 | 859 |
prefix[1] = (len & 0xFF00) >> 8; |
852 |
prefix[2] = len & 0xFF; |
|
853 |
char checksum = xbee_compute_checksum(buf, len);
|
|
860 |
prefix[2] = len & 0x00FF;
|
|
861 |
uint8_t checksum = xbee_compute_checksum(buf, len);
|
|
854 | 862 |
|
855 | 863 |
if (xbee_send(prefix, 3) != 0) { |
856 |
return -1;
|
|
864 |
return WL_ERROR_SEND;
|
|
857 | 865 |
} |
858 | 866 |
|
859 | 867 |
if (xbee_send(buf, len) != 0) { |
860 |
return -1;
|
|
868 |
return WL_ERROR_SEND;
|
|
861 | 869 |
} |
862 | 870 |
|
863 | 871 |
if (xbee_send(&checksum, 1) != 0) { |
864 |
return -1;
|
|
872 |
return WL_ERROR_SEND;
|
|
865 | 873 |
} |
866 | 874 |
|
867 |
return 0;
|
|
875 |
return WL_SUCCESS;
|
|
868 | 876 |
} |
869 | 877 |
|
870 | 878 |
/** |
... | ... | |
874 | 882 |
* use ID to read the PAN ID and MY to return the XBee ID. |
875 | 883 |
* See the XBee reference guide for a complete listing. |
876 | 884 |
**/ |
877 |
int xbee_send_read_at_command(char* command)
|
|
885 |
int8_t xbee_send_read_at_command(uint8_t* command)
|
|
878 | 886 |
{ |
879 |
return xbee_send_modify_at_command(command, NULL); |
|
887 |
return xbee_send_modify_at_command(command, NULL, 0);
|
|
880 | 888 |
} |
881 | 889 |
|
882 | 890 |
/** |
... | ... | |
886 | 894 |
* @param value the value to pass as a parameter |
887 | 895 |
* (or NULL if there is no parameter) |
888 | 896 |
**/ |
889 |
static int xbee_send_modify_at_command(char* command, char* value)
|
|
897 |
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len)
|
|
890 | 898 |
{ |
891 |
char buf[16]; |
|
892 |
int i; |
|
899 |
uint8_t buf[12]; |
|
893 | 900 |
|
894 | 901 |
buf[0] = XBEE_FRAME_AT_COMMAND; |
895 | 902 |
buf[1] = 1; |
896 | 903 |
buf[2] = command[0]; |
897 | 904 |
buf[3] = command[1]; |
898 |
int valueLen = 0; |
|
899 | 905 |
if (value != NULL) |
900 | 906 |
{ |
901 |
valueLen = strlen(value); |
|
902 |
if (valueLen > 8) |
|
907 |
if (len > 8) |
|
903 | 908 |
{ |
904 | 909 |
WL_DEBUG_PRINT("AT Command too large.\r\n"); |
905 |
return -1;
|
|
910 |
return WL_ERROR_ARGUMENT;
|
|
906 | 911 |
} |
907 |
|
|
908 |
for (i = 0; i < valueLen; i++) { |
|
909 |
buf[4 + i] = value[i]; |
|
910 |
} |
|
912 |
memcpy(buf+4,value,len); |
|
911 | 913 |
} |
912 | 914 |
|
913 |
return xbee_send_frame(buf, 4 + valueLen);
|
|
915 |
return xbee_send_frame(buf, 4 + len);
|
|
914 | 916 |
} |
915 | 917 |
|
916 | 918 |
/** |
... | ... | |
1222 | 1224 |
} |
1223 | 1225 |
|
1224 | 1226 |
/** |
1225 |
* Attempts to handle the packet if it is dealt with |
|
1226 |
* by the library. |
|
1227 |
* We will handle the following packet types: |
|
1228 |
* Modem Status |
|
1229 |
* AT Command Response |
|
1230 |
* |
|
1231 |
* @param packet the packet to handle |
|
1232 |
* @param len the length of the packet |
|
1233 |
* |
|
1234 |
* @return 1 if we have handled the packet, 0 otherwise |
|
1235 |
*/ |
|
1236 |
static int xbee_handle_packet(char* packet, int len) |
|
1237 |
{ |
|
1238 |
|
|
1239 |
char command[3] = {1, 2, 3}; |
|
1240 |
if (len <= 0) //this should not happend |
|
1241 |
{ |
|
1242 |
WL_DEBUG_PRINT("Non-positive packet length.\r\n"); |
|
1243 |
return 0; |
|
1244 |
} |
|
1245 |
|
|
1246 |
switch ((unsigned char)packet[0]) //packet type |
|
1247 |
{ |
|
1248 |
case XBEE_FRAME_STATUS: |
|
1249 |
xbee_handle_status(packet[1]); |
|
1250 |
return 1; |
|
1251 |
case XBEE_FRAME_AT_COMMAND_RESPONSE: |
|
1252 |
command[0] = packet[2]; |
|
1253 |
command[1] = packet[3]; |
|
1254 |
command[2] = 0; |
|
1255 |
if (xbee_handle_at_command_response(command, packet[4], packet + 5, len - 5) != 0) |
|
1256 |
return -1; |
|
1257 |
else |
|
1258 |
return 1; |
|
1259 |
} |
|
1260 |
return 0; |
|
1261 |
} |
|
1262 |
|
|
1263 |
/** |
|
1264 | 1227 |
* Sets the personal area network id. |
1265 | 1228 |
* |
1266 | 1229 |
* @param id the new personal area network (PAN) id |
1267 | 1230 |
**/ |
1268 |
int xbee_set_pan_id(int id)
|
|
1231 |
int8_t xbee_set_pan_id(uint16_t id)
|
|
1269 | 1232 |
{ |
1270 |
char s[3]; |
|
1233 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
|
1234 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
1235 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
|
1236 |
|
|
1237 |
int16_t i=0; |
|
1238 |
// change status to command wait |
|
1239 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
|
1240 |
xbee_send_modify_at_command("ID",id); // send command to set the channel |
|
1241 |
// wait for up to 30 ms |
|
1242 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
|
1243 |
delay_us(1); // wait 3us |
|
1244 |
} |
|
1245 |
if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K') { |
|
1246 |
i = WL_SUCCESS; |
|
1247 |
else |
|
1248 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
|
1249 |
xbee_status = xbee_status&0x3F; // reset status |
|
1250 |
return (int8_t)i; // return |
|
1251 |
/* old version |
|
1252 |
char s[3]; |
|
1271 | 1253 |
s[0] = (id >> 8) & 0xFF; |
1272 | 1254 |
s[1] = id & 0xFF; |
1273 | 1255 |
s[2] = 0; |
1274 | 1256 |
xbee_pending_panID = id; |
1275 |
return xbee_send_modify_at_command("ID", s); |
|
1257 |
return xbee_send_modify_at_command("ID", s); */
|
|
1276 | 1258 |
} |
1277 | 1259 |
|
1278 | 1260 |
/** |
... | ... | |
1281 | 1263 |
* @return the personal area network id, or |
1282 | 1264 |
* XBEE_PAN_DEFAULT if it has not yet been set. |
1283 | 1265 |
**/ |
1284 |
unsigned int xbee_get_pan_id()
|
|
1266 |
uint16_t xbee_get_pan_id()
|
|
1285 | 1267 |
{ |
1286 |
return xbee_panID; |
|
1268 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
|
1269 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
1270 |
return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now |
|
1271 |
|
|
1272 |
uint16_t i=0; |
|
1273 |
// change status to command wait |
|
1274 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
|
1275 |
xbee_send_read_at_command("ID"); // send command to get the PAN |
|
1276 |
// wait for up to 30 ms |
|
1277 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
|
1278 |
delay_us(1); // wait 3us |
|
1279 |
} |
|
1280 |
if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D') { |
|
1281 |
i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN |
|
1282 |
else |
|
1283 |
i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code |
|
1284 |
xbee_status = xbee_status&0x3F; // reset status |
|
1285 |
return i; // return |
|
1287 | 1286 |
} |
1288 | 1287 |
|
1289 | 1288 |
/** |
... | ... | |
1294 | 1293 |
* |
1295 | 1294 |
* @see xbee_get_channel |
1296 | 1295 |
**/ |
1297 |
int xbee_set_channel(int channel)
|
|
1296 |
int8_t xbee_set_channel(uint8_t channel)
|
|
1298 | 1297 |
{ |
1299 | 1298 |
if (channel < 0x0B || channel > 0x1A) |
1300 | 1299 |
{ |
... | ... | |
1302 | 1301 |
return -1; |
1303 | 1302 |
} |
1304 | 1303 |
|
1305 |
char s[3]; |
|
1306 |
s[0] = channel & 0xFF; |
|
1307 |
s[1] = 0; |
|
1308 |
xbee_pending_channel = channel; |
|
1309 |
|
|
1310 |
return xbee_send_modify_at_command("CH", s); |
|
1304 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
|
1305 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
1306 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
|
1307 |
|
|
1308 |
int16_t i=0; |
|
1309 |
// change status to command wait |
|
1310 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
|
1311 |
xbee_send_modify_at_command("CH",channel); // send command to set the channel |
|
1312 |
// wait for up to 30 ms |
|
1313 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
|
1314 |
delay_us(1); // wait 3us |
|
1315 |
} |
|
1316 |
if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K') { |
|
1317 |
i = WL_SUCCESS; |
|
1318 |
else |
|
1319 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
|
1320 |
xbee_status = xbee_status&0x3F; // reset status |
|
1321 |
return (int8_t)i; // return |
|
1311 | 1322 |
} |
1312 | 1323 |
|
1313 | 1324 |
/** |
... | ... | |
1317 | 1328 |
* |
1318 | 1329 |
* @see xbee_set_channel |
1319 | 1330 |
**/ |
1320 |
int xbee_get_channel(void) |
|
1331 |
int8_t xbee_get_channel(void)
|
|
1321 | 1332 |
{ |
1322 |
return xbee_channel; |
|
1333 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
|
1334 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
1335 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
|
1336 |
|
|
1337 |
int16_t i=0; |
|
1338 |
// change status to command wait |
|
1339 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
|
1340 |
xbee_send_read_at_command("ID"); // send command to get the channel |
|
1341 |
// wait for up to 30 ms |
|
1342 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
|
1343 |
delay_us(1); // wait 3us |
|
1344 |
} |
|
1345 |
if (i < 1000 && xbee_command[0] == 'C' && xbee_command[1] == 'H') { |
|
1346 |
i = xbee_command[2]; // get channel |
|
1347 |
else |
|
1348 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
|
1349 |
xbee_status = xbee_status&0x3F; // reset status |
|
1350 |
return i; // return |
|
1323 | 1351 |
} |
1324 | 1352 |
|
1325 | 1353 |
/** |
... | ... | |
1329 | 1357 |
* |
1330 | 1358 |
* @return the 16-bit address of the XBee. |
1331 | 1359 |
**/ |
1332 |
unsigned int xbee_get_address()
|
|
1360 |
uint16_t xbee_get_address()
|
|
1333 | 1361 |
{ |
1334 |
return xbee_address; |
|
1362 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT |
|
1363 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE) |
|
1364 |
return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now |
|
1365 |
|
|
1366 |
uint16_t i=0; |
|
1367 |
// change status to command wait |
|
1368 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
|
1369 |
xbee_send_read_at_command("MY"); // send command to get the address |
|
1370 |
// wait for up to 30 ms |
|
1371 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
|
1372 |
delay_us(1); // wait 3us |
|
1373 |
} |
|
1374 |
if (i < 1000 && xbee_command[0] == 'M' && xbee_command[1] == 'Y') { |
|
1375 |
i = (xbee_command[2]<<8)+xbee_command[3]; // get address |
|
1376 |
else |
|
1377 |
i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code |
|
1378 |
xbee_status = xbee_status&0x3F; // reset status |
|
1379 |
return i; // return |
|
1335 | 1380 |
} |
1336 | 1381 |
|
1337 |
#ifndef ROBOT |
|
1338 |
void xbee_set_com_port(char* port) |
|
1339 |
{ |
|
1340 |
xbee_com_port = port; |
|
1341 |
} |
|
1342 |
#endif |
|
1343 |
|
|
1344 | 1382 |
/**@} **/ // end xbee group |
1345 | 1383 |
|
Also available in: Unified diff