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 |
|