Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/main.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/main.c	(revision 354)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/main.c	(revision 355)
@@ -2,6 +2,7 @@
 #include <i2c.h>
 
 void recv(char i2c_byte){
+	usb_puts("ab");
 	usb_putc(i2c_byte);
 	}
 
@@ -14,4 +15,3 @@
 	
 	while(1);
 }
-	
\ No newline at end of file
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/Makefile
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/Makefile	(revision 354)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Robot Debug/Makefile	(revision 355)
@@ -17,7 +17,7 @@
  USE_WIRELESS = 1
 
 # com1 = serial port. Use lpt1 to connect to parallel port.
-AVRDUDE_PORT = com4 #/dev/ttyUSB1
+AVRDUDE_PORT = com2 #/dev/ttyUSB1
 #
 #
 ###################################
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/ConstantCharging.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/ConstantCharging.c	(revision 354)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/ConstantCharging.c	(revision 355)
@@ -1,8 +1,9 @@
 #include <avr/io.h>
+#include <avr/io.h>
 #include <avr/interrupt.h>
 #include <avr/sleep.h>
+#include "ring_buffer.h"
 #include "i2c.h"
-#include "ring_buffer.h"
 
 
 // for i2c_byte coming from charge board
@@ -22,8 +23,10 @@
 #define SW0 PA6
 #define HOMING_PIN PA7
 
-//#define DEBUG 1
+#define DEBUG 0
+#define USE_I2C 1
 
+
 #define MAX_T 300
 #define MIN_T 730
 //range is 0 to 45 C
@@ -244,10 +247,13 @@
 
 void send_done(void)
 {
+
+#if use_I2C
 	char tempData;
 	//Finished, leave
 	tempData = 'F';
 	i2c_putpacket(0x01, &tempData, 1);
+#endif
 	
 	PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); 
 	
@@ -256,7 +262,7 @@
 void setup(void)
 {
       DDRA = _BV(PA3);
-#ifdef debug
+#if DEBUG
 	//DDRA = (_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in));
 #endif
 	PORTA = 0x00;
@@ -432,20 +438,22 @@
 			{
 				PORTB |= _BV(LED1);
 				//curr = regulate_current(500);
-				//+++curr = get_avg_current();
+				curr = get_avg_current();
 				
 				if(status==0)
 				{
 					status=1;
+#if use_I2C
 					data[1]='a';
 					i2c_putpacket(0x01, data, 2);
 					data[1]=I2C_MSG_BATTERY_CHARGING;
 					i2c_putpacket(0x01, data, 2);
+#endif
 				}
 				
         /* Trickle Charge */
 				if(status==1)
-					OCR1B = 200;
+					OCR1B = 128;
 			}
       /* NO CONTACT */
 			else
@@ -454,8 +462,10 @@
 				if(status==1)
 				{
 					status=0;
+#if use_I2C
 					data[1]=I2C_MSG_CONTACT_ERROR;
 					i2c_putpacket(0x01, data, 2);
+#endif
 				}
 				else
 				{
@@ -529,10 +539,10 @@
 
 		temp=6666;
 	}
-	
+#if use_I2C
 	data[1]=I2C_MSG_BATTERY_FULL;
 	i2c_putpacket(0x01, data, 2);
-
+#endif
 }
 
 int main(void)
@@ -541,7 +551,11 @@
 	char tempData[5];	//For i2c communication
   
 	setup();
+
+#if use_I2C
 	i2c_init();
+	i2c_putpacket(0x01,"I2C init'd on ARCHS\r\n", 21);
+#endif
 	
 	
 	/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts
@@ -715,9 +729,9 @@
 
 ISR(TIMER1_OVF_vect)
 {
-	wait(5); //wait a bit so we know the ouput gets set (which happens at timer = 0)
+	wait(2); //wait a bit so we know the ouput gets set (which happens at timer = 0)
 	
-	TCNT1 = 156; // start out at 156. Now OCR1B - 156 = duty cycle
+	TCNT1 = 0;//156; // start out at 156. Now OCR1B - 156 = duty cycle
 }
 
 ISR(PCINT_vect){;} //so the interrupt doesnt go to the reset vector
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.c	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.c	(revision 355)
@@ -0,0 +1,253 @@
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File              : USI_TWI_Master.c
+* Compiler          : IAR EWAAVR 2.28a/3.10a
+* Revision          : $Revision: 1.11 $
+* Date              : $Date: Tuesday, September 13, 2005 09:09:36 UTC $
+* Updated by        : $Author: jtyssoe $
+*
+* Support mail      : avr@atmel.com
+*
+* Supported devices : All device with USI module can be used.
+*                     The example is written for the ATmega169, ATtiny26 and ATtiny2313
+*
+* AppNote           : AVR310 - Using the USI module as a TWI Master
+*
+* Description       : This is an implementation of an TWI master using
+*                     the USI module as basis. The implementation assumes the AVR to
+*                     be the only TWI master in the system and can therefore not be
+*                     used in a multi-master system.
+* Usage             : Initialize the USI module by calling the USI_TWI_Master_Initialise() 
+*                     function. Hence messages/data are transceived on the bus using
+*                     the USI_TWI_Transceive() function. The transceive function 
+*                     returns a status byte, which can be used to evaluate the 
+*                     success of the transmission.
+*
+****************************************************************************/
+#ifndef _USI_TWI_MASTER_H
+#define _USI_TWI_MASTER_H
+
+#include <util/delay.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "USI_TWI_Master.h"
+
+unsigned char USI_TWI_Master_Transfer( unsigned char );
+unsigned char USI_TWI_Master_Stop( void );
+
+union  USI_TWI_state
+{
+  unsigned char errorState;         // Can reuse the TWI_state for error states due to that it will not be need if there exists an error.
+  struct
+  {
+    unsigned char addressMode         : 1;
+    unsigned char masterWriteDataMode : 1;
+    unsigned char unused              : 6;
+  }; 
+}   USI_TWI_state;
+
+/*---------------------------------------------------------------
+ USI TWI single master initialization function
+---------------------------------------------------------------*/
+void USI_TWI_Master_Initialise( void )
+{
+  PORT_USI |= (1<<PIN_USI_SDA);           // Enable pullup on SDA, to set high as released state.
+  PORT_USI |= (1<<PIN_USI_SCL);           // Enable pullup on SCL, to set high as released state.
+  
+  DDR_USI  |= (1<<PIN_USI_SCL);           // Enable SCL as output.
+  DDR_USI  |= (1<<PIN_USI_SDA);           // Enable SDA as output.
+  
+  USIDR    =  0xFF;                       // Preload dataregister with "released level" data.
+  USICR    =  (0<<USISIE)|(0<<USIOIE)|                            // Disable Interrupts.
+              (1<<USIWM1)|(0<<USIWM0)|                            // Set USI in Two-wire mode.
+              (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|                // Software stobe as counter clock source
+              (0<<USITC);
+  USISR   =   (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Clear flags,
+              (0x0<<USICNT0);                                     // and reset counter.
+}
+
+/*---------------------------------------------------------------
+Use this function to get hold of the error message from the last transmission
+---------------------------------------------------------------*/
+unsigned char USI_TWI_Get_State_Info( void )
+{
+  return ( USI_TWI_state.errorState );                            // Return error state.
+}
+
+/*---------------------------------------------------------------
+ USI Transmit and receive function. LSB of first byte in data 
+ indicates if a read or write cycles is performed. If set a read
+ operation is performed.
+
+ Function generates (Repeated) Start Condition, sends address and
+ R/W, Reads/Writes Data, and verifies/sends ACK.
+ 
+ Success or error code is returned. Error codes are defined in 
+ USI_TWI_Master.h
+---------------------------------------------------------------*/
+unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize)
+{
+  unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
+                                 (0x0<<USICNT0);                                     // set USI to shift 8 bits i.e. count 16 clock edges.
+  unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
+                                 (0xE<<USICNT0);                                     // set USI to shift 1 bit i.e. count 2 clock edges.
+
+  USI_TWI_state.errorState = 0;
+  USI_TWI_state.addressMode = TRUE;
+
+
+
+  if ( !(*msg & (1<<TWI_READ_BIT)) )                // The LSB in the address byte determines if is a masterRead or masterWrite operation.
+  {
+    USI_TWI_state.masterWriteDataMode = TRUE;
+  }
+
+/* Release SCL to ensure that (repeated) Start can be performed */
+  PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
+  while( !(PORT_USI & (1<<PIN_USI_SCL)) );          // Verify that SCL becomes high.
+
+  _delay_loop_1(T2_TWI);
+  //_delay_us(T4_TWI);
+  //__delay_cycles( T2_TWI );                         // Delay for T2TWI if TWI_STANDARD_MODE
+
+
+/* Generate Start Condition */
+  PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
+  _delay_loop_1(T4_TWI);
+  //_delay_us(T4_TWI);
+  //__delay_cycles( T4_TWI );                         
+  PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.
+  PORT_USI |= (1<<PIN_USI_SDA);                     // Release SDA.
+
+//Start
+PORTA |= _BV(PA3);
+
+
+/*Write address and Read/Write data */
+  do
+  {
+    /* If masterWrite cycle (or inital address tranmission)*/
+    if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)
+    {
+       PORTA |= _BV(PA4);
+      /* Write a byte */
+      PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
+      USIDR     = *(msg++);                        // Setup data.
+      USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
+      
+      /* Clock and verify (N)ACK from slave */
+      DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
+      
+      PORTA |= _BV(PA5);
+      
+      if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) 
+      {
+        //Shit
+        PORTA |= _BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6) | _BV(PA7);
+        
+        if ( USI_TWI_state.addressMode )
+          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
+        else
+          USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
+        return (FALSE);
+      }
+      USI_TWI_state.addressMode = FALSE;            // Only perform address transmission once.
+      
+      
+      PORTA &= (~_BV(PA4) | ~_BV(PA5));
+    }
+    /* Else masterRead cycle*/
+    else
+    {
+      /* Read a data byte */
+      DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as input.
+      *(msg++)  = USI_TWI_Master_Transfer( tempUSISR_8bit );
+
+      /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
+      if( msgSize == 1)                            // If transmission of last byte was performed.
+      {
+        USIDR = 0xFF;                              // Load NACK to confirm End Of Transmission.
+      }
+      else
+      {
+        USIDR = 0x00;                              // Load ACK. Set data register bit 7 (output for SDA) low.
+      }
+      USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate ACK/NACK.
+    }
+  }while( --msgSize) ;                             // Until all data sent/received.
+  
+  
+  PORTA |= _BV(PA6);
+  
+  USI_TWI_Master_Stop();                           // Send a STOP condition on the TWI bus.
+
+/* Transmission successfully completed*/
+  return (TRUE);
+}
+
+/*---------------------------------------------------------------
+ Core function for shifting data in and out from the USI.
+ Data to be sent has to be placed into the USIDR prior to calling
+ this function. Data read, will be return'ed from the function.
+---------------------------------------------------------------*/
+unsigned char USI_TWI_Master_Transfer( unsigned char temp )
+{
+  USISR = temp;                                     // Set USISR according to temp.
+                                                    // Prepare clocking.
+  temp  =  (0<<USISIE)|(0<<USIOIE)|                 // Interrupts disabled
+           (1<<USIWM1)|(0<<USIWM0)|                 // Set USI in Two-wire mode.
+           (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|     // Software clock strobe as source.
+           (1<<USITC);                              // Toggle Clock Port.
+  do
+  {
+    //__delay_cycles( T2_TWI );              
+    _delay_loop_1(T2_TWI);
+    //_delay_us(T2_TWI);
+    USICR = temp;                          // Generate positve SCL edge.
+    while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
+    _delay_loop_1(T4_TWI);
+    //__delay_cycles( T4_TWI );              
+   // _delay_us(T4_TWI);
+    USICR = temp;                          // Generate negative SCL edge.
+  }while( !(USISR & (1<<USIOIF)) );        // Check for transfer complete.
+  _delay_loop_1(T2_TWI);
+  //_delay_us(T2_TWI);
+  //__delay_cycles( T2_TWI );                
+  temp  = USIDR;                           // Read out data.
+  USIDR = 0xFF;                            // Release SDA.
+  DDR_USI |= (1<<PIN_USI_SDA);             // Enable SDA as output.
+
+  return temp;                             // Return the data from the USIDR
+}
+
+/*---------------------------------------------------------------
+ Function for generating a TWI Stop Condition. Used to release 
+ the TWI bus.
+---------------------------------------------------------------*/
+unsigned char USI_TWI_Master_Stop( void )
+{
+  PORT_USI &= ~(1<<PIN_USI_SDA);           // Pull SDA low.
+  PORT_USI |= (1<<PIN_USI_SCL);            // Release SCL.
+  while( !(PIN_USI & (1<<PIN_USI_SCL)) );  // Wait for SCL to go high.
+  _delay_loop_1(T4_TWI);
+  //_delay_us(T4_TWI);
+  //__delay_cycles( T4_TWI );               
+  PORT_USI |= (1<<PIN_USI_SDA);            // Release SDA.
+  _delay_loop_1(T2_TWI);
+  //_delay_us(T2_TWI);
+  //__delay_cycles( T2_TWI );                
+  
+#ifdef SIGNAL_VERIFY
+  if( !(USISR & (1<<USIPF)) )
+  {
+    USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON;    
+    return (FALSE);
+  }
+#endif
+
+  return (TRUE);
+}
+
+#endif
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.h
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.h	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.h	(revision 355)
@@ -0,0 +1,120 @@
+// This file has been prepared for Doxygen automatic documentation generation.
+/*! \file ********************************************************************
+*
+* Atmel Corporation
+*
+* File              : USI_TWI_Slave.h
+* Compiler          : IAR EWAAVR 4.11A
+* Revision          : $Revision: 1.14 $
+* Date              : $Date: Friday, December 09, 2005 17:25:38 UTC $
+* Updated by        : $Author: jtyssoe $
+*
+* Support mail      : avr@atmel.com
+*
+* Supported devices : All device with USI module can be used.
+*                     The example is written for the ATmega169, ATtiny26 & ATtiny2313
+*
+* AppNote           : AVR312 - Using the USI module as a TWI slave
+*
+* Description       : Header file for USI_TWI driver
+*
+*
+*
+****************************************************************************/
+
+
+
+//! Prototypes
+void          USI_TWI_Slave_Initialise( unsigned char );
+void          USI_TWI_Transmit_Byte( unsigned char );
+unsigned char USI_TWI_Receive_Byte( void );
+unsigned char USI_TWI_Data_In_Receive_Buffer( void );
+void          Timer_Init(void);
+
+#define TRUE                1
+#define FALSE               0
+
+typedef     unsigned char       uint8_t;
+
+//////////////////////////////////////////////////////////////////
+///////////////// Driver Buffer Definitions //////////////////////
+//////////////////////////////////////////////////////////////////
+// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes
+
+#define TWI_RX_BUFFER_SIZE  (16)
+#define TWI_RX_BUFFER_MASK ( TWI_RX_BUFFER_SIZE - 1 )
+
+#if ( TWI_RX_BUFFER_SIZE & TWI_RX_BUFFER_MASK )
+        #error TWI RX buffer size is not a power of 2
+#endif
+
+// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes
+
+#define TWI_TX_BUFFER_SIZE  (16)
+#define TWI_TX_BUFFER_MASK ( TWI_TX_BUFFER_SIZE - 1 )
+
+#if ( TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK )
+        #error TWI TX buffer size is not a power of 2
+#endif
+
+
+
+#define USI_SLAVE_CHECK_ADDRESS                (0x00)
+#define USI_SLAVE_SEND_DATA                    (0x01)
+#define USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA (0x02)
+#define USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA   (0x03)
+#define USI_SLAVE_REQUEST_DATA                 (0x04)
+#define USI_SLAVE_GET_DATA_AND_SEND_ACK        (0x05)
+
+#define DDR_USI             DDRB
+#define PORT_USI            PORTB
+#define PIN_USI             PINB
+#define PORT_USI_SDA        PORTB0
+#define PORT_USI_SCL        PORTB2
+#define PIN_USI_SDA         PINB0
+#define PIN_USI_SCL         PINB2
+#define USI_START_COND_INT  USISIF
+#define USI_START_VECTOR    USI_START_vect
+#define USI_OVERFLOW_VECTOR USI_OVF_vect
+
+
+//! Functions implemented as macros
+#define SET_USI_TO_SEND_ACK()                                                                                 \
+{                                                                                                             \
+        USIDR    =  0;                                              /* Prepare ACK                         */ \
+        DDR_USI |=  (1<<PORT_USI_SDA);                              /* Set SDA as output                   */ \
+        USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|  /* Clear all flags, except Start Cond  */ \
+                    (0x0E<<USICNT0);                                /* set USI counter to shift 1 bit. */ \
+}
+
+#define SET_USI_TO_READ_ACK()                                                                                 \
+{                                                                                                             \
+        DDR_USI &=  ~(1<<PORT_USI_SDA);                             /* Set SDA as intput */                   \
+        USIDR    =  0;                                              /* Prepare ACK        */                  \
+        USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|  /* Clear all flags, except Start Cond  */ \
+                    (0x0E<<USICNT0);                                /* set USI counter to shift 1 bit. */ \
+}
+
+#define SET_USI_TO_TWI_START_CONDITION_MODE()                                                                                     \
+{                                                                                                                                 \
+  USICR    =  (1<<USISIE)|(0<<USIOIE)|                        /* Enable Start Condition Interrupt. Disable Overflow Interrupt.*/  \
+              (1<<USIWM1)|(0<<USIWM0)|                        /* Set USI in Two-wire mode. No USI Counter overflow hold.      */  \
+              (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|            /* Shift Register Clock Source = External, positive edge        */  \
+              (0<<USITC);                                                                                                         \
+  USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|  /* Clear all flags, except Start Cond                            */ \
+              (0x0<<USICNT0);                                                                                                     \
+}
+
+#define SET_USI_TO_SEND_DATA()                                                                               \
+{                                                                                                            \
+    DDR_USI |=  (1<<PORT_USI_SDA);                                  /* Set SDA as output                  */ \
+    USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      /* Clear all flags, except Start Cond */ \
+                (0x0<<USICNT0);                                     /* set USI to shift out 8 bits        */ \
+}
+
+#define SET_USI_TO_READ_DATA()                                                                               \
+{                                                                                                            \
+    DDR_USI &= ~(1<<PORT_USI_SDA);                                  /* Set SDA as input                   */ \
+    USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      /* Clear all flags, except Start Cond */ \
+                (0x0<<USICNT0);                                     /* set USI to shift out 8 bits        */ \
+}
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.h
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.h	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.h	(revision 355)
@@ -0,0 +1,22 @@
+/* i2c.h
+    
+        constants and stuff
+*/
+#ifndef _I2C_H_
+#define _I2C_H_
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+
+#include "USI_TWI_Master.c"
+#include "USI_TWI_Slave.c" 
+#include "i2c.c"
+
+void i2c_init(void);
+void i2c_putpacket(char addr, char *data, char data_size);
+int i2c_getpacket(char *c);
+void i2c_test(void);
+void delay_ms(int ms);
+
+#endif
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.h
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.h	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Master.h	(revision 355)
@@ -0,0 +1,95 @@
+
+
+
+/*****************************************************************************
+*
+* Atmel Corporation
+*
+* File              : USI_TWI_Master.h
+* Compiler          : IAR EWAAVR 2.28a/3.10a
+* Revision          : $Revision: 1.11 $
+* Date              : $Date: Tuesday, September 13, 2005 09:09:36 UTC $
+* Updated by        : $Author: jtyssoe $
+*
+* Support mail      : avr@atmel.com
+*
+* Supported devices : All device with USI module can be used.
+*                     The example is written for the ATmega169, ATtiny26 and ATtiny2313
+*
+* AppNote           : AVR310 - Using the USI module as a TWI Master
+*
+* Description       : This is an implementation of an TWI master using
+*                     the USI module as basis. The implementation assumes the AVR to
+*                     be the only TWI master in the system and can therefore not be
+*                     used in a multi-master system.
+* Usage             : Initialize the USI module by calling the USI_TWI_Master_Initialise() 
+*                     function. Hence messages/data are transceived on the bus using
+*                     the USI_TWI_Start_Transceiver_With_Data() function. If the transceiver
+*                     returns with a fail, then use USI_TWI_Get_Status_Info to evaluate the 
+*                     couse of the failure.
+*
+****************************************************************************/
+    
+//********** Defines **********//
+
+// Defines controlling timing limits
+//#define TWI_FAST_MODE
+
+//#define SYS_CLK   4000.0  // [kHz]
+
+//Note, this is only a variable that determines how long to delay between
+// individual bits of I2C send. This has been tested down to 1MHz and it works.
+// It is possible that even slower speeds can be obtained.
+#define SYS_CLK     1.0 // [mHz]
+
+// TWI FAST mode timing limits. SCL = 100-400kHz
+//#define T2_TWI    ((SYS_CLK *1300) /1000000) +1 // >1,3us
+//#define T4_TWI    ((SYS_CLK * 600) /1000000) +1 // >0,6us
+ 
+ 
+//This may or may not make it faster. Uncomfirmed. But it works. 
+#define T2_TWI 0.000001
+#define T4_TWI 0.000001
+ 
+// TWI STANDARD mode timing limits. SCL <= 100kHz
+//#define T2_TWI    ((SYS_CLK *4700) /1000000) +1 // >4,7us
+//#define T4_TWI    ((SYS_CLK *4000) /1000000) +1 // >4,0us
+
+//USI_TWI messages and flags and bit masks
+//#define SUCCESS   7
+//#define MSG       0
+/****************************************************************************
+  Bit and byte definitions
+****************************************************************************/
+#define TWI_READ_BIT  0       // Bit position for R/W bit in "address byte".
+#define TWI_ADR_BITS  1       // Bit position for LSB of the slave address bits in the init byte.
+#define TWI_NACK_BIT  0       // Bit position for (N)ACK bit.
+
+#define USI_TWI_NO_DATA             0x00  // Transmission buffer is empty
+#define USI_TWI_DATA_OUT_OF_BOUND   0x01  // Transmission buffer is outside SRAM space
+#define USI_TWI_UE_START_CON        0x02  // Unexpected Start Condition
+#define USI_TWI_UE_STOP_CON         0x03  // Unexpected Stop Condition
+#define USI_TWI_UE_DATA_COL         0x04  // Unexpected Data Collision (arbitration)
+#define USI_TWI_NO_ACK_ON_DATA      0x05  // The slave did not acknowledge  all data
+#define USI_TWI_NO_ACK_ON_ADDRESS   0x06  // The slave did not acknowledge  the address
+#define USI_TWI_MISSING_START_CON   0x07  // Generated Start Condition not detected on bus
+#define USI_TWI_MISSING_STOP_CON    0x08  // Generated Stop Condition not detected on bus
+
+// Device dependant defines
+#define DDR_USI             DDRB
+#define PORT_USI            PORTB
+#define PIN_USI             PINB
+#define PORT_USI_SDA        PORTB0
+#define PORT_USI_SCL        PORTB2
+#define PIN_USI_SDA         PINB0
+#define PIN_USI_SCL         PINB2
+
+// General defines
+#define TRUE  1
+#define FALSE 0
+
+//********** Prototypes **********//
+
+void USI_TWI_Master_Initialise( void );
+unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char );
+unsigned char USI_TWI_Get_State_Info( void );
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/main.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/main.c	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/main.c	(revision 355)
@@ -0,0 +1,177 @@
+#include <avr/io.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include "ring_buffer.h"
+#include "i2c.h"
+
+
+// for i2c_byte coming from charge board
+//I2C Message Codes
+#define I2C_MSG_ACKNOWLEDGE       'A'
+#define I2C_MSG_BATTERY_CHARGING  'C'
+#define I2C_MSG_DATA              'D'
+#define I2C_MSG_CONTACT_ERROR     'E'
+#define I2C_MSG_BATTERY_FULL      'F'
+#define I2C_MSG_NO_CONTACT        'N'
+#define I2C_MSG_REQUEST_DATA      'R'
+#define I2C_MSG_GO_TO_SLEEP       'Y'
+#define I2C_MSG_ENTERING_SLEEP    'Z'
+#define I2C_MSG_HOMING            'H'
+
+
+#define SW0 PA6
+#define HOMING_PIN PA7
+
+#define DEBUG 0
+#define USE_I2C 1
+
+
+#define MAX_T 300
+#define MIN_T 730
+//range is 0 to 45 C
+//cal tests:
+//room temp - 25
+//value ~500, varies from battery to battery, but is consistent on one battery
+//freezer 737
+//heat gun at a distance 461
+
+#define MAX_DT -4 //this is the LOWEST ACCEPTABLE ADC value
+#define MAX_DT_ABS 400
+#define VOLT_PLATEAU 50
+
+
+//The following times are in seconds
+#define MAX_FAST_TIME 5400
+#define MAX_TRICKLE_TIME 600
+
+//debug pins
+#define debug_time PA3
+#define debug_curr PA4
+#define debug_volt PA5
+#define debug_temp PA6
+#define debug_12in PA7
+
+//be sure admux also sets the MUX5 bit which is in ADCSRB
+#define ADMUX_I
+#define ADMUX_V
+#define ADMUX_T
+
+#define ROBOT_TX PB1
+#define ROBOT_RX PB2
+#define PWM PB3
+#define DETECT_12V PB6
+
+#define LED1 PB4 //Green
+#define LED2 PB5 //Red
+
+
+//LED States:
+//Red - Fast Charging
+//Green - Trickle Charging
+//Both steady - done charging
+//Both Blinking - Error
+
+#define INT_COUNT 2 //interrupts per second
+#define AVG_COUNT 64 //number of times to count current
+
+//To enable the PWM write : 	TCCR1B = (_Bv(CS10));//enable PWM
+
+uint8_t interrupt_count = INT_COUNT;
+
+volatile uint32_t abs_time=1; // start at one second so it doesnt do the minute checks right away
+volatile uint8_t new_second=0; //only used as a boolean
+
+volatile uint8_t error=0;
+volatile uint8_t status;
+
+volatile uint8_t steady_current = 0;
+
+//DT must be triggered twice in a row
+volatile uint8_t last_DT = 0;
+//same for DV
+volatile uint8_t last_DV = 0;
+
+#define FAST_CHARGE 1
+#define TRICKLE_CHARGE 2
+
+
+void setup(void)
+{
+    DDRA = _BV(PA3);
+	PORTA = 0x00;
+	DDRB = (_BV(ROBOT_TX)|_BV(PWM)|_BV(LED1)|_BV(LED2)); //confiure output pins
+	PORTB = 0x00;
+	/*
+	ADCSRA = (_BV(ADEN)|_BV(ADPS2)|_BV(ADPS1)); //start ADC with a division factor of 64
+	
+	TCCR0B = (_BV(CS01)); //set timer 0 for realtime mode
+	TCCR0A = (_BV(TCW0));
+	TIMSK = (_BV(TOIE0)); //enable overflow interrupts
+	
+	TCCR1A = (_BV(COM1B1)|_BV(PWM1B)|_BV(COM1A1)|_BV(PWM1A)); //clear timer 1 on compare, set at 0x00. Fast PWM mode
+	TCCR1B |= _BV(CS10); //leave timer on and set compare to 0 to make output off	
+	
+	//hack stuff so it will run in continuous mode
+	TIMSK |= _BV(TOIE1); //enable overflow interrupt for timer 1
+	
+	OCR1B = 0;
+	OCR1A = 0;
+	
+	
+	sei();*/
+}
+
+
+int main(void)
+{
+	setup();
+
+	i2c_init();
+	setup();
+
+	OCR1B=0;
+	
+	sei();
+	
+	
+	PORTB|=_BV(LED2);
+	PORTB|=_BV(LED1);
+	delay_ms(500);
+	PORTB&=~_BV(LED2);
+	PORTB&=~_BV(LED1);
+	
+	i2c_putpacket(0x01,"a ", 2);
+
+	delay_ms(500);
+	PORTB|=_BV(LED2);
+	PORTB|=_BV(LED1);
+
+while(1);
+	
+	return 1;
+}
+
+ISR(TIMER0_OVF_vect)
+{
+	if(error)
+		PORTB ^= (_BV(LED1)|_BV(LED2));
+
+	interrupt_count--;
+	if(interrupt_count==0)
+	{
+		abs_time++;
+		new_second=1;
+			
+		interrupt_count=INT_COUNT;
+	}
+}
+
+ISR(TIMER1_OVF_vect)
+{
+	//wait(2); //wait a bit so we know the ouput gets set (which happens at timer = 0)
+	
+	TCNT1 = 0;//156; // start out at 156. Now OCR1B - 156 = duty cycle
+}
+
+ISR(PCINT_vect){;} //so the interrupt doesnt go to the reset vector
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.c	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/USI_TWI_Slave.c	(revision 355)
@@ -0,0 +1,218 @@
+// This file has been prepared for Doxygen automatic documentation generation.
+/*! \file ********************************************************************
+*
+* Atmel Corporation
+*
+* File              : USI_TWI_Slave.c
+* Compiler          : IAR EWAAVR 4.11A
+* Revision          : $Revision: 1.14 $
+* Date              : $Date: Friday, December 09, 2005 17:25:38 UTC $
+* Updated by        : $Author: jtyssoe $
+*
+* Support mail      : avr@atmel.com
+*
+* Supported devices : All device with USI module can be used.
+*
+* AppNote           : AVR312 - Using the USI module as a I2C slave
+*
+* Description       : Functions for USI_TWI_receiver and USI_TWI_transmitter.
+*
+*
+****************************************************************************/
+
+#ifndef _USI_TWI_SLAVE_H
+#define _USI_TWI_SLAVE_H
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "USI_TWI_Slave.h"
+
+/*! Static Variables */
+
+static unsigned char TWI_slaveAddress;
+static volatile unsigned char USI_TWI_Overflow_State;
+
+/*! Local variables */
+static uint8_t TWI_RxBuf[TWI_RX_BUFFER_SIZE];
+static volatile uint8_t TWI_RxHead;
+static volatile uint8_t TWI_RxTail;
+
+static uint8_t TWI_TxBuf[TWI_TX_BUFFER_SIZE];
+static volatile uint8_t TWI_TxHead;
+static volatile uint8_t TWI_TxTail;
+
+/*! \brief Flushes the TWI buffers
+ */
+void Flush_TWI_Buffers(void)
+{
+    TWI_RxTail = 0;
+    TWI_RxHead = 0;
+    TWI_TxTail = 0;
+    TWI_TxHead = 0;
+}
+
+//********** USI_TWI functions **********//
+
+/*! \brief
+ * Initialise USI for TWI Slave mode.
+ */
+void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress )
+{
+  Flush_TWI_Buffers();
+
+  TWI_slaveAddress = TWI_ownAddress;
+
+  PORT_USI |=  (1<<PORT_USI_SCL);                                 // Set SCL high
+  PORT_USI |=  (1<<PORT_USI_SDA);                                 // Set SDA high
+  DDR_USI  |=  (1<<PORT_USI_SCL);                                 // Set SCL as output
+  DDR_USI  &= ~(1<<PORT_USI_SDA);                                 // Set SDA as input
+  USICR    =  (1<<USISIE)|(0<<USIOIE)|                            // Enable Start Condition Interrupt. Disable Overflow Interrupt.
+              (1<<USIWM1)|(0<<USIWM0)|                            // Set USI in Two-wire mode. No USI Counter overflow prior
+                                                                  // to first Start Condition (potentail failure)
+              (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|                // Shift Register Clock Source = External, positive edge
+              (0<<USITC);
+  USISR    = 0xF0;                                                // Clear all flags and reset overflow counter
+}
+
+
+/*! \brief Puts data in the transmission buffer, Waits if buffer is full.
+*/
+void USI_TWI_Transmit_Byte( unsigned char data )
+{
+    unsigned char tmphead;
+
+    tmphead = ( TWI_TxHead + 1 ) & TWI_TX_BUFFER_MASK;         // Calculate buffer index.
+    while ( tmphead == TWI_TxTail );                           // Wait for free space in buffer.
+    TWI_TxBuf[tmphead] = data;                                 // Store data in buffer.
+    TWI_TxHead = tmphead;                                      // Store new index.
+}
+
+/*! \brief Returns a byte from the receive buffer. Waits if buffer is empty.
+ */
+unsigned char USI_TWI_Receive_Byte( void )
+{
+    unsigned char tmptail;
+    unsigned char tmpRxTail;                                  // Temporary variable to store volatile
+    tmpRxTail = TWI_RxTail;                                   // Not necessary, but prevents warnings
+    while ( TWI_RxHead == tmpRxTail );
+    tmptail = ( TWI_RxTail + 1 ) & TWI_RX_BUFFER_MASK;        // Calculate buffer index
+    TWI_RxTail = tmptail;                                     // Store new index
+    return TWI_RxBuf[tmptail];                                // Return data from the buffer.
+}
+
+/*! \brief Check if there is data in the receive buffer.
+ */
+unsigned char USI_TWI_Data_In_Receive_Buffer( void )
+{
+    unsigned char tmpRxTail;                            // Temporary variable to store volatile
+    tmpRxTail = TWI_RxTail;                             // Not necessary, but prevents warnings
+    return ( TWI_RxHead != tmpRxTail );                 // Return 0 (FALSE) if the receive buffer is empty.
+}
+
+/*! \brief Usi start condition ISR
+ * Detects the USI_TWI Start Condition and intialises the USI
+ * for reception of the "TWI Address" packet.
+ */
+ISR(USI_START_vect) {
+
+    unsigned char tmpUSISR;                                         // Temporary variable to store volatile
+    tmpUSISR = USISR;                                               // Not necessary, but prevents warnings
+// Set default starting conditions for new TWI package
+    USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS;
+    DDR_USI  &= ~(1<<PORT_USI_SDA);                                 // Set SDA as input
+    while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) );   // Wait for SCL to go low to ensure the "Start Condition" has completed.
+                                                                       // If a Stop condition arises then leave the interrupt to prevent waiting forever.
+    USICR   =   (1<<USISIE)|(1<<USIOIE)|                            // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
+                (1<<USIWM1)|(1<<USIWM0)|                            // Set USI in Two-wire mode.
+                (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|                // Shift Register Clock Source = External, positive edge
+                (0<<USITC);
+    USISR  =    (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Clear flags
+                (0x0<<USICNT0);                                     // Set USI to sample 8 bits i.e. count 16 external pin toggles.
+}
+
+
+/*! \brief USI counter overflow ISR
+ * Handels all the comunication. Is disabled only when waiting
+ * for new Start Condition.
+ */
+ISR(USI_OVF_vect) {
+
+  unsigned char tmpTxTail;     // Temporary variables to store volatiles
+  unsigned char tmpUSIDR;
+
+
+  switch (USI_TWI_Overflow_State)
+  {
+    // ---------- Address mode ----------
+    // Check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK, else reset USI.
+    case USI_SLAVE_CHECK_ADDRESS:
+      if ((USIDR == 0) || (( USIDR>>1 ) == TWI_slaveAddress))
+      {
+        if ( USIDR & 0x01 )
+          USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA;
+        else
+          USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
+          SET_USI_TO_SEND_ACK();
+      }
+      else
+      {
+        SET_USI_TO_TWI_START_CONDITION_MODE();
+      }
+      break;
+
+    // ----- Master write data mode ------
+    // Check reply and goto USI_SLAVE_SEND_DATA if OK, else reset USI.
+    case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
+      if ( USIDR ) // If NACK, the master does not want more data.
+      {
+        SET_USI_TO_TWI_START_CONDITION_MODE();
+        return;
+      }
+      // From here we just drop straight into USI_SLAVE_SEND_DATA if the master sent an ACK
+
+    // Copy data from buffer to USIDR and set USI to shift byte. Next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA
+    case USI_SLAVE_SEND_DATA:
+
+      // Get data from Buffer
+      tmpTxTail = TWI_TxTail;           // Not necessary, but prevents warnings
+      if ( TWI_TxHead != tmpTxTail )
+      {
+        TWI_TxTail = ( TWI_TxTail + 1 ) & TWI_TX_BUFFER_MASK;
+        USIDR = TWI_TxBuf[TWI_TxTail];
+      }
+      else // If the buffer is empty then:
+      {
+          SET_USI_TO_TWI_START_CONDITION_MODE();
+          return;
+      }
+      USI_TWI_Overflow_State = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
+      SET_USI_TO_SEND_DATA();
+      break;
+
+    // Set USI to sample reply from master. Next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
+    case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
+      USI_TWI_Overflow_State = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
+      SET_USI_TO_READ_ACK();
+      break;
+
+    // ----- Master read data mode ------
+    // Set USI to sample data from master. Next USI_SLAVE_GET_DATA_AND_SEND_ACK.
+    case USI_SLAVE_REQUEST_DATA:
+      USI_TWI_Overflow_State = USI_SLAVE_GET_DATA_AND_SEND_ACK;
+      SET_USI_TO_READ_DATA();
+      break;
+
+    // Copy data from USIDR and send ACK. Next USI_SLAVE_REQUEST_DATA
+    case USI_SLAVE_GET_DATA_AND_SEND_ACK:
+      // Put data into Buffer
+      tmpUSIDR = USIDR;             // Not necessary, but prevents warnings
+      TWI_RxHead = ( TWI_RxHead + 1 ) & TWI_RX_BUFFER_MASK;
+      TWI_RxBuf[TWI_RxHead] = tmpUSIDR;
+
+      USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
+      SET_USI_TO_SEND_ACK();
+      break;
+  }
+}
+
+#endif
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.c
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.c	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/i2c.c	(revision 355)
@@ -0,0 +1,115 @@
+/* I2C.c
+
+    I2C Communication
+    
+    Problem switching into slave mode. So never run as a slave otherwise you will never be able
+        to speak again (unless a master tells you to).
+    
+*/
+
+#include "i2c.h"
+/*
+int main(void) {
+	i2c_test();
+}
+*/
+//Call this to start I2C up
+void i2c_init(void) {
+  //Start off in slave mode so you can catch any data that comes your way
+  //USI_TWI_Slave_Initialise(0x02);
+  
+  //Can't ever be a slave otherwise you will die. Stay as master and never give it up.
+    USI_TWI_Master_Initialise();
+ 
+}
+
+
+//Call this to send a packet. *data is a char array of data_size. Make sure you put in data_size or we won't send
+//everything.
+//Note, mainboard is addr = 0x01.
+void i2c_putpacket(char addr, char *data, char data_size) {
+  //The packet that we will transmit over I2C
+  unsigned char packet[data_size + 1];
+  
+  //First byte is the destination address + R/W (R = 1, W = 0)
+  packet[0] = addr << 1;    //Shift the address over 1 bit, LSB is 0 which means write
+  
+  //Put data into packet
+  for (int i = 0; i < data_size; i++) {
+    packet[i+1] = data[i];
+  }
+  
+  //Send packet. Will open line, transmit, and close line.
+  USI_TWI_Start_Transceiver_With_Data(packet, (data_size + 1));
+
+}
+
+int i2c_getpacket(char *c) {
+  if (USI_TWI_Data_In_Receive_Buffer()) {
+    *c =  USI_TWI_Receive_Byte();
+    return 0;
+  } else{
+      return -1;
+  
+  }
+}
+
+void delay_ms(int ms) 
+{
+	for(; ms > 15; ms-=15)
+		_delay_ms(15);
+	_delay_ms(ms);
+}
+
+
+// Note this will fail. You need to fix the switch from slave -> master before it will succeed.
+void i2c_test(void) {
+    char datatx[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+   char datarx;
+  
+  DDRA = _BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6) | _BV(PA7);
+  PORTA = 0;
+  PORTA |= _BV(PA3);
+  
+  //delay_ms(1000);
+  
+  sei();
+  i2c_init();
+   
+    while(1) {
+	delay_ms(1000);
+    i2c_putpacket(0x01, datatx, 26);
+	}
+  
+  /*
+    while(1) {
+      i2c_getpacket(&datarx);
+      
+      switch (datarx) {
+        case 'a':
+            PORTA |= _BV(PA4);
+            break;
+        case 'b':
+            PORTA |= _BV(PA5);
+            break;
+        case 'c':
+            PORTA |= _BV(PA6);
+            break;
+        case 'd':
+            PORTA |= _BV(PA7);
+            break;
+      }
+      
+      if (datarx == 'd')
+        break;
+  }
+  
+   PORTA = 0;
+ 
+
+  //PORTA |= _BV(PA5);
+  delay_ms(1000);
+  i2c_putpacket(0x01, datatx, 26);
+  */
+}
+
Index: branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/ring_buffer.h
===================================================================
--- branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/ring_buffer.h	(nonexistent)
+++ branches/autonomous_recharging/code/projects/autonomous_recharging/archs/I2c test/ring_buffer.h	(revision 355)
@@ -0,0 +1,149 @@
+/** @file Include macros to create a ring buffer. Originally written for 15-410.
+ *  Modified for use in ATMega128 serial driver
+ *
+ *	@author Cornell Wright (cgwright)
+ *	@author Jason P. Winters (jpwinter)
+ *
+ *	@bugs None known.
+ */
+
+#ifndef _RING_BUFFER_H
+#define _RING_BUFFER_H
+
+/** @brief Creates the struct for a new ring buffer. This just expands to a
+ *	structure definition and thus should be invoked in the global context.
+ *
+ *	@param struct_name Name of the ring buffer struct.
+ *
+ *	@param size The size of the buffer to create.
+ *
+ *	@param type The type of object that the queue is to hold.
+ *
+ *	@param ... Name or names of the instance or instances of the ring buffer(s)
+ *	to be created.
+ */
+#define RING_BUFFER_NEW(struct_name, size, type, ...)	\
+	struct struct_name {	\
+		type queue[size];	\
+		uint8_t start;			\
+		uint8_t end;			\
+		uint8_t buffer_size;			\
+	} __VA_ARGS__
+
+
+#define RING_BUFFER_BIT_NEW(struct_name, size, ...)	\
+	struct struct_name {	\
+		int8_t queue[(size / 8) + 1];	\
+		uint16_t start;	\
+		uint16_t end;	\
+	} __VA_ARGS__
+
+/** @brief Initializes the ring buffer, setting its size to the correct value
+ *
+ *	@param buf The ring buffer to initialize.
+ *
+ *  @param size The size of the ring buffer (in array elements)
+ */
+#define RING_BUFFER_INIT(buf, size) 			\
+	do {										\
+		(buf).buffer_size = size;				\
+	} while(0)
+
+#define RING_BUFFER_BIT_INIT(buf, size) 		\
+	do {										\
+		(buf).buffer_size = size;				\
+	} while(0)
+	
+
+/** @brief Sets the specified ring buffer to be empty.
+ *
+ *	@param buf The ring buffer to make empty.
+ */
+#define RING_BUFFER_CLEAR(buf)	\
+	do {						\
+		(buf).start = 0;		\
+		(buf).end = 0;			\
+	} while (0)
+
+#define RING_BUFFER_BIT_CLEAR(buf) RING_BUFFER_CLEAR(buf)
+/** @brief Returns true if the ring buffer specified is empty.
+ *
+ *	@param buf The buffer to check emptiness of.
+ */
+#define RING_BUFFER_EMPTY(buf) ((buf).start == (buf).end)
+
+
+
+#define RING_BUFFER_BIT_EMPTY(buf) RING_BUFFER_EMPTY(buf)
+
+
+/** @brief Returns true if the ring buffer specified is full.
+ *
+ *	@param buf The buffer to check fullness of.
+ */
+#define RING_BUFFER_FULL(buf)	\
+		(((buf).end + 1) % (buf).buffer_size == (buf).start)
+
+#define RING_BUFFER_BIT_FULL(buf) RING_BUFFER_FULL(buf)
+
+/** @brief Adds val to ring buffer buf. Note that val must be of the type
+ *	used in creating the ring buffer to prevent the compiler from spewing
+ *	confusing errors. Also, this assumes that the ring buffer is not full.
+ *
+ *	@param buf The ring buffer to add to.
+ *	@param val The value to add.
+ */
+#define RING_BUFFER_ADD(buf, val)		\
+	do {								\
+		(buf).queue[(buf).end] = val;	\
+		(buf).end = ((buf).end + 1) % (buf).buffer_size;	\
+	} while (0)
+
+#define RING_BUFFER_BIT_ADD(buf, val)	\
+	do {								\
+		if (val) {						\
+			(buf).queue[((buf).end >> 3) & 0xff] |= _BV((buf).end & 0x7);	\
+		}								\
+		else {							\
+			(buf).queue[((buf).end >> 3) & 0xff] &= ~_BV((buf).end & 0x7);	\
+		}								\
+		(buf).end = ((buf).end + 1) % ((buf).buffer_size) << 3);			\
+	} while (0)
+
+
+/** @brief Removes the value at the head of the ring buffer and puts it in
+ *	val_ret. Note that val_ret must be the same type used in creating the ring
+ *	buffer to prevent the compiler from spewing confusing errors. Also, this
+ *	assumes that the ring buffer is not empty.
+ *
+ *	@param buf The ring buffer to remove from.
+ *	@param val_ret Where to put the value removed from the head of the ring
+ *	buffer.
+ */
+#define RING_BUFFER_REMOVE(buf, val_ret)	\
+	do {	\
+		(val_ret) = (buf).queue[(buf).start];	\
+		(buf).start = ((buf).start + 1) % (buf).buffer_size;	\
+	} while (0)
+
+#define RING_BUFFER_BIT_REMOVE(buf, val_ret)	\
+	do {	\
+		(val_ret) = ((buf).queue[((buf).start >> 3) & 0xff] & _BV((buf).start & 0x7)) ? 1 : 0;	\
+		(buf).start = ((buf).start + 1) % ((buf).buffer_size << 3);	\
+	} while (0)
+
+/** @brief Checks the value at the head of the ring buffer without removing it
+ *  and puts it into val_ret. Note that val_ret must be the same type used in
+ *  creating the ring buffer to prevent the compiler from spewing confusing
+ *  errors. Also, this assumes that the ring buffer is not empty.
+ *
+ *  @param buf The ring buffer to check from
+ *  @param val_ret where to put the value checked from the head of the ring
+ */
+ #define RING_BUFFER_PEEK(buf, val_ret)  \
+  do { \
+    (val_ret) = (buf).queue[(buf).start]; \
+  } while(0)
+
+#endif /* _RING_BUFFER_H */
+
