Index: trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.c	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/Charging.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/Charging.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/Charging.c	(revision 80)
@@ -0,0 +1,798 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include "i2c.h"
+
+#define TRICKLE
+
+
+//These are in ADC steps; if any values change in the charging
+//circuitry these will have to be recalculated
+#ifndef TRICKLE
+	#define FAST_I 450//660 //660 fries the 5A fuse!!
+#else
+	#define FAST_I 20 //Works => 1.3A
+#endif
+
+#define TEST_CURR 550
+
+#define MAX_V 1020//990 //7.75V
+
+
+#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
+
+//change in one minute
+#define MAX_DT 30
+#define MAX_DV 30
+
+
+//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 wait(int ops)
+{
+	int i = 0;
+	while(i<ops)
+		i++;
+}
+
+
+
+int avg_ADC(void)
+{
+	int av;
+	char i;
+
+	//Calculate a average out of the next 8 A/D conversions
+    for(av=0,i=8;i;--i)
+    {
+        ADCSRA |= _BV(ADSC);                      // start new A/D conversion
+        while (!(ADCSRA & (_BV(ADIF))))        // wait until ADC is ready
+            ;      
+        av = av+ADC;
+    }
+    av = av/8;
+	
+	//ADCSRA &= ~_BV(ADEN);
+
+	return av;
+	
+}
+
+int get_voltage(void)
+{
+	ADMUX = _BV(MUX0);
+	
+	ADCSRB &= ~_BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_current(void)
+{
+	ADMUX = _BV(MUX1);
+	
+	ADCSRB |= _BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_temperature(void)
+{
+	ADMUX = _BV(MUX1);
+	
+	ADCSRB &= ~_BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_avg_voltage(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_voltage();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+int get_avg_current(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_current();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+int get_avg_temperature(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_temperature();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+
+uint8_t supply_voltage(void)
+{
+	return PINB & _BV(DETECT_12V);
+}
+
+void clear_err(void)
+{
+	error=0;
+	PORTB &= ~(_BV(LED1)|_BV(LED2));
+	
+	if(status==FAST_CHARGE)
+		PORTB |= _BV(LED2);
+		
+	if(status==TRICKLE_CHARGE)
+		PORTB |= _BV(LED1);
+}
+	
+void wait_8th(void)
+{
+	uint8_t start = abs_time % 8;
+	
+	while(abs_time % 8 == start)
+	{
+		/*if(supply_voltage())
+			PORTB |= _BV(LED1);
+		else
+			PORTB &= ~_BV(LED1);
+		if(get_voltage()>100)
+			PORTB |= _BV(LED2);
+		else
+			PORTB &= ~_BV(LED2);*/
+	}
+}
+
+void send_err(void)
+{
+	OCR1B=0;//turn off the PWM to be safe
+
+	PORTB &= ~(_BV(LED1)|_BV(LED2));
+	if(status!=0)//leave last error if there was one
+		PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); 
+	error=1;
+	status=0;
+}
+
+void send_done(void)
+{
+	char tempData;
+	//Finished, leave
+	tempData = 'F';
+	i2c_putpacket(0x01, &tempData, 1);
+	
+	PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); 
+	
+}
+
+void setup(void)
+{
+	DDRA = (_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in));
+	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(CS12)|_BV(CS10); //leave timer on and set compare to 0 to make output off	
+	OCR1B = 0;
+	OCR1A = 0;
+	
+	sei();
+}
+
+int regulate_current(int i)
+{
+	if(status==0)
+	{
+		OCR1B = 0;
+		return 0;
+	}
+		
+	PORTA ^= _BV(debug_curr);
+	
+	int curr=0;
+	int count=0;
+	int diff=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_current();
+		count++;
+	}
+
+	curr = sum/AVG_COUNT;
+	//OCR1A = curr >> 2;
+	
+	
+	 //old linear regulation
+	 /*
+	if(OCR1B <255 && curr < i)
+			OCR1B++;
+	else if(OCR1B >0 && curr > i)
+			OCR1B--;
+	
+	return curr;
+	*/
+	
+	
+	//cool control law stuff
+	diff=curr-i;
+	
+	OCR1B = diff/4 + curr/4; //K*Ierr + Kguess
+	
+	
+	
+	//1024/255
+	/*if(OCR1B <255 && curr<i)
+		OCR1B += (i-curr)/4;
+	else if(OCR1B >0 && curr > i)
+		OCR1B -= (curr-i)/4;*/
+	//differential regulation (sort of)
+	/*diff = i-curr;
+	
+	if(diff<8)
+		steady_current=1;
+	else
+		steady_current=0;
+	
+	OCR1B += diff/4;*/
+	
+}
+
+void check_voltage(void)
+{
+	int volt = get_avg_voltage();
+	
+	
+	if(volt > MAX_V)
+	{
+		OCR1A = 128;
+		send_err();
+		PORTA |= _BV(debug_volt);
+		status = 0;
+	}
+}
+
+void check_temperature(void)
+{
+	int temp = get_avg_temperature();
+	
+	//temp readings are reversed
+	if(temp < MAX_T || temp > MIN_T)
+	{
+		OCR1A = 192;
+		send_err();
+		PORTA |= _BV(debug_temp);
+		status=0;
+	}
+}
+
+
+//takes a 7-bit ionteger and displays it on the 7 LEDs with the Green being the MSB
+void LED_out(int i)
+{
+	if(i & 64)
+		PORTB |= _BV(LED1);
+	else
+		PORTB &= ~_BV(LED1);
+		
+	if(i & 32)
+		PORTB |= _BV(LED2);
+	else
+		PORTB &= ~_BV(LED2);
+		
+	if(i & 16)
+		PORTA |= _BV(PA3);
+	else
+		PORTA &= ~_BV(PA3);
+	
+	if(i & 8)
+		PORTA |= _BV(PA4);
+	else
+		PORTA &= ~_BV(PA4);
+		
+	if(i & 4)
+		PORTA |= _BV(PA5);
+	else
+		PORTA &= ~_BV(PA5);
+	
+	if(i & 2)
+		PORTA |= _BV(PA6);
+	else
+		PORTA &= ~_BV(PA6);
+		
+	if(i & 1)
+		PORTA |= _BV(PA7);
+	else
+		PORTA &= ~_BV(PA7);
+}
+	
+
+void test_board(void)
+{
+	setup();
+	abs_time = 0;
+	status = 1;
+	char tempData[5];
+	i2c_init();
+	int volt;
+	int temp;
+	int curr;
+	int meas_count;
+	int mod=0;
+	sei();
+	OCR1B = 0;
+	while(1)
+	{
+		mod=abs_time%4;
+		while(abs_time%4==mod);
+		
+		/*if((abs_time>>3)%3==0)
+			OCR1B=21;
+		else if((abs_time>>3)%3==1)
+			OCR1B=57;
+		else
+			OCR1B=85;*/
+		
+		tempData[0] = 'C';
+		tempData[1] = abs_time>>8;
+		tempData[2] = abs_time&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			if(supply_voltage())
+			{
+				//curr = regulate_current(500);
+				curr = get_avg_current();
+				OCR1B = 100;
+			}
+			else
+			{
+				curr = 0;
+				OCR1B = 0;
+			}
+		}
+		
+
+		tempData[0] = 'P';
+		tempData[1] = 0;
+		tempData[2] = OCR1B;
+		i2c_putpacket(0x01, tempData, 3);
+		tempData[0] = 'I';
+		tempData[1] = curr>>8;
+		tempData[2] = curr&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		curr=6666;
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			volt = get_avg_voltage();
+		}
+
+		tempData[0] = 'V';
+		tempData[1] = volt>>8;
+		tempData[2] = volt&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+
+		volt=6666;
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			temp = get_avg_temperature();
+			
+		}
+		
+		tempData[0] = 'T';
+		tempData[1] = temp>>8;
+		tempData[2] = temp&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+
+		temp=6666;
+	}
+	int c=0,oc;
+	oc=get_avg_temperature();
+	//this will read the temperature and output it to the LEDS.
+	//to read the value, enter the LEDs as binary, with the bottom green as the MSB.
+	//after two second the LEDS will toggle to the next 7 bits
+	/*while(1)
+	{
+		c=oc-get_avg_temperature();
+		oc+=c;
+		
+		if(c<0)
+			c=-c;
+		
+		if(c<5)
+			break;
+	}*/
+/*
+	while(1)
+	{
+		LED_out(oc>>7);
+		for(c=0;c<16;c++)
+			wait_8th();
+		LED_out(oc);
+		for(c=0;c<16;c++)
+			wait_8th();
+	}*/
+	
+	
+	/*PORTB |= (_BV(LED1)|_BV(LED2));
+	
+	while(1)
+	{
+		PORTA ^= _BV(debug_time);
+		wait_8th();
+		c=get_current()-FAST_I;
+		if(c<0)
+			c=-c;
+		if(c<4)
+			PORTA |= _BV(debug_curr);
+		else
+			PORTA &= ~_BV(debug_curr);
+		wait_8th();
+		if(get_avg_voltage() > 50)
+			PORTA |= _BV(debug_volt);
+		else
+			PORTA &= ~_BV(debug_volt);
+		wait_8th();
+		if(get_avg_temperature() > MAX_T)
+			PORTA |= _BV(debug_temp);
+		else
+			PORTA &= ~_BV(debug_temp);
+		wait_8th();
+		if(supply_voltage())
+			PORTA |= _BV(debug_12in);
+		else
+			PORTA &= ~_BV(debug_12in);
+		wait_8th();
+	}*/
+	
+}
+
+
+int main(void)
+{
+	test_board();
+	new_second=0;
+	char tempData[5];	//For i2c communication
+	//test_board();
+	char noVoltagePrintFlag = 0;
+  
+	setup();
+	i2c_init();
+	
+	/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts
+	PCMSK1 = (_BV(PCINT10)); //enable pin change interrupt on ROBOT_RX
+	MCUCR = (_BV(SE)|_BV(SM1));// (power-down mode)
+	*/
+	
+	OCR1B=0;
+	
+	sei();
+	
+	tempData[0] = 'S';
+	tempData[1] = 'S';
+	tempData[2] = 'S';
+	tempData[3] = 'S';
+	tempData[4] = 'S';
+	i2c_putpacket(0x01, tempData, 5);	
+	
+	int temp=0;
+	int last_temp = get_avg_temperature();
+	
+	int volt=0;
+	int last_volt = get_avg_voltage();
+	
+	
+	while(1)
+	{
+		/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts
+		sleep_cpu();*/
+		
+		PORTB=0;//clear outputs
+		
+		GIMSK = 0;
+		
+		error=0;
+		
+		OCR1B = 0;
+		
+		//wait for 12v source
+		
+		while(!supply_voltage()) {
+			if (!noVoltagePrintFlag) {
+				tempData[0] = 'N';
+				tempData[1] = 'N';
+				tempData[2] = 'N';
+				tempData[3] = 'N';
+				tempData[4] = 'N';
+				i2c_putpacket(0x01, tempData, 5);
+				noVoltagePrintFlag = 1;
+			}
+		}
+		
+		noVoltagePrintFlag = 0;
+		
+		//Contact 
+		tempData[0] = 'C';
+		tempData[1] = 'C';
+		tempData[2] = 'C';
+		tempData[3] = 'C';
+		tempData[4] = 'C';
+		i2c_putpacket(0x01, tempData, 5);
+		
+		PORTA |= _BV(debug_12in);
+		
+		abs_time=1;
+
+		//--------------FAST CHARGE-----------------------
+		//split seconds into eights as following:
+		//1: abs_volt
+		//2: reg
+		//3: abs_temp
+		//4: reg
+		//5: abs_volt
+		//6: reg
+		//7: abs_temp
+		//between seconds: abs time and minute checks, which takes an extra 8th
+		status = FAST_CHARGE;
+		
+		PORTB |= _BV(LED2);
+		
+		while(status == FAST_CHARGE)
+		{
+			
+			if(!supply_voltage())
+			{
+				
+				
+				send_err();
+				//Lost Contact
+				tempData[0] = 'N';
+				tempData[1] = 'N';
+				tempData[2] = 'N';
+				tempData[3] = 'N';
+				tempData[4] = 'N';
+				i2c_putpacket(0x01, tempData, 5);
+				
+				PORTA &= ~_BV(debug_12in);
+				while(!supply_voltage());
+				
+				//Contact again
+				tempData[0] = 'C';
+				tempData[1] = 'C';
+				tempData[2] = 'C';
+				tempData[3] = 'C';
+				tempData[4] = 'C';
+				i2c_putpacket(0x01, tempData, 5);
+				
+				PORTA |= _BV(debug_12in);
+				clear_err();
+			}
+			
+			check_voltage();
+			wait_8th();
+			regulate_current(FAST_I);
+			wait_8th();
+			check_temperature();
+			wait_8th();
+			regulate_current(FAST_I);
+			wait_8th();
+			check_voltage();
+			wait_8th();
+			regulate_current(FAST_I);
+			wait_8th();
+			check_temperature();
+			wait_8th();
+			
+#ifdef TRICKLE
+			
+			if(abs_time > 9600) //90 minute time limit
+			{
+				OCR1A = 32;
+				send_done();
+				PORTA |= _BV(debug_time);
+				break;
+			}
+
+#else
+
+			if(abs_time > 43200) //90 minute time limit
+			{
+				OCR1A = 32;
+				send_err();
+				PORTA |= _BV(debug_time);
+				break;
+			}
+			
+			//minute checks
+			if( (abs_time >> 3)%55 == 0/* && steady_current*/)
+			{
+				PORTA ^= _BV(debug_time);
+				
+				temp = get_avg_temperature();
+				wait_8th(); //to avoid interference
+				volt = get_avg_voltage(); 
+				
+				OCR1A = volt >> 2;
+				
+				//seems to be some random drops when connected to a power supply
+				//may need a fudge factor but maybe not becuase voltage should be climbing during charge
+				if(volt < last_volt - MAX_DV)
+				{
+          PORTA |= _BV(debug_volt);
+          if(last_DV)
+          {
+            OCR1A = 64;
+            
+            send_done();
+            PORTA |= _BV(debug_volt);
+            status = TRICKLE_CHARGE;
+          }
+          else
+            last_DV=1;
+          
+				}
+        else
+        {
+          last_DV=0;
+          PORTA &= ~_BV(debug_volt);
+         }
+				
+				
+				if(temp < last_temp - MAX_DT)
+				{
+          PORTA |= _BV(debug_temp);
+          if(last_DT)
+          {       
+            OCR1A = 128;
+            
+            send_done();
+            PORTA |= _BV(debug_temp);
+            status = TRICKLE_CHARGE;
+          }
+          else
+            last_DT=1;
+				}
+        else
+        {
+          last_DT=0;
+          PORTA &= ~_BV(debug_temp);
+        }
+				
+				last_volt = volt;
+				last_temp = temp;
+			}
+#endif
+
+		}
+		if (error) {
+			//We have an error...let's bail out of this ship captain!
+			tempData[0] = 'F';
+			tempData[1] = 'F';
+			tempData[2] = 'F';
+			tempData[3] = 'F';
+			tempData[4] = 'F';
+			i2c_putpacket(0x01, tempData, 5);
+		}
+		
+		//PORTB ^= _BV(LED2);
+		
+	}
+
+	
+	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(PCINT_vect){;} //so the interrupt doesnt go to the reset vector
Index: trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.h
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.h	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.h	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/i2c.h
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/i2c.h	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/i2c.h	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.h
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.h	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/USI_TWI_Master.h	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/homing stop/stop.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/homing stop/stop.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/homing stop/stop.c	(revision 80)
@@ -0,0 +1,61 @@
+#include<avr/io.h>
+#include "i2c.h"
+
+#define LED1 PB4 //Green
+#define LED2 PB5 //Red
+
+int main( void )
+{
+	DDRB = _BV(PB0) | _BV(PB5) | _BV(PB4);
+  i2c_init();
+  
+  /*tempData[0] = 'C';
+		tempData[1] = abs_time>>8;
+		tempData[2] = abs_time&0xFF;
+		i2c_putpacket(0x01, tempData, 3);*/
+  
+  char data[2];
+  data[0]=I2C_MSG_DATA;
+
+  while(1)
+  {
+    PORTB=_BV(LED2);
+    while(1)
+    {
+      if(PINB & _BV(PB6))
+      {
+        PORTB = _BV(LED1);
+        //This is a junk byte. For some reason the first packet is always ignored????
+        data[1] = 'a';
+        i2c_putpacket(0x01, data, 2);
+        data[1]=I2C_MSG_BATTERY_CHARGING;
+        i2c_putpacket(0x01, data, 2);
+        break;
+      }
+      else
+      {
+        data[1]=I2C_MSG_NO_CONTACT;
+        i2c_putpacket(0x01, data, 2);
+      }
+    }
+    
+    for(int i=0;i<5000;i++)
+    {
+      delay_ms(1);
+      if(! PINB & _BV(PB6))
+      {
+          PORTB = _BV(LED2);
+          data[1]=I2C_MSG_CONTACT_ERROR;
+          i2c_putpacket(0x01, data, 2);
+          
+          while(! PINB & _BV(PB6));
+            break;
+      }
+      
+    }
+    
+    data[1]=I2C_MSG_BATTERY_FULL;
+    i2c_putpacket(0x01, data, 2);
+  }
+    
+}
\ No newline at end of file
Index: trunk/code/projects/autonomous_recharging/archs/homing stop/Makefile
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/homing stop/Makefile	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/homing stop/Makefile	(revision 80)
@@ -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 = attiny861
+
+
+# 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 = 8000000
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+
+# Target file name (without extension).
+TARGET = stop
+
+
+# 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: trunk/code/projects/autonomous_recharging/archs/ConstantCharging.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/ConstantCharging.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/ConstantCharging.c	(revision 80)
@@ -0,0 +1,707 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include "i2c.h"
+#include "ring_buffer.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 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
+
+RING_BUFFER_NEW(ring_buffer, 12, int, buffer);
+
+void wait(int ops)
+{
+	int i = 0;
+	while(i<ops)
+		i++;
+}
+
+
+
+int avg_ADC(void)
+{
+	int av;
+	char i;
+
+	//Calculate a average out of the next 8 A/D conversions
+    for(av=0,i=8;i;--i)
+    {
+        ADCSRA |= _BV(ADSC);                      // start new A/D conversion
+        while (!(ADCSRA & (_BV(ADIF))))        // wait until ADC is ready
+            ;      
+        av = av+ADC;
+    }
+    av = av/8;
+	
+	//ADCSRA &= ~_BV(ADEN);
+
+	return av;
+	
+}
+
+int get_voltage(void)
+{
+	ADMUX = _BV(MUX0);
+	
+	ADCSRB &= ~_BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_current(void)
+{
+	ADMUX = _BV(MUX1);
+	
+	ADCSRB |= _BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_temperature(void)
+{
+	ADMUX = _BV(MUX1);
+	
+	ADCSRB &= ~_BV(MUX5);
+	
+	return avg_ADC();
+}
+
+int get_avg_voltage(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_voltage();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+int get_avg_current(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_current();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+int get_avg_temperature(void)
+{
+	int count=0;
+	uint32_t sum=0;
+		
+		//OCR1B =120;
+	while(count < AVG_COUNT)
+	{
+		sum += get_temperature();
+		count++;
+	}
+
+	return sum/AVG_COUNT;
+}
+
+
+uint8_t supply_voltage(void)
+{
+	return PINB & _BV(DETECT_12V);
+}
+
+void clear_err(void)
+{
+	error=0;
+	PORTB &= ~(_BV(LED1)|_BV(LED2));
+	
+	if(status==FAST_CHARGE)
+		PORTB |= _BV(LED2);
+		
+	if(status==TRICKLE_CHARGE)
+		PORTB |= _BV(LED1);
+}
+	
+void wait_8th(void)
+{
+	uint8_t start = abs_time % 8;
+	
+	while(abs_time % 8 == start)
+	{
+		/*if(supply_voltage())
+			PORTB |= _BV(LED1);
+		else
+			PORTB &= ~_BV(LED1);
+		if(get_voltage()>100)
+			PORTB |= _BV(LED2);
+		else
+			PORTB &= ~_BV(LED2);*/
+	}
+}
+
+void send_err(void)
+{
+	OCR1B=0;//turn off the PWM to be safe
+
+	PORTB &= ~(_BV(LED1)|_BV(LED2));
+	if(status!=0)//leave last error if there was one
+		PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); 
+	error=1;
+	status=0;
+}
+
+void send_done(void)
+{
+	char tempData;
+	//Finished, leave
+	tempData = 'F';
+	i2c_putpacket(0x01, &tempData, 1);
+	
+	PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); 
+	
+}
+
+void setup(void)
+{
+      DDRA = _BV(PA3);
+#ifdef debug
+	//DDRA = (_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in));
+#endif
+	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(CS12)|_BV(CS10); //leave timer on and set compare to 0 to make output off	
+	OCR1B = 0;
+	OCR1A = 0;
+	
+	
+	RING_BUFFER_CLEAR(buffer);
+	RING_BUFFER_INIT(buffer, 12);
+	for(int i=0;i<10;i++)
+		RING_BUFFER_ADD(buffer, 0);
+	
+	sei();
+}
+
+
+
+
+//takes a 7-bit ionteger and displays it on the 7 LEDs with the Green being the MSB
+void LED_out(int i)
+{
+	if(i & 64)
+		PORTB |= _BV(LED1);
+	else
+		PORTB &= ~_BV(LED1);
+		
+	if(i & 32)
+		PORTB |= _BV(LED2);
+	else
+		PORTB &= ~_BV(LED2);
+		
+	if(i & 16)
+		PORTA |= _BV(PA3);
+	else
+		PORTA &= ~_BV(PA3);
+	
+	if(i & 8)
+		PORTA |= _BV(PA4);
+	else
+		PORTA &= ~_BV(PA4);
+		
+	if(i & 4)
+		PORTA |= _BV(PA5);
+	else
+		PORTA &= ~_BV(PA5);
+	
+	if(i & 2)
+		PORTA |= _BV(PA6);
+	else
+		PORTA &= ~_BV(PA6);
+		
+	if(i & 1)
+		PORTA |= _BV(PA7);
+	else
+		PORTA &= ~_BV(debug_12in);
+}
+
+//get the difference of the current value minues the value 10 entires ago
+int ring_buffer_d10(int y)
+{	
+	int x;
+	RING_BUFFER_REMOVE(buffer, x);
+		
+	RING_BUFFER_ADD(buffer, y);
+	return y-x;
+}
+
+
+uint8_t read_homing()
+{
+    uint8_t ret = PINA & _BV(HOMING_PIN);
+    if(ret)
+        PORTA |= _BV(PA3);
+    else
+        PORTA &= ~_BV(PA3);
+    return ret;
+}
+
+//copied from scheduler/seeking.c
+uint8_t get_delay(void)
+{
+    uint8_t count = 0;
+    
+	PORTB|=_BV(LED2);
+    while(read_homing())
+    {
+        delay_ms(1);
+        count++;
+        if (count >= 100)
+            return 1;
+    } //wait a beacon cycle to make sure we aren't starting the count in the middle of one
+	PORTB&=~_BV(LED2);
+    count = 0;
+    PORTB|=_BV(LED1);
+    while(!read_homing())
+    {
+        delay_ms(1);
+        count++;
+        if(count==255)
+          return 2;
+    }
+    PORTB&=~_BV(LED1);
+	
+  /*RECH_PUTS("\n\rCount: ");
+	RECH_PUTI(count);
+	RECH_PUTC('.');*/
+	
+    return count;
+}
+
+void trickle_charge(void)
+{
+
+	abs_time = 0;
+	status = 0;
+	char tempData[5];
+	char data[2];
+	data[0]='D';
+	int volt = 0;
+	int temp = 0;
+	int curr = 0;
+	int meas_count = 0;
+	int mod=0;
+	sei();
+	OCR1B = 0;
+	
+	while(status!=2)
+	{
+		mod=abs_time%4;
+		
+		if(supply_voltage())
+		  while(abs_time%4==mod);
+		
+    /* TIME TERMINATION */
+		if(abs_time>500) //12000=25 minutes
+		{
+			//SEND_DONE
+			OCR1B=0;
+			break;
+		}
+		
+#if DEBUG		
+		tempData[0] = 'C';
+		tempData[1] = abs_time>>8;
+		tempData[2] = abs_time&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+#endif
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+      /* CONTACT */
+			if(supply_voltage())
+			{
+				//curr = regulate_current(500);
+				curr = get_avg_current();
+				
+				if(status==0)
+				{
+					status=1;
+					data[1]='a';
+					i2c_putpacket(0x01, data, 2);
+					data[1]=I2C_MSG_BATTERY_CHARGING;
+					i2c_putpacket(0x01, data, 2);
+				}
+				
+        /* Trickle Charge */
+				if(status==1)
+					OCR1B = 50;
+			}
+      /* NO CONTACT */
+			else
+			{
+				if(status==1)
+				{
+					status=0;
+					data[1]=I2C_MSG_CONTACT_ERROR;
+					i2c_putpacket(0x01, data, 2);
+				}
+				else
+				{
+          get_delay(); //reject the first reading
+					data[0]=I2C_MSG_HOMING;
+					data[1]=get_delay();
+          i2c_putpacket(0x01, data, 2);
+          
+          data[0]='D';
+				}
+				curr = 0;
+				OCR1B = 0;
+			}
+		}
+		
+#if DEBUG
+		tempData[0] = 'P';
+		tempData[1] = 0;
+		tempData[2] = OCR1B;
+		i2c_putpacket(0x01, tempData, 3);
+		tempData[0] = 'I';
+		tempData[1] = curr>>8;
+		tempData[2] = curr&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+#endif
+		curr=6666;
+		
+    /* Absolute Voltage Termination */
+		if(supply_voltage())
+		  {
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			volt = get_avg_voltage();
+		}
+		
+		if(volt>1010)
+		{
+			//SEND ERROR
+			status=0;
+		}
+    
+#if DEBUG
+		tempData[0] = 'V';
+		tempData[1] = volt>>8;
+		tempData[2] = volt&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+#endif
+		volt=6666;
+		
+    /* Absolute Temperature Termination */
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			temp = get_avg_temperature();
+		}
+		
+		if(temp<250)
+		{
+			//SEND ERROR
+			status=0;
+		}
+
+#if DEBUG
+		tempData[0] = 'T';
+		tempData[1] = temp>>8;
+		tempData[2] = temp&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+#endif
+		  }
+
+		temp=6666;
+	}
+	
+	data[1]=I2C_MSG_BATTERY_FULL;
+	i2c_putpacket(0x01, data, 2);
+
+}
+
+int main(void)
+{
+	new_second=0;
+	char tempData[5];	//For i2c communication
+	//test_board();
+  
+	setup();
+	i2c_init();
+	
+	
+	/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts
+	PCMSK1 = (_BV(PCINT10)); //enable pin change interrupt on ROBOT_RX
+	MCUCR = (_BV(SE)|_BV(SM1));// (power-down mode)
+	*/
+	
+	OCR1B=0;
+	
+	sei();
+  
+  //test delay_ms
+  PORTB|=_BV(LED2);
+  PORTB|=_BV(LED1);
+  delay_ms(1000);
+  PORTB&=~_BV(LED2);
+  PORTB&=~_BV(LED1);
+	
+	//*******************************
+	while(1)
+		trickle_charge();
+	
+	/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts
+	sleep_cpu();*/
+	
+	PORTB=0;//clear outputs
+	
+	GIMSK = 0;
+	
+	error=0;
+		
+	i2c_init();
+	int volt=0, last_volt=0, same_volt=0;
+	int temp=0, dt;
+	int curr=0;
+	int meas_count;
+	int mod=0;
+	
+	status=FAST_CHARGE;
+	
+	while(1)
+	{
+		mod=abs_time%4;
+		while(abs_time%4==mod);
+		
+		/*if((abs_time>>3)%3==0)
+			OCR1B=21;
+		else if((abs_time>>3)%3==1)
+			OCR1B=57;
+		else
+			OCR1B=85;*/
+		
+		tempData[0] = 'C';
+		tempData[1] = abs_time>>8;
+		tempData[2] = abs_time&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+      /* CONTACT */
+			if(supply_voltage())
+			{
+				//curr = regulate_current(500);
+				curr = get_avg_current();
+				
+				if(status==FAST_CHARGE)
+					OCR1B=50;
+			}
+      /* NO CONTACT */
+			else
+			{
+				curr = 0;
+				OCR1B = 0;
+			}
+		}
+		
+
+		tempData[0] = 'P';
+		tempData[1] = 0;
+		tempData[2] = OCR1B;
+		i2c_putpacket(0x01, tempData, 3);
+		tempData[0] = 'I';
+		tempData[1] = curr>>8;
+		tempData[2] = curr&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		curr=6666;
+		
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			volt = get_avg_voltage();
+		}
+		
+    //Same volt - Last volt upkeep
+		if(volt==last_volt && supply_voltage())
+				same_volt++;
+    else
+    {
+      last_volt = volt;
+      same_volt=0;
+    }
+
+			
+		tempData[0] = 'v';
+		tempData[1] = same_volt>>8;
+		tempData[2] = same_volt&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		
+    /* Voltage Dip Termination */
+		if(volt<last_volt && same_volt>=VOLT_PLATEAU)
+		{
+			OCR1B=0;
+			status=0;
+		}
+
+		tempData[0] = 'V';
+		tempData[1] = volt>>8;
+		tempData[2] = volt&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+
+		volt=6666;
+		
+    //Temp ring buffer upkeep
+		mod=abs_time%4;
+		while(abs_time%4==mod)
+		{
+			temp = get_avg_temperature();			
+		}
+		
+		dt=ring_buffer_d10(temp);
+		
+		tempData[0] = 't';
+		tempData[1] = dt>>8;
+		tempData[2] = dt&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+		
+    /* Temperature Rise Termination */
+		if(dt < MAX_DT && temp < MAX_DT_ABS)
+		{
+			status=0;
+			OCR1B=0;
+		}
+		
+		tempData[0] = 'T';
+		tempData[1] = temp>>8;
+		tempData[2] = temp&0xFF;
+		i2c_putpacket(0x01, tempData, 3);
+
+		temp=6666;
+	}
+
+	
+	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(PCINT_vect){;} //so the interrupt doesnt go to the reset vector
Index: trunk/code/projects/autonomous_recharging/archs/Makefile
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/Makefile	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/Makefile	(revision 80)
@@ -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 = attiny861
+
+
+# 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 = 8000000
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+
+# Target file name (without extension).
+TARGET = ConstantCharging
+
+
+# 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: trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/USI_TWI_Slave.c	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/i2c.c
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/i2c.c	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/i2c.c	(revision 80)
@@ -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: trunk/code/projects/autonomous_recharging/archs/ring_buffer.h
===================================================================
--- trunk/code/projects/autonomous_recharging/archs/ring_buffer.h	(nonexistent)
+++ trunk/code/projects/autonomous_recharging/archs/ring_buffer.h	(revision 80)
@@ -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 */
+
