// #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
}