code:interrupt_driven_ubx
under construction…
demo code
#include <stdlib.h> #include <stdio.h> #include <avr/interrupt.h> #include <avr/io.h> #include "ubx.h" volatile ubx_gps_type Gps; 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); void main(void) { UCSR0B = (1<<RXCIE0)|(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 stdout = &mystdout; sei(); //enable interrupts TOGGLE_PIN; for(;;) { if(Gps.packetflag==REQUIRED_DATA) { printf("%li,%li,%li,%2X,%2X\n",Gps.latitude,Gps.longitude,Gps.altitude,Gps.status,Gps.nosats); Gps.packetflag=0; //unlock the data } } } ISR(USART_RX_vect) //UART interrupt on mega xx8 series { static u08 state,class,id,checksum_1,checksum_2,counter; static u16 lenght; static ubx_gps_type gps; u08 c = UDR0; 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; counter=0; 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; /*if(id==SVINFO_DATA)//this appears to find the number of hardware channels avaliable { counter++;//this counts from the start of data if(counter==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==SVINFO_DATA) gps.packetflag|=0x08; if(id==SOL_DATA) gps.packetflag|=0x04; if(id==LLH_DATA) gps.packetflag|=0x02; if(id==VELNED_DATA) gps.packetflag|=0x01; } if(!Gps.packetflag && gps.packetflag==REQUIRED_DATA)//main has unlocked the data and we have all the required data { TOGGLE_PIN;//toggles pin D5 - flashing LED tells us gps is working Gps=gps;//copy into the global variable gps.packetflag=0;//we now wait for more data to arrive } //complete } 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; } }
header
typedef unsigned char u08; typedef uint16_t u16; typedef uint32_t u32; typedef int32_t 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 REQUIRED_DATA 0x0F #define LLH_DATA 0x02 #define VELNED_DATA 0x12 #define SVINFO_DATA 0x30 #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 38400UL #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/interrupt_driven_ubx.txt · Last modified: 2009/05/11 20:17 by laurenceb