Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / projects / libwireless / xbee_computer.c @ 1604

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