diff options
Diffstat (limited to 'src/usart.c')
-rw-r--r-- | src/usart.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/usart.c b/src/usart.c new file mode 100644 index 0000000..9187bc6 --- /dev/null +++ b/src/usart.c @@ -0,0 +1,177 @@ +#include "../usart.h" + +#ifdef MCUSUPPORT_USART + +volatile int8_t _usart_busy; + +inline void usart_init_uart(void) { + usart_init_async(USART_BAUDRATE_115200, USART_PARITY_NONE, + USART_STOPBIT_SINGLE, USART_DATABITS_8); +} + +void usart_init_async(enum usartBaudrate baudrate, + enum usartParity parity, enum usartStopBit stopbit, + enum usartDataBits databits) { + _usart_busy = 0; + switch (baudrate) { + case USART_BAUDRATE_2400: +#define BAUD 2400 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_4800: +#define BAUD 4800 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_9600: +#define BAUD 9600 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_19200: +#define BAUD 19200 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_38400: +#define BAUD 38400 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_57600: +#define BAUD 57600 +#include "usart_baundrate_helper.h" + break; + case USART_BAUDRATE_115200: +#define BAUD 115200 +#include "usart_baundrate_helper.h" + break; + } + switch (parity) { + case USART_PARITY_NONE: + UCSR0C &= ~(_BV(UPM00) | _BV(UPM01)); + break; + case USART_PARITY_ODD: + UCSR0C &= ~_BV(UPM00); + UCSR0C |= _BV(UPM01); + break; + case USART_PARITY_EVEN: + UCSR0C |= _BV(UPM00) | _BV(UPM01); + break; + } + switch (stopbit) { + case USART_STOPBIT_SINGLE: + UCSR0C &= ~_BV(USBS0); + break; + case USART_STOPBIT_DOUBLE: + UCSR0C |= _BV(USBS0); + break; + } + switch (databits) { + case USART_DATABITS_5: + UCSR0C &= ~(_BV(UCSZ00) | _BV(UCSZ01)); + break; + case USART_DATABITS_6: + UCSR0C &= ~_BV(UCSZ01); + UCSR0C |= _BV(UCSZ00); + break; + case USART_DATABITS_7: + UCSR0C &= ~_BV(UCSZ00); + UCSR0C |= _BV(UCSZ01); + break; + case USART_DATABITS_8: + UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01); + break; + } + // Enable receiver, transmitter and RX complete, + // Data register empty interrupts + UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UDRIE0); +#ifdef _IOE_USART_INBUFFER + IOEBUFFER_INIT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE); +#endif +#ifdef _IOE_USART_OUTBUFFER + IOEBUFFER_INIT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE); +#endif +} + +inline void usart_send(uint8_t data) { +#ifdef _IOE_USART_OUTBUFFER + if (!_usart_busy) { + _usart_busy = 1; + UDR0 = data; + } else { + IOEBUFFER_PUT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, + data, CONFIG_IOE_USART_OUTBUFFER_MODE); + } +#else + _usart_busy = 1; + UDR0 = data; +#endif /* _IOE_USART_OUTBUFFER */ +} + +#ifdef _IOE_USART_OUTBUFFER +void usart_send_str(char *str) { + while(*str != '\0') { + usart_send((uint8_t) *str); + str++; + } +} +#endif /* _IOE_USART_OUTBUFFER */ + +#ifdef _IOE_USART_INBUFFER +uint8_t usart_get(void) { + uint8_t rtn = 0; + IOEBUFFER_GET(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, rtn); + return rtn; +} +#endif + +inline uint8_t usart_queryerror(void) { + return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0)); +} + +inline int8_t usart_busy(void) { + return _usart_busy; +} + +#ifdef _IOE_USART_INBUFFER +uint8_t usart_inbuffered(void) { + uint8_t rtn; + IOEBUFFER_CNT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, rtn); + return rtn; +} +#endif + +#ifdef _IOE_USART_OUTBUFFER +uint8_t usart_outbuffered(void) { + uint8_t rtn; + IOEBUFFER_CNT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, rtn); + return rtn; +} +#endif + +////// Interrupts //////////////////////////////// +void (*usart_receive) (uint8_t data) = 0; +void (*usart_sent) (void) = 0; + +SIGNAL(USART_RX_vect) { +#ifdef _IOE_USART_INBUFFER + IOEBUFFER_PUT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, + UDR0, CONFIG_IOE_USART_INBUFFER_MODE); +#endif /* _IOE_USART_INBUFFER */ + if (usart_receive) + usart_receive(UDR0); +} + +SIGNAL(USART_UDRE_vect) { +#ifdef _IOE_USART_OUTBUFFER + uint8_t val; + IOEBUFFER_GET(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, val); + if (val) + UDR0 = val; + else + _usart_busy = 0; +#else + _usart_busy = 0; +#endif /* _IOE_USART_OUTBUFFER */ + if (usart_sent) + usart_sent(); +} + +#endif |