under construction...
===== demo code =====
#include
#include
#include
#include
#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<>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(lenghtPOS_START)
((u08*)&gps)[POS_OFFSET-lenght]=c;
}
if(id==VELNED_DATA)
{
if(lenghtVEL_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