Project

General

Profile

Statistics
| Revision:

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

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

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