From: Erik Andresen <erik@vontaene.de>
Date: Wed, 6 May 2015 10:10:35 +0000 (+0200)
Subject: added initial avr/nano program
X-Git-Url: https://defiant.homedns.org/gitweb/?a=commitdiff_plain;h=4053424236542640b1cb23624877725d5ae8e50f;p=ros_wild_thumper.git

added initial avr/nano program
---

diff --git a/avr/.gitignore b/avr/.gitignore
new file mode 100644
index 0000000..9cb13a5
--- /dev/null
+++ b/avr/.gitignore
@@ -0,0 +1,8 @@
+.dep
+*.eep
+*.elf
+*.lss
+*.lst
+*.map
+*.o
+*.sym
diff --git a/avr/nano/Makefile b/avr/nano/Makefile
new file mode 100644
index 0000000..f8864cc
--- /dev/null
+++ b/avr/nano/Makefile
@@ -0,0 +1,438 @@
+# Hey Emacs, this is a -*- makefile -*-
+#
+# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+# Additional material for this makefile was submitted by:
+#  Tim Henigan
+#  Peter Fleury
+#  Reiner Patommel
+#  Sander Pool
+#  Frederik Rouleau
+#  Markus Pfaff
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
+#
+# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
+#                4.07 or greater).
+#
+# make program = Download the hex file to the device, using avrdude.  Please
+#                customize the avrdude settings below first!
+#
+# make filename.s = Just compile filename.c into the assembler code only
+#
+# To rebuild project do "make clean" then "make all".
+#
+
+# mth 2004/09 
+# Differences from WinAVR 20040720 sample:
+# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum)
+# - F_OSC Define in CFLAGS and AFLAGS
+
+
+# MCU name
+MCU = atmega328p
+
+# Main Oscillator Frequency
+# This is only used to define F_OSC in all assembler and c-sources.
+#F_OSC = 3686400
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Target file name (without extension).
+TARGET = main
+
+
+# List C source files here. (C dependencies are automatically generated.)
+SRC = $(TARGET).c uart.c
+
+
+# List Assembler source files here.
+# Make them always end in a capital .S.  Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC = 
+
+
+
+# Optimization level, can be [0, 1, 2, 3, s]. 
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+#DEBUG = dwarf-2
+
+# List any extra directories to look for include files here.
+#     Each directory must be seperated by a space.
+EXTRAINCDIRS = 
+
+
+# Compiler flag to set the C Standard level.
+# c89   - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99   - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options here
+CDEFS = -DF_CPU=16000000
+
+# Place -I options here
+CINCS = -Ii2c/
+
+
+# Compiler flags.
+#  -g*:          generate debugging information
+#  -O*:          optimization level
+#  -f...:        tuning, see GCC manual and avr-libc documentation
+#  -Wall...:     warning level
+#  -Wa,...:      tell GCC to pass this to the assembler.
+#    -adhlns...: create assembler listing
+CFLAGS = -g$(DEBUG)
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -Wall -Wstrict-prototypes
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+CFLAGS += -DF_OSC=$(F_OSC)
+
+
+
+# Assembler flags.
+#  -Wa,...:   tell GCC to pass this to the assembler.
+#  -ahlms:    create listing
+#  -gstabs:   have the assembler create line number information; note that
+#             for use in COFF files, additional information about filenames
+#             and function names needs to be present in the assembler source
+#             files -- see avr-libc docs [FIXME: not yet described there]
+ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 
+ASFLAGS += -DF_OSC=$(F_OSC)
+
+
+#Additional libraries.
+
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt -lm
+
+PRINTF_LIB = 
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+SCANF_LIB = 
+
+MATH_LIB = -lm
+
+# External memory options
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+# Linker flags.
+#  -Wl,...:     tell GCC to pass this to linker.
+#    -Map:      create map file
+#    --cref:    add cross reference to  map file
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS += $(EXTMEMOPTS)
+LDFLAGS += $(PRINTF_LIB_MIN) $(SCANF_LIB) $(MATH_LIB)
+
+
+
+
+# Programming support using avrdude. Settings and variables.
+
+# Programming hardware: alf avr910 avrisp bascom bsd 
+# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
+#
+# Type: avrdude -c ?
+# to get a full listing.
+#
+#AVRDUDE_PROGRAMMER = avr911
+AVRDUDE_PROGRAMMER = avrisp2
+
+# com1 = serial port. Use lpt1 to connect to parallel port.
+#AVRDUDE_PORT = /dev/ttyUSB0    # programmer connected to serial device
+AVRDUDE_PORT = usb    # programmer connected to serial device
+
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE_COUNTER = -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_NO_VERIFY = -V
+
+# Increase verbosity level.  Please use this when submitting bug
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
+# to submit bug reports.
+#AVRDUDE_VERBOSE = -v -v
+
+AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
+AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
+AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
+
+
+
+# ---------------------------------------------------------------------------
+
+# Define directories, if needed.
+DIRAVR = c:/winavr
+DIRAVRBIN = $(DIRAVR)/bin
+DIRAVRUTILS = $(DIRAVR)/utils/bin
+DIRINC = .
+DIRLIB = $(DIRAVR)/avr/lib
+
+
+# Define programs and commands.
+SHELL = sh
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+NM = avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+COPY = cp
+
+
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = --------  end  --------
+MSG_SIZE_BEFORE = Size before: 
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+
+
+
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) 
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+
+# Compiler flags to generate dependency files.
+### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
+GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+build: elf hex eep lss sym
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss 
+sym: $(TARGET).sym
+
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+	@echo
+	@echo $(MSG_BEGIN)
+
+finished:
+	@echo $(MSG_ERRORS_NONE)
+
+end:
+	@echo $(MSG_END)
+	@echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+sizebefore:
+	@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+	@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+
+# Display compiler version information.
+gccversion : 
+	@$(CC) --version
+
+
+
+# Program the device.  
+program: $(TARGET).hex $(TARGET).eep
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000 
+
+
+coff: $(TARGET).elf
+	@echo
+	@echo $(MSG_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	@echo
+	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+	@echo
+	@echo $(MSG_FLASH) $@
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+	@echo
+	@echo $(MSG_EEPROM) $@
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+	--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+	@echo
+	@echo $(MSG_EXTENDED_LISTING) $@
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+	@echo
+	@echo $(MSG_SYMBOL_TABLE) $@
+	$(NM) -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+	@echo
+	@echo $(MSG_LINKING) $@
+	$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+%.o : %.c
+	@echo
+	@echo $(MSG_COMPILING) $<
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+%.o : %.S
+	@echo
+	@echo $(MSG_ASSEMBLING) $<
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+clean_list :
+	@echo
+	@echo $(MSG_CLEANING)
+	$(REMOVE) $(TARGET).hex
+	$(REMOVE) $(TARGET).eep
+	$(REMOVE) $(TARGET).obj
+	$(REMOVE) $(TARGET).cof
+	$(REMOVE) $(TARGET).elf
+	$(REMOVE) $(TARGET).map
+	$(REMOVE) $(TARGET).obj
+	$(REMOVE) $(TARGET).a90
+	$(REMOVE) $(TARGET).sym
+	$(REMOVE) $(TARGET).lnk
+	$(REMOVE) $(TARGET).lss
+	$(REMOVE) $(OBJ)
+	$(REMOVE) $(LST)
+	$(REMOVE) $(SRC:.c=.s)
+	$(REMOVE) $(SRC:.c=.d)
+	$(REMOVE) .dep/*
+
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program
+
diff --git a/avr/nano/main.c b/avr/nano/main.c
new file mode 100644
index 0000000..0cb0acf
--- /dev/null
+++ b/avr/nano/main.c
@@ -0,0 +1,167 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include "uart.h"
+
+/*
+ * I2C Register Map (8 Bit)
+ * 0x00 Register select
+ * 0x01 Distance left MSB
+ * 0x02 Distance left LSB
+ * 0x03 Distance right MSB
+ * 0x04 Distance right LSB
+ *
+ * 0xff Bootloader
+ */
+
+
+#define TWI_ACK		TWCR = (1<<TWEA) | (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
+#define TWI_RESET	TWCR &= ~((1 << TWSTO) | (1 << TWEN)); TWI_ACK
+#define TWI_NAK		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
+
+static volatile uint8_t ireg=0;
+static volatile uint8_t bootloader=0;
+static volatile uint16_t dist_left=0;
+static volatile uint16_t dist_right=0;
+
+ISR(TWI_vect)
+{
+	static int16_t tmp16=0;
+
+	switch (TWSR & 0xF8)
+	{  
+		case 0x60: // start write
+			TWI_ACK;
+			ireg = 0;
+			break;
+		case 0x80: // write
+			switch(ireg) {
+				case 0x00: // register select
+					ireg = TWDR;
+					ireg--; // because we do ireg++ below
+					TWI_ACK;
+					break;
+				case 0xff: // bootloader
+					bootloader = TWDR;
+				default:
+					TWI_NAK;
+			}
+			ireg++;
+			break;
+		case 0xA8: // start read
+		case 0xB8: // read
+			switch(ireg) {
+				case 0x01: // Distance left MSB
+					tmp16 = dist_left;
+					TWDR = tmp16>>8;
+					TWI_ACK;
+					break;
+				case 0x02: // Distance right LSB
+					TWDR = tmp16;
+					TWI_ACK;
+					break;
+				case 0x03: // Distance right MSB
+					tmp16 = dist_right;
+					TWDR = tmp16>>8;
+					TWI_ACK;
+					break;
+				case 0x04: // Distance right LSB
+					TWDR = tmp16;
+					TWI_ACK;
+					break;
+				default:
+					TWDR = 0;
+					TWI_NAK;
+			}
+			ireg++;
+			break;
+		default:
+			TWI_RESET;
+	}
+}
+
+
+uint16_t ReadChannel(uint8_t mux) {
+	uint8_t i;
+	uint16_t result;
+
+	ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
+	// setzen auf 8 (1) und ADC aktivieren (1)
+
+	ADMUX = mux;                      // Kanal waehlen
+	ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen 
+
+	/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
+	   also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
+	ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
+	while ( ADCSRA & (1<<ADSC)  ) {
+		     // auf Abschluss der Konvertierung warten 
+	}
+	result = ADCW;  // ADCW muss einmal gelesen werden,
+	// sonst wird Ergebnis der nächsten Wandlung
+	// nicht übernommen.
+
+	/* Eigentliche Messung - Mittelwert aus 5 aufeinanderfolgenden Wandlungen */
+	result = 0;
+	for( i=0; i<5; i++ )
+	{
+		ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
+		while ( ADCSRA & (1<<ADSC) ) {
+			   // auf Abschluss der Konvertierung warten
+		}
+		result += ADCW;		    // Wandlungsergebnisse aufaddieren
+	}
+
+	ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
+
+	result /= 5;                     // Summe durch 5 teilen = arithm. Mittelwert
+	
+	return result;
+}
+
+
+static unsigned short get_distance(uint8_t i) {
+	return ReadChannel(i);
+}
+
+
+int main(void) {
+	bootloader = 0x00;
+	setup_uart(9600);
+	uart_setup_stdout();
+
+	// I2C
+	TWAR = 0x52;
+	TWI_RESET;
+
+	printf("\r\nStart\r\n");
+
+	set_sleep_mode(SLEEP_MODE_IDLE);
+	sei();
+	while(1) {
+		switch(ireg) {
+			case 1: // ir left
+				dist_left = get_distance(0);
+				break;
+			case 3: // ir right
+				dist_right = get_distance(1);
+				break;
+			case 0xff: // Magic reg that starts the bootloader
+				if (bootloader == 0xa5) {
+					cli();
+					{
+						void (*start)(void) = (void*)0x1800;
+						start();
+					}
+				}
+				break;
+		}
+
+		sleep_mode();
+	}
+
+	return 0;
+}
diff --git a/avr/nano/main.hex b/avr/nano/main.hex
new file mode 100644
index 0000000..c6b1c2d
--- /dev/null
+++ b/avr/nano/main.hex
@@ -0,0 +1,204 @@
+:100000000C9440000C945D000C945D000C945D0019
+:100010000C945D000C945D000C945D000C945D00EC
+:100020000C945D000C945D000C945D000C945D00DC
+:100030000C945D000C945D000C945D000C945D00CC
+:100040000C945D000C945D000C9401010C945D0017
+:100050000C945D000C945D000C945D000C945D00AC
+:100060000C945F000C945D00454647656667002070
+:100070002B2D2E3031323334353637383968000085
+:1000800011241FBECFEFD8E0DEBFCDBF11E0A0E04E
+:10009000B1E0EEE9FCE002C005900D92A031B1079D
+:1000A000D9F721E0A0E1B1E001C01D92AD38B2075F
+:1000B000E1F70E940A020C944D060C9400001F9276
+:1000C0000F920FB60F9211248F939F938091B900D6
+:1000D000887F803879F048F4803609F04DC085EC8F
+:1000E0008093BC00109217014FC0883AC1F0883B42
+:1000F000B1F042C080911701882339F08F3F99F504
+:100100008091BB00809316012EC08091BB0080932C
+:1001100017018091170181508093170120C08091B1
+:1001200017018230C1F038F48130D9F48091140184
+:100130009091150109C0833019F0843061F011C02D
+:1001400080911201909113018093100190931101FD
+:100150009093BB0004C0809110018093BB0085EC9C
+:1001600003C01092BB0085E88093BC00809117010A
+:100170008F5F8093170108C08091BC008B7E8093B5
+:10018000BC0085EC8093BC009F918F910F900FBEB7
+:100190000F901F90189593E890937A0080937C00BD
+:1001A00080917C00806C80937C0080917A008064D8
+:1001B00080937A0080917A0086FDFCCF8091780050
+:1001C0009091790045E080E090E020917A002064F1
+:1001D00020937A0020917A0026FDFCCF20917800B0
+:1001E00030917900820F931F415079F720917A0066
+:1001F0002F7720937A0065E070E00E949B03CB018B
+:1002000008951F920F920FB60F9211248F939F9310
+:10021000EF93FF938091C00087FF17C0E0911A0110
+:10022000F0911B018091C600808381E0EF37F807D1
+:1002300030F43196F0931B01E0931A0106C08CE173
+:1002400091E090931B0180931A01FF91EF919F9190
+:100250008F910F900FBE0F901F9018959C01E1ECAD
+:10026000F0E0808188618083808180688083E2EC17
+:10027000F0E080818660808340E050E084E0220FDF
+:10028000331F441F551F8A95D1F760E074E284EF55
+:1002900090E00E94AF03DA01C9010197A109B109F9
+:1002A000892F9A2FAB2FBB27A7FDBA958093C50046
+:1002B00021502093C4008CE191E090931901809328
+:1002C000180190931B0180931A0108952091C0009A
+:1002D00025FFFCCFFC0180818093C6000895CF9359
+:1002E000DF931F92CDB7DEB78983CE0101960E94BE
+:1002F000660180E090E00F90DF91CF910895CF9359
+:10030000DF93EC01CE012196FC012081222319F01C
+:100310000E946601F7CFDF91CF9108958091C000D0
+:1003200087FFFCCF8091C60090E008950C948E0169
+:1003300066E971E08FE691E00C94FB03CF93DF93C5
+:10034000FC01E253FF4FA081B181EC01C453DF4FA8
+:1003500028813981A217B307B9F02091C00025FF89
+:1003600013C02C912093C60020813181AC014553EC
+:100370005F4F2417350718F42F5F3F4F03C09C01D0
+:1003800028593F4F31832083E0911801F0911901E2
+:1003900020911A0130911B012E173F07C1F1DC019A
+:1003A000AC59BF4FCD91DC911197208128836D917D
+:1003B0007C9111979C012B523F4FE9013881EB0151
+:1003C0002881321307C09C012C523F4FE90148811C
+:1003D0004F5F48839C012D593F4F6217730728F4E4
+:1003E000EB012196CD93DC9302C08D939C93D1E0D9
+:1003F000EF37FD0730F43196F0931901E0931801BF
+:1004000006C08CE191E09093190180931801DF916F
+:10041000CF9108951092160180E895E20E942E0176
+:100420000E94980182E58093BA008091BC008B7E87
+:100430008093BC0085EC8093BC0086E091E00E9434
+:10044000780483B7817F83BF7894C0E0D8E180913E
+:100450001701833061F08F3F91F08130B9F480E073
+:100460000E94CB0090931501809314010FC081E08E
+:100470000E94CB00909313018093120107C08091DA
+:100480001601853A19F4F894FE01099583B7816045
+:1004900083BF889583B78E7F83BFD9CF6F927F92BA
+:1004A0009F92AF92BF92CF92DF92EF92FF920F9303
+:1004B0001F93CF93DF93CDB7DEB72C970FB6F89489
+:1004C000DEBF0FBECDBF8C017B013A01FC0117825C
+:1004D0001682838181FF19C1CE0101965C01F8016A
+:1004E000D380F701D3FC2591D3FE21917F012223F4
+:1004F00009F407C1253249F4D3FC2591D3FE21919B
+:100500007F01253211F0912C1BC0B801822F90E0A1
+:100510000E94460463013601E2CF222309F4F1C0B0
+:10052000622F70E08FE690E02C870E94F0032C850C
+:10053000892B49F0F701D3FC2591D3FE21917F014E
+:1005400097FEEBCF0CC0233221F4F92DF0619F2EE2
+:10055000F1CF2C3639F4292D2068922EEBCF2223AF
+:1005600009F4CFC0622F70E088E690E02C870E94EB
+:10057000F0032C85892B41F06301F4E0CF0ED11CF0
+:10058000B8018FE390E012C0233641F0233789F0A1
+:10059000233521F5F92DF1609F2E0BC0630122E078
+:1005A000C20ED11CB801F301808191810E944604E2
+:1005B000B2CF630122E0C20ED11CF30160807180D2
+:1005C000F30190FC859190FE81913F01882309F40D
+:1005D000A2CFB80190E00E944604F2CF243611F079
+:1005E000293639F5630197FE09C0F4E0CF0ED11C1E
+:1005F000F30160817181828193810AC0F2E0CF0EA4
+:10060000D11CF30160817181882777FD8095982F37
+:10061000F92DFF7E9F2E97FF09C0909580957095CC
+:1006200061957F4F8F4F9F4FF0649F2E2AE030E0FF
+:1006300038C02037A1F040F42835D1F02F3609F02A
+:1006400060C028E030E019C0253719F0283751F094
+:1006500058C0292D2F7E922E2AE030E00EC0892D21
+:100660008061982E992D9462992E20E130E005C08A
+:10067000E92DE4609E2E20E132E0630197FE09C07F
+:10068000F4E0CF0ED11CF3016081718182819381EE
+:1006900008C0F2E0CF0ED11CF3016081718180E0CF
+:1006A00090E0A5010E94A504782E7A1896FE05C058
+:1006B000B8018DE290E00E94460494FE16C0FE014F
+:1006C000E70DF11D8081803381F0B80180E390E077
+:1006D0000E94460492FE09C0292D2072822F90E0CC
+:1006E000B801885A9F4F0E9446047A94F501E70D9D
+:1006F000F11D8081B80190E00E9446047110F5CF91
+:100700000ACFF8018681978102C08FEF9FEF2C9668
+:100710000FB6F894DEBF0FBECDBFDF91CF911F9112
+:100720000F91FF90EF90DF90CF90BF90AF909F9090
+:100730007F906F900895AA1BBB1B51E107C0AA1FB1
+:10074000BB1FA617B70710F0A61BB70B881F991F72
+:100750005A95A9F780959095BC01CD010895052E75
+:1007600097FB1EF400940E94C60357FD07D00E9419
+:10077000CE0307FC03D04EF40C94C603509540956D
+:10078000309521953F4F4F4F5F4F0895909580953D
+:10079000709561957F4F8F4F9F4F0895A1E21A2E5C
+:1007A000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F15
+:1007B000A217B307E407F50720F0A21BB30BE40B65
+:1007C000F50B661F771F881F991F1A9469F76095AC
+:1007D0007095809590959B01AC01BD01CF01089566
+:1007E000FC010590061621F00020D9F7C0010895FC
+:1007F0003197CF0108950F931F93CF93DF93EC01AF
+:100800008B01009731F46115710519F480E090E0D7
+:1008100038C06EE070E081E090E00E940305FC01CA
+:100820000097A1F380E883830115110571F0138708
+:10083000028781E883838091830190918401892BD1
+:1008400021F4F0938401E09383012097C9F0D187CC
+:10085000C087838182608383809185019091860126
+:10086000892B71F4F0938601E093850180918701D3
+:1008700090918801892B21F4F0938801E0938701FE
+:10088000CF01DF91CF911F910F9108950F931F9387
+:10089000CF93DF93182F092FEB018B8181FD03C0CC
+:1008A0008FEF9FEF20C082FF10C04E815F812C81AF
+:1008B0003D81421753077CF4E881F9819F012F5F46
+:1008C0003F4F39832883108306C0E885F985812F3F
+:1008D0000995892B29F72E813F812F5F3F4F3F8359
+:1008E0002E83812F902FDF91CF911F910F9108952B
+:1008F0000F931F93CF93DF93E0918501F0918601D1
+:10090000238121FF1BC0EC0100E010E08991609180
+:10091000850170918601DB011896ED91FC91199784
+:10092000882331F00995892B89F30FEF1FEFEECF64
+:100930008AE00995892B11F4C80102C08FEF9FEF5F
+:10094000DF91CF911F910F910895FA01AA272830C6
+:1009500051F1203181F1E8946F936E7F6E5F7F4F8C
+:100960008F4F9F4FAF4FB1E03ED0B4E03CD0670F08
+:10097000781F891F9A1FA11D680F791F8A1F911D5B
+:10098000A11D6A0F711D811D911DA11D20D009F4AB
+:1009900068943F912AE0269F11243019305D3193ED
+:1009A000DEF6CF010895462F4770405D4193B3E0D6
+:1009B0000FD0C9F7F6CF462F4F70405D4A3318F07D
+:1009C000495D31FD4052419302D0A9F7EACFB4E02E
+:1009D000A6959795879577956795BA95C9F70097E6
+:1009E0006105710508959B01AC010A2E0694579587
+:1009F000479537952795BA95C9F7620F731F841FDE
+:100A0000951FA01D08950F931F93CF93DF93869F8B
+:100A10008001879F100D969F100D1124C8010E9420
+:100A20001F05EC01009729F0A80160E070E00E942A
+:100A30004606CE01DF91CF911F910F910895CF937C
+:100A4000DF938230910510F482E090E0E0918B0119
+:100A5000F0918C0120E030E0A0E0B0E0309739F177
+:100A60004081518148175907B8F04817590771F468
+:100A700082819381109729F013969C938E931297FD
+:100A80002CC090938C0180938B0127C021153105D8
+:100A900031F04217530718F0A901DB0101C0EF0143
+:100AA0009A01BD01DF010280F381E02DD7CF21152E
+:100AB0003105F9F0281B390B2430310580F48A8187
+:100AC0009B816115710521F0FB019383828304C032
+:100AD00090938C0180938B01FE01329644C0FE01FD
+:100AE000E20FF31F819391932250310939832883B8
+:100AF0003AC02091890130918A01232B41F4209141
+:100B000002013091030130938A01209389012091E1
+:100B10000001309101012115310541F42DB73EB797
+:100B20004091040150910501241B350BE09189018E
+:100B3000F0918A01E217F307A0F42E1B3F0B281750
+:100B4000390778F0AC014E5F5F4F2417350748F046
+:100B50004E0F5F1F50938A014093890181939193B7
+:100B600002C0E0E0F0E0CF01DF91CF910895CF9394
+:100B7000DF93009709F487C0FC0132971382128239
+:100B8000C0918B01D0918C01209781F4208131811B
+:100B9000280F391F8091890190918A01821793074C
+:100BA00079F5F0938A01E09389016DC0DE0120E0C0
+:100BB00030E0AE17BF0750F412964D915C91139739
+:100BC0009D014115510509F1DA01F3CFB383A283E9
+:100BD00040815181840F951F8A179B0771F48D9175
+:100BE0009C911197840F951F029691838083129692
+:100BF0008D919C911397938382832115310529F45C
+:100C0000F0938C01E0938B013EC0D9011396FC93C5
+:100C1000EE9312974D915D91A40FB51FEA17FB0754
+:100C200079F480819181840F951F0296D9011196E4
+:100C30009C938E938281938113969C938E931297AB
+:100C4000E0E0F0E08A819B81009719F0FE01EC0161
+:100C5000F9CFCE01029628813981820F931F20910E
+:100C6000890130918A012817390769F4309729F4EE
+:100C700010928C0110928B0102C013821282D093C9
+:100C80008A01C0938901DF91CF910895DC0101C0F1
+:0E0C90006D9341505040E0F70895F894FFCF67
+:100C9E0000008D0120000D0A53746172740D000066
+:00000001FF
diff --git a/avr/nano/ringbuffer.h b/avr/nano/ringbuffer.h
new file mode 100644
index 0000000..ed8b022
--- /dev/null
+++ b/avr/nano/ringbuffer.h
@@ -0,0 +1,34 @@
+#ifndef RINGBUFFER_H
+#define RINGBUFFER_H
+
+#define RINGBUFFER_LEN 100
+#define RINGBUFFER_MAX_NUM 1
+
+typedef struct ringbuffer {
+	char read[RINGBUFFER_LEN];
+	char *in_read_ptr;
+	char *out_read_ptr;
+	char write[RINGBUFFER_LEN];
+	char *in_write_ptr;
+	char *out_write_ptr;
+	FILE *dev;
+	FILE *dev_in_as_out;
+	uint8_t newlines;
+	char block_read;
+} ringbuffer_t;
+
+ringbuffer_t *ringbuffers[RINGBUFFER_MAX_NUM];
+uint8_t num_ringbuffers;
+
+void ringbuffer_setup(FILE *stream, ringbuffer_t *buffer);
+void ringbuffer_setup_in_as_out(FILE *stream, ringbuffer_t *buffer);
+void init_ringbuffers(void);
+void stream_setup(FILE *uart_stream);
+void stream_setup_out_only(FILE *stream);
+void stream_setup_in_as_out(FILE *stream, int ringbuffer_putchar_sound(char, FILE*));
+uint8_t ringbuffer_busy(void);
+void ringbuffer_set_read_noblock(FILE *stream);
+void ringbuffer_set_read_block(FILE *stream, char c);
+
+#endif
+
diff --git a/avr/nano/uart.c b/avr/nano/uart.c
new file mode 100644
index 0000000..1a3707a
--- /dev/null
+++ b/avr/nano/uart.c
@@ -0,0 +1,97 @@
+#include <stdlib.h>
+#include "uart.h"
+#include <avr/interrupt.h>
+
+#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
+
+static volatile	char read[RINGBUFFER_LEN];
+static volatile	char *in_read_ptr;
+static volatile	char *out_read_ptr;
+
+ISR(USART_RX_vect) {
+	// update read from uart
+	if (UCSR0A & (1<<RXC0)) {
+		*in_read_ptr = UDR0;
+
+		if (in_read_ptr < read + RINGBUFFER_LEN - 1) in_read_ptr++;
+		else in_read_ptr = (char *)read;
+	}
+}
+
+
+void setup_uart(unsigned int rate) {
+	UCSR0B |= (1<<TXEN0) | (1<<RXEN0); // UART TX & RX
+	UCSR0B |= (1<<RXCIE0); 		// RX Interrupt
+	UCSR0C |= (3<<UCSZ00); // Asynchron 8N1
+
+	UBRR0H = (uint8_t)(UART_UBRR_CALC(rate, F_CPU) >> 8);
+	UBRR0L = (uint8_t)UART_UBRR_CALC(rate, F_CPU);
+
+	in_read_ptr = out_read_ptr = read;
+}
+
+
+void uart_putc(char *c) {
+	while (!(UCSR0A & (1<<UDRE0)));
+	UDR0 = *c;
+}
+
+
+int uart_putchar(char c, FILE *stream)
+{
+	uart_putc(&c);
+	return 0;
+}
+
+
+void uart_puts(char *s) {
+	char *c;
+
+	for (c = s; *c != '\0'; c++)
+		uart_putc(c);
+}
+
+
+int uart_getchar(FILE *stream)
+{
+	return uart_getc();
+}
+
+
+int uart_getc() {
+	while (!(UCSR0A & (1<<RXC0)));
+	return UDR0;
+}
+
+
+void uart_setup_stdout() {
+	fdevopen(uart_putchar, uart_getchar);
+}
+
+
+void uart_stream_update(ringbuffer_t *buffer) {
+	// update write to uart
+	if (buffer->out_write_ptr != buffer->in_write_ptr) {
+		if (UCSR0A & (1<<UDRE0)) {
+			UDR0 = *buffer->out_write_ptr;
+			if (buffer->out_write_ptr < buffer->write + RINGBUFFER_LEN - 1) buffer->out_write_ptr++;
+			else buffer->out_write_ptr = buffer->write;
+		}
+	}
+
+	// update read from uart	
+	if (in_read_ptr != out_read_ptr) {
+		*buffer->in_read_ptr = *out_read_ptr;
+
+		// update newline chars
+		if (buffer->block_read == *buffer->in_read_ptr) buffer->newlines++;
+
+		if (buffer->in_read_ptr < buffer->read + RINGBUFFER_LEN - 1) buffer->in_read_ptr++;
+		else buffer->in_read_ptr = buffer->read;
+
+		// move pointer
+		if (out_read_ptr < read + RINGBUFFER_LEN - 1) out_read_ptr++;
+		else out_read_ptr = read;
+	}
+}
+
diff --git a/avr/nano/uart.h b/avr/nano/uart.h
new file mode 100644
index 0000000..1225590
--- /dev/null
+++ b/avr/nano/uart.h
@@ -0,0 +1,18 @@
+#ifndef UART_H
+#define UART_H
+
+#include <stdio.h>
+#include "ringbuffer.h"
+
+void setup_uart(unsigned int rate);
+void uart_putc(char *c);
+void uart_puts(char *s);
+int uart_getc(void);
+void uart_puti(int i);
+int uart_putchar(char c, FILE *stream);
+int uart_getchar(FILE *stream);
+void uart_setup_stdout(void);
+void uart_stream_update(ringbuffer_t *buffer);
+
+#endif
+