// #include <avr/interrupt.h>
// #include <avr/io.h>
#define BUFFER_SIZE 64
volatile char txBuffer[BUFFER_SIZE]; // Transmission buffer
volatile uint8_t txHead = 0; // Head index for the buffer
volatile uint8_t txTail = 0; // Tail index for the buffer
volatile bool transmitting = false; // Transmission state
// Function to initialize UART
void uartInit(uint32_t baudRate) {
uint16_t ubrr = (F_CPU / 16 / baudRate) - 1;
UBRR0H = (ubrr >> 8);
UBRR0L = ubrr;
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 data bits, no parity, 1 stop bit
}
// Function to add data to the transmission buffer
void uartWrite(char c) {
uint8_t nextHead = (txHead + 1) % BUFFER_SIZE;
while (nextHead == txTail) {
// Wait if the buffer is full
}
txBuffer[txHead] = c; // Store the character
txHead = nextHead; // Update the head index
// Enable UDRE interrupt if not already transmitting
cli(); // Disable interrupts temporarily
if (!transmitting) {
transmitting = true;
UCSR0B |= (1 << UDRIE0); // Enable the UDRE interrupt
}
sei(); // Re-enable interrupts
}
// ISR for Data Register Empty interrupt
ISR(USART_UDRE_vect) {
if (txTail != txHead) { // If there is data to send
UDR0 = txBuffer[txTail]; // Load the next character into the UDR register
txTail = (txTail + 1) % BUFFER_SIZE; // Update the tail index
} else {
// Buffer is empty, disable the UDRE interrupt
UCSR0B &= ~(1 << UDRIE0);
transmitting = false;
}
}
// Main function
void setup() {
uartInit(9600); // Initialize UART with a baud rate of 9600
sei(); // Enable global interrupts
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// Example: send "Hello, World!" repeatedly
const char* message = "Hello, World!\n";
for (const char* p = message; *p; ++p) {
uartWrite(*p);
}
digitalWrite(LED_BUILTIN, HIGH);
delay(500); // Wait before sending again
digitalWrite(LED_BUILTIN, LOW);
delay(500); // Wait before sending again
}