Revision 1611
wl updates: compile issues; now finished (for now)
branches/wireless/code/projects/libwireless/xbee_computer.c | ||
---|---|---|
1 |
// this is all the xbee.c computer code |
|
2 |
|
|
3 |
#include <stdio.h> |
|
4 |
#include <stdlib.h> |
|
5 |
|
|
6 |
#ifndef ROBOT |
|
7 |
|
|
8 |
#include <fcntl.h> |
|
9 |
#include <unistd.h> |
|
10 |
#include <pthread.h> |
|
11 |
#include <errno.h> |
|
12 |
#include <termios.h> |
|
13 |
|
|
14 |
#endif |
|
15 |
|
|
16 |
#ifdef USE_STDIO |
|
17 |
|
|
18 |
#include <stdio.h> |
|
19 |
|
|
20 |
/** |
|
21 |
* For use with fprintf() and related stdio functions |
|
22 |
**/ |
|
23 |
FILE *xbee_fd; |
|
24 |
|
|
25 |
#endif |
|
26 |
|
|
27 |
uint8_t xbee_initd=0; |
|
28 |
|
|
29 |
/** |
|
30 |
* Initializes communication over the XBee. |
|
31 |
* This must be called before any other xbee function |
|
32 |
* may be used. |
|
33 |
**/ |
|
34 |
int xbee_init() { |
|
35 |
|
|
36 |
if(xbee_initd) { |
|
37 |
return ERROR_INIT_ALREADY_INITD; |
|
38 |
} |
|
39 |
|
|
40 |
//Set baud rate |
|
41 |
// - 115200 (both wired and wireless) is UBRR=8, U2X=1 |
|
42 |
// - 9600 is U2X =1, UBRR = 107. |
|
43 |
#if (XBEE_BAUD == 115200) |
|
44 |
UBRR1H = 0x00; |
|
45 |
UBRR1L = 8; |
|
46 |
UCSR1A |= _BV(U2X1); |
|
47 |
#elif (XBEE_BAUD == 9600) |
|
48 |
UBRR1H = 0x00; |
|
49 |
UBRR1L = 103; |
|
50 |
UCSR1A |= _BV(U2X1); |
|
51 |
#else //Baud rate is defined in the header file, we should not get here |
|
52 |
return 0; |
|
53 |
#endif |
|
54 |
|
|
55 |
//Enable receiver and transmitter |
|
56 |
UCSR1B |= (1<<RXEN1)|(1<<TXEN1); |
|
57 |
|
|
58 |
// Set frame format: 8data, 1stop bit, asynchronous normal mode |
|
59 |
UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11); |
|
60 |
|
|
61 |
// if we have enabled the stdio stuff, then we init it here |
|
62 |
#ifdef USE_STDIO |
|
63 |
/* Open the stdio stream corresponding to this port */ |
|
64 |
xbee_fd = fdevopen(xbee_putc, xbee_getc); |
|
65 |
#endif |
|
66 |
|
|
67 |
xbee_initd = 1; |
|
68 |
return 0; |
|
69 |
|
|
70 |
} |
|
71 |
|
|
72 |
|
|
73 |
/**@brief The port to use the XBee from on the computer. **/ |
|
74 |
#ifndef ROBOT |
|
75 |
#define XBEE_PORT_DEFAULT "/dev/ttyUSB1" |
|
76 |
#endif |
|
77 |
|
|
78 |
|
|
79 |
/**@brief Set the com port on a computer, undefined on the robot**/ |
|
80 |
void xbee_set_com_port(char* port); |
|
81 |
|
|
82 |
#define XBEE_GET_PACKET_TIMEOUT 1000 |
|
83 |
|
|
84 |
#ifndef ROBOT |
|
85 |
static int xbee_read(char* buf, int size); |
|
86 |
#endif |
|
87 |
|
|
88 |
#ifndef ROBOT |
|
89 |
static char* xbee_com_port = XBEE_PORT_DEFAULT; |
|
90 |
static int xbee_stream; |
|
91 |
static pthread_t* xbee_listen_thread; |
|
92 |
#endif |
|
93 |
|
|
94 |
#ifndef ROBOT |
|
95 |
|
|
96 |
// Computer code |
|
97 |
|
|
98 |
/** |
|
99 |
* Thread that listens to the xbee. |
|
100 |
**/ |
|
101 |
static void* listen_to_xbee(void* x) |
|
102 |
{ |
|
103 |
char c; |
|
104 |
while (1) |
|
105 |
{ |
|
106 |
if (xbee_read(&c, 1) != 0) { |
|
107 |
WL_DEBUG_PRINT("xbee_read failed.\n"); |
|
108 |
return NULL; |
|
109 |
} |
|
110 |
|
|
111 |
arrival_buf[buffer_last] = c; |
|
112 |
int t = buffer_last + 1; |
|
113 |
if (t == XBEE_BUFFER_SIZE) |
|
114 |
t = 0; |
|
115 |
if (t == buffer_first) |
|
116 |
{ |
|
117 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
118 |
} |
|
119 |
buffer_last = t; |
|
120 |
|
|
121 |
usleep(1000); |
|
122 |
} |
|
123 |
|
|
124 |
return NULL; |
|
125 |
} |
|
126 |
|
|
127 |
#endif |
|
128 |
|
|
129 |
/** |
|
130 |
* Initializes the XBee library so that other functions may be used. |
|
131 |
**/ |
|
132 |
int8_t xbee_lib_init() |
|
133 |
{ |
|
134 |
// do serial.c xbee init TODO: merge this into xbee.c |
|
135 |
if (xbee_init() != 0) { |
|
136 |
usb_puts("xbee_init error"); |
|
137 |
return WL_ERROR_INIT_FAILED; |
|
138 |
} |
|
139 |
|
|
140 |
WL_DEBUG_PRINT("in xbee_init\n"); |
|
141 |
#ifdef ROBOT |
|
142 |
|
|
143 |
//enable the receiving interrupt |
|
144 |
#ifdef FIREFLY |
|
145 |
UCSR0B |= _BV(RXCIE) | _BV(RXEN); |
|
146 |
#else |
|
147 |
#ifdef BAYBOARD |
|
148 |
UCSR1B |= _BV(RXCIE1); |
|
149 |
#else |
|
150 |
UCSR1B |= _BV(RXCIE); |
|
151 |
#endif |
|
152 |
#endif |
|
153 |
sei(); |
|
154 |
#else |
|
155 |
xbee_stream = open(xbee_com_port, O_RDWR); |
|
156 |
if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/) |
|
157 |
{ |
|
158 |
WL_DEBUG_PRINT("Failed to open connection to XBee on port "); |
|
159 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
160 |
WL_DEBUG_PRINT(".\n"); |
|
161 |
return -1; |
|
162 |
} else { |
|
163 |
WL_DEBUG_PRINT("Successfully opened connection to XBee on port "); |
|
164 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
165 |
WL_DEBUG_PRINT(".\n"); |
|
166 |
} |
|
167 |
|
|
168 |
// set baud rate, etc. correctly |
|
169 |
struct termios options; |
|
170 |
|
|
171 |
tcgetattr(xbee_stream, &options); |
|
172 |
cfsetispeed(&options, B9600); |
|
173 |
cfsetospeed(&options, B9600); |
|
174 |
options.c_iflag &= ~ICRNL; |
|
175 |
options.c_oflag &= ~OCRNL; |
|
176 |
options.c_cflag |= (CLOCAL | CREAD); |
|
177 |
options.c_cflag &= ~PARENB; |
|
178 |
options.c_cflag &= ~CSTOPB; |
|
179 |
options.c_cflag &= ~CSIZE; |
|
180 |
options.c_cflag |= CS8; |
|
181 |
options.c_lflag &= ~ICANON; |
|
182 |
options.c_cc[VMIN] = 1; |
|
183 |
options.c_cc[VTIME] = 50; |
|
184 |
|
|
185 |
if (tcsetattr(xbee_stream, TCSANOW, &options)) |
|
186 |
{ |
|
187 |
WL_DEBUG_PRINT("Error setting attributes.\n"); |
|
188 |
return -1; |
|
189 |
} |
|
190 |
|
|
191 |
xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t)); |
|
192 |
if (xbee_listen_thread == NULL) |
|
193 |
{ |
|
194 |
WL_DEBUG_PRINT("Malloc failed.\n"); |
|
195 |
return -1; |
|
196 |
} |
|
197 |
|
|
198 |
int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL); |
|
199 |
if (ret) |
|
200 |
{ |
|
201 |
WL_DEBUG_PRINT("Failed to create listener thread.\n"); |
|
202 |
return -1; |
|
203 |
} |
|
204 |
#endif |
|
205 |
|
|
206 |
WL_DEBUG_PRINT("Entering command mode.\r\n"); |
|
207 |
|
|
208 |
if (xbee_enter_command_mode() != 0) { |
|
209 |
usb_puts("error entering command mode\r\n"); |
|
210 |
return -1; |
|
211 |
} |
|
212 |
|
|
213 |
WL_DEBUG_PRINT("Entered command mode.\r\n"); |
|
214 |
|
|
215 |
// reset baud rate |
|
216 |
WL_DEBUG_PRINT("Resetting Baud to "); |
|
217 |
WL_DEBUG_PRINT(XBEE_BAUD_STR); |
|
218 |
WL_DEBUG_PRINT("\r\n"); |
|
219 |
|
|
220 |
// set baud on xbee |
|
221 |
//#if (XBEE_BAUD == 250000) |
|
222 |
#if (XBEE_BAUD == 115200) |
|
223 |
xbee_send_string("ATBD7\r\n"); |
|
224 |
#elif (XBEE_BAUD == 57600) |
|
225 |
xbee_send_string("ATBD6\r\n"); |
|
226 |
#elif (XBEE_BAUD == 38400) |
|
227 |
xbee_send_string("ATBD5\r\n"); |
|
228 |
#elif (XBEE_BAUD == 19200) |
|
229 |
xbee_send_string("ATBD4\r\n"); |
|
230 |
#elif (XBEE_BAUD == 9600) |
|
231 |
// already at this baud rate |
|
232 |
//xbee_send_string("ATBD3\r\n"); |
|
233 |
#else |
|
234 |
WL_DEBUG_PRINT("undefined baud rate\r\n"); |
|
235 |
#endif |
|
236 |
// exit command mode |
|
237 |
xbee_wait_for_ok(); |
|
238 |
WL_DEBUG_PRINT("got ok from baud reset\r\n"); |
|
239 |
xbee_send_string("ATCN\r\n"); |
|
240 |
xbee_wait_for_ok(); |
|
241 |
WL_DEBUG_PRINT("got ok from exiting command mode\r\n"); |
|
242 |
|
|
243 |
// set UART baud |
|
244 |
#if (XBEE_BAUD == 250000) |
|
245 |
UBRR1H = 0x00; |
|
246 |
UBRR1L = 3; |
|
247 |
UCSR1A |= _BV(U2X1); |
|
248 |
#elif (XBEE_BAUD == 115200) |
|
249 |
UBRR1H = 0x00; |
|
250 |
UBRR1L = 8; |
|
251 |
UCSR1A |= _BV(U2X1); |
|
252 |
#elif (XBEE_BAUD == 57600) |
|
253 |
UBRR1H = 0x00; |
|
254 |
UBRR1L = 16; |
|
255 |
UCSR1A |= _BV(U2X1); |
|
256 |
#elif (XBEE_BAUD == 38400) |
|
257 |
UBRR1H = 0x00; |
|
258 |
UBRR1L = 25; |
|
259 |
UCSR1A |= _BV(U2X1); |
|
260 |
#elif (XBEE_BAUD == 19200) |
|
261 |
UBRR1H = 0x00; |
|
262 |
UBRR1L = 51; |
|
263 |
UCSR1A |= _BV(U2X1); |
|
264 |
#elif (XBEE_BAUD == 9600) |
|
265 |
/* this is the default baud rate, so do nothing |
|
266 |
UBRR1H = 0x00; |
|
267 |
UBRR1L = 103; |
|
268 |
UCSR1A |= _BV(U2X1);*/ |
|
269 |
#else //Baud rate is defined in the header file, we should not get here |
|
270 |
return 0; |
|
271 |
#endif |
|
272 |
delay_ms(50); |
|
273 |
|
|
274 |
// enter command mode |
|
275 |
WL_DEBUG_PRINT("entering command mode 2\r\n"); |
|
276 |
xbee_send_string("+++"); |
|
277 |
xbee_wait_for_ok(); |
|
278 |
WL_DEBUG_PRINT("entered command mode 2\r\n"); |
|
279 |
|
|
280 |
if (xbee_enter_api_mode() != 0) { |
|
281 |
WL_DEBUG_PRINT("can't enter api mode\r\n"); |
|
282 |
return -1; |
|
283 |
} |
|
284 |
|
|
285 |
WL_DEBUG_PRINT("Entered api mode.\r\n"); |
|
286 |
|
|
287 |
if (xbee_exit_command_mode() != 0) { |
|
288 |
WL_DEBUG_PRINT("can't exit command mode\r\n"); |
|
289 |
return -1; |
|
290 |
} |
|
291 |
|
|
292 |
WL_DEBUG_PRINT("Left command mode.\r\n"); |
|
293 |
|
|
294 |
// get baud rate |
|
295 |
if (xbee_send_read_at_command("BD")) { |
|
296 |
WL_DEBUG_PRINT("can't send BD command\r\n"); |
|
297 |
return -1; |
|
298 |
} |
|
299 |
WL_DEBUG_PRINT("Getting ATBD rate.\n"); |
|
300 |
|
|
301 |
// get MY address |
|
302 |
if (xbee_send_read_at_command("MY")) { |
|
303 |
WL_DEBUG_PRINT("can't send my command\r\n"); |
|
304 |
return -1; |
|
305 |
} |
|
306 |
WL_DEBUG_PRINT("Getting ATMY address.\n"); |
|
307 |
|
|
308 |
#ifndef ROBOT |
|
309 |
int i; |
|
310 |
for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) { |
|
311 |
ret = xbee_get_packet(NULL); |
|
312 |
|
|
313 |
usleep(1000); |
|
314 |
|
|
315 |
/* if (ret == -1) { */ |
|
316 |
/* WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */ |
|
317 |
/* return -1; */ |
|
318 |
/* } */ |
|
319 |
} |
|
320 |
#else |
|
321 |
//wait to return until the address is set |
|
322 |
//TODO: this shouldn't wait indefinitely. There should be some sort of reasonable timeout |
|
323 |
// so if the address is never set right, an error can be returned instead of having the |
|
324 |
// robot hang forever |
|
325 |
while (xbee_address == 0) { |
|
326 |
xbee_get_packet(NULL); |
|
327 |
} |
|
328 |
#endif |
|
329 |
WL_DEBUG_PRINT("Got ATMY address.\n"); |
|
330 |
|
|
331 |
#ifndef ROBOT |
|
332 |
if (i == XBEE_GET_PACKET_TIMEOUT) { // We timed-out. |
|
333 |
|
|
334 |
WL_DEBUG_PRINT("xbee_get_packet timed out.\n"); |
|
335 |
return -1; |
|
336 |
} else { |
|
337 |
return 0; |
|
338 |
} |
|
339 |
#else |
|
340 |
return 0; |
|
341 |
#endif |
|
342 |
} |
|
343 |
|
|
344 |
void xbee_terminate() |
|
345 |
{ |
|
346 |
#ifndef ROBOT |
|
347 |
pthread_cancel(*xbee_listen_thread); |
|
348 |
pthread_join(*xbee_listen_thread, NULL); |
|
349 |
free(xbee_listen_thread); |
|
350 |
lockf(xbee_stream, F_ULOCK, 0); |
|
351 |
close(xbee_stream); |
|
352 |
#else |
|
353 |
xbee_exit_api_mode(); |
|
354 |
#endif |
|
355 |
} |
|
356 |
|
|
357 |
|
|
358 |
|
|
359 |
static int xbee_send(char* buf, int size) |
|
360 |
#ifndef ROBOT |
|
361 |
|
|
362 |
int ret = write(xbee_stream, buf, size); |
|
363 |
//success |
|
364 |
if (ret == size) |
|
365 |
return 0; |
|
366 |
if (ret == -1) |
|
367 |
{ |
|
368 |
//interrupted by system signal, probably timer interrupt. |
|
369 |
//just try again |
|
370 |
if (errno == 4) |
|
371 |
{ |
|
372 |
return xbee_send(buf, size); |
|
373 |
} |
|
374 |
WL_DEBUG_PRINT("Failed to write to xbee\r\n"); |
|
375 |
return -1; |
|
376 |
} |
|
377 |
|
|
378 |
//write was interrupted after writing ret bytes |
|
379 |
return xbee_send(buf + ret, size - ret); |
|
380 |
#endif |
|
381 |
|
|
382 |
|
|
383 |
#ifndef ROBOT |
|
384 |
static int xbee_read(char* buf, int size) |
|
385 |
{ |
|
386 |
if (read(xbee_stream, buf, size) == -1) { |
|
387 |
WL_DEBUG_PRINT("Failed to read from xbee.\r\n"); |
|
388 |
return -1; |
|
389 |
} |
|
390 |
|
|
391 |
return 0; |
|
392 |
} |
|
393 |
#endif |
|
394 |
|
|
395 |
|
|
396 |
#ifndef ROBOT |
|
397 |
void xbee_set_com_port(char* port) |
|
398 |
{ |
|
399 |
xbee_com_port = port; |
|
400 |
} |
|
401 |
#endif |
|
402 |
|
branches/wireless/code/projects/libwireless/xbee.c | ||
---|---|---|
35 | 35 |
#include <string.h> |
36 | 36 |
#include <avr/interrupt.h> |
37 | 37 |
#include <time.h> |
38 |
#include <serial.h> // TODO: integrate serial xbee functions into this file |
|
39 | 38 |
#include "wl_defs.h" |
39 |
#include "wireless.h" |
|
40 | 40 |
#include "xbee.h" |
41 | 41 |
|
42 | 42 |
|
... | ... | |
45 | 45 |
// TODO: convert all int references to int16_t syntax (see stdint.h) |
46 | 46 |
|
47 | 47 |
/* I/O Functions */ |
48 |
static int8_t xbee_send_string(unsigned char* c);
|
|
48 |
static int8_t xbee_send_string(uint8_t* c);
|
|
49 | 49 |
|
50 | 50 |
/* Command Mode Functions */ |
51 |
static int xbee_enter_command_mode(void); |
|
52 |
static int xbee_exit_command_mode(void); |
|
53 |
static int xbee_enter_api_mode(void); |
|
54 |
static int xbee_exit_api_mode(void); |
|
55 |
static int xbee_wait_for_string(char* s, uint16_t len);
|
|
56 |
static int xbee_wait_for_ok(void); |
|
51 |
static int8_t xbee_enter_command_mode(void);
|
|
52 |
static int8_t xbee_exit_command_mode(void);
|
|
53 |
static int8_t xbee_enter_api_mode(void);
|
|
54 |
static int8_t xbee_exit_api_mode(void);
|
|
55 |
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len);
|
|
56 |
static int8_t xbee_wait_for_ok(void);
|
|
57 | 57 |
|
58 | 58 |
/* API Mode Functions */ |
59 |
static int xbee_handle_packet(uint8_t* packet, uint16_t len); |
|
60 |
static int xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len); |
|
61 |
static int xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len); |
|
59 |
static int8_t xbee_handle_packet(uint8_t* packet, uint16_t len);
|
|
60 |
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
|
|
61 |
static int8_t xbee_handle_at_command_response(uint16_t command, uint8_t result, uint8_t len);
|
|
62 | 62 |
static void xbee_handle_status(uint8_t status); |
63 |
static int xbee_verify_checksum(uint8_t* packet, uint16_t len); |
|
64 |
static char xbee_compute_checksum(uint8_t* packet, uint16_t len);
|
|
65 |
static int xbee_send_frame(uint8_t* buf, int len);
|
|
66 |
int xbee_send_read_at_command(uint8_t* command); |
|
67 |
static int xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len); |
|
63 |
static int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len);
|
|
64 |
static uint8_t xbee_compute_checksum(uint8_t* packet, uint16_t len);
|
|
65 |
static int8_t xbee_send_frame(uint8_t* buf, uint16_t len);
|
|
66 |
int8_t xbee_send_read_at_command(uint8_t* command);
|
|
67 |
static int8_t xbee_send_modify_at_command(uint8_t* command, uint8_t* value, uint8_t len);
|
|
68 | 68 |
|
69 | 69 |
/* Buffer Manipulation Functions */ |
70 | 70 |
int8_t xbee_basic_buf_add(uint8_t *ptr, uint8_t byte); |
... | ... | |
172 | 172 |
// do something based on the type |
173 | 173 |
i=1; |
174 | 174 |
switch(apitype) { |
175 |
case XBEE_FRAME_AT_COMMAND_RESPONSE: |
|
175 |
case XBEE_FRAME_AT_COMMAND_RESPONSE: {
|
|
176 | 176 |
// AT command response |
177 | 177 |
if ((xbee_status&0xC0) == XBEE_COMMAND_RESPONSE) |
178 | 178 |
return; // we're currently processing a command, so drop the incoming one |
... | ... | |
198 | 198 |
} |
199 | 199 |
// handle AT command |
200 | 200 |
xbee_handle_at_command_response(atcommand,apitype,i-5); // TODO: rewrite function |
201 |
break; |
|
202 |
case XBEE_FRAME_TX_STATUS: |
|
201 |
break; }
|
|
202 |
case XBEE_FRAME_TX_STATUS: {
|
|
203 | 203 |
// TX status |
204 |
if (0) { WL_DEBUG_PRINT("test"); } // why do I need this statement? |
|
205 | 204 |
uint8_t frame_id = 0; |
206 | 205 |
while(i<len) { |
207 | 206 |
if (FLAG) { |
... | ... | |
214 | 213 |
i++; |
215 | 214 |
} |
216 | 215 |
} |
217 |
break; |
|
218 |
case XBEE_FRAME_RX_64: |
|
216 |
break; }
|
|
217 |
case XBEE_FRAME_RX_64: {
|
|
219 | 218 |
// receive a packet with 64bit address |
220 |
break; // TODO: implement this (even if we don't use it) |
|
221 |
case XBEE_FRAME_RX_16: |
|
219 |
break; } // TODO: implement this (even if we don't use it)
|
|
220 |
case XBEE_FRAME_RX_16: {
|
|
222 | 221 |
// receive a packet with 16bit address |
223 | 222 |
uint16_t source = 0; |
224 | 223 |
uint8_t framenum = 0; |
... | ... | |
292 | 291 |
} |
293 | 292 |
} |
294 | 293 |
} |
295 |
break; |
|
294 |
break; }
|
|
296 | 295 |
} // end of switch statement |
297 | 296 |
while (1) { |
298 | 297 |
if (FLAG) { |
... | ... | |
310 | 309 |
WL_DEBUG_PRINT("basic buffer full\r\n"); |
311 | 310 |
return -1; |
312 | 311 |
} |
313 |
xbee_basic_buf[(*ptr)++] = byte);
|
|
312 |
xbee_basic_buf[(*ptr)++] = byte; |
|
314 | 313 |
if (*ptr == PACKET_BUFFER_SIZE) |
315 | 314 |
*ptr = 0; |
316 | 315 |
return 0; |
... | ... | |
330 | 329 |
return -1; |
331 | 330 |
} |
332 | 331 |
xbee_other_buf[(*ptr)++] = byte; |
333 |
if (ptr == PACKET_BUFFER_SIZE) |
|
332 |
if (*ptr == PACKET_BUFFER_SIZE)
|
|
334 | 333 |
*ptr = 0; |
335 | 334 |
return 0; |
336 | 335 |
} |
... | ... | |
343 | 342 |
{ |
344 | 343 |
WL_DEBUG_PRINT("in xbee_init\n"); |
345 | 344 |
|
346 |
if(xbee_status&0x08 == XBEE_INITD) {
|
|
345 |
if((xbee_status&0x08) == XBEE_INITD) {
|
|
347 | 346 |
return WL_ERROR_INIT_ALREADY_INITD; |
348 | 347 |
} |
349 | 348 |
|
... | ... | |
368 | 367 |
|
369 | 368 |
WL_DEBUG_PRINT("Entering command mode.\r\n"); |
370 | 369 |
if (xbee_enter_command_mode() != 0) { |
371 |
usb_puts("error entering command mode\r\n");
|
|
370 |
WL_DEBUG_PRINT("error entering command mode\r\n");
|
|
372 | 371 |
return -1; |
373 | 372 |
} |
374 | 373 |
WL_DEBUG_PRINT("Entered command mode.\r\n"); |
... | ... | |
380 | 379 |
|
381 | 380 |
// set baud on xbee |
382 | 381 |
#if (XBEE_BAUD == 115200) |
383 |
xbee_send_string("ATBD7\r"); |
|
382 |
xbee_send_string((uint8_t*)"ATBD7\r"); |
|
383 |
xbee_send_string((uint8_t*)"ATBD7\r"); |
|
384 | 384 |
#elif (XBEE_BAUD == 57600) |
385 |
xbee_send_string("ATBD6\r"); |
|
385 |
xbee_send_string((uint8_t*)"ATBD6\r");
|
|
386 | 386 |
#elif (XBEE_BAUD == 38400) |
387 |
xbee_send_string("ATBD5\r"); |
|
387 |
xbee_send_string((uint8_t*)"ATBD5\r");
|
|
388 | 388 |
#elif (XBEE_BAUD == 19200) |
389 |
xbee_send_string("ATBD4\r"); |
|
389 |
xbee_send_string((uint8_t*)"ATBD4\r");
|
|
390 | 390 |
#elif (XBEE_BAUD == 9600) |
391 | 391 |
// already at this baud rate |
392 | 392 |
//xbee_send_string("ATBD3\r\n"); |
... | ... | |
397 | 397 |
// exit command mode |
398 | 398 |
xbee_wait_for_ok(); |
399 | 399 |
WL_DEBUG_PRINT("got ok from baud reset\r\n"); |
400 |
xbee_send_string("ATCN\r"); |
|
400 |
xbee_send_string((uint8_t*)"ATCN\r");
|
|
401 | 401 |
xbee_wait_for_ok(); |
402 | 402 |
WL_DEBUG_PRINT("got ok from exiting command mode\r\n"); |
403 | 403 |
|
... | ... | |
449 | 449 |
|
450 | 450 |
// enter command mode |
451 | 451 |
WL_DEBUG_PRINT("entering command mode 2\r\n"); |
452 |
xbee_send_string("+++"); |
|
452 |
xbee_send_string((uint8_t*)"+++");
|
|
453 | 453 |
xbee_wait_for_ok(); |
454 | 454 |
WL_DEBUG_PRINT("entered command mode 2\r\n"); |
455 | 455 |
|
... | ... | |
495 | 495 |
* @param c the byte to send |
496 | 496 |
* @return 0 for success, nonzero for failure |
497 | 497 |
**/ |
498 |
int xbee_putc(char c) {
|
|
498 |
int8_t xbee_putc(uint8_t c) {
|
|
499 | 499 |
if(!(xbee_status&XBEE_INITD)) |
500 | 500 |
return WL_ERROR_LIBRARY_NOT_INITD; |
501 | 501 |
|
... | ... | |
573 | 573 |
**/ |
574 | 574 |
static int8_t xbee_send(uint8_t* buf, uint16_t size) |
575 | 575 |
{ |
576 |
while(--size > 0) |
|
577 |
if (xbee_putc(buf[i]) != WL_SUCCESS) |
|
576 |
uint16_t i=0; // check if we need this variable |
|
577 |
while(i<size) { |
|
578 |
if (xbee_putc(buf[i++]) != WL_SUCCESS) |
|
578 | 579 |
return WL_ERROR_SEND; |
579 | 580 |
} |
580 | 581 |
if (xbee_putc(buf[0]) != WL_SUCCESS) |
... | ... | |
588 | 589 |
* |
589 | 590 |
* @param c the string to send to the XBEE |
590 | 591 |
**/ |
591 |
static int8_t xbee_send_string(unsigned char* c)
|
|
592 |
static int8_t xbee_send_string(uint8_t* c)
|
|
592 | 593 |
{ |
593 |
return xbee_send(c, strlen(c)); |
|
594 |
return xbee_send(c, strlen((char*)c));
|
|
594 | 595 |
} |
595 | 596 |
|
596 | 597 |
|
597 | 598 |
/** |
598 | 599 |
* Enter into command mode. |
599 | 600 |
**/ |
600 |
static int8_t xbee_enter_command_mode() |
|
601 |
static int8_t xbee_enter_command_mode(void)
|
|
601 | 602 |
{ |
602 |
if (xbee_send_string("+++") != WL_SUCCESS) { |
|
603 |
if (xbee_send_string((uint8_t*)"+++") != WL_SUCCESS) {
|
|
603 | 604 |
return WL_ERROR_XBEE_COMMAND; |
604 | 605 |
} |
605 | 606 |
|
... | ... | |
615 | 616 |
**/ |
616 | 617 |
static int8_t xbee_exit_command_mode() |
617 | 618 |
{ |
618 |
if (xbee_send_string("ATCN\r") != 0) { |
|
619 |
if (xbee_send_string((uint8_t*)"ATCN\r") != 0) {
|
|
619 | 620 |
return WL_ERROR_SEND; |
620 | 621 |
} |
621 | 622 |
xbee_wait_for_ok(); |
... | ... | |
626 | 627 |
/** |
627 | 628 |
* Enter API mode. |
628 | 629 |
**/ |
629 |
static int8_t xbee_enter_api_mode() |
|
630 |
{ |
|
631 |
if (xbee_send_string("ATAP 1\r") != 0) { |
|
630 |
static int8_t xbee_enter_api_mode(void) { |
|
631 |
if (xbee_send_string((uint8_t*)"ATAP 1\r") != 0) { |
|
632 | 632 |
return WL_ERROR_SEND; |
633 | 633 |
} |
634 | 634 |
xbee_wait_for_ok(); |
... | ... | |
641 | 641 |
/** |
642 | 642 |
* Enter API mode 2. |
643 | 643 |
**/ |
644 |
static int8_t xbee_enter_api_mode2() |
|
645 |
{ |
|
646 |
if (xbee_send_string("ATAP 2\r") != 0) { |
|
644 |
static int8_t xbee_enter_api_mode2(void) { |
|
645 |
if (xbee_send_string((uint8_t*)"ATAP 2\r") != 0) { |
|
647 | 646 |
return WL_ERROR_SEND; |
648 | 647 |
} |
649 | 648 |
xbee_wait_for_ok(); |
... | ... | |
658 | 657 |
**/ |
659 | 658 |
static int8_t xbee_exit_api_mode() |
660 | 659 |
{ |
661 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT
|
|
662 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE)
|
|
660 |
if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
|
|
661 |
|| (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
|
|
663 | 662 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
664 | 663 |
|
665 | 664 |
int16_t i=0; |
666 | 665 |
// change status to command wait |
667 | 666 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
668 |
xbee_send_modify_at_command("AP","0",1); // send command
|
|
667 |
xbee_send_modify_at_command((uint8_t*)"AP",(uint8_t*)"0",1); // send command
|
|
669 | 668 |
// wait for up to 30 ms |
670 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
669 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
671 | 670 |
delay_us(1); // wait 3us |
672 | 671 |
} |
673 |
if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') {
|
|
672 |
if (i < 1000 && xbee_command[0] == 'A' && xbee_command[1] == 'P') |
|
674 | 673 |
i = WL_SUCCESS; |
675 | 674 |
else |
676 | 675 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
... | ... | |
681 | 680 |
/** |
682 | 681 |
* Wait until the string "OK\r" is received from the XBee. |
683 | 682 |
**/ |
684 |
static int xbee_wait_for_ok() |
|
683 |
static int8_t xbee_wait_for_ok()
|
|
685 | 684 |
{ |
686 |
return xbee_wait_for_string("OK\r", 3); |
|
685 |
return xbee_wait_for_string((uint8_t*)"OK\r", 3);
|
|
687 | 686 |
} |
688 | 687 |
|
689 | 688 |
/** |
... | ... | |
695 | 694 |
* @param s the string to receive |
696 | 695 |
* @param len the length of the string |
697 | 696 |
**/ |
698 |
static int8_t xbee_wait_for_string(char* s, int len)
|
|
697 |
static int8_t xbee_wait_for_string(uint8_t* s, uint16_t len)
|
|
699 | 698 |
{ |
700 | 699 |
uint8_t i=0; |
701 |
if (xbee_status&0x03 == XBEE_API_OFF) {
|
|
700 |
if ((xbee_status&0x03) == XBEE_API_OFF) {
|
|
702 | 701 |
// wait until the response is received (only wait 1 second) |
703 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 1000) {
|
|
702 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
|
|
704 | 703 |
delay_us(1); |
705 | 704 |
} |
706 | 705 |
// check response |
... | ... | |
728 | 727 |
* @param s the string to store the response in |
729 | 728 |
* @param len the length of the string |
730 | 729 |
*/ |
731 |
static int8_t xbee_wait_for_response(char* s, int len) {
|
|
730 |
static int8_t xbee_wait_for_response(uint8_t* s, int16_t len) {
|
|
732 | 731 |
uint8_t i=0; |
733 |
if (xbee_status&0x03 == XBEE_API_OFF) {
|
|
732 |
if ((xbee_status&0x03) == XBEE_API_OFF) {
|
|
734 | 733 |
// wait until the response is received (only wait 1 second) |
735 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 1000) {
|
|
734 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 1000) {
|
|
736 | 735 |
delay_us(1); |
737 | 736 |
} |
738 | 737 |
// check response |
739 |
if (i >= 1000) |
|
738 |
if (i >= 1000) {
|
|
740 | 739 |
return -1; |
741 | 740 |
} else { |
742 |
i=strcspn(xbee_basic_buf,"\r"); |
|
741 |
i=strcspn((char*)xbee_basic_buf,"\r");
|
|
743 | 742 |
if (i<PACKET_BUFFER_SIZE) { |
744 | 743 |
memcpy(s,xbee_basic_buf,i); |
745 | 744 |
xbee_status = xbee_status&0x3F; // clear response |
... | ... | |
768 | 767 |
* @return 0 if the checksum is incorrect, nonzero |
769 | 768 |
* otherwise |
770 | 769 |
**/ |
771 |
uint8_t xbee_verify_checksum(uint8_t* packet, uint16_t len)
|
|
770 |
int8_t xbee_verify_checksum(uint8_t* packet, uint16_t len) |
|
772 | 771 |
{ |
773 | 772 |
uint8_t sum = 0; |
774 | 773 |
while(--len > 0) { |
... | ... | |
834 | 833 |
if (xbee_putc((uint8_t)(len & 0x00FF)) != WL_SUCCESS) |
835 | 834 |
return WL_ERROR_SEND; |
836 | 835 |
|
837 |
if (xbee_send(buf, len) != WL_SUCCESS) |
|
838 |
return WL_ERROR_SEND; |
|
839 |
|
|
840 |
if (xbee_putc(checksum) != WL_SUCCESS) |
|
841 |
return WL_ERROR_SEND; |
|
842 |
|
|
843 | 836 |
return WL_SUCCESS; |
844 | 837 |
} |
845 | 838 |
|
... | ... | |
988 | 981 |
* |
989 | 982 |
* @param status the type of status packet received. |
990 | 983 |
**/ |
991 |
void xbee_handle_status(char status)
|
|
984 |
void xbee_handle_status(uint8_t status)
|
|
992 | 985 |
{ |
993 | 986 |
switch (status) |
994 | 987 |
{ |
... | ... | |
1075 | 1068 |
**/ |
1076 | 1069 |
int8_t xbee_set_pan_id(uint16_t id) |
1077 | 1070 |
{ |
1078 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT
|
|
1079 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE)
|
|
1071 |
if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
|
|
1072 |
|| (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
|
|
1080 | 1073 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
1081 | 1074 |
|
1082 | 1075 |
int16_t i=0; |
1083 | 1076 |
// change status to command wait |
1084 | 1077 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
1085 |
xbee_send_modify_at_command("ID",id,2); // send command to set the channel
|
|
1078 |
xbee_send_modify_at_command((uint8_t*)"ID",(uint8_t*)(&id),2); // send command to set the channel
|
|
1086 | 1079 |
// wait for up to 30 ms |
1087 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
1080 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
1088 | 1081 |
delay_us(1); // wait 3us |
1089 | 1082 |
} |
1090 |
if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K') {
|
|
1083 |
if (i < 1000 && xbee_command[0] == 'O' && xbee_command[1] == 'K') |
|
1091 | 1084 |
i = WL_SUCCESS; |
1092 | 1085 |
else |
1093 | 1086 |
i = WL_ERROR_XBEE_COMMAND; // set error code |
... | ... | |
1103 | 1096 |
**/ |
1104 | 1097 |
uint16_t xbee_get_pan_id() |
1105 | 1098 |
{ |
1106 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT
|
|
1107 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE)
|
|
1099 |
if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
|
|
1100 |
|| (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
|
|
1108 | 1101 |
return WL_ERROR_XBEE_COMMAND_16BIT; // can't do command right now |
1109 | 1102 |
|
1110 | 1103 |
uint16_t i=0; |
1111 | 1104 |
// change status to command wait |
1112 | 1105 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
1113 |
xbee_send_read_at_command("ID"); // send command to get the PAN |
|
1106 |
xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the PAN
|
|
1114 | 1107 |
// wait for up to 30 ms |
1115 |
while(xbee_status&0xC0 != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
1108 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) {
|
|
1116 | 1109 |
delay_us(1); // wait 3us |
1117 | 1110 |
} |
1118 |
if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D') {
|
|
1111 |
if (i < 1000 && xbee_command[0] == 'I' && xbee_command[1] == 'D') |
|
1119 | 1112 |
i = (xbee_command[2]<<8)|xbee_command[3]; // get PAN |
1120 | 1113 |
else |
1121 | 1114 |
i = WL_ERROR_XBEE_COMMAND_16BIT; // set error code |
... | ... | |
1139 | 1132 |
return -1; |
1140 | 1133 |
} |
1141 | 1134 |
|
1142 |
if (xbee_status&0xC0 == XBEE_COMMAND_WAIT
|
|
1143 |
|| xbee_status&0xC0 == XBEE_COMMAND_RESPONSE)
|
|
1135 |
if ((xbee_status&0xC0) == XBEE_COMMAND_WAIT
|
|
1136 |
|| (xbee_status&0xC0) == XBEE_COMMAND_RESPONSE)
|
|
1144 | 1137 |
return WL_ERROR_XBEE_COMMAND; // can't do command right now |
1145 | 1138 |
|
1146 | 1139 |
int16_t i=0; |
1147 | 1140 |
// change status to command wait |
1148 | 1141 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
1149 |
xbee_send_modify_at_command("CH",channel,1); // send command to set the channel
|
|
1142 |
xbee_send_modify_at_command((uint8_t*)"CH",&channel,1); // send command to set the channel
|
|
1150 | 1143 |
// wait for up to 30 ms |
1151 | 1144 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
1152 | 1145 |
delay_us(1); // wait 3us |
... | ... | |
1175 | 1168 |
int16_t i=0; |
1176 | 1169 |
// change status to command wait |
1177 | 1170 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
1178 |
xbee_send_read_at_command("ID"); // send command to get the channel |
|
1171 |
xbee_send_read_at_command((uint8_t*)"ID"); // send command to get the channel
|
|
1179 | 1172 |
// wait for up to 30 ms |
1180 | 1173 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
1181 | 1174 |
delay_us(1); // wait 3us |
... | ... | |
1204 | 1197 |
uint16_t i=0; |
1205 | 1198 |
// change status to command wait |
1206 | 1199 |
xbee_status = (xbee_status&0x3F)|XBEE_COMMAND_WAIT; |
1207 |
xbee_send_read_at_command("MY"); // send command to get the address |
|
1200 |
xbee_send_read_at_command((uint8_t*)"MY"); // send command to get the address
|
|
1208 | 1201 |
// wait for up to 30 ms |
1209 | 1202 |
while((xbee_status&0xC0) != XBEE_COMMAND_RESPONSE && i++ < 10000) { |
1210 | 1203 |
delay_us(1); // wait 3us |
branches/wireless/code/projects/libwireless/xbee.h | ||
---|---|---|
123 | 123 |
/**@brief Read a byte from the xbee (nonblocking) **/ |
124 | 124 |
int8_t xbee_getc_nb(uint8_t *c); |
125 | 125 |
/**@brief Send an array of bytes to the xbee **/ |
126 |
int8_t xbee_send(uint8_t* buf, uint16_t size); |
|
126 |
static int8_t xbee_send(uint8_t* buf, uint16_t size);
|
|
127 | 127 |
/**@brief Add a buffer to the checksum value **/ |
128 |
int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum); |
|
128 |
static int8_t xbee_checksum_add(uint8_t *buf, uint8_t len, uint8_t* sum);
|
|
129 | 129 |
/**@brief Send a frame header to the xbee **/ |
130 |
int8_t xbee_send_header(uint8_t type, uint16_t len); |
|
130 |
static int8_t xbee_send_header(uint8_t type, uint16_t len);
|
|
131 | 131 |
/**@brief Send a packet to the XBee **/ |
132 | 132 |
int8_t xbee_send_packet(uint8_t* packet, uint8_t len, uint16_t dest, uint8_t options, uint8_t frame); |
133 | 133 |
/**@brief Set the PAN ID for the XBee **/ |
134 |
int16_t xbee_set_pan_id(int id);
|
|
134 |
int8_t xbee_set_pan_id(uint16_t id);
|
|
135 | 135 |
/**@brief Get the XBee's PAN ID **/ |
136 | 136 |
uint16_t xbee_get_pan_id(void); |
137 | 137 |
/**@brief Set the channel the XBee is currently using **/ |
138 |
int8_t xbee_set_channel(int channel);
|
|
138 |
int8_t xbee_set_channel(uint8_t channel);
|
|
139 | 139 |
/**@brief Get the channel the XBee is currently using **/ |
140 | 140 |
int8_t xbee_get_channel(void); |
141 | 141 |
/**@brief Get the XBee's 16-bit address **/ |
branches/wireless/code/projects/libwireless/xbee_computer.c.bak | ||
---|---|---|
1 |
// this is all the xbee.c computer code |
|
2 |
|
|
3 |
#include <stdio.h> |
|
4 |
#include <stdlib.h> |
|
5 |
|
|
6 |
#ifndef ROBOT |
|
7 |
|
|
8 |
#include <fcntl.h> |
|
9 |
#include <unistd.h> |
|
10 |
#include <pthread.h> |
|
11 |
#include <errno.h> |
|
12 |
#include <termios.h> |
|
13 |
|
|
14 |
#endif |
|
15 |
|
|
16 |
#ifdef USE_STDIO |
|
17 |
|
|
18 |
#include <stdio.h> |
|
19 |
|
|
20 |
/** |
|
21 |
* For use with fprintf() and related stdio functions |
|
22 |
**/ |
|
23 |
FILE *xbee_fd; |
|
24 |
|
|
25 |
#endif |
|
26 |
|
|
27 |
uint8_t xbee_initd=0; |
|
28 |
|
|
29 |
/** |
|
30 |
* Initializes communication over the XBee. |
|
31 |
* This must be called before any other xbee function |
|
32 |
* may be used. |
|
33 |
**/ |
|
34 |
int xbee_init() { |
|
35 |
|
|
36 |
if(xbee_initd) { |
|
37 |
return ERROR_INIT_ALREADY_INITD; |
|
38 |
} |
|
39 |
|
|
40 |
//Set baud rate |
|
41 |
// - 115200 (both wired and wireless) is UBRR=8, U2X=1 |
|
42 |
// - 9600 is U2X =1, UBRR = 107. |
|
43 |
#if (XBEE_BAUD == 115200) |
|
44 |
UBRR1H = 0x00; |
|
45 |
UBRR1L = 8; |
|
46 |
UCSR1A |= _BV(U2X1); |
|
47 |
#elif (XBEE_BAUD == 9600) |
|
48 |
UBRR1H = 0x00; |
|
49 |
UBRR1L = 103; |
|
50 |
UCSR1A |= _BV(U2X1); |
|
51 |
#else //Baud rate is defined in the header file, we should not get here |
|
52 |
return 0; |
|
53 |
#endif |
|
54 |
|
|
55 |
//Enable receiver and transmitter |
|
56 |
UCSR1B |= (1<<RXEN1)|(1<<TXEN1); |
|
57 |
|
|
58 |
// Set frame format: 8data, 1stop bit, asynchronous normal mode |
|
59 |
UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11); |
|
60 |
|
|
61 |
// if we have enabled the stdio stuff, then we init it here |
|
62 |
#ifdef USE_STDIO |
|
63 |
/* Open the stdio stream corresponding to this port */ |
|
64 |
xbee_fd = fdevopen(xbee_putc, xbee_getc); |
|
65 |
#endif |
|
66 |
|
|
67 |
xbee_initd = 1; |
|
68 |
return 0; |
|
69 |
|
|
70 |
} |
|
71 |
|
|
72 |
|
|
73 |
/**@brief The port to use the XBee from on the computer. **/ |
|
74 |
#ifndef ROBOT |
|
75 |
#define XBEE_PORT_DEFAULT "/dev/ttyUSB1" |
|
76 |
#endif |
|
77 |
|
|
78 |
|
|
79 |
/**@brief Set the com port on a computer, undefined on the robot**/ |
|
80 |
void xbee_set_com_port(char* port); |
|
81 |
|
|
82 |
#define XBEE_GET_PACKET_TIMEOUT 1000 |
|
83 |
|
|
84 |
#ifndef ROBOT |
|
85 |
static int xbee_read(char* buf, int size); |
|
86 |
#endif |
|
87 |
|
|
88 |
#ifndef ROBOT |
|
89 |
static char* xbee_com_port = XBEE_PORT_DEFAULT; |
|
90 |
static int xbee_stream; |
|
91 |
static pthread_t* xbee_listen_thread; |
|
92 |
#endif |
|
93 |
|
|
94 |
#ifndef ROBOT |
|
95 |
|
|
96 |
// Computer code |
|
97 |
|
|
98 |
/** |
|
99 |
* Thread that listens to the xbee. |
|
100 |
**/ |
|
101 |
static void* listen_to_xbee(void* x) |
|
102 |
{ |
|
103 |
char c; |
|
104 |
while (1) |
|
105 |
{ |
|
106 |
if (xbee_read(&c, 1) != 0) { |
|
107 |
WL_DEBUG_PRINT("xbee_read failed.\n"); |
|
108 |
return NULL; |
|
109 |
} |
|
110 |
|
|
111 |
arrival_buf[buffer_last] = c; |
|
112 |
int t = buffer_last + 1; |
|
113 |
if (t == XBEE_BUFFER_SIZE) |
|
114 |
t = 0; |
|
115 |
if (t == buffer_first) |
|
116 |
{ |
|
117 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
118 |
} |
|
119 |
buffer_last = t; |
|
120 |
|
|
121 |
usleep(1000); |
|
122 |
} |
|
123 |
|
|
124 |
return NULL; |
|
125 |
} |
|
126 |
|
|
127 |
#endif |
|
128 |
|
|
129 |
/** |
|
130 |
* Initializes the XBee library so that other functions may be used. |
|
131 |
**/ |
|
132 |
int8_t xbee_lib_init() |
|
133 |
{ |
|
134 |
// do serial.c xbee init TODO: merge this into xbee.c |
|
135 |
if (xbee_init() != 0) { |
|
136 |
usb_puts("xbee_init error"); |
|
137 |
return WL_ERROR_INIT_FAILED; |
|
138 |
} |
|
139 |
|
|
140 |
WL_DEBUG_PRINT("in xbee_init\n"); |
|
141 |
#ifdef ROBOT |
|
142 |
|
|
143 |
//enable the receiving interrupt |
|
144 |
#ifdef FIREFLY |
|
145 |
UCSR0B |= _BV(RXCIE) | _BV(RXEN); |
|
146 |
#else |
|
147 |
#ifdef BAYBOARD |
|
148 |
UCSR1B |= _BV(RXCIE1); |
|
149 |
#else |
|
150 |
UCSR1B |= _BV(RXCIE); |
|
151 |
#endif |
|
152 |
#endif |
|
153 |
sei(); |
|
154 |
#else |
|
155 |
xbee_stream = open(xbee_com_port, O_RDWR); |
|
156 |
if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/) |
|
157 |
{ |
|
158 |
WL_DEBUG_PRINT("Failed to open connection to XBee on port "); |
|
159 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
160 |
WL_DEBUG_PRINT(".\n"); |
|
161 |
return -1; |
|
162 |
} else { |
|
163 |
WL_DEBUG_PRINT("Successfully opened connection to XBee on port "); |
|
164 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
165 |
WL_DEBUG_PRINT(".\n"); |
|
166 |
} |
|
167 |
|
|
168 |
// set baud rate, etc. correctly |
|
169 |
struct termios options; |
|
170 |
|
|
171 |
tcgetattr(xbee_stream, &options); |
|
172 |
cfsetispeed(&options, B9600); |
|
173 |
cfsetospeed(&options, B9600); |
|
174 |
options.c_iflag &= ~ICRNL; |
|
175 |
options.c_oflag &= ~OCRNL; |
|
176 |
options.c_cflag |= (CLOCAL | CREAD); |
|
177 |
options.c_cflag &= ~PARENB; |
|
178 |
options.c_cflag &= ~CSTOPB; |
|
179 |
options.c_cflag &= ~CSIZE; |
|
180 |
options.c_cflag |= CS8; |
|
181 |
options.c_lflag &= ~ICANON; |
|
182 |
options.c_cc[VMIN] = 1; |
|
183 |
options.c_cc[VTIME] = 50; |
|
184 |
|
|
185 |
if (tcsetattr(xbee_stream, TCSANOW, &options)) |
|
186 |
{ |
|
187 |
WL_DEBUG_PRINT("Error setting attributes.\n"); |
|
188 |
return -1; |
|
189 |
} |
|
190 |
|
|
191 |
xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t)); |
|
192 |
if (xbee_listen_thread == NULL) |
|
193 |
{ |
|
194 |
WL_DEBUG_PRINT("Malloc failed.\n"); |
|
195 |
return -1; |
|
196 |
} |
|
197 |
|
|
198 |
int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL); |
|
199 |
if (ret) |
|
200 |
{ |
|
201 |
WL_DEBUG_PRINT("Failed to create listener thread.\n"); |
|
202 |
return -1; |
|
203 |
} |
|
204 |
#endif |
|
205 |
|
|
206 |
WL_DEBUG_PRINT("Entering command mode.\r\n"); |
|
207 |
|
|
208 |
if (xbee_enter_command_mode() != 0) { |
|
209 |
usb_puts("error entering command mode\r\n"); |
|
210 |
return -1; |
|
211 |
} |
|
212 |
|
|
213 |
WL_DEBUG_PRINT("Entered command mode.\r\n"); |
|
214 |
|
|
215 |
// reset baud rate |
|
216 |
WL_DEBUG_PRINT("Resetting Baud to "); |
|
217 |
WL_DEBUG_PRINT(XBEE_BAUD_STR); |
|
218 |
WL_DEBUG_PRINT("\r\n"); |
|
219 |
|
|
220 |
// set baud on xbee |
|
221 |
//#if (XBEE_BAUD == 250000) |
|
222 |
#if (XBEE_BAUD == 115200) |
|
223 |
xbee_send_string("ATBD7\r\n"); |
|
224 |
#elif (XBEE_BAUD == 57600) |
|
225 |
xbee_send_string("ATBD6\r\n"); |
|
226 |
#elif (XBEE_BAUD == 38400) |
|
227 |
xbee_send_string("ATBD5\r\n"); |
|
228 |
#elif (XBEE_BAUD == 19200) |
|
229 |
xbee_send_string("ATBD4\r\n"); |
|
230 |
#elif (XBEE_BAUD == 9600) |
|
231 |
// already at this baud rate |
|
232 |
//xbee_send_string("ATBD3\r\n"); |
|
233 |
#else |
|
234 |
WL_DEBUG_PRINT("undefined baud rate\r\n"); |
|
235 |
#endif |
|
236 |
// exit command mode |
|
237 |
xbee_wait_for_ok(); |
|
238 |
WL_DEBUG_PRINT("got ok from baud reset\r\n"); |
|
239 |
xbee_send_string("ATCN\r\n"); |
|
240 |
xbee_wait_for_ok(); |
|
241 |
WL_DEBUG_PRINT("got ok from exiting command mode\r\n"); |
|
242 |
|
|
243 |
// set UART baud |
|
244 |
#if (XBEE_BAUD == 250000) |
|
245 |
UBRR1H = 0x00; |
|
246 |
UBRR1L = 3; |
|
247 |
UCSR1A |= _BV(U2X1); |
|
248 |
#elif (XBEE_BAUD == 115200) |
|
249 |
UBRR1H = 0x00; |
|
250 |
UBRR1L = 8; |
|
251 |
UCSR1A |= _BV(U2X1); |
|
252 |
#elif (XBEE_BAUD == 57600) |
|
253 |
UBRR1H = 0x00; |
|
254 |
UBRR1L = 16; |
|
255 |
UCSR1A |= _BV(U2X1); |
|
256 |
#elif (XBEE_BAUD == 38400) |
|
257 |
UBRR1H = 0x00; |
|
258 |
UBRR1L = 25; |
|
259 |
UCSR1A |= _BV(U2X1); |
|
260 |
#elif (XBEE_BAUD == 19200) |
|
261 |
UBRR1H = 0x00; |
|
262 |
UBRR1L = 51; |
|
263 |
UCSR1A |= _BV(U2X1); |
|
264 |
#elif (XBEE_BAUD == 9600) |
|
265 |
/* this is the default baud rate, so do nothing |
|
266 |
UBRR1H = 0x00; |
|
267 |
UBRR1L = 103; |
|
268 |
UCSR1A |= _BV(U2X1);*/ |
|
269 |
#else //Baud rate is defined in the header file, we should not get here |
|
270 |
return 0; |
|
271 |
#endif |
|
272 |
delay_ms(50); |
|
273 |
|
|
274 |
// enter command mode |
|
275 |
WL_DEBUG_PRINT("entering command mode 2\r\n"); |
|
276 |
xbee_send_string("+++"); |
|
277 |
xbee_wait_for_ok(); |
|
278 |
WL_DEBUG_PRINT("entered command mode 2\r\n"); |
|
279 |
|
|
280 |
if (xbee_enter_api_mode() != 0) { |
|
281 |
WL_DEBUG_PRINT("can't enter api mode\r\n"); |
|
282 |
return -1; |
|
283 |
} |
|
284 |
|
|
285 |
WL_DEBUG_PRINT("Entered api mode.\r\n"); |
|
286 |
|
|
287 |
if (xbee_exit_command_mode() != 0) { |
|
288 |
WL_DEBUG_PRINT("can't exit command mode\r\n"); |
|
289 |
return -1; |
|
290 |
} |
|
291 |
|
|
292 |
WL_DEBUG_PRINT("Left command mode.\r\n"); |
|
293 |
|
|
294 |
// get baud rate |
|
295 |
if (xbee_send_read_at_command("BD")) { |
|
296 |
WL_DEBUG_PRINT("can't send BD command\r\n"); |
|
297 |
return -1; |
|
298 |
} |
|
299 |
WL_DEBUG_PRINT("Getting ATBD rate.\n"); |
|
300 |
|
|
301 |
// get MY address |
|
302 |
if (xbee_send_read_at_command("MY")) { |
|
303 |
WL_DEBUG_PRINT("can't send my command\r\n"); |
|
304 |
return -1; |
|
305 |
} |
|
306 |
WL_DEBUG_PRINT("Getting ATMY address.\n"); |
|
307 |
|
|
308 |
#ifndef ROBOT |
|
309 |
int i; |
|
310 |
for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) { |
|
311 |
ret = xbee_get_packet(NULL); |
|
312 |
|
|
313 |
usleep(1000); |
|
314 |
|
|
315 |
/* if (ret == -1) { */ |
|
316 |
/* WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */ |
|
317 |
/* return -1; */ |
|
318 |
/* } */ |
|
319 |
} |
|
320 |
#else |
|
321 |
//wait to return until the address is set |
|
322 |
//TODO: this shouldn't wait indefinitely. There should be some sort of reasonable timeout |
|
323 |
// so if the address is never set right, an error can be returned instead of having the |
|
324 |
// robot hang forever |
|
325 |
while (xbee_address == 0) { |
|
326 |
xbee_get_packet(NULL); |
|
327 |
} |
|
328 |
#endif |
|
329 |
WL_DEBUG_PRINT("Got ATMY address.\n"); |
|
330 |
|
|
331 |
#ifndef ROBOT |
|
332 |
if (i == XBEE_GET_PACKET_TIMEOUT) { // We timed-out. |
|
333 |
|
|
334 |
WL_DEBUG_PRINT("xbee_get_packet timed out.\n"); |
|
335 |
return -1; |
|
336 |
} else { |
|
337 |
return 0; |
|
338 |
} |
|
339 |
#else |
|
340 |
return 0; |
|
341 |
#endif |
|
342 |
} |
|
343 |
|
|
344 |
void xbee_terminate() |
|
345 |
{ |
|
346 |
#ifndef ROBOT |
|
347 |
pthread_cancel(*xbee_listen_thread); |
|
348 |
pthread_join(*xbee_listen_thread, NULL); |
|
349 |
free(xbee_listen_thread); |
|
350 |
lockf(xbee_stream, F_ULOCK, 0); |
|
351 |
close(xbee_stream); |
|
352 |
#else |
|
353 |
xbee_exit_api_mode(); |
|
354 |
#endif |
|
355 |
} |
|
356 |
|
|
357 |
|
|
358 |
|
|
359 |
static int xbee_send(char* buf, int size) |
|
360 |
#ifndef ROBOT |
|
361 |
|
|
362 |
int ret = write(xbee_stream, buf, size); |
|
363 |
//success |
|
364 |
if (ret == size) |
|
365 |
return 0; |
|
366 |
if (ret == -1) |
|
367 |
{ |
|
368 |
//interrupted by system signal, probably timer interrupt. |
|
369 |
//just try again |
|
370 |
if (errno == 4) |
|
371 |
{ |
|
372 |
return xbee_send(buf, size); |
|
373 |
} |
|
374 |
WL_DEBUG_PRINT("Failed to write to xbee\r\n"); |
|
375 |
return -1; |
|
376 |
} |
|
377 |
|
|
378 |
//write was interrupted after writing ret bytes |
|
379 |
return xbee_send(buf + ret, size - ret); |
|
380 |
#endif |
|
381 |
|
|
382 |
|
|
383 |
#ifndef ROBOT |
|
384 |
static int xbee_read(char* buf, int size) |
|
385 |
{ |
|
386 |
if (read(xbee_stream, buf, size) == -1) { |
|
387 |
WL_DEBUG_PRINT("Failed to read from xbee.\r\n"); |
|
388 |
return -1; |
|
389 |
} |
|
390 |
|
|
391 |
return 0; |
|
392 |
} |
|
393 |
#endif |
|
394 |
|
|
395 |
|
|
396 |
#ifndef ROBOT |
|
397 |
void xbee_set_com_port(char* port) |
|
398 |
{ |
|
399 |
xbee_com_port = port; |
|
400 |
} |
|
401 |
#endif |
|
402 |
|
Also available in: Unified diff