Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (9.91 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
    return ERROR_INIT_ALREADY_INITD;
72
  }
73

    
74
#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
  return 0;
84
#endif
85

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

    
98
  usb_initd = 1;
99
  return 0;
100

    
101
}
102

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

    
110
  if(xbee_initd) {
111
    return ERROR_INIT_ALREADY_INITD;
112
  }
113

    
114
  //Set baud rate
115
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
116
  // - 9600 is U2X =1, UBRR = 107.
117
#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
  return 0;
127
#endif
128

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

    
141
  xbee_initd = 1;
142
  return 0;
143

    
144
}
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
int usb_putc(char c) {
153

    
154
  if(!usb_initd)
155
    return ERROR_LIBRARY_NOT_INITD;
156

    
157
  // 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
int xbee_putc(char c) {
172

    
173
  if(!xbee_initd)
174
    return ERROR_LIBRARY_NOT_INITD;
175

    
176
  // 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
int usb_puts(char *s) {
191
  char *t = s;
192

    
193
  if(!usb_initd)
194
    return ERROR_LIBRARY_NOT_INITD;
195

    
196
  while (*t != 0) {
197
    usb_putc(*t);
198
    t++;
199
  }
200
  return 0;
201
}
202

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

    
213
    if(!usb_initd)
214
      return ERROR_LIBRARY_NOT_INITD;
215
        
216
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
217
        usb_putc (buf);
218
        s++;
219
    }
220

    
221
    return 0;
222
}
223

    
224

    
225

    
226
/**
227
 * 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
 * @return the first character in the usb buffer, -1 on error
232
 *
233
 * @see usb_init, usb_getc_nb
234
 **/
235
int usb_getc(void) {
236

    
237
  if(!usb_initd)
238
    return -1;
239

    
240
  // Wait for the receive buffer to be filled
241
  loop_until_bit_is_set(UCSR0A, RXC0);
242
        
243
  // Read the receive buffer
244
  return UDR0;
245
}
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
 * @return the first character in the xbee buffer, -1 on error
254
 * 
255
 * @see xbee_init, xbee_getc_nb
256
 **/
257
int xbee_getc(void) {
258

    
259
  if(!usb_initd)
260
    return -1;
261

    
262
  // Wait for the receive buffer to be filled
263
  loop_until_bit_is_set(UCSR1A, RXC1);
264
        
265
  // Read the receive buffer
266
  return UDR1;
267
}
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
 * @return -1 if no character is available, 0 otherwise, positive for error
278
 * 
279
 * @see usb_init, usb_getc
280
 **/
281
int usb_getc_nb(char *c) {
282

    
283
  if(!usb_initd)
284
    return ERROR_LIBRARY_NOT_INITD;
285

    
286
  // check if the receive buffer is filled
287
  if (UCSR0A & _BV(RXC0)) {
288
    // Read the receive buffer
289
    (*c) = UDR0;
290
    return 0;
291
  } else {
292
    // Return empty
293
    return -1;
294
  }
295
}
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
 * @return -1 if no character is available, 0 otherwise, positive for error
306
 *
307
 * @see xbee_init, xbee_getc
308
 **/
309
int xbee_getc_nb(char *c) {
310
  if(!xbee_initd)
311
    return ERROR_LIBRARY_NOT_INITD;
312

    
313
  // check if the receive buffer is filled
314
  if (UCSR1A & _BV(RXC1)) {
315
    // Read the receive buffer
316
    (*c) = UDR1;
317
    return 0;
318
  } else {
319
    // Return empty
320
    return -1;
321
  }
322
}
323

    
324

    
325
/*
326
  prints an int to serial
327

328
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
329
  uses usb_putc
330
*/
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
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
343

    
344
  if(!usb_initd)
345
    return ERROR_LIBRARY_NOT_INITD;
346

    
347

    
348
  /* 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

    
359
    
360
  /* start displaying the number */
361
  for(;position<=(sizeof(usb_data)-1);position++) {
362
            
363
    usb_putc(usb_data[position]);
364
  }
365

    
366
  return 0;
367
}
368

    
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
 *
394
 * @return 0 if init succesfull, an error code otherwise
395
 **/
396
int usb_puth16 (uint16_t value)
397
{
398
    if(!usb_initd)
399
      return ERROR_LIBRARY_NOT_INITD;
400

    
401
    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

    
406
    return 0;
407
}
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
 *
418
 * @return 0 if init succesfull, an error code otherwise
419
 **/
420
int usb_puth8(uint8_t value)
421
{
422
    if(!usb_initd)
423
      return ERROR_LIBRARY_NOT_INITD;
424

    
425
    usb_putc (hex_digit ((value)>>4 &0xF));
426
    usb_putc (hex_digit ( value     &0xF));
427

    
428
    return 0;
429
}
430