UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:i2c_eeprom

This is an old revision of the document!


I2Cmem.c

#include "i2cmem.h"
#ifdef EEPROM
 
//----------General I2C functions-------------------------------------------------------------------------
 
volatile u08 I2Cerr;
 
void init_i2c()
{
	TWBR=(u08)((float)F_CPU/(2*SCL)-8.0);	//sets the correct clock rate defined as SCL
}											//we dont need to enable the hardware - its done in write
 
void i2cstart()
{
	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	//send start
	while (!(TWCR & (1<<TWINT)));			//wait for a start to be transmitted
	if (((TWSR & 0xF8) != TW_START)&&((TWSR & 0xF8) != TW_REP_START))
		I2Cerr|=1;							//error
}
 
void i2cstop()
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
	while (!(TWCR & (1<<TWSTO)));			//wait for stop to be sent
}
 
void i2cwrite(u08 c)
{
	TWDR = c;								//load the data
	TWCR = (1<<TWINT)|(1<<TWEN);
	while (!(TWCR & (1<<TWINT)));			//wait for it to be sent
	if ( ((TWSR & 0xF8) !=TW_MT_SLA_ACK) & ((TWSR & 0xF8) !=TW_MR_SLA_ACK) )
		I2Cerr|=2;							//error
}
 
u08 i2cread(u08 AK)
{
	u16 timeout=1;
	TWCR=AK;
	while (!(TWCR & (1<<TWINT)) & timeout)
		timeout++;							//wait for it to be recieved
	if(!timeout)
		I2Cerr|=8;							//timeout out waiting for data error
	if((TWSR & 0xF8) !=TW_MR_DATA_ACK)
		I2Cerr|=4;
	return TWDR;
}
 
//----------EEPROM specific stuff-------------------------------------------------------------------------
//Designed for 12 byte records atm
 
void set_address(u32 * address)					//Sets an address from a paointer - cannot switch between physical devices
{
	i2cstart();
	i2cwrite(SLA_W|(((*address)>>13)&0x08));	//the block
	i2cwrite((u08)((*address)>>8));				//address write MSB
	i2cwrite((u08)(*address));					//address write LSB
}	
 
void write_data(u08 * c, u08 datasize, u32 * address)//The address will be incremented as the data is written
{
	u08 n;										//up to 256 bytes can be written at once
	for(n=0;n<datasize;n++,(*address)++)
	{
		if(!((u08)*address)&0xEF)				//check the address for overflow for the 7 LSB
		{
			i2cstop();							//triggers a page write
			_delay_loop_2( (u16) ( (float)F_CPU*0.003/4.0 ) );//delay 3 ms for page write
			set_address(address);				//set the new address
		}
		i2cwrite(c[n]);							//write the data
	}
}
 
void read_data(u08 * destination, u08 datasize, u32 * address)//Reads a block of data from some address
{
	u08 n;
	datasize--;
	i2cstart();
	i2cwrite(SLA_R|(((*address)>>13)&0x08));	//set read to the correct block
	for(n=0;n<datasize;n++)
	{
		destination[n]=i2cread(_AK_);
		(*address)++;							//increment our pointer
		if(!(u16)*address)						//we reached the end of the block
		{
			i2cstop(); 
			set_address(address);
		}
	}
	destination[datasize+1]=i2cread(_NAK_);		//send NAK for the last byte recieved
}
 
u32 findtop()									//Find the address of record number where we enter painted eeprom
{
	u32 top=0;									//half way through rounded to nearest 12
	u08 n;
	for(n=17;n;)								//start by probing half way through
	{
		n--;
		top+=1<<n;								//trial setting of bit
		top = 12*( (u32) (top/12) );			//round down to nearest 12
		set_address(&top);						//the probe address
		if(i2cread(_NAK_)==MAGIC_NUMBER)		//see if its painted
			top-=1<<n;							//clear the nth bit
	}
	top =12*( (u32) (top/12) );					//make sure our answer is rounded correctly
	return top;
}
 
void painteeprom()								//Paints every 12th location with the magic number
{
	u08 magic=MAGIC_NUMBER;						//magic is our painting value
	u32 n=0;
	for(n=0;n<131072;n+=11)						//need to skip 11 bytes between each write location
	{
		set_address(&n);						//set the eeproms internal address register
		write_data(&magic,1,&n);				//write the data
	}
}
#endif

I2Cmem.h

#include "global.h"
#include "avrlibdefs.h"
#include "avrlibtypes.h"
#include "matrix.h"
#include "kalman.h"
#include "TSIP.h"
#include "rprintf.h"
#include "i2cmem.h"
#include <avr/io.h>
#include <stdlib.h>
#include <math.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay_basic.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
 
#define BAUDRATE (int)9600						//9600 baud for lassen iq
#define DELTA_TIME (float)0.02					//20ms
#define DELAY _delay_loop_2((u16)((float)F_CPU/(4.0*(float)BAUDRATE)))	//delay for suart routine
#define SET	PORTD |= 0x10						//PORTD.4 is the tx
#define CLEAR PORTD &= ~0x10
 
//kalman filter - NOTE: these constants are airframe specific
#define CONTROL_GAIN (float)PI/4.0				//full control input of 1 gives ~ this turn rate
#define DAMPING_CONSTANT (float)0.3				//approx how fast oscillations die down as faction per second
 
#define TOP_COUNT (u16)((float)F_CPU*DELTA_TIME/8.0)		//timer1 pwm frequency
#define PWM_COUNT_TIME (u16)((float)F_CPU*0.0005/8.0)			//500us
 
#define I_C -0.001								//control loop
#define P_C -0.3
#define D_C -0.5
#define INTEGRAL_LIMIT 0.2/I_C					//integral servo shift limited to 1/5 of full scale range
 
#define SCALEHEIGHT (float)(-1.0/160.0)			//optimised descent- 1/( atm scale height in 100m units * 2) - http://en.wikipedia.org/wiki/Scale_height
#define WEIGHTINGFACTOR (float)(20.0)/(1012000.0)//time to drop 100m at STP/one radian expressed as meters on earth surface
 
#define read_rate (u08)0b10010100				//gyro specific
#define read_temp (u08)0b10011100
#define read_melexis (u08)0x80
 
#define gyro_null 1012
 
#define altitudelimit 10000						//flight termination conditions
#define timelimit 30							//NOTE: for debug
 
#define targeteast (float)(-1.0*Deg2rad)		//target waypoint ~ Cambridge
#define targetnorth (float)(52.0*Deg2rad)
 
#define Rad2deg 180.0/PI						//bloody obvious
#define Deg2rad PI/180.0
 
#define PRINT_COMMA rprintfChar(pgm_read_byte(&comma))	//prints a comma
 
#define battery_factor (float)0.02505			//for measuring battery voltage- checked from test
#define battery_chan 0x00						//ADC0
 
#define toggle_pin PIND=0x20					//led on port D.5
 
#define BAUDDIV  (u16)( ((float)F_CPU/(BAUDRATE*16UL)) -1 )//baud divider
 
#define radio_cts bit_is_set(PIND,2)			//hardware, however its wired up
 
#define led_left PORTC = ((PORTC & ~0x0C) | 0x04)
#define led_right PORTC = ((PORTC & ~0x0C) | 0x08)
 
#define USER_PRESENT !(PINC&0x02)
 
#define cutter_on PORTD|=(1<<7)					//release mechanism (hot resistor off mosfet)
#define cutter_off PORTD&=~(1<<7)
 
#define DISABLE_SMPS PORTD|=(1<<6)				//turns the SMPS for the servo on/off - never send pwm if its off
#define ENABLE_SMPS PORTD&=~(1<<6)
 
#define GYRO_OFF PORTB|=1<<1					//SS line
#define GYRO_ON PORTB&=~(1<<1)
 
#ifdef ADCSRA
	#ifndef ADCSR
		#define ADCSR   ADCSRA
	#endif
#endif
#ifdef ADATE
	#define ADFR    ADATE
#endif
#ifdef GROUND
	#define enable_ground_control	TIMSK1|=(1<<ICIE1)			//enables the input capture interrupt
	#define disable_ground_control	TIMSK1&=~(1<<ICIE1)			//disables input capture interrupt
	#define PULSE_MIN 0.001*F_CPU/8								//pwm must be in the range 1 to 2 ms
	#define PULSE_MAX 0.002*F_CPU/8
	#define GROUND_LED_ON PORTD|=(1<<3)
	#define GROUND_LED_OFF PORTD&=~(1<<3)
	#define GROUND_LED_SET PORTD&(1<<3)
#endif
 
typedef struct
{
	float vup;
	float vnorth;
	float veast;
	float time;
	float altitude;
	float longitude;
	float latitude;
	u08 packetflag;								//packetflag lets us see when our packet has been updated
	u08 status;
	u08 nosats;
} gps_type;
 
void put_char(unsigned char c);							//talk to the UART
void suart_send(char c);
void run_ground_control();
void _delay_10ms(char time);
float driftfactor(int altitude);
code/i2c_eeprom.1225956559.txt.gz · Last modified: 2008/11/06 07:29 by laurenceb

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki