#include #include #include "usart.h" #include "conf.h" #include "ringbuffer.h" #include volatile ringbuffer_t usart_tx_buffer; void usart_init(void) { usart_tx_buffer = ringbuffer_new(USART_BUFFER_SIZE); UBRR0H = (unsigned char)(UBRR_VALUE >> 8); UBRR0L = (unsigned char)UBRR_VALUE; #ifdef USART_U2X_EN UCSR0A |= _BV(U2X0); #endif UCSR0B = _BV(TXEN0) | _BV(TXCIE0); UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); sei(); } int usart_putc(char c) { // Basically this is really ugly, // but there is no other way to do it. // We let the main thread wait until the // sender thread has cleared one byte. while(ringbuffer_put_char(usart_tx_buffer, c)); // If the data register is already emtpy there is no // need to wait for the interrupt. // Also it is likely that the interrupt will never happen. // (For instance because this is the first byte sent) if(UCSR0A & _BV(UDRE0)) { UDR0 = ringbuffer_get_char(usart_tx_buffer); } return 0; } ISR(USART_TX_vect) { if(ringbuffer_nonempty(usart_tx_buffer)) { UDR0 = ringbuffer_get_char(usart_tx_buffer); } }