aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2015-10-08 20:59:26 +0200
committerKarel Kočí <cynerd@email.cz>2015-10-08 20:59:26 +0200
commitacdd758e56e28f22846e7d34d87f5533c8682574 (patch)
treed8fda0b554e99d6ace98a9300ecb5835b5bf50e0
parent0b534d81ac39eb5bbf2b9a0691519f6f7f0eaa13 (diff)
downloadavr-ioe-acdd758e56e28f22846e7d34d87f5533c8682574.tar.gz
avr-ioe-acdd758e56e28f22846e7d34d87f5533c8682574.tar.bz2
avr-ioe-acdd758e56e28f22846e7d34d87f5533c8682574.zip
Add implementation of USART and more ground changes
-rw-r--r--.gitignore1
-rw-r--r--KNOWN-PROBLEMS.md4
-rw-r--r--README.md2
-rw-r--r--avr-ioe.mk47
-rw-r--r--buffers.h70
-rw-r--r--examples/usartecho/echo.c25
-rw-r--r--examples/usartecho/makefile29
-rwxr-xr-xexamples/usartecho/usart.elfbin0 -> 15401 bytes
-rw-r--r--examples/usartecho/usart.hex63
-rw-r--r--makefile14
-rw-r--r--mcu/ATmega328P.h3
-rw-r--r--mcu/ATmega32U4.h3
-rw-r--r--mcu/ATmega8A.h3
-rw-r--r--mcu/ATtiny4313.h5
-rw-r--r--mcu/ATtiny85.h1
-rw-r--r--src/usart.c177
-rw-r--r--src/usart_baundrate_helper.h12
-rw-r--r--usart.h93
18 files changed, 542 insertions, 10 deletions
diff --git a/.gitignore b/.gitignore
index 3731604..15be192 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
!/.gitignore
*.o
+*.d
trash
diff --git a/KNOWN-PROBLEMS.md b/KNOWN-PROBLEMS.md
new file mode 100644
index 0000000..1f6332d
--- /dev/null
+++ b/KNOWN-PROBLEMS.md
@@ -0,0 +1,4 @@
+* Third char is lost when USART is used with output buffer. Probably buffer
+ problem or some synchronization problem. This happens only after start. So
+ problem is probably connected with buffers initialization. But simulation not
+ revealed any problem.
diff --git a/README.md b/README.md
index 7f7afbd..17d3110 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
#AVR-IOE
##AVR input/output expansion
-This is package of code for SPI, TWI and USB CDC inputs and outputs from AVR
+This is package of code for SPI, TWI and USART interfaces from AVR
micro-controllers.
Code is targeted for five different chips, ATmega328p, ATmega32u4, ATmega8A,
ATtiny4313 and ATtiny85. But support for more chips can be added.
diff --git a/avr-ioe.mk b/avr-ioe.mk
new file mode 100644
index 0000000..1248f11
--- /dev/null
+++ b/avr-ioe.mk
@@ -0,0 +1,47 @@
+ifndef IOE_PREFIX
+ IOE_PREFIX = .
+endif
+
+IOE_SRC_SPI = $(IOE_PREFIX)/src/spi.c
+IOE_SRC_USART = $(IOE_PREFIX)/src/usart.c
+IOE_SRC = $(IOE_SRC_SPI) $(IOE_SRC_USART)
+
+IOE_OBJ_SPI = $(patsubst %.c,%.o,$(IOE_SRC_SPI))
+IOE_OBJ_USART = $(patsubst %.c,%.o,$(IOE_SRC_USART))
+IOE_OBJ = $(patsubst %.c,%.o,$(IOE_SRC))
+
+IOE_DEP_SPI = $(patsubst %.c,%.d,$(IOE_SRC_SPI))
+IOE_DEP_USART = $(patsubst %.c,%.d,$(IOE_SRC_USART))
+IOE_DEP = $(patsubst %.c,%.d,$(IOE_SRC))
+
+
+ifndef IOE_ONLYPATHS # Following section can be suppressed by defining this variable
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),help)
+-include $(IOE_DEP)
+endif
+endif
+
+ifndef F_CPU
+ $(error Please define F_CPU variable in makefile before including avr-ioe.mk)
+endif
+ifndef MMCU
+ $(error Pleade define MMCU variable in makefile before including avr-ioe.mk)
+endif
+IOE_CFLAGS ?= -Os -ffunction-sections -fdata-sections -fshort-enums -Wall
+IOE_CFLAGS += -DF_CPU=$(F_CPU) -mmcu=$(MMCU)
+IOE_GCC ?= avr-gcc
+
+$(IOE_OBJ): %.o: %.c
+ $(IOE_GCC) $(IOE_CFLAGS) -c -o $@ $<
+
+$(IOE_DEP): %.d: %.c
+ $(IOE_GCC) -MM -MG -MT '$*.o $@' $(IOE_CFLAGS) -c -o $@ $<
+
+.PHONY: ioeclean
+ioeclean:
+ $(RM) $(IOE_OBJ)
+ $(RM) $(IOE_DEP)
+
+endif
diff --git a/buffers.h b/buffers.h
new file mode 100644
index 0000000..19edd2d
--- /dev/null
+++ b/buffers.h
@@ -0,0 +1,70 @@
+/* This defines common buffer code for whole library.
+ * It is preprocessor generated code.
+ * Preprocessor variables chose different implementations. But final
+ * implementation is only few lines of code. This way it is included directly
+ * to code.
+ */
+#ifndef _IOE_BUFFERS_H_
+#define _IOE_BUFFERS_H_
+
+// Define new buffer
+#define IOEBUFFER(name, size) struct { \
+ uint8_t rindex, windex; \
+ uint8_t data[size]; \
+ } name;
+
+#define IOEBUFFER_INIT(name, size) { \
+ name.windex = size - 1; \
+ name.rindex = size - 1; \
+ }
+
+#define IOEBUFFER_MODE_BLOCK 0
+#define IOEBUFFER_MODE_OVERWRITE 1
+#define IOEBUFFER_MODE_DROP 2
+// Add data to buffer. If buffer is full then behavior is defined by selected mode.
+#define IOEBUFFER_PUT(name, size, data, mode) \
+ if (mode == IOEBUFFER_MODE_BLOCK) { \
+ if (name.windex == 0) { \
+ while (name.rindex == size - 1); \
+ } else { \
+ while (name.rindex == name.windex - 1); \
+ } \
+ } \
+ name.data[name.windex] = data; \
+ if (mode != IOEBUFFER_MODE_DROP || \
+ (name.windex == 0 && name.rindex == size - 1) || \
+ (name.rindex + 1 == name.windex)) { \
+ if (name.windex == 0) \
+ name.windex = size - 1; \
+ else \
+ name.windex--; \
+ } \
+ if (mode == IOEBUFFER_MODE_OVERWRITE && name.windex == name.rindex) { \
+ if (name.windex == size - 1) \
+ name.windex = 0; \
+ else \
+ name.windex++; \
+ } else;
+
+// Get data from buffer and store it to variable
+#define IOEBUFFER_GET(name, size, variable) \
+ if (name.rindex != name.windex) { \
+ variable = name.data[name.rindex]; \
+ if (name.rindex == 0) \
+ name.rindex = size - 1; \
+ else \
+ name.rindex--; \
+ } else { \
+ variable = 0; \
+ }
+
+// Set count of buffered data to variable
+#define IOEBUFFER_CNT(name, size, variable) \
+ if (name.windex < name.rindex) \
+ variable = name.rindex - name.windex; \
+ else if (name.windex > name.rindex) \
+ variable = size - name.windex + name.rindex; \
+ else \
+ variable = 0;
+
+#endif /* _IOE_BUFFERS_H_ */
diff --git a/examples/usartecho/echo.c b/examples/usartecho/echo.c
new file mode 100644
index 0000000..4d978f7
--- /dev/null
+++ b/examples/usartecho/echo.c
@@ -0,0 +1,25 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <string.h>
+#include "../../usart.h"
+
+void rec(uint8_t data) {
+ if (data)
+ usart_send(data);
+}
+
+int main() {
+ DDRB |= _BV(DDB1) | _BV(DDB2);
+ usart_init_uart();
+ SREG |= _BV(7);
+ usart_send('a');
+ usart_send('b');
+ usart_send('c');
+ usart_send('d');
+ usart_send_str("\n\rHello, there is UART echo!\n\r");
+ usart_receive = rec;
+
+ while (1);
+}
+
+
diff --git a/examples/usartecho/makefile b/examples/usartecho/makefile
new file mode 100644
index 0000000..343addc
--- /dev/null
+++ b/examples/usartecho/makefile
@@ -0,0 +1,29 @@
+MAKEFLAGS += --no-builtin-rules
+
+MMCU = atmega328p
+F_CPU = 16000000L
+IOE_PREFIX = ../..
+IOE_CFLAGS = -Os -ffunction-sections -fdata-sections -fshort-enums -Wall -g \
+ -DCONFIG_IOE_USART_OUTBUFFER_SIZE=64 \
+ -DCONFIG_IOE_USART_OUTBUFFER_MODE=0
+
+all: usart.hex
+ @echo Flash usart.hex to chip
+
+install: usart.hex
+ # TODO
+
+clean: ioeclean
+ $(RM) echo.o
+ $(RM) usart.elf usart.hex
+
+include ../../avr-ioe.mk
+
+usart.elf: %.elf: $(IOE_OBJ_USART) echo.o
+ avr-gcc -mmcu=$(MMCU) $^ -o $@
+
+usart.hex: %.hex: %.elf
+ avr-objcopy -O ihex -R .eeprom $< $@
+
+echo.o: %.o: %.c
+ avr-gcc $(IOE_CFLAGS) -c -o $@ $<
diff --git a/examples/usartecho/usart.elf b/examples/usartecho/usart.elf
new file mode 100755
index 0000000..211d0e9
--- /dev/null
+++ b/examples/usartecho/usart.elf
Binary files differ
diff --git a/examples/usartecho/usart.hex b/examples/usartecho/usart.hex
new file mode 100644
index 0000000..0eb90f0
--- /dev/null
+++ b/examples/usartecho/usart.hex
@@ -0,0 +1,63 @@
+:100000000C943B000C9458000C9458000C9458002D
+:100010000C9458000C9458000C9458000C94580000
+:100020000C9458000C9458000C9458000C945800F0
+:100030000C9458000C9458000C9458000C945800E0
+:100040000C9458000C9458000C9441010C946C01D1
+:100050000C9458000C9458000C9458000C945800C0
+:100060000C9458000C94580065006A006E007200F1
+:1000700076007F00830011241FBECFEFD8E0DEBFE3
+:10008000CDBF11E0A0E0B1E0ECEBF3E002C00590E1
+:100090000D92A032B107D9F711E0A0E2B1E001C0A2
+:1000A0001D92A736B107E1F70E94B7010C94DC015D
+:1000B0000C9400001092660190E08730910568F57D
+:1000C000FC01EC5CFF4F0C94D60181E08093C500ED
+:1000D00080EA0FC01092C5008FEC0BC01092C500D3
+:1000E00087E607C01092C50083E303C01092C500E5
+:1000F00089E18093C4008091C0008D7F0CC0109274
+:10010000C50082E203C01092C50080E18093C40064
+:100110008091C00082608093C000613059F030F05F
+:10012000623091F48091C20080630CC08091C20063
+:100130008F7C08C08091C2008F7E8093C200809126
+:10014000C20080628093C200413031F0423049F4F5
+:100150008091C200886003C08091C200877F809335
+:10016000C200263079F030F42530F9F48091C200D5
+:10017000897F19C0273079F02830B9F48091C20006
+:10018000866011C08091C2008B7F8093C2008091F5
+:10019000C200826008C08091C2008D7F8093C2003F
+:1001A0008091C20084608093C20088EB8093C1007C
+:1001B0008FE38093250180932401089528E041E096
+:1001C00060E086E00C945A0090916601911106C09F
+:1001D00091E0909366018093C60008959091250167
+:1001E000911105C0909124019F33E1F30BC0409120
+:1001F00024012091250150E030E0215031094217BF
+:100200005307A9F3E0912501F0E0EC5DFE4F8283F6
+:1002100080912501811102C08FE303C080912501E7
+:100220008150809325010895CF93DF93EC0189914C
+:10023000882319F00E94E400FACFDF91CF9108954E
+:100240008091C0008C71089580916601089590910D
+:10025000250180912401981728F480912401909120
+:1002600025010BC09091250180912401891738F454
+:100270008091240190912501805C891B089580E084
+:1002800008951F920F920FB60F9211242F933F9350
+:100290004F935F936F937F938F939F93AF93BF938E
+:1002A000EF93FF93E0912201F0912301309719F031
+:1002B0008091C6000995FF91EF91BF91AF919F91F9
+:1002C0008F917F916F915F914F913F912F910F90FF
+:1002D0000FBE0F901F9018951F920F920FB60F929E
+:1002E00011242F933F934F935F936F937F938F933B
+:1002F0009F93AF93BF93EF93FF93909124018091CD
+:1003000025019817B1F0E0912401F0E0EC5DFE4F7B
+:10031000928180912401811102C08FE303C08091FA
+:100320002401815080932401992319F09093C600F1
+:1003300002C010926601E0912001F09121013097F6
+:1003400009F00995FF91EF91BF91AF919F918F9126
+:100350007F916F915F914F913F912F910F900FBEC1
+:100360000F901F90189581110C94E400089584B1AA
+:10037000866084B90E94DE008FB780688FBF81E6F7
+:100380000E94E40082E60E94E40083E60E94E4000A
+:1003900084E60E94E40080E091E00E94140183EB77
+:1003A00091E09093230180932201FFCFEE0FFF1F76
+:0C03B0000590F491E02D0994F894FFCF23
+:1003BC000A0D48656C6C6F2C207468657265206939
+:1003CC00732055415254206563686F210A0D00005B
+:00000001FF
diff --git a/makefile b/makefile
index 81f1910..14aa590 100644
--- a/makefile
+++ b/makefile
@@ -1,16 +1,16 @@
.PHONY: all help clean
-include files.mk
+IOE_ONLYPATHS = y
+include avr-ioe.mk
all:
- $(error This is not library, please include "files.mk" to your project makefile. For more informations refer to README.md)
+ $(error This is not library, please include "avr-ioe.mk" to your project makefile. For more informations refer to README.md)
help:
@echo This makefile only implements these targets:
- @echo help - prints this text
- @echo clean - removing all object files generated from source files
+ @echo help - prints this text
+ @echo clean - removing all object files generated from source files
clean:
- $(RM) $(IOE_SPI_OBJ)
- $(RM) $(IOE_SPI_USI_OBJ)
- $(RM) $(IOE_SPI_USART_OBJ)
+ $(RM) $(IOE_OBJ)
+ $(RM) $(IOE_DEP)
diff --git a/mcu/ATmega328P.h b/mcu/ATmega328P.h
index dc42233..b5527bf 100644
--- a/mcu/ATmega328P.h
+++ b/mcu/ATmega328P.h
@@ -5,6 +5,7 @@
#include <avr/io.h>
// SPI
+#define MCUSUPPORT_SPI
#define DDR_SPI DDRB
#define DD_SS DDB2
#define DD_MOSI DDB3
@@ -15,3 +16,5 @@
#define PORT_MOSI PORTB3
#define PORT_MISO PORTB4
#define PORT_SCLK PORTB5
+// USART
+#define MCUSUPPORT_USART
diff --git a/mcu/ATmega32U4.h b/mcu/ATmega32U4.h
index acf3a24..16351e8 100644
--- a/mcu/ATmega32U4.h
+++ b/mcu/ATmega32U4.h
@@ -4,6 +4,7 @@
#include <avr/io.h>
// SPI
+#define MCUSUPPORT_SPI
#define DDR_SPI DDRB
#define DD_SS DDB0
#define DD_SCLK DDB1
@@ -14,3 +15,5 @@
#define PORT_SCLK PORTB1
#define PORT_MOSI PORTB2
#define PORT_MISO PORTB3
+// USART
+#define MCUSUPPORT_USART0
diff --git a/mcu/ATmega8A.h b/mcu/ATmega8A.h
index 1ded665..a2d3adf 100644
--- a/mcu/ATmega8A.h
+++ b/mcu/ATmega8A.h
@@ -3,6 +3,7 @@
#include <avr/io.h>
// SPI
+#define MCUSUPPORT_SPI
#define DDR_SPI DDRB
#define DD_SS DDB2
#define DD_SCLK DDB5
@@ -13,3 +14,5 @@
#define PORT_SCLK PORTB5
#define PORT_MOSI PORTB3
#define PORT_MISO PORTB4
+// USART
+#define MCUSUPPORT_USART0
diff --git a/mcu/ATtiny4313.h b/mcu/ATtiny4313.h
index 748f6ff..efbc01d 100644
--- a/mcu/ATtiny4313.h
+++ b/mcu/ATtiny4313.h
@@ -4,6 +4,7 @@
#include <avr/io.h>
// SPI USI
+#define MCUSUPPORT_USI
#define DDR_USI DDRB
#define DD_DI DDB5
#define DD_DO DDB6
@@ -12,5 +13,5 @@
#define PORT_DI PORTB5
#define PORT_DO PORTB6
#define PORT_USCK PORTB7
-
-// SPI USART
+// USART
+#define MCUSUPPORT_USART0
diff --git a/mcu/ATtiny85.h b/mcu/ATtiny85.h
index 57f53e7..19db90d 100644
--- a/mcu/ATtiny85.h
+++ b/mcu/ATtiny85.h
@@ -4,6 +4,7 @@
#include <avr/io.h>
// SPI USI
+#define MCUSUPPORT_USI
#define DDR_USI DDRB
#define DD_DI DDB0
#define DD_DO DDB1
diff --git a/src/usart.c b/src/usart.c
new file mode 100644
index 0000000..9187bc6
--- /dev/null
+++ b/src/usart.c
@@ -0,0 +1,177 @@
+#include "../usart.h"
+
+#ifdef MCUSUPPORT_USART
+
+volatile int8_t _usart_busy;
+
+inline void usart_init_uart(void) {
+ usart_init_async(USART_BAUDRATE_115200, USART_PARITY_NONE,
+ USART_STOPBIT_SINGLE, USART_DATABITS_8);
+}
+
+void usart_init_async(enum usartBaudrate baudrate,
+ enum usartParity parity, enum usartStopBit stopbit,
+ enum usartDataBits databits) {
+ _usart_busy = 0;
+ switch (baudrate) {
+ case USART_BAUDRATE_2400:
+#define BAUD 2400
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_4800:
+#define BAUD 4800
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_9600:
+#define BAUD 9600
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_19200:
+#define BAUD 19200
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_38400:
+#define BAUD 38400
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_57600:
+#define BAUD 57600
+#include "usart_baundrate_helper.h"
+ break;
+ case USART_BAUDRATE_115200:
+#define BAUD 115200
+#include "usart_baundrate_helper.h"
+ break;
+ }
+ switch (parity) {
+ case USART_PARITY_NONE:
+ UCSR0C &= ~(_BV(UPM00) | _BV(UPM01));
+ break;
+ case USART_PARITY_ODD:
+ UCSR0C &= ~_BV(UPM00);
+ UCSR0C |= _BV(UPM01);
+ break;
+ case USART_PARITY_EVEN:
+ UCSR0C |= _BV(UPM00) | _BV(UPM01);
+ break;
+ }
+ switch (stopbit) {
+ case USART_STOPBIT_SINGLE:
+ UCSR0C &= ~_BV(USBS0);
+ break;
+ case USART_STOPBIT_DOUBLE:
+ UCSR0C |= _BV(USBS0);
+ break;
+ }
+ switch (databits) {
+ case USART_DATABITS_5:
+ UCSR0C &= ~(_BV(UCSZ00) | _BV(UCSZ01));
+ break;
+ case USART_DATABITS_6:
+ UCSR0C &= ~_BV(UCSZ01);
+ UCSR0C |= _BV(UCSZ00);
+ break;
+ case USART_DATABITS_7:
+ UCSR0C &= ~_BV(UCSZ00);
+ UCSR0C |= _BV(UCSZ01);
+ break;
+ case USART_DATABITS_8:
+ UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01);
+ break;
+ }
+ // Enable receiver, transmitter and RX complete,
+ // Data register empty interrupts
+ UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UDRIE0);
+#ifdef _IOE_USART_INBUFFER
+ IOEBUFFER_INIT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE);
+#endif
+#ifdef _IOE_USART_OUTBUFFER
+ IOEBUFFER_INIT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE);
+#endif
+}
+
+inline void usart_send(uint8_t data) {
+#ifdef _IOE_USART_OUTBUFFER
+ if (!_usart_busy) {
+ _usart_busy = 1;
+ UDR0 = data;
+ } else {
+ IOEBUFFER_PUT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE,
+ data, CONFIG_IOE_USART_OUTBUFFER_MODE);
+ }
+#else
+ _usart_busy = 1;
+ UDR0 = data;
+#endif /* _IOE_USART_OUTBUFFER */
+}
+
+#ifdef _IOE_USART_OUTBUFFER
+void usart_send_str(char *str) {
+ while(*str != '\0') {
+ usart_send((uint8_t) *str);
+ str++;
+ }
+}
+#endif /* _IOE_USART_OUTBUFFER */
+
+#ifdef _IOE_USART_INBUFFER
+uint8_t usart_get(void) {
+ uint8_t rtn = 0;
+ IOEBUFFER_GET(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, rtn);
+ return rtn;
+}
+#endif
+
+inline uint8_t usart_queryerror(void) {
+ return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0));
+}
+
+inline int8_t usart_busy(void) {
+ return _usart_busy;
+}
+
+#ifdef _IOE_USART_INBUFFER
+uint8_t usart_inbuffered(void) {
+ uint8_t rtn;
+ IOEBUFFER_CNT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE, rtn);
+ return rtn;
+}
+#endif
+
+#ifdef _IOE_USART_OUTBUFFER
+uint8_t usart_outbuffered(void) {
+ uint8_t rtn;
+ IOEBUFFER_CNT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, rtn);
+ return rtn;
+}
+#endif
+
+////// Interrupts ////////////////////////////////
+void (*usart_receive) (uint8_t data) = 0;
+void (*usart_sent) (void) = 0;
+
+SIGNAL(USART_RX_vect) {
+#ifdef _IOE_USART_INBUFFER
+ IOEBUFFER_PUT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE,
+ UDR0, CONFIG_IOE_USART_INBUFFER_MODE);
+#endif /* _IOE_USART_INBUFFER */
+ if (usart_receive)
+ usart_receive(UDR0);
+}
+
+SIGNAL(USART_UDRE_vect) {
+#ifdef _IOE_USART_OUTBUFFER
+ uint8_t val;
+ IOEBUFFER_GET(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE, val);
+ if (val)
+ UDR0 = val;
+ else
+ _usart_busy = 0;
+#else
+ _usart_busy = 0;
+#endif /* _IOE_USART_OUTBUFFER */
+ if (usart_sent)
+ usart_sent();
+}
+
+#endif
diff --git a/src/usart_baundrate_helper.h b/src/usart_baundrate_helper.h
new file mode 100644
index 0000000..0271bdd
--- /dev/null
+++ b/src/usart_baundrate_helper.h
@@ -0,0 +1,12 @@
+#include <util/setbaud.h>
+UBRR0H = UBRRH_VALUE;
+UBRR0L = UBRRL_VALUE;
+#if USE_2X
+UCSR0A |= _BV(U2X0);
+#else
+UCSR0A &= ~_BV(U2X0);
+#endif
+#undef BAUD
+#undef UBRRH_VALUE
+#undef UBRRL_VALUE
+#undef USE_2X
diff --git a/usart.h b/usart.h
new file mode 100644
index 0000000..3a06baf
--- /dev/null
+++ b/usart.h
@@ -0,0 +1,93 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+
+#include "mcu/mcu_def.h"
+#include "buffers.h"
+
+#ifndef _IOE_USART_H_
+#define _IOE_USART_H_
+
+#ifndef MCUSUPPORT_USART
+#error "No USART interface is known on your mcu."
+#endif
+
+enum usartBaudrate {
+ USART_BAUDRATE_2400,
+ USART_BAUDRATE_4800,
+ USART_BAUDRATE_9600,
+ USART_BAUDRATE_19200,
+ USART_BAUDRATE_38400,
+ USART_BAUDRATE_57600,
+ USART_BAUDRATE_115200
+};
+
+enum usartParity {
+ USART_PARITY_NONE,
+ USART_PARITY_ODD,
+ USART_PARITY_EVEN
+};
+
+enum usartStopBit {
+ USART_STOPBIT_SINGLE = 1,
+ USART_STOPBIT_DOUBLE = 2
+};
+
+enum usartDataBits {
+ USART_DATABITS_5 = 5,
+ USART_DATABITS_6 = 6,
+ USART_DATABITS_7 = 7,
+ USART_DATABITS_8 = 8,
+ // USART_DATABITS_9 = 9 // Not supported yet
+};
+
+// Not supported yet. This is for synchronous mode only
+//enum usartClockPolarity {
+ //USART_CLOCKPOLARITY_FALLING,
+ //USART_CLOCKPOLARITY_RISING
+//};
+
+#define USART_FRAMEERROR _BV(FE0)
+#define USART_DATAOVERRUN _BV(DOR0)
+#define USART_PARITYERROR _BV(UPE0)
+
+#if CONFIG_IOE_USART_INBUFFER_SIZE > 0
+#define _IOE_USART_INBUFFER
+volatile IOEBUFFER(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE);
+#endif
+#if CONFIG_IOE_USART_OUTBUFFER_SIZE > 0
+#define _IOE_USART_OUTBUFFER
+volatile IOEBUFFER(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE);
+#endif
+
+
+/*
+ * Initialize USART device with 115200 baud rate, no parity, single stop bit,
+ * and 8 data bits.
+ * This function serves as fast default initialization.
+ */
+void usart_init_uart(void);
+void usart_init_async(enum usartBaudrate,
+ enum usartParity, enum usartStopBit,
+ enum usartDataBits);
+void usart_send(uint8_t data);
+#ifdef _IOE_USART_OUTBUFFER
+void usart_send_str(char *str);
+#endif
+#ifdef _IOE_USART_INBUFFER
+uint8_t usart_get(void);
+#endif
+uint8_t usart_queryerror(void);
+int8_t usart_busy(void);
+#ifdef _IOE_USART_INBUFFER
+uint8_t usart_inbuffered(void);
+#endif
+#ifdef _IOE_USART_OUTBUFFER
+uint8_t usart_outbuffered(void);
+#endif
+
+// Following function must be user defined if relevant buffers not used.
+extern void (*usart_receive)(uint8_t data);
+extern void (*usart_sent)(void);
+
+#endif /* _IOE_USART_H_ */