Project

General

Profile

Statistics
| Revision:

root / branches / init_refactor / code / projects / libdragonfly / serial.c @ 1543

History | View | Annotate | Download (10.3 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
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee already init'd\r\n");
112
    return ERROR_INIT_ALREADY_INITD;
113
  }
114

    
115
  //Set baud rate
116
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
117
  // - 9600 is U2X =1, UBRR = 107.
118
#if (XBEE_BAUD == 115200)
119
  UBRR1H = 0x00;
120
  UBRR1L = 8;
121
  UCSR1A |= _BV(U2X1);
122
#elif (XBEE_BAUD == 9600)
123
  UBRR1H = 0x00;
124
  UBRR1L = 103;
125
  UCSR1A |= _BV(U2X1);
126
#else //Baud rate is defined in the header file, we should not get here
127
  return 0;
128
#endif
129

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

    
142
  xbee_initd = 1;
143
  return 0;
144

    
145
}
146

    
147
/**
148
 * Sends a character over USB.
149
 *
150
 * @param c the character to send
151
 * @return 0 for success, nonzero for failure
152
 **/
153
int usb_putc(char c) {
154

    
155
  if(!usb_initd)
156
    return ERROR_LIBRARY_NOT_INITD;
157

    
158
  // Wait until buffer is clear for sending
159
  loop_until_bit_is_set(UCSR0A, UDRE0);
160
        
161
  // Load buffer with your character
162
  UDR0 = c;
163
  return 0;
164
}
165

    
166
/**
167
 * Sends a character to the XBee.
168
 *
169
 * @param c the character to send
170
 * @return 0 for success, nonzero for failure
171
 **/
172
int xbee_putc(char c) {
173

    
174
  if(!xbee_initd) {
175
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
176
    return ERROR_LIBRARY_NOT_INITD;
177
  }
178

    
179
  // Wait until buffer is clear for sending
180
  loop_until_bit_is_set(UCSR1A, UDRE1);
181
        
182
  // Load buffer with your character
183
  UDR1 = c;
184
  return 0;
185
}
186

    
187
/**
188
 * Sends a sequence of characters over USB.
189
 *
190
 * @param s the string to send
191
 * @return 0 for success, nonzero for failure
192
 **/
193
int usb_puts(char *s) {
194
  char *t = s;
195

    
196
  if(!usb_initd) {
197
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
198
    return ERROR_LIBRARY_NOT_INITD;
199
  }
200

    
201
  while (*t != 0) {
202
    usb_putc(*t);
203
    t++;
204
  }
205
  return 0;
206
}
207

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

    
218
    if(!usb_initd) {
219
      DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
220
      return ERROR_LIBRARY_NOT_INITD;
221
    }
222
        
223
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
224
        usb_putc (buf);
225
        s++;
226
    }
227

    
228
    return 0;
229
}
230

    
231

    
232

    
233
/**
234
 * Returns the first character in the buffer received from USB.
235
 * This function blocks execution until a character has been received.
236
 * xbee_init must be called before this function may be used.
237
 * 
238
 * @return the first character in the usb buffer, -1 on error
239
 *
240
 * @see usb_init, usb_getc_nb
241
 **/
242
int usb_getc(void) {
243

    
244
  if(!usb_initd)
245
    return -1;
246

    
247
  // Wait for the receive buffer to be filled
248
  loop_until_bit_is_set(UCSR0A, RXC0);
249
        
250
  // Read the receive buffer
251
  return UDR0;
252
}
253

    
254
/**
255
 * Returns the first character in the buffer received from USB.
256
 * This function blocks execution until a character has been
257
 * received. xbee_init must be called before this function
258
 * may be used.
259
 * 
260
 * @return the first character in the xbee buffer, -1 on error
261
 * 
262
 * @see xbee_init, xbee_getc_nb
263
 **/
264
int xbee_getc(void) {
265

    
266
  if(!usb_initd) {
267
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
268
    return -1;
269
  }
270

    
271
  // Wait for the receive buffer to be filled
272
  loop_until_bit_is_set(UCSR1A, RXC1);
273
        
274
  // Read the receive buffer
275
  return UDR1;
276
}
277

    
278
/**
279
 * Non blocking version of usb_getc. If a character is present in the buffer,
280
 * it is returned, otherwise -1 is returned immediately. usb_init must be
281
 * called before this function can be used.
282
 *
283
 * @param c the received character. This will be set if a character has
284
 * been received.
285
 * 
286
 * @return -1 if no character is available, 0 otherwise, positive for error
287
 * 
288
 * @see usb_init, usb_getc
289
 **/
290
int usb_getc_nb(char *c) {
291

    
292
  if(!usb_initd)
293
    return ERROR_LIBRARY_NOT_INITD;
294

    
295
  // check if the receive buffer is filled
296
  if (UCSR0A & _BV(RXC0)) {
297
    // Read the receive buffer
298
    (*c) = UDR0;
299
    return 0;
300
  } else {
301
    // Return empty
302
    return -1;
303
  }
304
}
305

    
306
/**
307
 * Non blocking version of xbee_getc. If a character is present in the buffer,
308
 * it is returned, otherwise -1 is returned immediately. xbee_init
309
 * must be called before this function can be used.
310
 *
311
 * @param c the received character. This will be set if a character has
312
 * been received.
313
 * 
314
 * @return -1 if no character is available, 0 otherwise, positive for error
315
 *
316
 * @see xbee_init, xbee_getc
317
 **/
318
int xbee_getc_nb(char *c) {
319
  if(!xbee_initd) {
320
    DRAGONFLY_DEBUG_PRINT("ERROR: xbee not init'd\r\n"); 
321
    return ERROR_LIBRARY_NOT_INITD;
322
  }
323

    
324
  // check if the receive buffer is filled
325
  if (UCSR1A & _BV(RXC1)) {
326
    // Read the receive buffer
327
    (*c) = UDR1;
328
    return 0;
329
  } else {
330
    // Return empty
331
    return -1;
332
  }
333
}
334

    
335

    
336
/*
337
  prints an int to serial
338

339
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
340
  uses usb_putc
341
*/
342
/**
343
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
344
 * before this function can be used.
345
 *
346
 * @param value the integer to print
347
 * 
348
 * @return 0 if successful, nonzero otherwise
349
 *
350
 * @see usb_init, usb_putc
351
 **/
352
int usb_puti(int value ) {
353
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
354

    
355
  if(!usb_initd)
356
    return ERROR_LIBRARY_NOT_INITD;
357

    
358

    
359
  /* convert int to ascii  */ 
360
  if(value<0) { 
361
    usb_putc('-'); 
362
    value=-value; 
363
  }    
364
  do { 
365
    position--; 
366
    *(usb_data+position)=(value%radix)+'0'; 
367
    value/=radix;  
368
  } while(value); 
369

    
370
    
371
  /* start displaying the number */
372
  for(;position<=(sizeof(usb_data)-1);position++) {
373
            
374
    usb_putc(usb_data[position]);
375
  }
376

    
377
  return 0;
378
}
379

    
380
/**
381
 * Determines a hexadecimal digit in ASCII code.
382
 *
383
 * @param value the value of the digit (0<=value<=15)
384
 * 
385
 * @return the hexadecimal digit in ASCII code, or '?'
386
 * if the input is invalid.
387
 **/
388
uint8_t hex_digit (uint8_t value)
389
{
390
    if (value>15) return '?';
391
    // Postcondition: 0<=x<=15
392

    
393
    return "0123456789ABCDEF"[value];
394
}
395

    
396
/**
397
 * Prints a fixed width hexadecimal representation of an unsigned
398
 * 16 bit integer in ASCII code to USB.
399
 * usb_init must be called before this function can be used.
400
 *
401
 * @param value the value to print
402
 * 
403
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
404
 *
405
 * @return 0 if init succesfull, an error code otherwise
406
 **/
407
int usb_puth16 (uint16_t value)
408
{
409
    if(!usb_initd)
410
      return ERROR_LIBRARY_NOT_INITD;
411

    
412
    usb_putc (hex_digit((value >>12)&0xF));
413
    usb_putc (hex_digit((value >>8 )&0xF));
414
    usb_putc (hex_digit((value >>4 )&0xF));
415
    usb_putc (hex_digit( value      &0xF));
416

    
417
    return 0;
418
}
419

    
420
/**
421
 * Prints a fixed width hexadecimal representation of an unsigned
422
 * 8 bit integer in ASCII code to USB.
423
 * usb_init must be called before this function can be used.
424
 *
425
 * @param value the value to print
426
 * 
427
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
428
 *
429
 * @return 0 if init succesfull, an error code otherwise
430
 **/
431
int usb_puth8(uint8_t value)
432
{
433
    if(!usb_initd)
434
      return ERROR_LIBRARY_NOT_INITD;
435

    
436
    usb_putc (hex_digit ((value)>>4 &0xF));
437
    usb_putc (hex_digit ( value     &0xF));
438

    
439
    return 0;
440
}
441