Index: branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.h
===================================================================
--- branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.h	(nonexistent)
+++ branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.h	(revision 626)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/** @file i2c.h
+ *  @brief Header file for I2C
+ *
+ *  Contains functions for I2C.
+ *
+ *  @author Kevin Woo and Suresh Nidhiry, Colony Project, CMU Robotics Club
+ **/
+
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+#include <stddef.h>
+
+/** @brief Address of slave receive handler function **/
+typedef void (*fun_srecv_t)(char);
+
+/** @brief Address of master receive handler function**/
+typedef int (*fun_mrecv_t)(char);
+
+/** @brief Address of slave send handler function**/
+typedef char (*fun_send_t)(void);
+
+int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send);
+int i2c_send(char dest, char* data, size_t bytes);
+int i2c_request(char dest);
+
+void i2c_packet_rec (char i2c_byte);
+void i2c_packet_sniff(char data);
+#endif
+
Index: branches/charge_station_isp/code/projects/i2c_plugnplay/main.c
===================================================================
--- branches/charge_station_isp/code/projects/i2c_plugnplay/main.c	(nonexistent)
+++ branches/charge_station_isp/code/projects/i2c_plugnplay/main.c	(revision 626)
@@ -0,0 +1,6 @@
+#include <dragonfly_lib.h>
+
+int main(void) {
+	dragonfly_init(ALL_ON);
+	return 0;
+}
Index: branches/charge_station_isp/code/projects/i2c_plugnplay/Makefile
===================================================================
--- branches/charge_station_isp/code/projects/i2c_plugnplay/Makefile	(nonexistent)
+++ branches/charge_station_isp/code/projects/i2c_plugnplay/Makefile	(revision 626)
@@ -0,0 +1,508 @@
+# Hey Emacs, this is a -*- makefile -*-
+#----------------------------------------------------------------------------
+# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
+#
+# Released to the Public Domain
+#
+# Additional material for this makefile was written by:
+# Peter Fleury
+# Tim Henigan
+# Colin O'Flynn
+# Reiner Patommel
+# Markus Pfaff
+# Sander Pool
+# Frederik Rouleau
+#
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF.
+#
+# make extcoff = Convert ELF to AVR Extended COFF.
+#
+# make program = Download the hex file to the device, using avrdude.
+#                Please customize the avrdude settings below first!
+#
+# make debug = Start either simulavr or avarice as specified for debugging, 
+#              with avr-gdb or avr-insight as the front end for debugging.
+#
+# make filename.s = Just compile filename.c into the assembler code only.
+#
+# make filename.i = Create a preprocessed source file for use in submitting
+#                   bug reports to the GCC project.
+#
+# To rebuild project do "make clean" then "make all".
+#----------------------------------------------------------------------------
+
+
+# MCU name
+MCU = atmega164p
+
+
+# Processor frequency.
+#     This will define a symbol, F_CPU, in all source code files equal to the 
+#     processor frequency. You can then use this symbol in your source code to 
+#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+#     automatically to create a 32-bit value in your source code.
+F_CPU = 5000000
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+
+# Target file name (without extension).
+TARGET = timerBlink
+
+
+# List C source files here. (C dependencies are automatically generated.)
+SRC = $(TARGET).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 dwarf-2 [default] or stabs.
+#     AVR Studio 4.10 requires dwarf-2.
+#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
+DEBUG = dwarf-2
+
+
+# List any extra directories to look for include files here.
+#     Each directory must be seperated by a space.
+#     Use forward slashes for directory separators.
+#     For a directory that has spaces, enclose it in quotes.
+#EXTRAINCDIRS = C:\WinAVR\include\fwr
+
+
+# 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=$(F_CPU)UL
+
+
+# Place -I options here
+CINCS =
+
+
+
+#---------------- Compiler Options ----------------
+#  -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)
+
+
+#---------------- Assembler Options ----------------
+#  -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 
+
+
+#---------------- Library Options ----------------
+# 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
+
+# If this is left blank, then it will use the Standard printf version.
+PRINTF_LIB = 
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
+
+
+# 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
+
+# If this is left blank, then it will use the Standard scanf version.
+SCANF_LIB = 
+#SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
+
+
+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 Options ----------------
+#  -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 Options (avrdude) ----------------
+
+# 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 = avrisp
+
+# com1 = serial port. Use lpt1 to connect to parallel port.
+AVRDUDE_PORT = com1
+# programmer connected to serial device
+
+AVRDUDE_WRITE_FLASH = -b 4800 -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)
+
+
+
+#---------------- Debugging Options ----------------
+
+# For simulavr only - target MCU frequency.
+DEBUG_MFREQ = $(F_CPU)
+
+# Set the DEBUG_UI to either gdb or insight.
+# DEBUG_UI = gdb
+DEBUG_UI = insight
+
+# Set the debugging back-end to either avarice, simulavr.
+DEBUG_BACKEND = avarice
+#DEBUG_BACKEND = simulavr
+
+# GDB Init Filename.
+GDBINIT_FILE = __avr_gdbinit
+
+# When using avarice settings for the JTAG
+JTAG_DEV = /dev/com1
+
+# Debugging port used to communicate between GDB / avarice / simulavr.
+DEBUG_PORT = 4242
+
+# Debugging host used to communicate between GDB / avarice / simulavr, normally
+#     just set to localhost unless doing some sort of crazy debugging when 
+#     avarice is running on a different computer.
+DEBUG_HOST = localhost
+
+
+
+#============================================================================
+
+
+# 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
+WINSHELL = cmd
+
+
+# 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 = $(SRC:.c=.lst) $(ASRC:.S=.lst) 
+
+
+# Compiler flags to generate dependency files.
+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 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)
+
+end:
+	@echo $(MSG_END)
+	@echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
+
+sizebefore:
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
+	$(AVRMEM) 2>/dev/null; echo; fi
+
+sizeafter:
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
+	$(AVRMEM) 2>/dev/null; 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)
+
+
+# Generate avr-gdb config/init file which does the following:
+#     define the reset signal, load the target file, connect to target, and set 
+#     a breakpoint at main().
+gdb-config: 
+	@$(REMOVE) $(GDBINIT_FILE)
+	@echo define reset >> $(GDBINIT_FILE)
+	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
+	@echo end >> $(GDBINIT_FILE)
+	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
+	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
+ifeq ($(DEBUG_BACKEND),simulavr)
+	@echo load  >> $(GDBINIT_FILE)
+endif	
+	@echo break main >> $(GDBINIT_FILE)
+	
+debug: gdb-config $(TARGET).elf
+ifeq ($(DEBUG_BACKEND), avarice)
+	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
+	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
+	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
+	@$(WINSHELL) /c pause
+	
+else
+	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
+	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
+endif
+	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
+	
+
+
+
+# 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) $^ --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 $@
+
+# Create preprocessed source for use in sending a bug report.
+%.i : %.c
+	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
+
+
+# Target: clean project.
+clean: begin clean_list end
+
+clean_list :
+	@echo
+	@echo $(MSG_CLEANING)
+	$(REMOVE) $(TARGET).hex
+	$(REMOVE) $(TARGET).eep
+	$(REMOVE) $(TARGET).cof
+	$(REMOVE) $(TARGET).elf
+	$(REMOVE) $(TARGET).map
+	$(REMOVE) $(TARGET).sym
+	$(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 debug gdb-config
+
Index: branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.c
===================================================================
--- branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.c	(nonexistent)
+++ branches/charge_station_isp/code/projects/i2c_plugnplay/i2c.c	(revision 626)
@@ -0,0 +1,345 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file i2c.c
+ * @brief Implemenation of I2C communications protocol
+ * 
+ * In the case where you have master sends and then a master request to the same
+ * address, you will not give up control of the line because the send and
+ * request addresses are seen as different addresses. In between it will send a
+ * restart but will not give up the line.
+ *
+ * @author CMU Robotics Club, Kevin Woo, Sursh Nidhiry
+ * @bug Not tested.
+ */
+
+#include <avr/interrupt.h>
+#include <util/twi.h>
+
+#include "i2c.h"
+#include "ring_buffer.h"
+
+/**
+ * @defgroup i2c I2C 
+ *
+ * @brief Provides Inter-Interconnected-Communications (I2C)
+ * 
+ * Initiates I2C functions on an ATMega128 which has a fully hardware Two Wire 
+ * Interface (TWI) module. Any Atmel chip with this hardware should be able to
+ * use the software.
+ *
+ * This code will operate in a multi-master enviornment and can be either a
+ * slave or a master at any time (as long as they are not one or the other at
+ * the moment. You can queue up multiple transmission modes in the buffer up to 
+ * the buffer size. The buffer is implemented as a ring buffer.
+ *
+ * It is implemented using callback functions. Whenever you want to send a packet
+ * you can call the built in send function (as a master) and it will send an array
+ * of bytes. Master recieve and slave send/receive are all handled by the call back
+ * functions. It is up to the end user to create functions that will handle the
+ * receiving of packets. Their functions will be called with every byte recieved
+ * so you must either buffer the inputs or handle each one separately.
+ *
+ * On errors we will simply flush the entire buffer.
+ * 
+ * For information on how I2C operates, read the wikipedia article
+ * http://en.wikipedia.org/wiki/I2c
+ * for a good explanation of how it works.
+ * @{
+ */
+
+/** 
+ * @brief Set bit rate 12 = 100kbit/s (max speed setting is 10 for an
+ *  8 MHz clock). It is a divider, so the lower the number the faster the speed.
+ */
+#define I2C_BIT_RATE_DIVIDER 0x0C
+
+static int start_flag;
+
+static fun_mrecv_t master_recv_function;
+static fun_srecv_t slave_recv_function;
+static fun_send_t slave_send_function;
+
+RING_BUFFER_NEW(i2c_buffer, 128, char, i2c_write_buff, i2c_addr_buff);
+
+
+/**
+ * @brief Initializes the i2c module.
+ *
+ * Initializes the I2C module to start listening on the i2c lines. If the callback functions
+ * are not set to null they will be called when that transmission mode is called. The address
+ * is your address that you will listen to when you are not the master.
+ *
+ * @param addr 			Your address on the I2C bus.
+ * @param master_recv 	The address of the function to call when you receive a byte when you are a
+ *                    	master.
+ * @param slave_recv 	The address of the function to call when you are a slave you receive data
+ *								from the master
+ * @param slave_send		The address of the function to call when you are a slave and the master
+ *								requests data from you.
+ *
+ * @return 0 for success, nonzero for failure
+ **/
+int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) {
+    master_recv_function = master_recv;
+    slave_recv_function = slave_recv;
+    slave_send_function = slave_send;
+
+    RING_BUFFER_CLEAR(i2c_write_buff);
+    RING_BUFFER_CLEAR(i2c_addr_buff);
+  
+    /* enables twi interrupt, automatic ack sending, and all twi hardware */
+    TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
+
+    /* sets the bit rate of data transmission */
+    TWBR = I2C_BIT_RATE_DIVIDER;
+
+    /* sets the address (it is stored in the 7 most significant bits) and allows
+     * global messages to be accepted */
+    TWAR = (addr << 1) | 1;
+  
+    return 0;
+}
+
+/**
+ * @brief Sends a byte array over I2C as a master
+ *
+ * Will perform a send over I2C to the destination from data for the ammount of
+ * bytes that bytes is.
+ *
+ * @param dest		Destination address of the data on the I2C bus.
+ * @param data 	The pointer to the byte array of data
+ * @param bytes	The amount of bytes long that the byte array is. This is how
+ *						many bytes from the array that the function will send.
+ *
+ * @return zero for success, nonzero for failure
+ **/
+int i2c_send(char dest, char *data, size_t bytes) {
+    int i;
+
+    /* adding data to be sent to ring buffers is not atomic,
+     * so disable interrupts */
+    cli();
+    for(i = 0; i < bytes; i++) {
+        if(RING_BUFFER_FULL(i2c_write_buff)) {
+            sei();
+            return -1;
+        }
+
+        RING_BUFFER_ADD(i2c_write_buff, data[i]);
+        RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
+    }
+    
+    /* re-enable the interrupts */
+    sei();
+    
+    /* send the start bit, only if this device is not currently master */
+    if(!start_flag) {
+        start_flag = 1;
+        TWCR |= _BV(TWSTA);
+        TWCR |= _BV(TWINT);
+    }
+  
+    return 0;
+}
+ 
+/**
+ * @brief Send a master request to the destination
+ *
+ * Sends a request of data from the target address and calls
+ * the callback function to handle data as it comes in. This function will
+ * not work if the slave has not informationt to send or has nothing implemented
+ * to send it.
+ *
+ * @param dest		The destination that we want to receive information from.
+ *
+ * @return 0 for success, nonzero for failure
+ **/ 
+int i2c_request(char dest) {
+    if(RING_BUFFER_FULL(i2c_write_buff))
+        return -1;
+  
+    RING_BUFFER_ADD(i2c_write_buff, 0);
+    RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
+  
+    if(!start_flag) {
+        start_flag = 1;
+        TWCR |= _BV(TWSTA);
+        TWCR |= _BV(TWINT);
+    }
+  
+    return 0;
+}
+
+/** @} **/
+ 
+/**
+ * @brief Interrupt to handle I2C interrupts from the I2C hardware.
+ * 
+ * Uses the status codes from the I2C register to handle the events
+ * needed to advance in I2C stages. For instance, you will get a bit for
+ * receiving a start ack, then a address ack, then a data ack, etc.
+ * The events are handled in each switch case. The status codes are defined
+ * by avr-gcc in /util/twi.h but are the same codes as the Atmel documentation.
+ *
+ * Bytes are sent by popping off the ring buffer. It also will keep track
+ * of what modes the send is in.
+ *
+ * Errors are handled here as well.
+ **/ 
+ISR(TWI_vect) {
+	static char data_to_send;
+	static char addr_to_send = -1;
+	char addr, statusCode;
+  
+	//Get status code (only upper 5 bits)
+	statusCode = (TWSR & 0xF8);
+
+    switch (statusCode) {
+        //Start sent successfully
+        case TW_START:
+        case TW_REP_START:
+            /* Send address and write
+             * ring_buffer will not be empty */
+            RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
+            RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
+            
+            /* first send the address */
+            TWDR = addr_to_send; 
+            
+            //Turn off start bits
+            TWCR &= ~_BV(TWSTA);
+            break;
+
+        //Master Transmit - Address sent succesfully
+        case TW_MT_SLA_ACK:
+        //Send byte
+            TWDR = data_to_send;
+            PORTG &= ~_BV(PG2);
+            break;
+	 
+        //Master Transmit - Data sent succesfully
+        case TW_MT_DATA_ACK:    
+            //If there is still data to send
+            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
+                RING_BUFFER_PEEK(i2c_addr_buff, addr);
+        
+                //Still data for this address
+                if (addr == addr_to_send) {
+                    RING_BUFFER_REMOVE(i2c_addr_buff, addr);
+                    RING_BUFFER_REMOVE(i2c_write_buff, TWDR);
+                    break;
+                //No more data for this address, data for another address -> resend start
+                } else {
+                    TWCR |= _BV(TWSTA);
+                    break;
+                }
+            }
+            /* there are no bytes to send */
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            break; 
+            
+        //Master Transmit - Slave sends a nack, transmit is done
+        case TW_MT_DATA_NACK:
+            PORTG |= _BV(PG2);
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            break;
+    
+        //Master Receive - Address sent succesfully
+        case TW_MR_SLA_ACK:
+            PORTG |= _BV(PG2);
+            break;
+            
+        //Master Receive - Data received succesfully
+        case TW_MR_DATA_ACK:
+            if(master_recv_function) {
+                if(!master_recv_function(TWDR)) {
+                    TWCR &= ~_BV(TWEA);
+                }
+            }
+            break;
+            
+        //Master Receive - Slave sends a nack, transmission is done    
+        case TW_MR_DATA_NACK:
+            TWCR |= _BV(TWEA);
+      
+            //If there is still data to send
+            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
+                TWCR |= _BV(TWSTA);
+                break;
+            }
+      
+            /* there are no bytes to send */
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;  
+            break;
+    
+        //Slave Transmit - Address received
+        case TW_ST_SLA_ACK:
+            break;
+    
+        //Slave Transmit - Nack received, no data requsted
+        case TW_ST_DATA_NACK:
+            break;
+        
+        //Slave Transmit - Data requested, ack received
+        case TW_ST_DATA_ACK:
+            if (slave_send_function) {
+                TWDR = slave_send_function();
+            }
+            break;
+    
+        //Slave Receive - Address received  
+        case TW_SR_SLA_ACK:
+            break;
+    
+        //Slave Receive - Data received, ack returned
+        case TW_SR_DATA_ACK:
+            if(slave_recv_function) {
+                slave_recv_function(TWDR);
+            }
+            
+            break;
+      
+        //Stop sent  
+        case TW_SR_STOP:
+            break;
+	
+        //Problem on the bus, reset everything
+        default:
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            RING_BUFFER_CLEAR(i2c_write_buff);
+            RING_BUFFER_CLEAR(i2c_addr_buff);  	
+    }
+  
+  /* Toggle TWINT so that it resets and executes the commands */
+  TWCR |= _BV(TWINT);
+}
+
