1 | /************************************************************************/
|
---|
2 | /* */
|
---|
3 | /* Interrupt driven buffered UART */
|
---|
4 | /* */
|
---|
5 | /* Author: Peter Dannegger */
|
---|
6 | /* */
|
---|
7 | /************************************************************************/
|
---|
8 | #include "main.h"
|
---|
9 | #include "uart0.h"
|
---|
10 |
|
---|
11 |
|
---|
12 | static u8 rx_buff[RX0_SIZE];
|
---|
13 | static u8 rx_in;
|
---|
14 | static u8 rx_out;
|
---|
15 | static u8 tx_buff[TX0_SIZE];
|
---|
16 | static u8 tx_in;
|
---|
17 | static u8 tx_out;
|
---|
18 |
|
---|
19 |
|
---|
20 | #define ROLLOVER( x, max ) x = ++x >= max ? 0 : x
|
---|
21 | // count up and wrap around
|
---|
22 |
|
---|
23 | void init_uart0( u16 bauddivider )
|
---|
24 | {
|
---|
25 | UBRR0H = bauddivider >> 8;
|
---|
26 | UBRR0L = bauddivider; // set baud rate
|
---|
27 | UCSR0A = 0; // no U2X, MPCM
|
---|
28 | UCSR0C = 1<<UCSZ01^1<<UCSZ00 // 8 Bit
|
---|
29 | #ifdef URSEL0
|
---|
30 | ^1<<URSEL0 // if UCSR0C shared with UBRR0H
|
---|
31 | #endif
|
---|
32 | ;
|
---|
33 | UCSR0B = 1<<RXEN0^1<<TXEN0^ // enable RX, TX
|
---|
34 | 1<<RXCIE0; // enable RX interrupt
|
---|
35 | rx_in = rx_out; // set buffer empty
|
---|
36 | tx_in = tx_out;
|
---|
37 | }
|
---|
38 |
|
---|
39 |
|
---|
40 | u8 ukbhit0( void )
|
---|
41 | {
|
---|
42 | return rx_out ^ vu8(rx_in); // rx_in modified by interrupt !
|
---|
43 | }
|
---|
44 |
|
---|
45 |
|
---|
46 | u8 ugetchar0( void )
|
---|
47 | {
|
---|
48 | u8 data;
|
---|
49 |
|
---|
50 | while( !ukbhit0() ); // until at least one byte in
|
---|
51 | data = rx_buff[rx_out]; // get byte
|
---|
52 | ROLLOVER( rx_out, RX0_SIZE );
|
---|
53 | URX0_IEN = 1; // enable RX interrupt
|
---|
54 | return data;
|
---|
55 | }
|
---|
56 |
|
---|
57 |
|
---|
58 | ISR( USART0_RX_vect )
|
---|
59 | {
|
---|
60 | u8 i = rx_in;
|
---|
61 |
|
---|
62 | ROLLOVER( i, RX0_SIZE );
|
---|
63 | if( i == rx_out ){ // buffer overflow
|
---|
64 | URX0_IEN = 0; // disable RX interrupt
|
---|
65 | return;
|
---|
66 | }
|
---|
67 | rx_buff[rx_in] = UDR0;
|
---|
68 | rx_in = i;
|
---|
69 | }
|
---|
70 |
|
---|
71 |
|
---|
72 | ISR( USART0_UDRE_vect )
|
---|
73 | {
|
---|
74 | if( tx_in == tx_out ){ // nothing to sent
|
---|
75 | UTX0_IEN = 0; // disable TX interrupt
|
---|
76 | return;
|
---|
77 | }
|
---|
78 | UDR0 = tx_buff[tx_out];
|
---|
79 | ROLLOVER( tx_out, TX0_SIZE );
|
---|
80 | }
|
---|
81 |
|
---|
82 |
|
---|
83 | u8 utx0_ready( void )
|
---|
84 | {
|
---|
85 | u8 i = tx_in;
|
---|
86 |
|
---|
87 | ROLLOVER( i, TX0_SIZE );
|
---|
88 | return vu8(tx_out) ^ i; // 0 = busy
|
---|
89 | }
|
---|
90 |
|
---|
91 |
|
---|
92 | void uputchar0( u8 c )
|
---|
93 | {
|
---|
94 | u8 i = tx_in;
|
---|
95 |
|
---|
96 | ROLLOVER( i, TX0_SIZE );
|
---|
97 | tx_buff[tx_in] = c;
|
---|
98 | while( i == vu8(tx_out)); // until at least one byte free
|
---|
99 | // tx_out modified by interrupt !
|
---|
100 | tx_in = i;
|
---|
101 | UTX0_IEN = 1; // enable TX interrupt
|
---|
102 | }
|
---|
103 |
|
---|
104 |
|
---|
105 | void uputs0_( u8 *s )
|
---|
106 | {
|
---|
107 | while( *s )
|
---|
108 | uputchar0( *s++ );
|
---|
109 | }
|
---|