avrinput/usart.c

53 lines
1.1 KiB
C
Raw Normal View History

2019-01-01 15:48:54 +00:00
#include <avr/io.h>
#include <stdlib.h>
#include "usart.h"
#include "conf.h"
#include "ringbuffer.h"
2019-01-17 18:39:05 +00:00
#include <avr/interrupt.h>
2019-01-01 15:48:54 +00:00
2019-04-07 18:35:05 +00:00
volatile ringbuffer_t usart_tx_buffer;
2019-01-01 15:48:54 +00:00
void
usart_init(void)
{
2019-04-07 18:35:05 +00:00
usart_tx_buffer = ringbuffer_new(USART_BUFFER_SIZE);
2019-01-17 18:39:05 +00:00
UBRR0H = (unsigned char)(UBRR_VALUE >> 8);
UBRR0L = (unsigned char)UBRR_VALUE;
2019-04-07 18:35:05 +00:00
#ifdef USART_U2X_EN
UCSR0A |= _BV(U2X0);
#endif
2019-01-17 18:39:05 +00:00
UCSR0B = _BV(TXEN0) | _BV(TXCIE0);
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
sei();
2019-01-01 15:48:54 +00:00
}
int
usart_putc(char c)
{
2019-04-07 18:35:05 +00:00
// 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
2019-01-17 18:39:05 +00:00
// 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))
{
2019-04-07 18:35:05 +00:00
UDR0 = ringbuffer_get_char(usart_tx_buffer);
2019-01-17 18:39:05 +00:00
}
2019-04-07 18:35:05 +00:00
return 0;
2019-01-01 15:48:54 +00:00
}
ISR(USART_TX_vect)
{
2019-04-07 18:35:05 +00:00
if(ringbuffer_nonempty(usart_tx_buffer))
2019-01-01 15:48:54 +00:00
{
2019-04-07 18:35:05 +00:00
UDR0 = ringbuffer_get_char(usart_tx_buffer);
2019-01-01 15:48:54 +00:00
}
}