Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / libdragonfly / serial.c @ 1461

History | View | Annotate | Download (9.88 KB)

1 241 bcoltin
/**
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 8 bcoltin
26 241 bcoltin
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 8 bcoltin
#include <avr/io.h>
37
#include "serial.h"
38
39 1461 bneuman
unsigned char usb_initd=0;
40
unsigned char xbee_initd=0;
41
42 1452 dsschult
#ifdef USE_STDIO
43
44
#include <stdio.h>
45
46 1370 dsschult
/**
47
 * For use with fprintf() and related stdio functions
48
 **/
49
FILE *usb_fd;
50 8 bcoltin
51
/**
52 1370 dsschult
 * For use with fprintf() and related stdio functions
53
 **/
54
FILE *xbee_fd;
55
56 1452 dsschult
#endif
57
58 1370 dsschult
/**
59 8 bcoltin
 * Initializes communication over the USB serial port.
60
 * This must be called before any other usb function
61
 * may be used.
62
 **/
63 1461 bneuman
int usb_init() {
64 8 bcoltin
  //Set baud rate
65
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
66
  // - 9600 is U2X =1, UBRR = 107.
67 1461 bneuman
68
  if(usb_initd) {
69
    return ERROR_INIT_ALREADY_INITD;
70
  }
71
72 380 jknichel
#if (USB_BAUD == 115200)
73
  UBRR0H = 0x00;
74
  UBRR0L = 8;
75
  UCSR0A |= _BV(U2X0);
76
#elif (USB_BAUD == 9600)
77
  UBRR0H = 0x00;
78
  UBRR0L = 103;
79
  UCSR0A |= _BV(U2X0);
80
#else //Baud rate is defined in the header file, we should not get here
81 1461 bneuman
  return 0;
82 380 jknichel
#endif
83 8 bcoltin
84
  /*Enable receiver and transmitter */
85 380 jknichel
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
86 8 bcoltin
87 380 jknichel
  /* Set frame format: 8data, 1stop bit, asynchronous normal mode */
88
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
89 8 bcoltin
90
  // if we have enabled the stdio stuff, then we init it here
91 380 jknichel
#ifdef USE_STDIO
92
  /* Open the stdio stream corresponding to this port */
93
  usb_fd = fdevopen(usb_putc, usb_getc);
94
#endif
95 1461 bneuman
96
  usb_initd = 1;
97
  return 0;
98
99 8 bcoltin
}
100
101
/**
102
 * Initializes communication over the XBee.
103
 * This must be called before any other xbee function
104
 * may be used.
105
 **/
106 1461 bneuman
int xbee_init() {
107
108
  if(xbee_initd) {
109
    return ERROR_INIT_ALREADY_INITD;
110
  }
111
112 8 bcoltin
  //Set baud rate
113
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
114
  // - 9600 is U2X =1, UBRR = 107.
115 380 jknichel
#if (XBEE_BAUD == 115200)
116
  UBRR1H = 0x00;
117
  UBRR1L = 8;
118
  UCSR1A |= _BV(U2X1);
119
#elif (XBEE_BAUD == 9600)
120
  UBRR1H = 0x00;
121
  UBRR1L = 103;
122
  UCSR1A |= _BV(U2X1);
123
#else //Baud rate is defined in the header file, we should not get here
124 1461 bneuman
  return 0;
125 380 jknichel
#endif
126 8 bcoltin
127 380 jknichel
  //Enable receiver and transmitter
128
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
129 8 bcoltin
130 380 jknichel
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
131
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
132 8 bcoltin
133
  // if we have enabled the stdio stuff, then we init it here
134 380 jknichel
#ifdef USE_STDIO
135
  /* Open the stdio stream corresponding to this port */
136
  xbee_fd = fdevopen(xbee_putc, xbee_getc);
137
#endif
138 1461 bneuman
139
  xbee_initd = 1;
140
  return 0;
141
142 8 bcoltin
}
143
144
/**
145
 * Sends a character over USB.
146
 *
147
 * @param c the character to send
148
 * @return 0 for success, nonzero for failure
149
 **/
150 380 jknichel
int usb_putc(char c) {
151 1461 bneuman
152
  if(!usb_initd)
153
    return ERROR_LIBRARY_NOT_INITD;
154
155 8 bcoltin
  // Wait until buffer is clear for sending
156
  loop_until_bit_is_set(UCSR0A, UDRE0);
157
158
  // Load buffer with your character
159
  UDR0 = c;
160
  return 0;
161
}
162
163
/**
164
 * Sends a character to the XBee.
165
 *
166
 * @param c the character to send
167
 * @return 0 for success, nonzero for failure
168
 **/
169 380 jknichel
int xbee_putc(char c) {
170 1461 bneuman
171
  if(!xbee_initd)
172
    return ERROR_LIBRARY_NOT_INITD;
173
174 8 bcoltin
  // Wait until buffer is clear for sending
175
  loop_until_bit_is_set(UCSR1A, UDRE1);
176
177
  // Load buffer with your character
178
  UDR1 = c;
179
  return 0;
180
}
181
182
/**
183
 * Sends a sequence of characters over USB.
184
 *
185
 * @param s the string to send
186
 * @return 0 for success, nonzero for failure
187
 **/
188 380 jknichel
int usb_puts(char *s) {
189
  char *t = s;
190 1461 bneuman
191
  if(!usb_initd)
192
    return ERROR_LIBRARY_NOT_INITD;
193
194 380 jknichel
  while (*t != 0) {
195
    usb_putc(*t);
196
    t++;
197
  }
198 8 bcoltin
  return 0;
199
}
200
201
/**
202 1207 deffi
 * Sends a sequence of characters from program space over USB.
203
 *
204
 * @param s the string to send
205 1461 bneuman
 *
206
 * @return 0 if init succesfull, an error code otherwise
207 1207 deffi
 **/
208 1461 bneuman
int usb_puts_P (PGM_P s) {
209 1207 deffi
    char buf;
210 1461 bneuman
211
    if(!usb_initd)
212
      return ERROR_LIBRARY_NOT_INITD;
213 1207 deffi
214
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
215
        usb_putc (buf);
216
        s++;
217
    }
218 1461 bneuman
219
    return 0;
220 1207 deffi
}
221
222
223
224
/**
225 8 bcoltin
 * Returns the first character in the buffer received from USB.
226
 * This function blocks execution until a character has been received.
227
 * xbee_init must be called before this function may be used.
228
 *
229 1461 bneuman
 * @return the first character in the usb buffer, -1 on error
230 8 bcoltin
 *
231
 * @see usb_init, usb_getc_nb
232
 **/
233 380 jknichel
int usb_getc(void) {
234 1461 bneuman
235
  if(!usb_initd)
236
    return -1;
237
238 380 jknichel
  // Wait for the receive buffer to be filled
239
  loop_until_bit_is_set(UCSR0A, RXC0);
240 8 bcoltin
241 380 jknichel
  // Read the receive buffer
242
  return UDR0;
243 8 bcoltin
}
244
245
/**
246
 * Returns the first character in the buffer received from USB.
247
 * This function blocks execution until a character has been
248
 * received. xbee_init must be called before this function
249
 * may be used.
250
 *
251 1461 bneuman
 * @return the first character in the xbee buffer, -1 on error
252 8 bcoltin
 *
253
 * @see xbee_init, xbee_getc_nb
254
 **/
255 380 jknichel
int xbee_getc(void) {
256 1461 bneuman
257
  if(!usb_initd)
258
    return -1;
259
260 380 jknichel
  // Wait for the receive buffer to be filled
261
  loop_until_bit_is_set(UCSR1A, RXC1);
262 8 bcoltin
263 380 jknichel
  // Read the receive buffer
264
  return UDR1;
265 8 bcoltin
}
266
267
/**
268
 * Non blocking version of usb_getc. If a character is present in the buffer,
269
 * it is returned, otherwise -1 is returned immediately. usb_init must be
270
 * called before this function can be used.
271
 *
272
 * @param c the received character. This will be set if a character has
273
 * been received.
274
 *
275 1461 bneuman
 * @return -1 if no character is available, 0 otherwise, positive for error
276 8 bcoltin
 *
277
 * @see usb_init, usb_getc
278
 **/
279 380 jknichel
int usb_getc_nb(char *c) {
280 1461 bneuman
281
  if(!usb_initd)
282
    return ERROR_LIBRARY_NOT_INITD;
283
284 380 jknichel
  // check if the receive buffer is filled
285 8 bcoltin
  if (UCSR0A & _BV(RXC0)) {
286
    // Read the receive buffer
287
    (*c) = UDR0;
288
    return 0;
289 380 jknichel
  } else {
290 8 bcoltin
    // Return empty
291
    return -1;
292 380 jknichel
  }
293 8 bcoltin
}
294
295
/**
296
 * Non blocking version of xbee_getc. If a character is present in the buffer,
297
 * it is returned, otherwise -1 is returned immediately. xbee_init
298
 * must be called before this function can be used.
299
 *
300
 * @param c the received character. This will be set if a character has
301
 * been received.
302
 *
303 1461 bneuman
 * @return -1 if no character is available, 0 otherwise, positive for error
304 8 bcoltin
 *
305
 * @see xbee_init, xbee_getc
306
 **/
307 380 jknichel
int xbee_getc_nb(char *c) {
308 1461 bneuman
  if(!xbee_initd)
309
    return ERROR_LIBRARY_NOT_INITD;
310
311 380 jknichel
  // check if the receive buffer is filled
312 8 bcoltin
  if (UCSR1A & _BV(RXC1)) {
313
    // Read the receive buffer
314
    (*c) = UDR1;
315
    return 0;
316 380 jknichel
  } else {
317 8 bcoltin
    // Return empty
318
    return -1;
319 380 jknichel
  }
320 8 bcoltin
}
321
322
323
/*
324 380 jknichel
  prints an int to serial
325 8 bcoltin

326 380 jknichel
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
327
  uses usb_putc
328 8 bcoltin
*/
329
/**
330
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
331
 * before this function can be used.
332
 *
333
 * @param value the integer to print
334
 *
335
 * @return 0 if successful, nonzero otherwise
336
 *
337
 * @see usb_init, usb_putc
338
 **/
339
int usb_puti(int value ) {
340 380 jknichel
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10;
341 8 bcoltin
342 1461 bneuman
  if(!usb_initd)
343
    return ERROR_LIBRARY_NOT_INITD;
344
345
346 380 jknichel
  /* convert int to ascii  */
347
  if(value<0) {
348
    usb_putc('-');
349
    value=-value;
350
  }
351
  do {
352
    position--;
353
    *(usb_data+position)=(value%radix)+'0';
354
    value/=radix;
355
  } while(value);
356 8 bcoltin
357
358 380 jknichel
  /* start displaying the number */
359
  for(;position<=(sizeof(usb_data)-1);position++) {
360 8 bcoltin
361 380 jknichel
    usb_putc(usb_data[position]);
362
  }
363 8 bcoltin
364 380 jknichel
  return 0;
365 8 bcoltin
}
366 1143 deffi
367
/**
368
 * Determines a hexadecimal digit in ASCII code.
369
 *
370
 * @param value the value of the digit (0<=value<=15)
371
 *
372
 * @return the hexadecimal digit in ASCII code, or '?'
373
 * if the input is invalid.
374
 **/
375
uint8_t hex_digit (uint8_t value)
376
{
377
    if (value>15) return '?';
378
    // Postcondition: 0<=x<=15
379
380
    return "0123456789ABCDEF"[value];
381
}
382
383
/**
384
 * Prints a fixed width hexadecimal representation of an unsigned
385
 * 16 bit integer in ASCII code to USB.
386
 * usb_init must be called before this function can be used.
387
 *
388
 * @param value the value to print
389
 *
390
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
391 1461 bneuman
 *
392
 * @return 0 if init succesfull, an error code otherwise
393 1143 deffi
 **/
394 1461 bneuman
int usb_puth16 (uint16_t value)
395 1143 deffi
{
396 1461 bneuman
    if(!usb_initd)
397
      return ERROR_LIBRARY_NOT_INITD;
398
399 1143 deffi
    usb_putc (hex_digit((value >>12)&0xF));
400
    usb_putc (hex_digit((value >>8 )&0xF));
401
    usb_putc (hex_digit((value >>4 )&0xF));
402
    usb_putc (hex_digit( value      &0xF));
403 1461 bneuman
404
    return 0;
405 1143 deffi
}
406
407
/**
408
 * Prints a fixed width hexadecimal representation of an unsigned
409
 * 8 bit integer in ASCII code to USB.
410
 * usb_init must be called before this function can be used.
411
 *
412
 * @param value the value to print
413
 *
414
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
415 1461 bneuman
 *
416
 * @return 0 if init succesfull, an error code otherwise
417 1143 deffi
 **/
418 1461 bneuman
int usb_puth8(uint8_t value)
419 1143 deffi
{
420 1461 bneuman
    if(!usb_initd)
421
      return ERROR_LIBRARY_NOT_INITD;
422
423 1143 deffi
    usb_putc (hex_digit ((value)>>4 &0xF));
424
    usb_putc (hex_digit ( value     &0xF));
425 1461 bneuman
426
    return 0;
427 1143 deffi
}