Commits

Anonymous committed 7388ac5

initial import; pulled AVR related sources out of subversion repo

  • Participants

Comments (0)

Files changed (8)

+# Hey Emacs, this is a -*- makefile -*-
+#
+# WinAVR Sample 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".
+#
+
+
+# MCU name
+MCU = at90can128
+
+# 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 clock.c usb.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
+
+# 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 =
+
+# Place -I options here
+CINCS =
+
+
+# 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 += -Wall 
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+
+
+
+# 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 
+
+
+
+#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
+
+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) $(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 = stk200
+
+# com1 = serial port. Use lpt1 to connect to parallel port.
+AVRDUDE_PORT = com1    # 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 = bash
+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
+
+
+# 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-c $(ASFLAGS)
+
+
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+build: elf hex eep lss sym extcoff
+
+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
+
+
+
+
+
+
+
+
+
+
+
+/**
+  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
+  * @copyright   (c) 2009 Sven Hendriks
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "clock.h"
+
+const uint8_t sevenSegData[CLOCK_MAX_BASE] = {
+  0b00111111, // 0
+  0b00000110, // 1
+  0b01011011, // 2
+  0b01001111, // 3
+  0b01100110, // 4
+  0b01101101, // 5
+  0b01111101, // 6
+  0b00000111, // 7
+  0b01111111, // 8
+  0b01101111, // 9
+  0b01110111, // A
+  0b01111100, // b
+  0b00111001, // C
+  0b01011110, // d
+  0b01111001, // E
+  0b01110001, // F
+  0b00111101, // G
+  0b01110110, // H
+  0b00110000, // I
+  0b00011110  // J
+};
+
+/*struct {
+    uint16_t year;
+    uint8_t  month, day, hour, minute, second, weekDay, daySavingTime;
+} dateTime;
+*/
+
+uint8_t displayData[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+void clock_init(void) {
+    dateTime.year     = 1970;
+    dateTime.month    = 1;
+    dateTime.day      = 1;
+    dateTime.hour     = 0;
+    dateTime.minute   = 0;
+    dateTime.second   = 0;
+    dateTime.weekDay  = 0;
+    dateTime.daySavingTime = 0;
+}
+
+void clock_incOneSec(void) {
+    dateTime.second++;
+    if(dateTime.second >= 60) {
+        dateTime.second = 0;
+        dateTime.minute++;
+        if(dateTime.minute >= 60) {
+            dateTime.minute = 0;
+            dateTime.hour++;
+            if(dateTime.hour >= 24) {
+                dateTime.hour = 0;
+                dateTime.day += 1;
+                if(   (dateTime.month == 2 && dateTime.day > 28)
+                   || ((   dateTime.month == 1 || dateTime.month == 3
+                        || dateTime.month == 5 || dateTime.month == 7
+                        || dateTime.month == 8 || dateTime.month == 10
+                        || dateTime.month == 12) && dateTime.day > 31)
+                   || ((   dateTime.month == 4 || dateTime.month == 6
+                        || dateTime.month == 9 || dateTime.month == 11)
+                        && dateTime.day > 30)) {
+                    dateTime.day = 1;
+                    dateTime.month += 1;
+                    if(dateTime.month > 12) {
+                        dateTime.month = 1;
+                        dateTime.year += 1;
+                    }
+                }
+
+            }
+        }
+    }
+}
+
+void clock_setDateTime(uint16_t year,     uint8_t month,  uint8_t day, 
+                           uint8_t  hour,     uint8_t minute, uint8_t second, 
+                           uint8_t  week_day, uint8_t day_saving_time) {
+    dateTime.year    = year;
+    dateTime.month   = month;
+    dateTime.day     = day;
+    dateTime.hour    = hour;
+    dateTime.minute  = minute;
+    dateTime.second  = second;
+    dateTime.weekDay = week_day;
+    dateTime.daySavingTime = day_saving_time;
+}
+
+uint16_t pow2(uint16_t base, uint16_t exp) {
+    uint16_t i, p = 1;
+    for(i=0; i<exp; i++) p *= base;
+    return p;
+}
+
+void iToDigits(uint16_t i, uint8_t no_of_digits, uint8_t base, uint8_t *result) {
+    volatile uint16_t divisor;
+    volatile uint8_t last_digit, digit_pos, digit;
+
+    if(NULL != result && 1 <= no_of_digits) {
+        divisor = pow2(base, no_of_digits-1);
+        last_digit = 0;
+        for(digit_pos = 0; digit_pos < no_of_digits; digit_pos++) {
+            digit = (uint8_t) i / divisor - last_digit * base;
+            if(digit < CLOCK_MAX_BASE) {
+              *result = sevenSegData[digit];
+            } else {
+              *result = 0b01001001;
+            }
+            result++;
+            last_digit = digit;
+            divisor /= base;
+        } 
+    }
+}
+
+uint8_t* clock_to7SegmentData(uint8_t base) {
+    // convert date and time into a string
+    // the bytes of this string can be used
+    // to drive 7 segment display elements
+    // directly
+    iToDigits(dateTime.year,   4, base, &displayData[ 0]);
+    iToDigits(dateTime.month,  2, base, &displayData[ 4]);
+    iToDigits(dateTime.day,    2, base, &displayData[ 6]);
+    iToDigits(dateTime.hour,   2, base, &displayData[ 8]);
+    iToDigits(dateTime.minute, 2, base, &displayData[10]);
+    iToDigits(dateTime.second, 2, base, &displayData[12]);
+    return displayData;
+}
+
+void clock_toStr(uint8_t *str) {
+    sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d %d %d",
+            dateTime.year + 2000, dateTime.month,  dateTime.day,
+            dateTime.hour,        dateTime.minute, dateTime.second,
+            dateTime.weekDay,     dateTime.daySavingTime);
+}
+/**
+  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
+  * @copyright   (c) 2009 Sven Hendriks
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+
+#ifndef CLOCK_H_INCLUDED
+#define CLOCK_H_INCLUDED
+
+#include <stdint.h>
+
+#define CLOCK_MAX_BASE 20
+
+struct {
+    uint16_t year;
+    uint8_t  month, day, hour, minute, second, weekDay, daySavingTime;
+} dateTime;
+
+void clock_init(void);
+void clock_incOneSec(void);
+void clock_setDateTime(uint16_t year,     uint8_t month,  uint8_t day, 
+                           uint8_t  hour,     uint8_t minute, uint8_t second, 
+                           uint8_t  week_day, uint8_t day_saving_time);
+uint8_t* clock_to7SegmentData(uint8_t base);
+void clock_toStr(uint8_t *str);
+
+#endif
+
+/**
+  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
+  * @copyright   (c) 2009 Sven Hendriks
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <compat/deprecated.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include "clock.h"
+#include "uart.h"
+#include "usb.h"
+#include <string.h>
+#include <stdio.h>
+#ifndef F_CPU
+#define F_CPU 16000000UL 
+#endif
+#define CLOCK_SPEED 16000000
+#include <util/delay.h>
+#define UART_BAUD 9600
+#define FILE_NAME "loolog.log"
+
+#define DIFF(t0,t1) ((t0)<(t1) ? (t1)-(t0) : (t1) + (65535-(t0))) 
+
+volatile uint8_t timer_counter = 0;
+volatile uint8_t datetime[32];
+volatile uint8_t buffer[100];
+
+volatile uint8_t global_synced = 0;
+
+volatile uint16_t timestamp_rising = 0, timestamp_falling = 0;
+volatile uint8_t errors = 0, counter = 0;
+volatile uint16_t hightime = 0, lowtime = 0;
+volatile uint16_t year;
+volatile uint8_t month, day, hour, minute, daySavingTime, dayOfWeek;
+volatile uint8_t synced = 0;
+volatile uint8_t dcf77_bit = 0, parity = 0;
+
+void wait(int cycles) {
+    int i, j;
+    for(j=0; j<cycles; j++)
+        for(i=0; i<cycles; i++) {
+            asm volatile("nop");
+        }
+}
+
+ISR(TIMER0_OVF_vect) {
+    TCNT0 = 130;
+    timer_counter++;
+    if( 124 == timer_counter ) {
+        PORTC ^= 1;
+        timer_counter = 0;
+        clock_incOneSec();
+    }
+}
+
+void bcd_decoder(uint8_t bit, uint8_t counter, uint8_t min_counter, volatile uint8_t *value) {
+    uint8_t rel_counter = counter - min_counter;
+
+    if(0 == rel_counter) {
+        if(bit) {
+            *value = 1;
+        } else {
+            *value = 0;
+        }
+    }
+
+    if(rel_counter >= 1 && rel_counter <= 3) {
+       if(bit) {
+           *value += 1 << rel_counter;
+       }
+    } else if(rel_counter >= 4 && rel_counter <= 7) {
+       if(bit) {
+           *value += (1 << (rel_counter-4)) * 10;
+       }
+    }
+}
+
+// ISR for external interrupt on PD0;
+// decodes the DCF77 signal
+ISR(INT0_vect) {
+    // detect type of edge
+    if( ! (EICRA & (1 << ISC00))) {
+        // falling edge
+        PORTA ^= 128;
+
+        // measure hightime
+        timestamp_falling = TCNT1;
+        hightime = DIFF(timestamp_rising, timestamp_falling);
+	
+        // detect bit
+        if(hightime <= 2344) { // 2344 counts ~ 150 ms
+            dcf77_bit = 0;
+        } else {
+            dcf77_bit = 1;
+        }
+	
+        // decode
+        if(counter == 17) {
+            parity = 0;
+            if(1 == dcf77_bit) { // bit17 = 0: MEZ, bit17 = 1: MESZ
+                daySavingTime = 0;
+            } else {
+                daySavingTime = 1;
+            }
+   	    } else if(counter >= 21 && counter <= 27) {
+            parity ^= dcf77_bit;
+	        bcd_decoder(dcf77_bit, counter, 21, &minute);
+        } else if(28 == counter) {
+            if(parity != dcf77_bit) errors += 0x01;
+            parity = 0;
+    	} else if(counter >= 29 && counter <= 34) {
+            parity ^= dcf77_bit;
+    	    bcd_decoder(dcf77_bit, counter, 29, &hour);
+        } else if(35 == counter) {
+            if(parity != dcf77_bit) errors += 0x02;
+            parity = 0;
+    	} else if(counter >= 36 && counter <= 41) {
+            parity ^= dcf77_bit;
+	        bcd_decoder(dcf77_bit, counter, 36, &day);
+    	} else if(counter >= 42 && counter <= 44) {
+            parity ^= dcf77_bit;
+     	    bcd_decoder(dcf77_bit, counter, 42, &dayOfWeek);
+    	} else if(counter >= 45 && counter <= 49) {
+            parity ^= dcf77_bit;
+	        bcd_decoder(dcf77_bit, counter, 45, &month);
+	    } else if(counter >= 50 && counter <= 57) {
+            parity ^= dcf77_bit;
+	        bcd_decoder(dcf77_bit, counter, 50, &year);
+	    } else if(58 == counter) {
+            if(parity != dcf77_bit) errors += 0x04;
+            parity = 0;
+        }
+	    counter++;
+        sbi(EICRA, ISC00);
+    } else {
+        // rising edge
+        PORTA ^= 128;
+
+        // measure lowtime
+        timestamp_rising = TCNT1;
+        lowtime = DIFF(timestamp_falling, timestamp_rising);
+
+        // is this the first bit?
+        if(lowtime > 23440) { // 23440 counts ~ 1500 ms
+            // yes,i first bit
+            counter = 0;
+
+            // went everything ok?
+            if(0 == errors && 1 == synced) {
+                // copy local time to global clock "object"
+                clock_setDateTime(year, month,  day, 
+                                  hour, minute, 0, 
+                                  dayOfWeek,    daySavingTime);
+            }
+            if(0 == errors) {
+                synced = 1;
+                global_synced = 1;
+                PORTC ^= 128;
+            } else {
+                // log error
+                // TODO: does not work, because the uart
+                // routine works interrupt based
+                // and we are in an ISR already
+                /*usb_openFile((uint8_t *)FILE_NAME);
+                waitForUSBModule();
+                sprintf(buffer, "Parity error: 0x%02x\n", errors);
+                usb_write(buffer, 19);
+                waitForUSBModule(); 
+                usb_closeFile((uint8_t *)FILE_NAME);
+                waitForUSBModule();*/
+                synced = 0;
+                global_synced = 0;
+                errors = 0;
+            }
+        }
+        cbi(EICRA, ISC00); // switch to rising edge detection
+    }
+}
+
+void timer_init(void) {
+    // init timer 0
+    TCCR0A = ( 1 << CS02 ) | ( 1 << CS00 ); // prescaler 1024    
+    TIMSK0 = ( 0 << OCIE0A ) | ( 1 << TOIE0); // enable overflow interrupt
+    TCNT0  = 130;
+    
+    // init timer 1
+    TCCR1B = (1 << CS12) | (1 << CS10); // prescaler 1024
+
+    sei(); // TODO: kann das weg?
+}
+
+void extint_init(void) {
+    outb(DDRD,  0x00); // all PINs in
+    outb(PORTD, 0xff); // enable pull-up
+
+    // enable external interrupt on D0 
+    EICRA = (1 << ISC01) | (1 << ISC00);
+    EIMSK =  1;
+}
+
+int main(int argc, char *argv[]) {
+    volatile uint16_t cnt = 0;
+    volatile uint8_t st1 = 0, st2 = 0, old_st = 255;
+    volatile uint8_t status[3];
+    //volatile uint8_t filename[20];
+
+    outb(DDRA, 0xff);  // all pins out
+    outb(PORTA, 0x00); // turn all pins low
+
+    outb(DDRC, 0xff);  // all pins out
+    outb(PORTC, 0x00); // turn all pins low
+
+    clock_init();
+    timer_init();
+
+    _delay_ms(1000);
+    outb(PORTA, 0x01); // turn STI 100 on
+
+    // init uart interface
+    uart1_init(UART_BAUD_SELECT(UART_BAUD, CLOCK_SPEED));
+
+    // wait for usb module
+    while((uart1_getc() & 0xff) != 0x3e);
+    while((uart1_getc() & 0xff) != 0x0d);
+
+    // init usb module
+    usb_init(uart1_putc, uart1_getc);
+
+    // write hello message
+    usb_openFile((uint8_t *)FILE_NAME);
+    waitForUSBModule();
+    usb_write((uint8_t *)"Hello world\n", 12);
+    waitForUSBModule();
+    usb_closeFile((uint8_t *)FILE_NAME);
+    waitForUSBModule();
+
+    // enable external interrupt for dcf77
+    extint_init();
+
+    TCNT1 = 0; // reset Timer 1
+
+    // wait until we are synced to dcf77
+    while(0 == global_synced);
+    global_synced = 0;
+    while(0 == global_synced);
+    global_synced = 0;
+    while(0 == global_synced);
+
+    // synced, start logging
+    PORTC ^= 64;
+    usb_openFile((uint8_t *)FILE_NAME);
+    waitForUSBModule();
+    usb_write((uint8_t *)"Synced. Start logging\n", 22);
+    waitForUSBModule(); 
+    usb_closeFile((uint8_t *)FILE_NAME);
+    waitForUSBModule();
+
+    // enable watchdog timer;
+    // whenever we get stuck somewhere
+    // for more than 2 seconds, restart
+    // the system
+    wdt_enable(WDTO_2S);
+
+    // poll PIND1 for loo status changes
+    while(1) {
+        wdt_reset(); // reset watchdog timer to prevent system reset
+
+        PORTC ^= 4; // indicate that we're doing something
+
+        // <debug>
+        /*if(   (dateTime.minute == 0  || dateTime.minute == 15
+           || dateTime.minute == 30 || dateTime.minute == 45)
+           && dateTime.second == 0) {
+            clock_toStr(&datetime[0]);
+            while(uart1_getc() != UART_NO_DATA);
+            usb_openFile((uint8_t *)FILE_NAME);
+            waitForUSBModule();
+            sprintf(buffer, "%05d ", cnt++);
+            strcat(buffer, datetime); // len 23
+            strcat(buffer, " -- MARK --");
+            strcat(buffer, "\n");
+            usb_write(buffer, 41);
+            waitForUSBModule();
+            usb_closeFile((uint8_t *)FILE_NAME);
+            waitForUSBModule();
+        }*/
+        // </debug>
+
+        // read the status;
+        // read input pin twice with a 100ms delay
+        // to do a simple debouncing
+        st1 = ((PIND & 2) != 0) ? 1 : 0;        
+        _delay_ms(100);
+        st2 = ((PIND & 2) != 0) ? 1 : 0;
+
+        // if both measurements yield the same value and 
+        // this value differs from the old one, then we
+        // have a change of status that we have to log
+        if(st1 == st2 && st1 != old_st) {
+            // status changed, save current status
+            old_st = st1;
+            PORTC ^= 32;
+
+            // if file on usb module is open, log status
+            // convert current date and time to string
+            clock_toStr(&datetime[0]);
+
+            // flush uart input buffer
+            while(uart1_getc() != UART_NO_DATA);
+
+            // open file and write data
+            //sprintf(filename, "%04d%02d%02d.loo", dateTime.year+2000, dateTime.month, dateTime.day);
+            //cli();
+            usb_openFile((uint8_t *)FILE_NAME);
+            //usb_openFile(filename);
+            waitForUSBModule();
+            sprintf(status, " %d", st1);
+            sprintf(buffer, "%05d ", cnt++);
+            strcat(buffer, datetime);
+            strcat(buffer, status);
+            strcat(buffer, "\n");
+            usb_write(buffer, 32);
+            waitForUSBModule();
+
+            // close file
+            usb_closeFile((uint8_t *)FILE_NAME);
+            //usb_closeFile(filename);
+            waitForUSBModule();
+            //sei();
+        }
+        _delay_ms(100);
+    }
+}
+
+/*************************************************************************
+Title:    Interrupt UART library with receive/transmit circular buffers
+Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
+File:     $Id: uart.c 0:acabf985a55f 2009-10-25 19:03 +0100 sven $
+Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
+Hardware: any AVR with built-in UART, 
+License:  GNU General Public License 
+          
+DESCRIPTION:
+    An interrupt is generated when the UART has finished transmitting or
+    receiving a byte. The interrupt handling routines use circular buffers
+    for buffering received and transmitted data.
+    
+    The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
+    the buffer size in bytes. Note that these variables must be a 
+    power of 2.
+    
+USAGE:
+    Refere to the header file uart.h for a description of the routines. 
+    See also example test_uart.c.
+
+NOTES:
+    Based on Atmel Application Note AVR306
+                    
+LICENSE:
+    Copyright (C) 2006 Peter Fleury
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+                        
+*************************************************************************/
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "uart.h"
+
+
+/*
+ *  constants and macros
+ */
+
+/* size of RX/TX buffers */
+#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
+#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
+
+#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
+#error RX buffer size is not a power of 2
+#endif
+#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
+#error TX buffer size is not a power of 2
+#endif
+
+#if defined(__AVR_AT90S2313__) \
+ || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
+ || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
+ || defined(__AVR_ATmega103__)
+ /* old AVR classic or ATmega103 with one UART */
+ #define AT90_UART
+ #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
+ #define UART0_STATUS   USR
+ #define UART0_CONTROL  UCR
+ #define UART0_DATA     UDR  
+ #define UART0_UDRIE    UDRIE
+#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
+ /* old AVR classic with one UART */
+ #define AT90_UART
+ #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
+ #define UART0_STATUS   UCSRA
+ #define UART0_CONTROL  UCSRB
+ #define UART0_DATA     UDR 
+ #define UART0_UDRIE    UDRIE
+#elif  defined(__AVR_ATmega8__)  || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
+  || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
+  || defined(__AVR_ATmega323__)
+  /* ATmega with one USART */
+ #define ATMEGA_USART
+ #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
+ #define UART0_STATUS   UCSRA
+ #define UART0_CONTROL  UCSRB
+ #define UART0_DATA     UDR
+ #define UART0_UDRIE    UDRIE
+#elif defined(__AVR_ATmega163__) 
+  /* ATmega163 with one UART */
+ #define ATMEGA_UART
+ #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
+ #define UART0_STATUS   UCSRA
+ #define UART0_CONTROL  UCSRB
+ #define UART0_DATA     UDR
+ #define UART0_UDRIE    UDRIE
+#elif defined(__AVR_ATmega162__) 
+ /* ATmega with two USART */
+ #define ATMEGA_USART0
+ #define ATMEGA_USART1
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
+ #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
+ #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
+ #define UART0_STATUS   UCSR0A
+ #define UART0_CONTROL  UCSR0B
+ #define UART0_DATA     UDR0
+ #define UART0_UDRIE    UDRIE0
+ #define UART1_STATUS   UCSR1A
+ #define UART1_CONTROL  UCSR1B
+ #define UART1_DATA     UDR1
+ #define UART1_UDRIE    UDRIE1
+#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) 
+ /* ATmega with two USART */
+ #define ATMEGA_USART0
+ #define ATMEGA_USART1
+ #define UART0_RECEIVE_INTERRUPT   SIG_UART0_RECV
+ #define UART1_RECEIVE_INTERRUPT   SIG_UART1_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_UART0_DATA
+ #define UART1_TRANSMIT_INTERRUPT  SIG_UART1_DATA
+ #define UART0_STATUS   UCSR0A
+ #define UART0_CONTROL  UCSR0B
+ #define UART0_DATA     UDR0
+ #define UART0_UDRIE    UDRIE0
+ #define UART1_STATUS   UCSR1A
+ #define UART1_CONTROL  UCSR1B
+ #define UART1_DATA     UDR1
+ #define UART1_UDRIE    UDRIE1
+#elif defined(__AVR_ATmega161__)
+ /* ATmega with UART */
+ #error "AVR ATmega161 currently not supported by this libaray !"
+#elif defined(__AVR_ATmega169__) 
+ /* ATmega with one USART */
+ #define ATMEGA_USART
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
+ #define UART0_STATUS   UCSRA
+ #define UART0_CONTROL  UCSRB
+ #define UART0_DATA     UDR
+ #define UART0_UDRIE    UDRIE
+#elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
+ /* ATmega with one USART */
+ #define ATMEGA_USART0
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
+ #define UART0_STATUS   UCSR0A
+ #define UART0_CONTROL  UCSR0B
+ #define UART0_DATA     UDR0
+ #define UART0_UDRIE    UDRIE0
+#elif defined(__AVR_ATtiny2313__)
+ #define ATMEGA_USART
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RX 
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_UDRE
+ #define UART0_STATUS   UCSRA
+ #define UART0_CONTROL  UCSRB
+ #define UART0_DATA     UDR
+ #define UART0_UDRIE    UDRIE
+#elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\
+      defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\
+      defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\
+      defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__)
+  /* ATmega with one USART */
+  #define ATMEGA_USART0
+  #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
+  #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
+  #define UART0_STATUS   UCSR0A
+  #define UART0_CONTROL  UCSR0B
+  #define UART0_DATA     UDR0
+  #define UART0_UDRIE    UDRIE0
+#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega640__) || defined(__AVR_AT90CAN128__)
+/* ATmega with two USART */
+  #define ATMEGA_USART0
+  #define ATMEGA_USART1
+  #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
+  #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
+  #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
+  #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
+  #define UART0_STATUS   UCSR0A
+  #define UART0_CONTROL  UCSR0B
+  #define UART0_DATA     UDR0
+  #define UART0_UDRIE    UDRIE0
+  #define UART1_STATUS   UCSR1A
+  #define UART1_CONTROL  UCSR1B
+  #define UART1_DATA     UDR1
+  #define UART1_UDRIE    UDRIE1  
+#elif defined(__AVR_ATmega644__)
+ /* ATmega with one USART */
+ #define ATMEGA_USART0
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
+ #define UART0_STATUS   UCSR0A
+ #define UART0_CONTROL  UCSR0B
+ #define UART0_DATA     UDR0
+ #define UART0_UDRIE    UDRIE0
+#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
+ /* ATmega with two USART */
+ #define ATMEGA_USART0
+ #define ATMEGA_USART1
+ #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
+ #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
+ #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
+ #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
+ #define UART0_STATUS   UCSR0A
+ #define UART0_CONTROL  UCSR0B
+ #define UART0_DATA     UDR0
+ #define UART0_UDRIE    UDRIE0
+ #define UART1_STATUS   UCSR1A
+ #define UART1_CONTROL  UCSR1B
+ #define UART1_DATA     UDR1
+ #define UART1_UDRIE    UDRIE1
+#else
+ #error "no UART definition for MCU available"
+#endif
+
+
+/*
+ *  module global variables
+ */
+static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
+static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
+static volatile unsigned char UART_TxHead;
+static volatile unsigned char UART_TxTail;
+static volatile unsigned char UART_RxHead;
+static volatile unsigned char UART_RxTail;
+static volatile unsigned char UART_LastRxError;
+
+#if defined( ATMEGA_USART1 )
+static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
+static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
+static volatile unsigned char UART1_TxHead;
+static volatile unsigned char UART1_TxTail;
+static volatile unsigned char UART1_RxHead;
+static volatile unsigned char UART1_RxTail;
+static volatile unsigned char UART1_LastRxError;
+#endif
+
+
+
+SIGNAL(UART0_RECEIVE_INTERRUPT)
+/*************************************************************************
+Function: UART Receive Complete interrupt
+Purpose:  called when the UART has received a character
+**************************************************************************/
+{
+    unsigned char tmphead;
+    unsigned char data;
+    unsigned char usr;
+    unsigned char lastRxError;
+ 
+ 
+    /* read UART status register and UART data register */ 
+    usr  = UART0_STATUS;
+    data = UART0_DATA;
+    
+    /* */
+#if defined( AT90_UART )
+    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
+#elif defined( ATMEGA_USART )
+    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
+#elif defined( ATMEGA_USART0 )
+    lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
+#elif defined ( ATMEGA_UART )
+    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
+#endif
+        
+    /* calculate buffer index */ 
+    tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
+    
+    if ( tmphead == UART_RxTail ) {
+        /* error: receive buffer overflow */
+        lastRxError = UART_BUFFER_OVERFLOW >> 8;
+    }else{
+        /* store new index */
+        UART_RxHead = tmphead;
+        /* store received data in buffer */
+        UART_RxBuf[tmphead] = data;
+    }
+    UART_LastRxError = lastRxError;   
+}
+
+
+SIGNAL(UART0_TRANSMIT_INTERRUPT)
+/*************************************************************************
+Function: UART Data Register Empty interrupt
+Purpose:  called when the UART is ready to transmit the next byte
+**************************************************************************/
+{
+    unsigned char tmptail;
+
+    
+    if ( UART_TxHead != UART_TxTail) {
+        /* calculate and store new buffer index */
+        tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
+        UART_TxTail = tmptail;
+        /* get one byte from buffer and write it to UART */
+        UART0_DATA = UART_TxBuf[tmptail];  /* start transmission */
+    }else{
+        /* tx buffer empty, disable UDRE interrupt */
+        UART0_CONTROL &= ~_BV(UART0_UDRIE);
+    }
+}
+
+
+/*************************************************************************
+Function: uart_init()
+Purpose:  initialize UART and set baudrate
+Input:    baudrate using macro UART_BAUD_SELECT()
+Returns:  none
+**************************************************************************/
+void uart_init(unsigned int baudrate)
+{
+    UART_TxHead = 0;
+    UART_TxTail = 0;
+    UART_RxHead = 0;
+    UART_RxTail = 0;
+    
+#if defined( AT90_UART )
+    /* set baud rate */
+    UBRR = (unsigned char)baudrate; 
+
+    /* enable UART receiver and transmmitter and receive complete interrupt */
+    UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
+
+#elif defined (ATMEGA_USART)
+    /* Set baud rate */
+    if ( baudrate & 0x8000 )
+    {
+    	 UART0_STATUS = (1<<U2X);  //Enable 2x speed 
+    	 baudrate &= ~0x8000;
+    }
+    UBRRH = (unsigned char)(baudrate>>8);
+    UBRRL = (unsigned char) baudrate;
+   
+    /* Enable USART receiver and transmitter and receive complete interrupt */
+    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
+    
+    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
+    #ifdef URSEL
+    UCSRC = (1<<URSEL)|(3<<UCSZ0);
+    #else
+    UCSRC = (3<<UCSZ0);
+    #endif 
+    
+#elif defined (ATMEGA_USART0 )
+    /* Set baud rate */
+    if ( baudrate & 0x8000 ) 
+    {
+   		UART0_STATUS = (1<<U2X0);  //Enable 2x speed 
+   		baudrate &= ~0x8000;
+   	}
+    UBRR0H = (unsigned char)(baudrate>>8);
+    UBRR0L = (unsigned char) baudrate;
+
+    /* Enable USART receiver and transmitter and receive complete interrupt */
+    UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
+    
+    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
+    #ifdef URSEL0
+    UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
+    #else
+    UCSR0C = (3<<UCSZ00);
+    #endif 
+
+#elif defined ( ATMEGA_UART )
+    /* set baud rate */
+    if ( baudrate & 0x8000 ) 
+    {
+    	UART0_STATUS = (1<<U2X);  //Enable 2x speed 
+    	baudrate &= ~0x8000;
+    }
+    UBRRHI = (unsigned char)(baudrate>>8);
+    UBRR   = (unsigned char) baudrate;
+
+    /* Enable UART receiver and transmitter and receive complete interrupt */
+    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
+
+#endif
+
+}/* uart_init */
+
+
+/*************************************************************************
+Function: uart_getc()
+Purpose:  return byte from ringbuffer  
+Returns:  lower byte:  received byte from ringbuffer
+          higher byte: last receive error
+**************************************************************************/
+unsigned int uart_getc(void)
+{    
+    unsigned char tmptail;
+    unsigned char data;
+
+
+    if ( UART_RxHead == UART_RxTail ) {
+        return UART_NO_DATA;   /* no data available */
+    }
+    
+    /* calculate /store buffer index */
+    tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
+    UART_RxTail = tmptail; 
+    
+    /* get data from receive buffer */
+    data = UART_RxBuf[tmptail];
+    
+    return (UART_LastRxError << 8) + data;
+
+}/* uart_getc */
+
+
+/*************************************************************************
+Function: uart_putc()
+Purpose:  write byte to ringbuffer for transmitting via UART
+Input:    byte to be transmitted
+Returns:  none          
+**************************************************************************/
+void uart_putc(unsigned char data)
+{
+    unsigned char tmphead;
+
+    
+    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
+    
+    while ( tmphead == UART_TxTail ){
+        ;/* wait for free space in buffer */
+    }
+    
+    UART_TxBuf[tmphead] = data;
+    UART_TxHead = tmphead;
+
+    /* enable UDRE interrupt */
+    UART0_CONTROL    |= _BV(UART0_UDRIE);
+
+}/* uart_putc */
+
+
+/*************************************************************************
+Function: uart_puts()
+Purpose:  transmit string to UART
+Input:    string to be transmitted
+Returns:  none          
+**************************************************************************/
+void uart_puts(const char *s )
+{
+    while (*s) 
+      uart_putc(*s++);
+
+}/* uart_puts */
+
+
+/*************************************************************************
+Function: uart_puts_p()
+Purpose:  transmit string from program memory to UART
+Input:    program memory string to be transmitted
+Returns:  none
+**************************************************************************/
+void uart_puts_p(const char *progmem_s )
+{
+    register char c;
+    
+    while ( (c = pgm_read_byte(progmem_s++)) ) 
+      uart_putc(c);
+
+}/* uart_puts_p */
+
+
+/*
+ * these functions are only for ATmegas with two USART
+ */
+#if defined( ATMEGA_USART1 )
+
+SIGNAL(UART1_RECEIVE_INTERRUPT)
+/*************************************************************************
+Function: UART1 Receive Complete interrupt
+Purpose:  called when the UART1 has received a character
+**************************************************************************/
+{
+    unsigned char tmphead;
+    unsigned char data;
+    unsigned char usr;
+    unsigned char lastRxError;
+ 
+ 
+    /* read UART status register and UART data register */ 
+    usr  = UART1_STATUS;
+    data = UART1_DATA;
+
+    /* */
+    lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
+        
+    /* calculate buffer index */ 
+    tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
+    
+    if ( tmphead == UART1_RxTail ) {
+        /* error: receive buffer overflow */
+        lastRxError = UART_BUFFER_OVERFLOW >> 8;
+    }else{
+        /* store new index */
+        UART1_RxHead = tmphead;
+        /* store received data in buffer */
+        UART1_RxBuf[tmphead] = data;
+    }
+    UART1_LastRxError = lastRxError;   
+}
+
+
+SIGNAL(UART1_TRANSMIT_INTERRUPT)
+/*************************************************************************
+Function: UART1 Data Register Empty interrupt
+Purpose:  called when the UART1 is ready to transmit the next byte
+**************************************************************************/
+{
+    unsigned char tmptail;
+
+    
+    if ( UART1_TxHead != UART1_TxTail) {
+        /* calculate and store new buffer index */
+        tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
+        UART1_TxTail = tmptail;
+        /* get one byte from buffer and write it to UART */
+        UART1_DATA = UART1_TxBuf[tmptail];  /* start transmission */
+    }else{
+        /* tx buffer empty, disable UDRE interrupt */
+        UART1_CONTROL &= ~_BV(UART1_UDRIE);
+    }
+}
+
+
+/*************************************************************************
+Function: uart1_init()
+Purpose:  initialize UART1 and set baudrate
+Input:    baudrate using macro UART_BAUD_SELECT()
+Returns:  none
+**************************************************************************/
+void uart1_init(unsigned int baudrate)
+{
+    UART1_TxHead = 0;
+    UART1_TxTail = 0;
+    UART1_RxHead = 0;
+    UART1_RxTail = 0;
+    
+
+    /* Set baud rate */
+    if ( baudrate & 0x8000 ) 
+    {
+    	UART1_STATUS = (1<<U2X1);  //Enable 2x speed 
+      baudrate &= ~0x8000;
+    }
+    UBRR1H = (unsigned char)(baudrate>>8);
+    UBRR1L = (unsigned char) baudrate;
+
+    /* Enable USART receiver and transmitter and receive complete interrupt */
+    UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
+    
+    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */   
+    #ifdef URSEL1
+    UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
+    #else
+    UCSR1C = (3<<UCSZ10);
+    #endif 
+}/* uart_init */
+
+
+/*************************************************************************
+Function: uart1_getc()
+Purpose:  return byte from ringbuffer  
+Returns:  lower byte:  received byte from ringbuffer
+          higher byte: last receive error
+**************************************************************************/
+unsigned int uart1_getc(void)
+{    
+    unsigned char tmptail;
+    unsigned char data;
+
+
+    if ( UART1_RxHead == UART1_RxTail ) {
+        return UART_NO_DATA;   /* no data available */
+    }
+    
+    /* calculate /store buffer index */
+    tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
+    UART1_RxTail = tmptail; 
+    
+    /* get data from receive buffer */
+    data = UART1_RxBuf[tmptail];
+
+    return (UART1_LastRxError << 8) + data;
+
+}/* uart1_getc */
+
+
+/*************************************************************************
+Function: uart1_putc()
+Purpose:  write byte to ringbuffer for transmitting via UART
+Input:    byte to be transmitted
+Returns:  none          
+**************************************************************************/
+void uart1_putc(unsigned char data)
+{
+    unsigned char tmphead;
+
+    tmphead  = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
+    
+    while ( tmphead == UART1_TxTail ){
+        ;/* wait for free space in buffer */
+    }
+    
+    UART1_TxBuf[tmphead] = data;
+    UART1_TxHead = tmphead;
+
+    /* enable UDRE interrupt */
+    UART1_CONTROL    |= _BV(UART1_UDRIE);
+
+}/* uart1_putc */
+
+
+/*************************************************************************
+Function: uart1_puts()
+Purpose:  transmit string to UART1
+Input:    string to be transmitted
+Returns:  none          
+**************************************************************************/
+void uart1_puts(const char *s )
+{
+    while (*s) 
+      uart1_putc(*s++);
+
+}/* uart1_puts */
+
+
+/*************************************************************************
+Function: uart1_puts_p()
+Purpose:  transmit string from program memory to UART1
+Input:    program memory string to be transmitted
+Returns:  none
+**************************************************************************/
+void uart1_puts_p(const char *progmem_s )
+{
+    register char c;
+    
+    while ( (c = pgm_read_byte(progmem_s++)) ) 
+      uart1_putc(c);
+
+}/* uart1_puts_p */
+
+
+#endif
+#ifndef UART_H
+#define UART_H
+/************************************************************************
+Title:    Interrupt UART library with receive/transmit circular buffers
+Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
+File:     $Id: uart.h 0:acabf985a55f 2009-10-25 19:03 +0100 sven $
+Software: AVR-GCC 4.1, AVR Libc 1.4
+Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz
+License:  GNU General Public License 
+Usage:    see Doxygen manual
+
+LICENSE:
+    Copyright (C) 2006 Peter Fleury
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    
+************************************************************************/
+
+/** 
+ *  @defgroup pfleury_uart UART Library
+ *  @code #include <uart.h> @endcode
+ * 
+ *  @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. 
+ *
+ *  This library can be used to transmit and receive data through the built in UART. 
+ *
+ *  An interrupt is generated when the UART has finished transmitting or
+ *  receiving a byte. The interrupt handling routines use circular buffers
+ *  for buffering received and transmitted data.
+ *
+ *  The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define
+ *  the size of the circular buffers in bytes. Note that these constants must be a power of 2.
+ *  You may need to adapt this constants to your target and your application by adding 
+ *  CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile.
+ *
+ *  @note Based on Atmel Application Note AVR306
+ *  @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury
+ */
+ 
+/**@{*/
+
+
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
+#endif
+
+
+/*
+** constants and macros
+*/
+
+/** @brief  UART Baudrate Expression
+ *  @param  xtalcpu  system clock in Mhz, e.g. 4000000L for 4Mhz          
+ *  @param  baudrate baudrate in bps, e.g. 1200, 2400, 9600     
+ */
+#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)
+
+/** @brief  UART Baudrate Expression for ATmega double speed mode
+ *  @param  xtalcpu  system clock in Mhz, e.g. 4000000L for 4Mhz           
+ *  @param  baudrate baudrate in bps, e.g. 1200, 2400, 9600     
+ */
+#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)
+
+
+/** Size of the circular receive buffer, must be power of 2 */
+#ifndef UART_RX_BUFFER_SIZE
+#define UART_RX_BUFFER_SIZE 128
+#endif
+/** Size of the circular transmit buffer, must be power of 2 */
+#ifndef UART_TX_BUFFER_SIZE
+#define UART_TX_BUFFER_SIZE 128
+#endif
+
+/* test if the size of the circular buffers fits into SRAM */
+#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )
+#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
+#endif
+
+/* 
+** high byte error return code of uart_getc()
+*/
+#define UART_FRAME_ERROR      0x0800              /* Framing Error by UART       */
+#define UART_OVERRUN_ERROR    0x0400              /* Overrun condition by UART   */
+#define UART_BUFFER_OVERFLOW  0x0200              /* receive ringbuffer overflow */
+#define UART_NO_DATA          0x0100              /* no receive data available   */
+
+
+/*
+** function prototypes
+*/
+
+/**
+   @brief   Initialize UART and set baudrate 
+   @param   baudrate Specify baudrate using macro UART_BAUD_SELECT()
+   @return  none
+*/
+extern void uart_init(unsigned int baudrate);
+
+
+/**
+ *  @brief   Get received byte from ringbuffer
+ *
+ * Returns in the lower byte the received character and in the 
+ * higher byte the last receive error.
+ * UART_NO_DATA is returned when no data is available.
+ *
+ *  @param   void
+ *  @return  lower byte:  received byte from ringbuffer
+ *  @return  higher byte: last receive status
+ *           - \b 0 successfully received data from UART
+ *           - \b UART_NO_DATA           
+ *             <br>no receive data available
+ *           - \b UART_BUFFER_OVERFLOW   
+ *             <br>Receive ringbuffer overflow.
+ *             We are not reading the receive buffer fast enough, 
+ *             one or more received character have been dropped 
+ *           - \b UART_OVERRUN_ERROR     
+ *             <br>Overrun condition by UART.
+ *             A character already present in the UART UDR register was 
+ *             not read by the interrupt handler before the next character arrived,
+ *             one or more received characters have been dropped.
+ *           - \b UART_FRAME_ERROR       
+ *             <br>Framing Error by UART
+ */
+extern unsigned int uart_getc(void);
+
+
+/**
+ *  @brief   Put byte to ringbuffer for transmitting via UART
+ *  @param   data byte to be transmitted
+ *  @return  none
+ */
+extern void uart_putc(unsigned char data);
+
+
+/**
+ *  @brief   Put string to ringbuffer for transmitting via UART
+ *
+ *  The string is buffered by the uart library in a circular buffer
+ *  and one character at a time is transmitted to the UART using interrupts.
+ *  Blocks if it can not write the whole string into the circular buffer.
+ * 
+ *  @param   s string to be transmitted
+ *  @return  none
+ */
+extern void uart_puts(const char *s );
+
+
+/**
+ * @brief    Put string from program memory to ringbuffer for transmitting via UART.
+ *
+ * The string is buffered by the uart library in a circular buffer
+ * and one character at a time is transmitted to the UART using interrupts.
+ * Blocks if it can not write the whole string into the circular buffer.
+ *
+ * @param    s program memory string to be transmitted
+ * @return   none
+ * @see      uart_puts_P
+ */
+extern void uart_puts_p(const char *s );
+
+/**
+ * @brief    Macro to automatically put a string constant into program memory
+ */
+#define uart_puts_P(__s)       uart_puts_p(PSTR(__s))
+
+
+
+/** @brief  Initialize USART1 (only available on selected ATmegas) @see uart_init */
+extern void uart1_init(unsigned int baudrate);
+/** @brief  Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */
+extern unsigned int uart1_getc(void);
+/** @brief  Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */
+extern void uart1_putc(unsigned char data);
+/** @brief  Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */
+extern void uart1_puts(const char *s );
+/** @brief  Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */
+extern void uart1_puts_p(const char *s );
+/** @brief  Macro to automatically put a string constant into program memory */
+#define uart1_puts_P(__s)       uart1_puts_p(PSTR(__s))
+
+/**@}*/
+
+
+#endif // UART_H 
+
+/**
+  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
+  * @copyright   (c) 2009 Sven Hendriks
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+
+#include <stdint.h>
+#include "usb.h"
+#include <string.h>
+
+void (*sendByteUSB) (uint8_t);
+uint16_t (*readByteUSB) (void);
+
+uint8_t usb_init(void    (*sendByteFnctn) (uint8_t), 
+                 uint16_t (*readByteFnctn) (void)    ) {
+    sendByteUSB = sendByteFnctn;
+    readByteUSB = readByteFnctn;
+
+    // switch to short instruction
+    sendByteUSB('S');
+    sendByteUSB('C');
+    sendByteUSB('S');
+    sendByteUSB(0x0d);
+
+    if(waitForUSBModule() == 1) {
+        // timeout detected
+        return 1;
+    }
+
+    return 0;
+}
+
+uint8_t usb_switchBaudRate(void) {
+
+    sendByteUSB(0x14);
+    sendByteUSB(0x20);
+    sendByteUSB(0x9c);
+    sendByteUSB(0x80);
+    sendByteUSB(0x00);
+    sendByteUSB(0x0d);
+
+    if(waitForUSBModule() == 1) {
+        return 1;
+    }
+
+    return 0;
+}
+
+uint8_t usb_openFile(uint8_t filename[]) {
+    uint8_t i, len = strlen(filename);
+
+    sendByteUSB(0x09);
+    sendByteUSB(0x20);
+
+    for(i=0; i<len; i++) {
+        sendByteUSB(filename[i]);
+    }
+
+    sendByteUSB(0x0d);
+  
+    //if(waitForUSBModule() == 1) {
+    //    return 1;
+    //}
+
+    return 0;
+}
+
+uint8_t usb_closeFile(uint8_t filename[]) {
+    uint8_t i, len = strlen(filename);
+
+    sendByteUSB(0x0a);
+    sendByteUSB(0x20);
+
+    for(i=0; i<len; i++) {
+        sendByteUSB(filename[i]);
+    }
+
+    sendByteUSB(0x0d);
+
+    //if(waitForUSBModule() == 1) {
+    //    return 1;
+    //}
+  
+    return 0;
+}
+
+void usb_write(uint8_t data[], uint8_t len) {
+    uint8_t i;
+
+    // write to open file
+    sendByteUSB(0x08);
+    sendByteUSB(0x20);
+
+    sendByteUSB(0x00);
+    sendByteUSB(0x00);
+    sendByteUSB(0x00);
+    sendByteUSB(len);
+
+    // newline
+    sendByteUSB(0x0d);
+
+    // write data
+    for(i=0; i<len; i++) {
+        sendByteUSB(data[i]);
+    }
+}
+
+uint8_t waitForUSBModule(void) {
+   uint8_t c;
+   c = 0;
+   while((readByteUSB() & 0xff) != '>'  ) c++;
+   c = 0;
+   while((readByteUSB() & 0xff) != 0x0d ) c++;
+   return 0;
+}
+
+/**
+  * @author      $Author: Sven Hendriks <sven@loolog.org> $ (Sven Hendriks)
+  * @copyright   (c) 2009 Sven Hendriks
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  */
+
+#ifndef USB_H_INCLUDED
+#define USB_H_INCLUDED
+
+#include <stdint.h>
+
+uint8_t usb_init(void    (*sendByteFnctn) (uint8_t), 
+                 uint16_t (*readByteFnctn) (void)    );
+uint8_t usb_openFile(uint8_t filename[]);
+uint8_t usb_closeFile(uint8_t filename[]);
+void usb_write(uint8_t data[], uint8_t len);
+uint8_t waitForUSBModule(void);
+uint8_t usb_switchBaudRate(void);
+
+#endif
+