Project

General

Profile

Statistics
| Revision:

root / branches / init_refactor / code / projects / libdragonfly / serial.c @ 1547

History | View | Annotate | Download (10.2 KB)

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
/**
28
 * @file serial.c
29
 * @brief Serial Input and Output
30
 *
31
 * Implementation of functions for serial input and output.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

    
36
#include <avr/io.h>
37

    
38
#include "dragonfly_defs.h"
39
#include "serial.h"
40

    
41
unsigned char usb_initd=0;
42
unsigned char xbee_initd=0;
43

    
44
#ifdef USE_STDIO
45

    
46
#include <stdio.h>
47

    
48
/**
49
 * For use with fprintf() and related stdio functions
50
 **/
51
FILE *usb_fd;
52

    
53
/**
54
 * For use with fprintf() and related stdio functions
55
 **/
56
FILE *xbee_fd;
57

    
58
#endif
59

    
60
/**
61
 * Initializes communication over the USB serial port.
62
 * This must be called before any other usb function
63
 * may be used.
64
 **/
65
int usb_init() {
66
  //Set baud rate
67
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
68
  // - 9600 is U2X =1, UBRR = 107.
69

    
70
  if(usb_initd) {
71
    DRAGONFLY_DEBUG_PRINT("ERROR: usb already init'd\r\n");
72
    return ERROR_INIT_ALREADY_INITD;
73
  }
74

    
75
#if (USB_BAUD == 115200)
76
  UBRR0H = 0x00;
77
  UBRR0L = 8;
78
  UCSR0A |= _BV(U2X0);
79
#elif (USB_BAUD == 9600)
80
  UBRR0H = 0x00;
81
  UBRR0L = 103;
82
  UCSR0A |= _BV(U2X0);
83
#else //Baud rate is defined in the header file, we should not get here
84
  return 0;
85
#endif
86

    
87
  /*Enable receiver and transmitter */
88
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
89
        
90
  /* Set frame format: 8data, 1stop bit, asynchronous normal mode */
91
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
92
  
93
  // if we have enabled the stdio stuff, then we init it here
94
#ifdef USE_STDIO
95
  /* Open the stdio stream corresponding to this port */
96
  usb_fd = fdevopen(usb_putc, usb_getc);
97
#endif
98

    
99
  usb_initd = 1;
100
  return 0;
101

    
102
}
103

    
104
/**
105
 * Initializes communication over the XBee.
106
 * This must be called before any other xbee function
107
 * may be used.
108
 **/
109
int xbee_init() {
110

    
111
  if(xbee_initd) {
112
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee already init'd\r\n");
113
    return ERROR_INIT_ALREADY_INITD;
114
  }
115

    
116
  //Set baud rate
117
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
118
  // - 9600 is U2X =1, UBRR = 107.
119
#if (XBEE_BAUD == 115200)
120
  UBRR1H = 0x00;
121
  UBRR1L = 8;
122
  UCSR1A |= _BV(U2X1);
123
#elif (XBEE_BAUD == 9600)
124
  UBRR1H = 0x00;
125
  UBRR1L = 103;
126
  UCSR1A |= _BV(U2X1);
127
#else //Baud rate is defined in the header file, we should not get here
128
  return 0;
129
#endif
130

    
131
  //Enable receiver and transmitter
132
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
133
        
134
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
135
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
136
  
137
  // if we have enabled the stdio stuff, then we init it here
138
#ifdef USE_STDIO
139
  /* Open the stdio stream corresponding to this port */
140
  xbee_fd = fdevopen(xbee_putc, xbee_getc);
141
#endif
142

    
143
  xbee_initd = 1;
144
  return 0;
145

    
146
}
147

    
148
/**
149
 * Sends a character over USB.
150
 *
151
 * @param c the character to send
152
 * @return 0 for success, nonzero for failure
153
 **/
154
int usb_putc(char c) {
155

    
156
  if(!usb_initd)
157
    return ERROR_LIBRARY_NOT_INITD;
158

    
159
  // Wait until buffer is clear for sending
160
  loop_until_bit_is_set(UCSR0A, UDRE0);
161
        
162
  // Load buffer with your character
163
  UDR0 = c;
164
  return 0;
165
}
166

    
167
/**
168
 * Sends a character to the XBee.
169
 *
170
 * @param c the character to send
171
 * @return 0 for success, nonzero for failure
172
 **/
173
int xbee_putc(char c) {
174

    
175
  if(!xbee_initd) {
176
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
177
    return ERROR_LIBRARY_NOT_INITD;
178
  }
179

    
180
  // Wait until buffer is clear for sending
181
  loop_until_bit_is_set(UCSR1A, UDRE1);
182
        
183
  // Load buffer with your character
184
  UDR1 = c;
185
  return 0;
186
}
187

    
188
/**
189
 * Sends a sequence of characters over USB.
190
 *
191
 * @param s the string to send
192
 * @return 0 for success, nonzero for failure
193
 **/
194
int usb_puts(char *s) {
195
  char *t = s;
196

    
197
  if(!usb_initd) {
198
    return ERROR_LIBRARY_NOT_INITD;
199
  }
200

    
201
  while (*t != 0) {
202
    usb_putc(*t);
203
    t++;
204
  }
205
  return 0;
206
}
207

    
208
/**
209
 * Sends a sequence of characters from program space over USB.
210
 *
211
 * @param s the string to send
212
 *
213
 * @return 0 if init succesfull, an error code otherwise
214
 **/
215
int usb_puts_P (PGM_P s) {
216
    char buf;
217

    
218
    if(!usb_initd) {
219
      return ERROR_LIBRARY_NOT_INITD;
220
    }
221
        
222
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
223
        usb_putc (buf);
224
        s++;
225
    }
226

    
227
    return 0;
228
}
229

    
230

    
231

    
232
/**
233
 * Returns the first character in the buffer received from USB.
234
 * This function blocks execution until a character has been received.
235
 * xbee_init must be called before this function may be used.
236
 * 
237
 * @return the first character in the usb buffer, -1 on error
238
 *
239
 * @see usb_init, usb_getc_nb
240
 **/
241
int usb_getc(void) {
242

    
243
  if(!usb_initd)
244
    return -1;
245

    
246
  // Wait for the receive buffer to be filled
247
  loop_until_bit_is_set(UCSR0A, RXC0);
248
        
249
  // Read the receive buffer
250
  return UDR0;
251
}
252

    
253
/**
254
 * Returns the first character in the buffer received from USB.
255
 * This function blocks execution until a character has been
256
 * received. xbee_init must be called before this function
257
 * may be used.
258
 * 
259
 * @return the first character in the xbee buffer, -1 on error
260
 * 
261
 * @see xbee_init, xbee_getc_nb
262
 **/
263
int xbee_getc(void) {
264

    
265
  if(!usb_initd) {
266
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
267
    return -1;
268
  }
269

    
270
  // Wait for the receive buffer to be filled
271
  loop_until_bit_is_set(UCSR1A, RXC1);
272
        
273
  // Read the receive buffer
274
  return UDR1;
275
}
276

    
277
/**
278
 * Non blocking version of usb_getc. If a character is present in the buffer,
279
 * it is returned, otherwise -1 is returned immediately. usb_init must be
280
 * called before this function can be used.
281
 *
282
 * @param c the received character. This will be set if a character has
283
 * been received.
284
 * 
285
 * @return -1 if no character is available, 0 otherwise, positive for error
286
 * 
287
 * @see usb_init, usb_getc
288
 **/
289
int usb_getc_nb(char *c) {
290

    
291
  if(!usb_initd)
292
    return ERROR_LIBRARY_NOT_INITD;
293

    
294
  // check if the receive buffer is filled
295
  if (UCSR0A & _BV(RXC0)) {
296
    // Read the receive buffer
297
    (*c) = UDR0;
298
    return 0;
299
  } else {
300
    // Return empty
301
    return -1;
302
  }
303
}
304

    
305
/**
306
 * Non blocking version of xbee_getc. If a character is present in the buffer,
307
 * it is returned, otherwise -1 is returned immediately. xbee_init
308
 * must be called before this function can be used.
309
 *
310
 * @param c the received character. This will be set if a character has
311
 * been received.
312
 * 
313
 * @return -1 if no character is available, 0 otherwise, positive for error
314
 *
315
 * @see xbee_init, xbee_getc
316
 **/
317
int xbee_getc_nb(char *c) {
318
  if(!xbee_initd) {
319
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
320
    return ERROR_LIBRARY_NOT_INITD;
321
  }
322

    
323
  // check if the receive buffer is filled
324
  if (UCSR1A & _BV(RXC1)) {
325
    // Read the receive buffer
326
    (*c) = UDR1;
327
    return 0;
328
  } else {
329
    // Return empty
330
    return -1;
331
  }
332
}
333

    
334

    
335
/*
336
  prints an int to serial
337

338
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
339
  uses usb_putc
340
*/
341
/**
342
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
343
 * before this function can be used.
344
 *
345
 * @param value the integer to print
346
 * 
347
 * @return 0 if successful, nonzero otherwise
348
 *
349
 * @see usb_init, usb_putc
350
 **/
351
int usb_puti(int value ) {
352
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
353

    
354
  if(!usb_initd)
355
    return ERROR_LIBRARY_NOT_INITD;
356

    
357

    
358
  /* convert int to ascii  */ 
359
  if(value<0) { 
360
    usb_putc('-'); 
361
    value=-value; 
362
  }    
363
  do { 
364
    position--; 
365
    *(usb_data+position)=(value%radix)+'0'; 
366
    value/=radix;  
367
  } while(value); 
368

    
369
    
370
  /* start displaying the number */
371
  for(;position<=(sizeof(usb_data)-1);position++) {
372
            
373
    usb_putc(usb_data[position]);
374
  }
375

    
376
  return 0;
377
}
378

    
379
/**
380
 * Determines a hexadecimal digit in ASCII code.
381
 *
382
 * @param value the value of the digit (0<=value<=15)
383
 * 
384
 * @return the hexadecimal digit in ASCII code, or '?'
385
 * if the input is invalid.
386
 **/
387
uint8_t hex_digit (uint8_t value)
388
{
389
    if (value>15) return '?';
390
    // Postcondition: 0<=x<=15
391

    
392
    return "0123456789ABCDEF"[value];
393
}
394

    
395
/**
396
 * Prints a fixed width hexadecimal representation of an unsigned
397
 * 16 bit integer in ASCII code to USB.
398
 * usb_init must be called before this function can be used.
399
 *
400
 * @param value the value to print
401
 * 
402
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
403
 *
404
 * @return 0 if init succesfull, an error code otherwise
405
 **/
406
int usb_puth16 (uint16_t value)
407
{
408
    if(!usb_initd)
409
      return ERROR_LIBRARY_NOT_INITD;
410

    
411
    usb_putc (hex_digit((value >>12)&0xF));
412
    usb_putc (hex_digit((value >>8 )&0xF));
413
    usb_putc (hex_digit((value >>4 )&0xF));
414
    usb_putc (hex_digit( value      &0xF));
415

    
416
    return 0;
417
}
418

    
419
/**
420
 * Prints a fixed width hexadecimal representation of an unsigned
421
 * 8 bit integer in ASCII code to USB.
422
 * usb_init must be called before this function can be used.
423
 *
424
 * @param value the value to print
425
 * 
426
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
427
 *
428
 * @return 0 if init succesfull, an error code otherwise
429
 **/
430
int usb_puth8(uint8_t value)
431
{
432
    if(!usb_initd)
433
      return ERROR_LIBRARY_NOT_INITD;
434

    
435
    usb_putc (hex_digit ((value)>>4 &0xF));
436
    usb_putc (hex_digit ( value     &0xF));
437

    
438
    return 0;
439
}
440