Rev Author Line No. Line
1144 kaklik 1  
2 /*
3 * Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>
4 *
5 * This file is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9  
10 #include <stdio.h>
11 #include <avr/interrupt.h>
12 #include <avr/io.h>
13 #include <avr/pgmspace.h>
14 #include <avr/sfr_defs.h>
15 #include <avr/sleep.h>
16  
17 #include "uart.h"
18  
19 /* some mcus have multiple uarts */
20 #ifdef UDR0
21 #define UBRRH UBRR0H
22 #define UBRRL UBRR0L
23 #define UDR UDR0
24  
25 #define UCSRA UCSR0A
26 #define UDRE UDRE0
27 #define RXC RXC0
28  
29 #define UCSRB UCSR0B
30 #define RXEN RXEN0
31 #define TXEN TXEN0
32 #define RXCIE RXCIE0
33  
34 #define UCSRC UCSR0C
35 #define URSEL
36 #define UCSZ0 UCSZ00
37 #define UCSZ1 UCSZ01
38 #define UCSRC_SELECT 0
39 #else
40 #define UCSRC_SELECT (1 << URSEL)
41 #endif
42  
43 #ifndef USART_RXC_vect
44 #if defined(UART0_RX_vect)
45 #define USART_RXC_vect UART0_RX_vect
46 #elif defined(UART_RX_vect)
47 #define USART_RXC_vect UART_RX_vect
48 #elif defined(USART0_RX_vect)
49 #define USART_RXC_vect USART0_RX_vect
50 #elif defined(USART_RX_vect)
51 #define USART_RXC_vect USART_RX_vect
52 #elif defined(USART0_RXC_vect)
53 #define USART_RXC_vect USART0_RXC_vect
54 #elif defined(USART_RXC_vect)
55 #define USART_RXC_vect USART_RXC_vect
56 #else
57 #error "Uart receive complete interrupt not defined!"
58 #endif
59 #endif
60  
61 #define BAUD 9600UL
62 #define UBRRVAL (F_CPU/(BAUD*16)-1)
63 #define USE_SLEEP 1
64  
65 void uart_init()
66 {
67 /* set baud rate */
68 UBRRH = UBRRVAL >> 8;
69 UBRRL = UBRRVAL & 0xff;
70 /* set frame format: 8 bit, no parity, 1 bit */
71 UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
72 /* enable serial receiver and transmitter */
73 #if !USE_SLEEP
74 UCSRB = (1 << RXEN) | (1 << TXEN);
75 #else
76 UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
77 #endif
78 }
79  
80 void uart_putc(uint8_t c)
81 {
82 if(c == '\n')
83 uart_putc('\r');
84  
85 /* wait until transmit buffer is empty */
86 while(!(UCSRA & (1 << UDRE)));
87  
88 /* send next byte */
89 UDR = c;
90 }
91  
92 void uart_putc_hex(uint8_t b)
93 {
94 /* upper nibble */
95 if((b >> 4) < 0x0a)
96 uart_putc((b >> 4) + '0');
97 else
98 uart_putc((b >> 4) - 0x0a + 'a');
99  
100 /* lower nibble */
101 if((b & 0x0f) < 0x0a)
102 uart_putc((b & 0x0f) + '0');
103 else
104 uart_putc((b & 0x0f) - 0x0a + 'a');
105 }
106  
107 void uart_putw_hex(uint16_t w)
108 {
109 uart_putc_hex((uint8_t) (w >> 8));
110 uart_putc_hex((uint8_t) (w & 0xff));
111 }
112  
113 void uart_putdw_hex(uint32_t dw)
114 {
115 uart_putw_hex((uint16_t) (dw >> 16));
116 uart_putw_hex((uint16_t) (dw & 0xffff));
117 }
118  
119 void uart_putw_dec(uint16_t w)
120 {
121 uint16_t num = 10000;
122 uint8_t started = 0;
123  
124 while(num > 0)
125 {
126 uint8_t b = w / num;
127 if(b > 0 || started || num == 1)
128 {
129 uart_putc('0' + b);
130 started = 1;
131 }
132 w -= b * num;
133  
134 num /= 10;
135 }
136 }
137  
138 void uart_putdw_dec(uint32_t dw)
139 {
140 uint32_t num = 1000000000;
141 uint8_t started = 0;
142  
143 while(num > 0)
144 {
145 uint8_t b = dw / num;
146 if(b > 0 || started || num == 1)
147 {
148 uart_putc('0' + b);
149 started = 1;
150 }
151 dw -= b * num;
152  
153 num /= 10;
154 }
155 }
156  
157 void uart_puts(const char* str)
158 {
159 while(*str)
160 uart_putc(*str++);
161 }
162  
163 void uart_puts_p(PGM_P str)
164 {
165 while(1)
166 {
167 uint8_t b = pgm_read_byte_near(str++);
168 if(!b)
169 break;
170  
171 uart_putc(b);
172 }
173 }
174  
175 uint8_t uart_getc()
176 {
177 /* wait until receive buffer is full */
178 #if USE_SLEEP
179 uint8_t sreg = SREG;
180 sei();
181  
182 while(!(UCSRA & (1 << RXC)))
183 sleep_mode();
184  
185 SREG = sreg;
186 #else
187 while(!(UCSRA & (1 << RXC)));
188 #endif
189  
190 uint8_t b = UDR;
191 if(b == '\r')
192 b = '\n';
193  
194 return b;
195 }
196  
197 EMPTY_INTERRUPT(USART_RXC_vect)
198