Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / projects / libwireless / xbee_computer.c.bak @ 1611

History | View | Annotate | Download (8.1 KB)

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