| 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 | }
|
|---|