AVR serial library

Simple AVR serial library with circular buffer for ATmega88/168/328.

serial.h

#ifndef SERIAL_H
#define SERIAL_H

#include <stdio.h>

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE ((F_CPU / 16 + USART_BAUDRATE / 2) / USART_BAUDRATE - 1)

const int serialBufferSize = 64;

void serialInit();

int serialWriteChar(char ch);
int serialWriteChar(char ch, FILE *stream);
bool serialBufferEmpty();
char serialRead();
uint8_t serialAvailable();
char serialPeek();

#endif

serial.cpp

#include <avr/interrupt.h>
#include <util/delay.h>

#include "serial.h"

volatile char serialBuffer[serialBufferSize];
volatile uint8_t serialBufferStart = 0;
volatile uint8_t serialBufferEnd = 0;
static FILE uartstdout = {0};

void serialInit() {
	UBRR0H = (unsigned char)(BAUD_PRESCALE >> 8);
	UBRR0L = (unsigned char)(BAUD_PRESCALE);
	// Enable receive and transmit
	UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
	UCSR0C = (3 << UCSZ00);

	// Set serialWriteChar as stdout
	fdev_setup_stream(&uartstdout, serialWriteChar, NULL, _FDEV_SETUP_WRITE);
	stdout = &uartstdout;
}

int serialWriteChar(char ch) {
	while (!(UCSR0A & (1 << UDRE0)));
	UDR0 = ch;
	return 0;
}

int serialWriteChar(char ch, FILE *stream) {
	return serialWriteChar(ch);
}

ISR(USART_RX_vect) {
	serialBuffer[serialBufferEnd] = UDR0;
	serialBufferEnd = (serialBufferEnd + 1) % serialBufferSize;
	if (serialBufferEnd == serialBufferStart) { // wrapped around, replacing earlier start value.
		serialBufferStart = (serialBufferStart + 1) % serialBufferSize;
	}
}

bool serialBufferEmpty() {
	return serialBufferStart == serialBufferEnd;
}

char serialRead() {
	while (serialBufferEmpty()) {
		_delay_ms(50);
	}
	char ch = serialBuffer[serialBufferStart];
	serialBufferStart = (serialBufferStart + 1) % serialBufferSize;
	return ch;
}

uint8_t serialAvailable() {
	return (serialBufferEnd - serialBufferStart) % serialBufferSize;
}

char serialPeek() {
	if (serialAvailable()) {
		return serialBuffer[serialBufferStart];
	}
	return '\0';
}