Project

General

Profile

Statistics
| Revision:

root / branches / wireless / code / projects / libdragonfly / serial.c @ 1604

History | View | Annotate | Download (7.24 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

    
43
#ifdef USE_STDIO
44

    
45
#include <stdio.h>
46

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

    
52
#endif
53

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

    
64
  if(usb_initd) {
65
    return ERROR_INIT_ALREADY_INITD;
66
  }
67

    
68
#if (USB_BAUD == 115200)
69
  UBRR0H = 0x00;
70
  UBRR0L = 8;
71
  UCSR0A |= _BV(U2X0);
72
#elif (USB_BAUD == 9600)
73
  UBRR0H = 0x00;
74
  UBRR0L = 103;
75
  UCSR0A |= _BV(U2X0);
76
#else //Baud rate is defined in the header file, we should not get here
77
  return 0;
78
#endif
79

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

    
92
  usb_initd = 1;
93
  return 0;
94

    
95
}
96

    
97

    
98
/**
99
 * Sends a character over USB.
100
 *
101
 * @param c the character to send
102
 * @return 0 for success, nonzero for failure
103
 **/
104
int usb_putc(char c) {
105

    
106
  if(!usb_initd)
107
    return ERROR_LIBRARY_NOT_INITD;
108

    
109
  // Wait until buffer is clear for sending
110
  loop_until_bit_is_set(UCSR0A, UDRE0);
111
        
112
  // Load buffer with your character
113
  UDR0 = c;
114
  return 0;
115
}
116

    
117
/**
118
 * Sends a sequence of characters over USB.
119
 *
120
 * @param s the string to send
121
 * @return 0 for success, nonzero for failure
122
 **/
123
int usb_puts(char *s) {
124
  char *t = s;
125

    
126
  if(!usb_initd)
127
    return ERROR_LIBRARY_NOT_INITD;
128

    
129
  while (*t != 0) {
130
    usb_putc(*t);
131
    t++;
132
  }
133
  return 0;
134
}
135

    
136
/**
137
 * Sends a sequence of characters from program space over USB.
138
 *
139
 * @param s the string to send
140
 *
141
 * @return 0 if init succesfull, an error code otherwise
142
 **/
143
int usb_puts_P (PGM_P s) {
144
    char buf;
145

    
146
    if(!usb_initd)
147
      return ERROR_LIBRARY_NOT_INITD;
148
        
149
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
150
        usb_putc (buf);
151
        s++;
152
    }
153

    
154
    return 0;
155
}
156

    
157

    
158

    
159
/**
160
 * Returns the first character in the buffer received from USB.
161
 * This function blocks execution until a character has been received.
162
 * xbee_init must be called before this function may be used.
163
 * 
164
 * @return the first character in the usb buffer, -1 on error
165
 *
166
 * @see usb_init, usb_getc_nb
167
 **/
168
int usb_getc(void) {
169

    
170
  if(!usb_initd)
171
    return -1;
172

    
173
  // Wait for the receive buffer to be filled
174
  loop_until_bit_is_set(UCSR0A, RXC0);
175
        
176
  // Read the receive buffer
177
  return UDR0;
178
}
179

    
180
/**
181
 * Non blocking version of usb_getc. If a character is present in the buffer,
182
 * it is returned, otherwise -1 is returned immediately. usb_init must be
183
 * called before this function can be used.
184
 *
185
 * @param c the received character. This will be set if a character has
186
 * been received.
187
 * 
188
 * @return -1 if no character is available, 0 otherwise, positive for error
189
 * 
190
 * @see usb_init, usb_getc
191
 **/
192
int usb_getc_nb(char *c) {
193

    
194
  if(!usb_initd)
195
    return ERROR_LIBRARY_NOT_INITD;
196

    
197
  // check if the receive buffer is filled
198
  if (UCSR0A & _BV(RXC0)) {
199
    // Read the receive buffer
200
    (*c) = UDR0;
201
    return 0;
202
  } else {
203
    // Return empty
204
    return -1;
205
  }
206
}
207

    
208
/*
209
  prints an int to serial
210

211
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
212
  uses usb_putc
213
*/
214
/**
215
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
216
 * before this function can be used.
217
 *
218
 * @param value the integer to print
219
 * 
220
 * @return 0 if successful, nonzero otherwise
221
 *
222
 * @see usb_init, usb_putc
223
 **/
224
int usb_puti(int value ) {
225
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
226

    
227
  if(!usb_initd)
228
    return ERROR_LIBRARY_NOT_INITD;
229

    
230

    
231
  /* convert int to ascii  */ 
232
  if(value<0) { 
233
    usb_putc('-'); 
234
    value=-value; 
235
  }    
236
  do { 
237
    position--; 
238
    *(usb_data+position)=(value%radix)+'0'; 
239
    value/=radix;  
240
  } while(value); 
241

    
242
    
243
  /* start displaying the number */
244
  for(;position<=(sizeof(usb_data)-1);position++) {
245
            
246
    usb_putc(usb_data[position]);
247
  }
248

    
249
  return 0;
250
}
251

    
252
/**
253
 * Determines a hexadecimal digit in ASCII code.
254
 *
255
 * @param value the value of the digit (0<=value<=15)
256
 * 
257
 * @return the hexadecimal digit in ASCII code, or '?'
258
 * if the input is invalid.
259
 **/
260
uint8_t hex_digit (uint8_t value)
261
{
262
    if (value>15) return '?';
263
    // Postcondition: 0<=x<=15
264

    
265
    return "0123456789ABCDEF"[value];
266
}
267

    
268
/**
269
 * Prints a fixed width hexadecimal representation of an unsigned
270
 * 16 bit integer in ASCII code to USB.
271
 * usb_init must be called before this function can be used.
272
 *
273
 * @param value the value to print
274
 * 
275
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
276
 *
277
 * @return 0 if init succesfull, an error code otherwise
278
 **/
279
int usb_puth16 (uint16_t value)
280
{
281
    if(!usb_initd)
282
      return ERROR_LIBRARY_NOT_INITD;
283

    
284
    usb_putc (hex_digit((value >>12)&0xF));
285
    usb_putc (hex_digit((value >>8 )&0xF));
286
    usb_putc (hex_digit((value >>4 )&0xF));
287
    usb_putc (hex_digit( value      &0xF));
288

    
289
    return 0;
290
}
291

    
292
/**
293
 * Prints a fixed width hexadecimal representation of an unsigned
294
 * 8 bit integer in ASCII code to USB.
295
 * usb_init must be called before this function can be used.
296
 *
297
 * @param value the value to print
298
 * 
299
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
300
 *
301
 * @return 0 if init succesfull, an error code otherwise
302
 **/
303
int usb_puth8(uint8_t value)
304
{
305
    if(!usb_initd)
306
      return ERROR_LIBRARY_NOT_INITD;
307

    
308
    usb_putc (hex_digit ((value)>>4 &0xF));
309
    usb_putc (hex_digit ( value     &0xF));
310

    
311
    return 0;
312
}
313