162 lines
2.6 KiB
C
162 lines
2.6 KiB
C
/*
|
|
* Stairs lighting
|
|
* Copyright 2017 (c) Mark van Renswoude
|
|
*
|
|
* https://git.x2software.net/pub/Stairs
|
|
*
|
|
* Source:
|
|
* https://github.com/akafugu/helloworld/blob/master/attiny2313/uart.c
|
|
*/
|
|
#include "TinyUART.h"
|
|
#include <avr/interrupt.h>
|
|
#include <avr/io.h>
|
|
#include <avr/pgmspace.h>
|
|
|
|
|
|
volatile static uint8_t rx_buffer[BUFFER_SIZE] = "xxxxxxxxxxxxxxxx";
|
|
volatile static uint8_t tx_buffer[BUFFER_SIZE] = "xxxxxxxxxxxxxxxx";
|
|
volatile static uint8_t rx_head = 0;
|
|
volatile static uint8_t rx_tail = 0;
|
|
volatile static uint8_t tx_head = 0;
|
|
volatile static uint8_t tx_tail = 0;
|
|
|
|
|
|
void uart_init(void)
|
|
{
|
|
// set baud rate
|
|
UBRRH = (uint8_t)(MYUBBR >> 8);
|
|
UBRRL = (uint8_t)(MYUBBR);
|
|
// enable receive and transmit
|
|
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
|
|
// set frame format
|
|
UCSRC = (1 << USBS) | (3 << UCSZ0); // asynchron 8n1
|
|
}
|
|
|
|
|
|
|
|
void uart_send(uint8_t c)
|
|
{
|
|
// wait for empty data register
|
|
while (!(UCSRA & (1<<UDRE)));
|
|
// set data into data register
|
|
UDR = c;
|
|
}
|
|
|
|
|
|
uint8_t uart_available(void)
|
|
{
|
|
return rx_head - rx_tail;
|
|
}
|
|
|
|
|
|
uint8_t uart_receive(void)
|
|
{
|
|
while (!(UCSRA & (1<<RXC)))
|
|
;
|
|
return UDR;
|
|
}
|
|
|
|
|
|
|
|
uint16_t uart_getc(void)
|
|
{
|
|
uint8_t c = 0;
|
|
uint8_t tmp_tail = 0;
|
|
if (rx_head == rx_tail)
|
|
return UART_NO_DATA;
|
|
|
|
tmp_tail = (rx_tail + 1) % BUFFER_SIZE;
|
|
c = rx_buffer[rx_tail];
|
|
rx_tail = tmp_tail;
|
|
return c;
|
|
}
|
|
|
|
|
|
|
|
uint8_t uart_getc_wait(void)
|
|
{
|
|
uint16_t c;
|
|
while ((c = uart_getc()) == UART_NO_DATA) {}
|
|
return c;
|
|
}
|
|
|
|
|
|
|
|
void uart_putc(uint8_t c)
|
|
{
|
|
uint8_t tmp_head = (tx_head + 1) % BUFFER_SIZE;
|
|
// wait for space in buffer
|
|
while (tmp_head == tx_tail)
|
|
;
|
|
|
|
tx_buffer[tx_head] = c;
|
|
tx_head = tmp_head;
|
|
// enable uart data interrupt (send data)
|
|
UCSRB |= (1<<UDRIE);
|
|
}
|
|
|
|
|
|
void uart_puts(const char *s)
|
|
{
|
|
while (*s)
|
|
{
|
|
uart_putc(*s);
|
|
s++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void uart_puts_P(const char *s)
|
|
{
|
|
while (pgm_read_byte(s) != 0x00)
|
|
{
|
|
uart_putc(pgm_read_byte(s++));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* ISR User Data Regiser Empty
|
|
* Send a char out of buffer via UART. If sending is complete, the
|
|
* interrupt gets disabled.
|
|
*/
|
|
ISR(USART_UDRE_vect)
|
|
{
|
|
uint8_t tmp_tail = 0;
|
|
if (tx_head != tx_tail)
|
|
{
|
|
tmp_tail = (tx_tail + 1) % BUFFER_SIZE;
|
|
UDR = tx_buffer[tx_tail];
|
|
tx_tail = tmp_tail;
|
|
}
|
|
else
|
|
{
|
|
// disable this interrupt if nothing more to send
|
|
UCSRB &= ~(1 << UDRIE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* ISR RX complete
|
|
* Receives a char from UART and stores it in ring buffer.
|
|
*/
|
|
ISR(USART_RX_vect)
|
|
{
|
|
uint8_t tmp_head = 0;
|
|
tmp_head = (rx_head + 1) % BUFFER_SIZE;
|
|
if (tmp_head == rx_tail)
|
|
{
|
|
// buffer overflow error!
|
|
}
|
|
else
|
|
{
|
|
rx_buffer[rx_head] = UDR;
|
|
rx_head = tmp_head;
|
|
}
|
|
}
|
|
|