Revision 743
Fixed compilation errors.
xbee.c | ||
---|---|---|
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 |
|
|
1 | 35 |
#include "xbee.h" |
2 | 36 |
#include "wl_defs.h" |
3 | 37 |
|
... | ... | |
7 | 41 |
#include <unistd.h> |
8 | 42 |
#include <pthread.h> |
9 | 43 |
#include <errno.h> |
44 |
#include <termios.h> |
|
10 | 45 |
|
11 | 46 |
#else |
12 | 47 |
|
... | ... | |
19 | 54 |
#include <stdlib.h> |
20 | 55 |
#include <string.h> |
21 | 56 |
|
22 |
#include <queue.h> |
|
23 |
|
|
24 | 57 |
#define XBEE_FRAME_START 0x7E |
25 | 58 |
|
26 | 59 |
/*Frame Types*/ |
... | ... | |
49 | 82 |
void xbee_enter_command_mode(void); |
50 | 83 |
void xbee_exit_command_mode(void); |
51 | 84 |
void xbee_enter_api_mode(void); |
85 |
void xbee_exit_api_mode(void); |
|
52 | 86 |
void xbee_wait_for_string(char* s, int len); |
53 | 87 |
void xbee_wait_for_ok(void); |
54 | 88 |
|
... | ... | |
67 | 101 |
/*Global Variables*/ |
68 | 102 |
|
69 | 103 |
#ifndef ROBOT |
104 |
char* xbee_com_port = XBEE_PORT_DEFAULT; |
|
70 | 105 |
int xbee_stream; |
71 | 106 |
pthread_t* xbee_listen_thread; |
72 | 107 |
#endif |
73 | 108 |
|
74 |
Queue* xbee_queue; |
|
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; |
|
75 | 117 |
|
118 |
|
|
76 | 119 |
//used to store packets as they are read |
77 | 120 |
char xbee_buf[128]; |
78 | 121 |
int currentBufPos = 0; |
... | ... | |
90 | 133 |
|
91 | 134 |
/** |
92 | 135 |
* Interrupt for the robot. Adds bytes received from the xbee |
93 |
* to the queue.
|
|
136 |
* to the buffer.
|
|
94 | 137 |
**/ |
95 | 138 |
#ifndef FIREFLY |
96 | 139 |
ISR(USART1_RX_vect) |
97 | 140 |
{ |
98 | 141 |
char c = UDR1; |
99 |
queue_add(xbee_queue, (void*)(int)c); |
|
142 |
arrival_buf[buffer_last] = c; |
|
143 |
int t = buffer_last + 1; |
|
144 |
if (t == XBEE_BUFFER_SIZE) |
|
145 |
t = 0; |
|
146 |
if (t == buffer_first) |
|
147 |
{ |
|
148 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
149 |
} |
|
150 |
buffer_last = t; |
|
100 | 151 |
} |
101 | 152 |
#else |
102 | 153 |
SIGNAL(SIG_USART0_RECV) |
103 | 154 |
{ |
104 | 155 |
char c = UDR0; |
105 |
queue_add(xbee_queue, (void*)(int)c); |
|
156 |
arrival_buf[buffer_last] = c; |
|
157 |
int t = buffer_last + 1; |
|
158 |
if (t == XBEE_BUFFER_SIZE) |
|
159 |
t = 0; |
|
160 |
if (t == buffer_first) |
|
161 |
{ |
|
162 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
163 |
} |
|
164 |
buffer_last = t; |
|
106 | 165 |
} |
107 | 166 |
#endif |
108 | 167 |
|
... | ... | |
117 | 176 |
while (1) |
118 | 177 |
{ |
119 | 178 |
xbee_read(&c, 1); |
120 |
queue_add(xbee_queue, (void*)(int)c); |
|
179 |
arrival_buf[buffer_last] = c; |
|
180 |
int t = buffer_last + 1; |
|
181 |
if (t == XBEE_BUFFER_SIZE) |
|
182 |
t = 0; |
|
183 |
if (t == buffer_first) |
|
184 |
{ |
|
185 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
186 |
} |
|
187 |
buffer_last = t; |
|
121 | 188 |
} |
122 | 189 |
return 0; |
123 | 190 |
} |
... | ... | |
126 | 193 |
|
127 | 194 |
/** |
128 | 195 |
* Initializes the XBee library so that other functions may be used. |
129 |
* |
|
130 |
* @param pan_id the PAN to join initially. Use XBEE_PAN_DEFAULT |
|
131 |
* to leave the PAN as it is initially. |
|
132 | 196 |
**/ |
133 |
void xbee_lib_init(void)
|
|
197 |
int xbee_lib_init(void)
|
|
134 | 198 |
{ |
135 |
xbee_queue = queue_create(); |
|
136 |
|
|
199 |
arrival_buf[0] = 'A'; |
|
200 |
arrival_buf[1] = 'A'; |
|
201 |
arrival_buf[2] = 'A'; |
|
137 | 202 |
#ifdef ROBOT |
138 | 203 |
|
139 | 204 |
//enable the receiving interrupt |
... | ... | |
144 | 209 |
#endif |
145 | 210 |
sei(); |
146 | 211 |
#else |
147 |
xbee_stream = open(XBEE_PORT, O_RDWR); |
|
148 |
if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0) |
|
149 |
xbee_stream = open(XBEE_PORT2, O_RDWR); |
|
150 |
if (xbee_stream == -1 || lockf(xbee_stream, F_TEST, 0) != 0) |
|
212 |
printf("Connecting to port %s.\n", xbee_com_port); |
|
213 |
xbee_stream = open(xbee_com_port, O_RDWR); |
|
214 |
if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/) |
|
151 | 215 |
{ |
152 |
printf("Failed to open connection to XBee.\r\n");
|
|
153 |
exit(0);
|
|
216 |
printf("Failed to open connection to XBee on port %s\r\n", xbee_com_port);
|
|
217 |
return -1;
|
|
154 | 218 |
} |
155 |
lockf(xbee_stream, F_LOCK, 0); |
|
156 | 219 |
|
220 |
// set baud rate, etc. correctly |
|
221 |
struct termios options; |
|
222 |
|
|
223 |
tcgetattr(xbee_stream, &options); |
|
224 |
cfsetispeed(&options, B9600); |
|
225 |
cfsetospeed(&options, B9600); |
|
226 |
options.c_iflag &= ~ICRNL; |
|
227 |
options.c_oflag &= ~OCRNL; |
|
228 |
options.c_cflag |= (CLOCAL | CREAD); |
|
229 |
options.c_cflag &= ~PARENB; |
|
230 |
options.c_cflag &= ~CSTOPB; |
|
231 |
options.c_cflag &= ~CSIZE; |
|
232 |
options.c_cflag |= CS8; |
|
233 |
options.c_lflag &= ~ICANON; |
|
234 |
options.c_cc[VMIN] = 1; |
|
235 |
options.c_cc[VTIME] = 50; |
|
236 |
|
|
237 |
if (tcsetattr(xbee_stream, TCSANOW, &options)) |
|
238 |
{ |
|
239 |
fprintf(stderr, "Error setting attributes.\n"); |
|
240 |
return -1; |
|
241 |
} |
|
242 |
|
|
243 |
//lockf(xbee_stream, F_LOCK, 0); |
|
244 |
|
|
157 | 245 |
xbee_listen_thread = |
158 | 246 |
(pthread_t*)malloc(sizeof(pthread_t)); |
247 |
if (xbee_listen_thread == NULL) |
|
248 |
{ |
|
249 |
fprintf(stderr, "%s: Malloc failed.\n", __FUNCTION__); |
|
250 |
return -1; |
|
251 |
} |
|
159 | 252 |
|
160 |
int ret = pthread_create(xbee_listen_thread, NULL,
|
|
253 |
int ret = pthread_create(xbee_listen_thread, NULL, |
|
161 | 254 |
listen_to_xbee, NULL); |
162 | 255 |
if (ret) |
163 | 256 |
{ |
164 |
printf("Failed to create listener thread.\r\n");
|
|
165 |
exit(0);
|
|
257 |
fprintf(stderr, "Failed to create listener thread.\r\n");
|
|
258 |
return -1;
|
|
166 | 259 |
} |
260 |
|
|
167 | 261 |
#endif |
168 | 262 |
xbee_enter_command_mode(); |
169 | 263 |
xbee_enter_api_mode(); |
... | ... | |
172 | 266 |
|
173 | 267 |
//wait to return until the address is set |
174 | 268 |
while (xbee_address == 0) xbee_get_packet(NULL); |
269 |
|
|
270 |
|
|
271 |
return 0; |
|
175 | 272 |
} |
176 | 273 |
|
177 | 274 |
/** |
... | ... | |
186 | 283 |
lockf(xbee_stream, F_ULOCK, 0); |
187 | 284 |
close(xbee_stream); |
188 | 285 |
#endif |
189 |
queue_destroy(xbee_queue); |
|
190 | 286 |
} |
191 | 287 |
|
192 | 288 |
/** |
... | ... | |
270 | 366 |
} |
271 | 367 |
|
272 | 368 |
/** |
369 |
* Exit API mode. (warning - does not check for response) |
|
370 |
**/ |
|
371 |
void xbee_exit_api_mode() |
|
372 |
{ |
|
373 |
xbee_send_string("ATAP 0\r"); |
|
374 |
} |
|
375 |
|
|
376 |
/** |
|
273 | 377 |
* Wait until the string "OK\r" is received from the XBee. |
274 | 378 |
**/ |
275 | 379 |
void xbee_wait_for_ok() |
... | ... | |
289 | 393 |
char* curr = s; |
290 | 394 |
while (curr - s < len) |
291 | 395 |
{ |
292 |
if (queue_is_empty(xbee_queue)) |
|
396 |
// check if buffer is empty |
|
397 |
if (buffer_last == buffer_first) |
|
293 | 398 |
continue; |
294 |
char c = (char)(int)queue_remove(xbee_queue); |
|
399 |
char c = arrival_buf[buffer_first++]; |
|
400 |
if (buffer_first == XBEE_BUFFER_SIZE) |
|
401 |
buffer_first = 0; |
|
295 | 402 |
if (c == *curr) |
296 | 403 |
curr++; |
297 | 404 |
else |
... | ... | |
499 | 606 |
if (currentBufPos == 0) |
500 | 607 |
{ |
501 | 608 |
do |
502 |
if (queue_is_empty(xbee_queue)) |
|
609 |
{ |
|
610 |
if (buffer_first == XBEE_BUFFER_SIZE) |
|
611 |
buffer_first = 0; |
|
612 |
// check if buffer is empty |
|
613 |
if (buffer_first == buffer_last) |
|
503 | 614 |
return -1; |
504 |
while ((char)(int)queue_remove(xbee_queue) != XBEE_FRAME_START); |
|
615 |
} |
|
616 |
while (arrival_buf[buffer_first++] != XBEE_FRAME_START); |
|
617 |
if (buffer_first == XBEE_BUFFER_SIZE) |
|
618 |
buffer_first = 0; |
|
505 | 619 |
xbee_buf[0] = XBEE_FRAME_START; |
506 | 620 |
currentBufPos++; |
507 | 621 |
} |
... | ... | |
514 | 628 |
|| currentBufPos < len + 4) |
515 | 629 |
{ |
516 | 630 |
if (currentBufPos == 3) |
631 |
{ |
|
517 | 632 |
len = (int)xbee_buf[2] + ((int)xbee_buf[1] << 8); |
518 |
if (queue_is_empty(xbee_queue)) |
|
633 |
if (len > 120) |
|
634 |
{ |
|
635 |
WL_DEBUG_PRINT("Packet too large. Probably error in XBee transmission.\n"); |
|
636 |
currentBufPos = 0; |
|
637 |
return -1; |
|
638 |
} |
|
639 |
} |
|
640 |
// check if buffer is empty |
|
641 |
if (buffer_first == buffer_last) |
|
519 | 642 |
return -1; |
520 |
xbee_buf[currentBufPos++] = (char)(int)queue_remove(xbee_queue); |
|
643 |
xbee_buf[currentBufPos++] = arrival_buf[buffer_first++]; |
|
644 |
if (buffer_first == XBEE_BUFFER_SIZE) |
|
645 |
buffer_first = 0; |
|
521 | 646 |
} |
522 | 647 |
|
523 | 648 |
currentBufPos = 0; |
524 | 649 |
|
525 | 650 |
if (!xbee_verify_checksum(xbee_buf, len + 4)) |
526 | 651 |
{ |
527 |
usb_puts("XBee checksum failed.\r\n");
|
|
652 |
WL_DEBUG_PRINT("XBee checksum failed.\r\n");
|
|
528 | 653 |
return -1; |
529 | 654 |
} |
530 | 655 |
|
... | ... | |
740 | 865 |
return xbee_address; |
741 | 866 |
} |
742 | 867 |
|
868 |
#ifndef ROBOT |
|
869 |
void xbee_set_com_port(char* port) |
|
870 |
{ |
|
871 |
xbee_com_port = port; |
|
872 |
} |
|
873 |
#endif |
|
874 |
|
Also available in: Unified diff