#include<avr/io.h>
#include<avr/interrupt.h>
#define FOSC 16000000
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD-1)
#define UART_BUFFER_SIZE (16)
#include "ring_buffer.h"
uint8_t buffer_array[UART_BUFFER_SIZE];
struct ring_buffer tx_buffer = {.buffer=&buffer_array[0],.size=UART_BUFFER_SIZE,.head=0U,.tail=0U,.full=false};
void mcu_init(){
sei();//enable interrupts
}
void uart_clear_interrupt(){
UCSR1A|=((1<<TXC1));
}
void uart_enable_tx_interrupt(){
UCSR1B|=(1<<TXCIE1);
}
void uart_disable_tx_interrupt(){
UCSR1B &=(~(1<<TXCIE1));
}
void uart_tx_start(){
if(!ring_buffer_empty(&tx_buffer)){
UDR1 = ring_buffer_peek(&tx_buffer);
}
}
ISR(USART1_TX_vect){
if(ring_buffer_empty(&tx_buffer)){
return;
}
char c = ring_buffer_get(&tx_buffer);
Serial.print(c);
//Serial.print(tx_buffer.tail);
uart_clear_interrupt();
if(!ring_buffer_empty(&tx_buffer)){
uart_tx_start();
}
}
void uart_putchar_interrupt(char c){
while(ring_buffer_full(&tx_buffer)){
//delay(1);
//delayMicroseconds(100);
}
uart_disable_tx_interrupt();
bool tx_goingon = !ring_buffer_empty(&tx_buffer);
ring_buffer_put(&tx_buffer,c);
if(!tx_goingon){
uart_tx_start();
}
uart_enable_tx_interrupt();
}
void USART_Init(unsigned int ubrr){
/* Set baud rate */
UBRR1L = (unsigned char)(ubrr>>8);
UBRR1H = (unsigned char)ubrr;
/* Enable receiver and transmitter and tx interrupt */
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
/* Set frame format: 8data, 2stop bit */
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
// uart_clear_interrupt();
uart_enable_tx_interrupt();
}
void setup() {
// put your setup code here, to run once:
mcu_init();
USART_Init (MYUBRR);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
uart_putchar_interrupt('a');
uart_putchar_interrupt('r');
uart_putchar_interrupt('t');
uart_putchar_interrupt('f');
uart_putchar_interrupt('u');
uart_putchar_interrupt('l');
uart_putchar_interrupt('\n');
}