UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


code:i2c_ubx
#include <stdlib.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/wdt.h>
 
#include "ubx.h"
#include "i2c.h"
extern volatile u08 I2Cerr; 
 
volatile u08 gps_arrived;
ubx_gps_type* get_gps(void);
 
int uart_putchar(char c, FILE *stream)
{
	if (c == '\n')
		uart_putchar('\r', stream);
	loop_until_bit_is_set(UCSR0A, UDRE0);
	UDR0 = c;
	return 0;
}
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar,NULL,_FDEV_SETUP_WRITE);
 
u16 probe_gps(void)
{
	i2cstart();
	i2cwrite(UBLOX_WRITE);
	i2cwrite(0xFD);
	i2cstart();
	i2cwrite(UBLOX_READ);
	u16 size=i2cread(_AK_)<<8;
	size|=i2cread(_NAK_);
	i2cstop();
	return size; 
}
 
 
void main(void)
{
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);//mega xx8 registers - enable tx and rx, with interrupts on RX only
	UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);	//setup 8N1
	UBRR0L = BAUDDIV;
	UBRR0H = BAUDDIV>>8;			//end of UART setup
	DDRD|=0x20;				//use portd 5 as an output for led
	PORTC|=0x30;				//i2c pullups
	DDRC=0x00;
	TCCR0B=(1<<CS02)|(1<<CS00);		//setup F_CPU/1024
	TIMSK0=1<<TOIE0;			//enable overflow interrupts
	stdout = &mystdout;
	ubx_gps_type* Gps;
	sei();					//enable interrupts
	init_i2c();
	u08 a;
	TOGGLE_PIN;
	printf("something screwed up\n");
	wdt_enable(WDTO_500MS);
	for(;;)
	{
		if(gps_arrived)
		{
			I2Cerr=0;			
			gps_arrived=0;
			Gps=get_gps();
			TOGGLE_PIN;
			wdt_reset();
			printf("%d,%2x\n",I2Cerr,Gps->packetflag);
			printf("%li,%li,%li,%li,%li,%li,%1X,%1X\n",Gps->latitude,Gps->longitude,Gps->altitude,Gps->vnorth,Gps->veast,Gps->vdown,Gps->status,Gps->nosats);
		}
	}
}
 
ISR(TIMER0_OVF_vect)					//overflow interrupt checks for data
{
	/*if(!probe_gps(void));
		TIMER0=SHORT_DELAY;
	else
	{
		TIMER0=LONG_DELAY;
		gps_arrived=0xF0;
	}*/
	if(probe_gps()>130)					//we have all the data
		gps_arrived=0xFF;
}
 
ubx_gps_type*get_gps(void)
{
	TIMSK0&=~(1<<TOIE0);				//disable the buffer polling while we empty the buffer
	static ubx_gps_type gps;
	u08 state,class,id,checksum_1,checksum_2,c;
	u16 lenght;
	i2cstart();
	i2cwrite(UBLOX_READ);
	//if(gps.packetflag==REQUIRED_DATA)
		gps.packetflag=0;			//reset the flag when we have gathered all the data
	while(gps.packetflag!=REQUIRED_DATA)
	{
		c = i2cread(_AK_);
		//printf("%2X\n",c);
		switch(state)
		{
			case 0:				//start be waiting for the first sync byte
				if(c==SYNC_1)
					state=1;
				else
					state=0;
				break;
			case 1:				//followed by the second one
				if(c==SYNC_2)
 
					state=2;
				else
					state=0;
				break;
			case 2:				//then store the class
				class=c;
				state=3;
				break;
			case 3:				//then the id
				id=c;
				state=4;
				break;
			case 4:				//the least significant byte of the lenght 
				lenght=c;
				state=5;
				break;
			case 5:				//the most significant byte
				lenght|=c<<8;
				state=6;
				break;
			case 6:				//the data follows
				if(class==NAV_CLASS)	//we have nav data
				{
					if(id==LLH_DATA)//needs macros defining in the header file for the correct data positions
					{
						if(lenght<POS_END && lenght>POS_START)
							((u08*)&gps)[POS_OFFSET-lenght]=c;
					}
					if(id==VELNED_DATA)
					{
						if(lenght<VEL_END && lenght>VEL_START)
							((u08*)&gps)[VEL_OFFSET-lenght]=c;
					}
					if(id==SOL_DATA && lenght==SOL_POS)
						gps.status=c;
					if(id==SOL_DATA && lenght==SATS_POS)
						gps.nosats=c;
				}
				lenght--;
				if(!lenght)		//we have reached the end of the data
					state=7;
				break;
			case 7:				//check the checksum
				if(checksum_1==c)
					state=8;
				else
					state=0;
				break;
			case 8:				//second byte of the checksum
				if(checksum_2==c)
				{
					if(class==NAV_CLASS)//if the class was NAV and we have valid id
					{
						if(id==SOL_DATA)
							gps.packetflag|=0x04;
						if(id==LLH_DATA)
							gps.packetflag|=0x02;
						if(id==VELNED_DATA)
							gps.packetflag|=0x01;
					}
				}
				state=0;
		}
		if(state>2 && state<8)			//in the valid range to add to the checksum
		{
			checksum_1+=c;
			checksum_2+=checksum_1;
		}
		else if(!state)
		{
			checksum_1=0;
			checksum_2=0;
		}
	}
	c=i2cread(_NAK_);
	i2cstop();
	TIMSK0|=(1<<TOIE0);
	return &gps;
}
#include <stdlib.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
typedef unsigned char u08;
typedef unsigned int u16;
typedef unsigned long u32;
typedef signed long s32;
typedef struct
{
	u32 time;					//milliseconds/week
	s32 vnorth;					//cm/s
	s32 veast;
	s32 vdown;
	s32 longitude;					//degrees/10^-7
	s32 latitude;
	s32 altitude;					//height/mm
	u08 packetflag;					//packetflag lets us see when our packet has been updated
	u08 status;					//type of fix
	u08 nosats;					//number of tracked satellites
} ubx_gps_type;
#define UBLOX 0x90
#define UBLOX_WRITE UBLOX
#define UBLOX_READ UBLOX|0x01
#define REQUIRED_DATA 0x07
#define DATA_LENGHT 130
#define LLH_DATA 0x02
#define VELNED_DATA 0x12
#define SOL_DATA 0x06
#define NAV_CLASS 0x01
#define SATS_POS 5
#define SOL_POS 42
#define POS_OFFSET 40
#define POS_START 12
#define POS_END 25
#define VEL_OFFSET 36 
#define VEL_START 20
#define VEL_END 37
#define SYNC_1 0xB5
#define SYNC_2 0x62
 
#define BAUDRATE 19200UL
//#define BAUDDIV 32
#define BAUDDIV  (u16)( ((float)F_CPU/(BAUDRATE*16UL)) -1 )//baud divider
#define TOGGLE_PIN PIND=0x20				//led on port D.5
code/i2c_ubx.txt ยท Last modified: 2009/05/27 21:30 by laurenceb