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; }
header
#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