Project

General

Profile

Statistics
| Revision:

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

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

266 380 jknichel
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
267
  uses usb_putc
268 8 bcoltin
*/
269
/**
270
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
271
 * before this function can be used.
272
 *
273
 * @param value the integer to print
274
 *
275
 * @return 0 if successful, nonzero otherwise
276
 *
277
 * @see usb_init, usb_putc
278
 **/
279
int usb_puti(int value ) {
280 380 jknichel
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10;
281 8 bcoltin
282 380 jknichel
  /* convert int to ascii  */
283
  if(value<0) {
284
    usb_putc('-');
285
    value=-value;
286
  }
287
  do {
288
    position--;
289
    *(usb_data+position)=(value%radix)+'0';
290
    value/=radix;
291
  } while(value);
292 8 bcoltin
293
294 380 jknichel
  /* start displaying the number */
295
  for(;position<=(sizeof(usb_data)-1);position++) {
296 8 bcoltin
297 380 jknichel
    usb_putc(usb_data[position]);
298
  }
299 8 bcoltin
300 380 jknichel
  return 0;
301 8 bcoltin
}
302 1143 deffi
303
/**
304
 * Determines a hexadecimal digit in ASCII code.
305
 *
306
 * @param value the value of the digit (0<=value<=15)
307
 *
308
 * @return the hexadecimal digit in ASCII code, or '?'
309
 * if the input is invalid.
310
 **/
311
uint8_t hex_digit (uint8_t value)
312
{
313
    if (value>15) return '?';
314
    // Postcondition: 0<=x<=15
315
316
    return "0123456789ABCDEF"[value];
317
}
318
319
/**
320
 * Prints a fixed width hexadecimal representation of an unsigned
321
 * 16 bit integer in ASCII code to USB.
322
 * usb_init must be called before this function can be used.
323
 *
324
 * @param value the value to print
325
 *
326
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
327
 **/
328
void usb_puth16 (uint16_t value)
329
{
330
    usb_putc (hex_digit((value >>12)&0xF));
331
    usb_putc (hex_digit((value >>8 )&0xF));
332
    usb_putc (hex_digit((value >>4 )&0xF));
333
    usb_putc (hex_digit( value      &0xF));
334
}
335
336
/**
337
 * Prints a fixed width hexadecimal representation of an unsigned
338
 * 8 bit integer in ASCII code to USB.
339
 * usb_init must be called before this function can be used.
340
 *
341
 * @param value the value to print
342
 *
343
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
344
 **/
345
void usb_puth8(uint8_t value)
346
{
347
    usb_putc (hex_digit ((value)>>4 &0xF));
348
    usb_putc (hex_digit ( value     &0xF));
349
}