Subversion Repositories FlightCtrl

Compare Revisions

Ignore whitespace Rev 2441 → Rev 2442

/I2C_Telemetry/trunk/main.c
106,10 → 106,9
#define MIN_CELL_VOLTAGE 330 // max cell volatage for LiPO
unsigned int timer, cells;
 
if(print) printf("\n\rBatt:");
 
timer = SetDelay(500);
if(print) while (!CheckDelay(timer));
if(print) printf("\n\rBatt: %d.%02dV", U_Bat/100, U_Bat%100);
// up to 6s LiPo, less than 2s is technical impossible
for(cells = 2; cells < 7; cells++)
{
175,7 → 174,7
RC_Init();
ADC_Init();
I2C_Init(1);
UBX_Init();
 
Capacity_Init();
LIBTEL_Init(LIB_TEL_COMPATIBLE);
 
182,9 → 181,6
GRN_ON;
sei();
 
 
 
 
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Check connected BL-Ctrls
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
235,6 → 231,7
Fat16_Init();
// initialize the settings
Settings_Init();
UBX_Init();
 
// initialize logging (needs settings)
Logging_Init();
/I2C_Telemetry/trunk/makefile
137,7 → 137,7
SRC += twimaster.c rc.c fc.c GPS.c spi.c led.c Spektrum.c
SRC += mymath.c jetimenu.c capacity.c debug.c
SRC += hottmenu.c sbus.c user_receiver.c
SRC += jeti_ex.c
SRC += jeti_ex.c mkprotocol.c buffer.c
##########################################################################################################
 
 
/I2C_Telemetry/trunk/settings.c
176,8 → 176,7
printf("ERROR: Opening settings file!");
return;
}
// read all lines from file
printf(".reading...");
// read all lines from file
while(fgets_(settingsline, LINE_MAX, fp) != 0 && (SD_WatchDog))
{
 
/I2C_Telemetry/trunk/uart.c
128,7 → 128,7
"8 ",
"Voltage [0.1V] ",
"Receiver Level ", //10
"11 ",
"GOS Data ",
"Motor 1 ",
"Motor 2 ",
"Motor 3 ",
419,7 → 419,19
UDR0 = c;
}
 
/****************************************************************/
/* Send Character */
/****************************************************************/
void USART0_PutString(char * s)
{
while(*s != 0)
{
USART0_PutChar(*s);
s++;
}
}
 
 
/****************************************************************/
/* Set Baudrate of the USART0 */
/****************************************************************/
426,7 → 438,13
void USART0_SetBaudrate(uint32_t baudrate)
{
uint16_t ubrr;
uint8_t sreg = SREG;
 
loop_until_bit_is_set(UCSR0A, UDRE0);
 
// disable all interrupts before configuration
cli();
 
// disable RX-Interrupt
UCSR0B &= ~(1 << RXCIE0);
// disable TX-Interrupt
454,9 → 472,47
// enable TX-Interrupt
UCSR0B |= (1 << TXCIE0);
 
// restore global interrupt flags
SREG = sreg;
 
}
 
 
void UART0_ConnectTo(uint8_t direction)
{
// wait for last bytes to send
loop_until_bit_is_set(UCSR0A, UDRE0);
 
switch(direction)
{
case PC:
TXD_PC_ON;
RXD_PC_ON;
TXD_GPS_OFF;
RXD_GPS_OFF;
break;
 
case GPS:
RXD_GPS_ON;
TXD_GPS_ON;
RXD_PC_OFF;
TXD_PC_OFF;
break;
 
case PC_GPS:
default:
TXD_PC_ON;
RXD_PC_ON;
TXD_GPS_ON;
RXD_GPS_OFF;
break;
}
asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop");
asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop"); asm volatile ("nop");
 
}
 
/****************************************************************/
/* Initialization of the USART0 */
/****************************************************************/
467,6 → 523,8
// disable all interrupts before configuration
cli();
 
UART0_ConnectTo(PC);
 
// disable RX-Interrupt
UCSR0B &= ~(1 << RXCIE0);
// disable TX-Interrupt
487,9 → 545,6
PORTD |= (1 << PORTD1);
DDRD |= (1 << DDD1);
 
// USART0 Baud Rate Register
USART0_SetBaudrate(USART0_BAUD);
 
// USART0 Control and Status Register A, B, C
 
// enable double speed operation
522,7 → 577,10
// enable TX-Interrupt
UCSR0B |= (1 << TXCIE0);
 
// USART0 Baud Rate Register
USART0_SetBaudrate(USART0_BAUD);
 
 
UART_VersionInfo.SWMajor = VERSION_MAJOR;
UART_VersionInfo.SWMinor = VERSION_MINOR;
UART_VersionInfo.SWPatch = VERSION_PATCH;
532,3 → 590,15
// restore global interrupt flags
SREG = sreg;
}
 
 
/**************************************************************/
/* Send a message to the UBLOX device */
/**************************************************************/
uint8_t UART0_UBXSendMsg(uint8_t* pData, uint16_t Len)
{
while(UART0_tx_buffer.Locked) USART0_TransmitTxData(); // output pending bytes in tx buffer;
UBX_CreateMsg(&UART0_tx_buffer, pData, Len); // build ubx message frame
while(UART0_tx_buffer.Locked) USART0_TransmitTxData(); // output pending bytes in tx buffer;
return(1);
}
/I2C_Telemetry/trunk/uart.h
4,6 → 4,14
//Baud rate of the USART
#define USART0_BAUD 57600L
 
#define RXD_PC_ON {PORTD = ~(1<<PORTD4); DDRD &= ~(1<<DDD4);} // input tristate
#define RXD_PC_OFF {DDRD |= (1<<DDD4); PORTD |= (1<<PORTD4);} // output high
#define RXD_GPS_ON {PORTD = ~(1<<PORTD5); DDRD &= ~(1<<DDD5);} // input tristate
#define RXD_GPS_OFF {DDRD |= (1<<DDD5); PORTD |= (1<<PORTD5);} // output high
#define TXD_GPS_ON {PORTB = ~(1<<PORTB2); DDRB &= ~(1<<DDB2);} // input tristate
#define TXD_GPS_OFF {DDRB |= (1<<DDB2); PORTB |= (1<<PORTB2);} // output high
#define TXD_PC_ON {PORTC = ~(1<<PORTC5); DDRC &= ~(1<<DDC5);} // input tristate
#define TXD_PC_OFF {DDRC |= (1<<DDC5); PORTC |= (1<<PORTC5);} // output high
 
// bitmask for UART_VersionInfo_t.HardwareError[0]
#define FC_ERROR0_GYRO_NICK 0x01
35,10 → 43,17
extern void USART0_Init(void);
extern void USART0_SetBaudrate(uint32_t baudrate);
extern void USART0_PutChar(char c);
extern void USART0_PutString(char * s);
extern void USART0_TransmitTxData(void);
extern void USART0_ProcessRxData(void);
 
#define PC 0
#define GPS 1
#define PC_GPS 2
extern void UART0_ConnectTo(uint8_t direction);
extern uint8_t UART0_UBXSendMsg(uint8_t* pData, uint16_t Len);
 
 
extern unsigned char MotorTest[16];
 
struct str_DebugOut
/I2C_Telemetry/trunk/ubx.c
24,9 → 24,9
 
// days per month in normal and leap years
const uint32_t Leap[ 13 ] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
const uint32_t Normal[ 13 ] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
const uint32_t Normal[ 13 ] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
 
#define LEAP_SECONDS_FROM_1980 15 // the last one was on the Dec 31th 2008
#define LEAP_SECONDS_FROM_1980 16
 
// message sync bytes
#define UBX_SYNC1_CHAR 0xB5
35,7 → 35,7
#define UBX_CLASS_NAV 0x01
// message id
#define UBX_ID_POSLLH 0x02
#define UBX_ID_SOL 0x06
#define UBX_ID_SOL 0x06
#define UBX_ID_VELNED 0x12
 
// ------------------------------------------------------------------------------------------------
105,8 → 105,6
uint8_t Status; // invalid/newdata/processed
} __attribute__((packed)) ubx_nav_posllh_t;
 
 
 
//------------------------------------------------------------------------------------
// global variables
 
114,19 → 112,25
volatile ubx_nav_sol_t UbxSol = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, INVALID};
volatile ubx_nav_posllh_t UbxPosLlh = {0,0,0,0,0,0,0, INVALID};
volatile ubx_nav_velned_t UbxVelNed = {0,0,0,0,0,0,0,0,0, INVALID};
ubxmsg_t UbxMsg;
 
uint16_t CheckGPSOkay = 0;
 
 
// shared buffer
gps_data_t GPSData = {{0,0,0,INVALID},0,0,0,0,0,0,0, INVALID};
gps_data_t GPSData = {200,{0,0,0,INVALID},0,0,0,0,0,0,0, INVALID};
DateTime_t GPSDateTime = {0,0,0,0,0,0,0, INVALID};
 
#define UBX_TIMEOUT 500 // 500 ms
uint16_t UBX_Timeout = 0;
 
 
//------------------------------------------------------------------------------------
// functions
 
uint8_t IsLeapYear(uint16_t year)
{
if((year%400 == 0) || ( (year%4 == 0) && (year%100 != 0) ) ) return 1;
else return 0;
if((year%400 == 0) || ( (year%4 == 0) && (year%100 != 0) ) ) return 1;
else return 0;
}
 
/********************************************************/
134,74 → 138,72
/********************************************************/
void SetGPSTime(DateTime_t * pTimeStruct)
{
uint32_t Days, Seconds, Week;
uint16_t YearPart;
uint32_t * MonthDayTab = 0;
uint8_t i;
uint32_t Days, Seconds, Week;
uint16_t YearPart;
uint32_t * MonthDayTab = 0;
uint8_t i;
 
 
 
// if GPS data show valid time data
if((UbxSol.Status != INVALID) && (UbxSol.Flags & FLAG_WKNSET) && (UbxSol.Flags & FLAG_TOWSET) )
{
Seconds = UbxSol.itow / 1000L;
Week = (uint32_t)UbxSol.week;
// correct leap seconds since 1980
if(Seconds < LEAP_SECONDS_FROM_1980)
{
Week--;
Seconds = SECONDS_PER_WEEK - LEAP_SECONDS_FROM_1980 + Seconds;
}
else Seconds -= LEAP_SECONDS_FROM_1980;
// if GPS data show valid time data
if((UbxSol.Status != INVALID) && (UbxSol.Flags & FLAG_WKNSET) && (UbxSol.Flags & FLAG_TOWSET) )
{
Seconds = UbxSol.itow / 1000L;
Week = (uint32_t)UbxSol.week;
// correct leap seconds since 1980
if(Seconds < LEAP_SECONDS_FROM_1980)
{
Week--;
Seconds = SECONDS_PER_WEEK - LEAP_SECONDS_FROM_1980 + Seconds;
}
else Seconds -= LEAP_SECONDS_FROM_1980;
 
Days = DAYS_FROM_JAN01YEAR0001_TO_JAN6_1980;
Days += (Week * DAYS_PER_WEEK);
Days += Seconds / SECONDS_PER_DAY; // seperate days from GPS seconds of week
Days = DAYS_FROM_JAN01YEAR0001_TO_JAN6_1980;
Days += (Week * DAYS_PER_WEEK);
Days += Seconds / SECONDS_PER_DAY; // seperate days from GPS seconds of week
 
pTimeStruct->Year = 1;
YearPart = (uint16_t)(Days / DAYS_PER_400YEARS);
pTimeStruct->Year += YearPart * 400;
Days = Days % DAYS_PER_400YEARS;
YearPart = (uint16_t)(Days / DAYS_PER_100YEARS);
pTimeStruct->Year += YearPart * 100;
Days = Days % DAYS_PER_100YEARS;
YearPart = (uint16_t)(Days / DAYS_PER_4YEARS);
pTimeStruct->Year += YearPart * 4;
Days = Days % DAYS_PER_4YEARS;
if(Days < (3* DAYS_PER_YEAR)) YearPart = (uint16_t)(Days / DAYS_PER_YEAR);
else YearPart = 3;
pTimeStruct->Year += YearPart;
// calculate remaining days of year
Days -= (uint32_t)(YearPart * DAYS_PER_YEAR);
Days += 1;
// check if current year is a leap year
if(IsLeapYear(pTimeStruct->Year)) MonthDayTab = (uint32_t*)Leap;
else MonthDayTab = (uint32_t*)Normal;
// seperate month and day from days of year
for ( i = 0; i < 12; i++ )
{
if ( (MonthDayTab[i]< Days) && (Days <= MonthDayTab[i+1]) )
{
pTimeStruct->Month = i+1;
pTimeStruct->Day = Days - MonthDayTab[i];
i = 12;
}
}
Seconds = Seconds % SECONDS_PER_DAY; // remaining seconds of current day
pTimeStruct->Hour = (uint8_t)(Seconds / SECONDS_PER_HOUR);
Seconds = Seconds % SECONDS_PER_HOUR; // remaining seconds of current hour
pTimeStruct->Min = (uint8_t)(Seconds / SECONDS_PER_MINUTE);
Seconds = Seconds % SECONDS_PER_MINUTE; // remaining seconds of current minute
pTimeStruct->Sec = (uint8_t)(Seconds);
pTimeStruct->mSec = (uint16_t)(UbxSol.itow % 1000L);
pTimeStruct->Valid = 1;
}
else
{
pTimeStruct->Valid = 0;
}
DebugOut.Analog[0]++;
 
pTimeStruct->Year = 1;
YearPart = (uint16_t)(Days / DAYS_PER_400YEARS);
pTimeStruct->Year += YearPart * 400;
Days = Days % DAYS_PER_400YEARS;
YearPart = (uint16_t)(Days / DAYS_PER_100YEARS);
pTimeStruct->Year += YearPart * 100;
Days = Days % DAYS_PER_100YEARS;
YearPart = (uint16_t)(Days / DAYS_PER_4YEARS);
pTimeStruct->Year += YearPart * 4;
Days = Days % DAYS_PER_4YEARS;
if(Days < (3* DAYS_PER_YEAR)) YearPart = (uint16_t)(Days / DAYS_PER_YEAR);
else YearPart = 3;
pTimeStruct->Year += YearPart;
// calculate remaining days of year
Days -= (uint32_t)(YearPart * DAYS_PER_YEAR);
Days += 1;
// check if current year is a leap year
if(IsLeapYear(pTimeStruct->Year)) MonthDayTab = (uint32_t*)Leap;
else MonthDayTab = (uint32_t*)Normal;
// seperate month and day from days of year
for ( i = 0; i < 12; i++ )
{
if ( (MonthDayTab[i]< Days) && (Days <= MonthDayTab[i+1]) )
{
pTimeStruct->Month = i+1;
pTimeStruct->Day = Days - MonthDayTab[i];
i = 12;
}
}
Seconds = Seconds % SECONDS_PER_DAY; // remaining seconds of current day
pTimeStruct->Hour = (uint8_t)(Seconds / SECONDS_PER_HOUR);
Seconds = Seconds % SECONDS_PER_HOUR; // remaining seconds of current hour
pTimeStruct->Min = (uint8_t)(Seconds / SECONDS_PER_MINUTE);
Seconds = Seconds % SECONDS_PER_MINUTE; // remaining seconds of current minute
pTimeStruct->Sec = (uint8_t)(Seconds);
pTimeStruct->mSec = (uint16_t)(UbxSol.itow % 1000L);
pTimeStruct->Valid = 1;
}
else
{
pTimeStruct->Valid = 0;
}
}
 
 
211,209 → 213,243
/********************************************************/
void UBX_Init(void)
{
// mark msg buffers invalid
UbxSol.Status = INVALID;
UbxPosLlh.Status = INVALID;
UbxVelNed.Status = INVALID;
GPSData.Status = INVALID;
// mark msg buffers invalid
UbxSol.Status = INVALID;
UbxPosLlh.Status = INVALID;
UbxVelNed.Status = INVALID;
UbxMsg.Status = INVALID;
GPSData.Status = INVALID;
 
UBX_Setup();
 
UBX_Timeout = SetDelay(2 * UBX_Timeout);
}
 
/********************************************************/
/* Upate GPS data stcructure */
/********************************************************/
void Update_GPSData (void)
void Update_GPSData(void)
{
static uint16_t Ubx_Timeout = 0;
static uint8_t Msg_Count = 0;
static uint32_t last_itow = 0;
 
// the timeout is used to detect the delay between two message sets
// and is used for synchronisation so that always a set is collected
// that belongs together
// _______NAVSOL|POSLLH|VELNED|___________________NAVSOL|POSLLH|VELNED|_____________
// | 8ms | 8ms | 184 ms | | |
// msg_count: 0 1 2 0 1 2
if(CheckDelay(Ubx_Timeout)) Msg_Count = 0;
else Msg_Count++;
Ubx_Timeout = SetDelay(100); // reset ubx msg timeout
// if a new set of ubx messages was collected
if((UbxSol.Status == NEWDATA) && (UbxPosLlh.Status == NEWDATA) && (UbxVelNed.Status == NEWDATA))
{ // and the itow is equal (same time base)
if((UbxSol.itow == UbxPosLlh.itow) && (UbxPosLlh.itow == UbxVelNed.itow))
{
UBX_Timeout = SetDelay(UBX_TIMEOUT);
DebugOut.Analog[11]++;
// update GPS data only if the status is INVALID or PROCESSED
if(GPSData.Status != NEWDATA)
{ // wait for new data at all neccesary ubx messages
GPSData.Status = INVALID;
// update message cycle time
GPSData.MsgCycleTime = (uint16_t)(UbxSol.itow-last_itow);
last_itow = UbxSol.itow; // update last itow
// NAV SOL
GPSData.Flags = (GPSData.Flags & 0xf0) | (UbxSol.Flags & 0x0f); // we take only the lower bits
GPSData.NumOfSats = UbxSol.numSV;
GPSData.SatFix = UbxSol.GPSfix;
GPSData.Position_Accuracy = UbxSol.PAcc; // in steps of 1cm
GPSData.Speed_Accuracy = UbxSol.SAcc; // in steps of 1cm/s
SetGPSTime(&SystemTime); // update system time
// NAV POSLLH
GPSData.Position.Status = INVALID;
GPSData.Position.Longitude = UbxPosLlh.LON; // in steps of 1E-7 deg
GPSData.Position.Latitude = UbxPosLlh.LAT; // in steps of 1E-7 deg
GPSData.Position.Altitude = UbxPosLlh.HMSL; // in steps of 1 mm
GPSData.Position.Status = NEWDATA;
// NAV VELNED
GPSData.Speed_East = UbxVelNed.VEL_E; // in steps of 1cm/s
GPSData.Speed_North = UbxVelNed.VEL_N; // in steps of 1cm/s
GPSData.Speed_Top = -UbxVelNed.VEL_D; // in steps of 1cm/s
GPSData.Speed_Ground = UbxVelNed.GSpeed; // in steps of 1cm/s
GPSData.Heading = UbxVelNed.Heading; //in steps of 1E-5 deg
 
// if a new set of ubx messages was collected
if((Msg_Count >= 2))
{ // if set is complete
if((UbxSol.Status == NEWDATA) && (UbxPosLlh.Status == NEWDATA) && (UbxVelNed.Status == NEWDATA))
{
CheckGPSOkay++;
CountNewGpsDataIn5Sec++;
// update GPS data only if the status is INVALID or PROCESSED and the last ubx message was received within less than 100 ms
if(GPSData.Status != NEWDATA) // if last data were processed
{ // wait for new data at all neccesary ubx messages
GPSData.Status = INVALID;
// NAV SOL
GPSData.Flags = UbxSol.Flags;
GPSData.NumOfSats = UbxSol.numSV;
GPSData.SatFix = UbxSol.GPSfix;
GPSData.Position_Accuracy = UbxSol.PAcc;
GPSData.Speed_Accuracy = UbxSol.SAcc;
SetGPSTime(&SystemTime); // update system time
// NAV POSLLH
GPSData.Position.Status = INVALID;
GPSData.Position.Longitude = UbxPosLlh.LON;
GPSData.Position.Latitude = UbxPosLlh.LAT;
GPSData.Position.Altitude = UbxPosLlh.HMSL;
GPSData.Position.Status = NEWDATA;
// NAV VELNED
GPSData.Speed_East = UbxVelNed.VEL_E;
GPSData.Speed_North = UbxVelNed.VEL_N;
GPSData.Speed_Top = -UbxVelNed.VEL_D;
GPSData.Speed_Ground = UbxVelNed.GSpeed;
GPSData.Heading = UbxVelNed.Heading;
 
GPSData.Status = NEWDATA; // new data available
GPSData.Status = PROCESSED; // TODO:
} // EOF if(GPSData.Status != NEWDATA)
} // EOF all ubx messages received
// set state to collect new data
UbxSol.Status = PROCESSED; // ready for new data
UbxPosLlh.Status = PROCESSED; // ready for new data
UbxVelNed.Status = PROCESSED; // ready for new data
}
GPSData.Status = NEWDATA; // new data available
} // EOF if(GPSData.Status != NEWDATA)
// set state to collect new data
UbxSol.Status = PROCESSED; // ready for new data
UbxPosLlh.Status = PROCESSED; // ready for new data
UbxVelNed.Status = PROCESSED; // ready for new data
} // EOF all itow are equal
} // EOF all ubx messages received
}
 
 
/********************************************************/
/* UBX Parser */
/********************************************************/
void UBX_Parser(uint8_t c)
{
static ubxState_t ubxState = UBXSTATE_IDLE;
static uint16_t msglen;
static uint8_t cka, ckb;
static uint8_t *ubxP, *ubxEp, *ubxSp; // pointers to data currently transfered
static ubxState_t ubxState = UBXSTATE_IDLE;
static ubxmsghdr_t RxHdr;
static uint8_t RxData[UBX_MSG_DATA_SIZE];
static uint16_t RxBytes = 0;
static uint8_t cka, ckb;
 
 
//state machine
switch (ubxState) // ubx message parser
{
case UBXSTATE_IDLE: // check 1st sync byte
if (c == UBX_SYNC1_CHAR) ubxState = UBXSTATE_SYNC1;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
//state machine
switch (ubxState) // ubx message parser
{
case UBXSTATE_IDLE: // check 1st sync byte
if (c == UBX_SYNC1_CHAR) ubxState = UBXSTATE_SYNC1;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
 
case UBXSTATE_SYNC1: // check 2nd sync byte
if (c == UBX_SYNC2_CHAR) ubxState = UBXSTATE_SYNC2;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
case UBXSTATE_SYNC1: // check 2nd sync byte
if (c == UBX_SYNC2_CHAR) ubxState = UBXSTATE_SYNC2;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
 
case UBXSTATE_SYNC2: // check msg class to be NAV
if (c == UBX_CLASS_NAV) ubxState = UBXSTATE_CLASS;
else ubxState = UBXSTATE_IDLE; // unsupported message class
break;
case UBXSTATE_SYNC2: // check msg class to be NAV
if (c == UBX_CLASS_NAV) ubxState = UBXSTATE_CLASS;
else ubxState = UBXSTATE_IDLE; // unsupported message class
break;
 
case UBXSTATE_CLASS: // check message identifier
switch(c)
{
case UBX_ID_POSLLH: // geodetic position
ubxP = (uint8_t *)&UbxPosLlh; // data start pointer
ubxEp = (uint8_t *)(&UbxPosLlh + 1); // data end pointer
ubxSp = (uint8_t *)&UbxPosLlh.Status; // status pointer
break;
case UBXSTATE_CLASS: // check message identifier
RxHdr.Id = c;
ubxState = UBXSTATE_LEN1;
cka = RxHdr.Class + RxHdr.Id;
ckb = RxHdr.Class + cka;
break;
 
case UBX_ID_SOL: // navigation solution
ubxP = (uint8_t *)&UbxSol; // data start pointer
ubxEp = (uint8_t *)(&UbxSol + 1); // data end pointer
ubxSp = (uint8_t *)&UbxSol.Status; // status pointer
break;
case UBXSTATE_LEN1: // 1st message length byte
RxHdr.Length = (uint16_t)c; // lowbyte first
cka += c;
ckb += cka;
ubxState = UBXSTATE_LEN2;
break;
 
case UBX_ID_VELNED: // velocity vector in tangent plane
ubxP = (uint8_t *)&UbxVelNed; // data start pointer
ubxEp = (uint8_t *)(&UbxVelNed + 1); // data end pointer
ubxSp = (uint8_t *)&UbxVelNed.Status; // status pointer
break;
case UBXSTATE_LEN2: // 2nd message length byte
RxHdr.Length += ((uint16_t)c)<<8; // high byte last
if (RxHdr.Length >= UBX_MSG_DATA_SIZE)
{
ubxState = UBXSTATE_IDLE;
}
else
{
cka += c;
ckb += cka;
RxBytes = 0; // reset data byte counter
ubxState = UBXSTATE_DATA;
}
break;
 
default: // unsupported identifier
ubxState = UBXSTATE_IDLE;
break;
}
if (ubxState != UBXSTATE_IDLE)
{
ubxState = UBXSTATE_LEN1;
cka = UBX_CLASS_NAV + c;
ckb = UBX_CLASS_NAV + cka;
}
break;
case UBXSTATE_DATA: // collecting data
if (RxBytes < UBX_MSG_DATA_SIZE)
{
RxData[RxBytes++] = c; // copy curent data byte if any space is left
cka += c;
ckb += cka;
if (RxBytes >= RxHdr.Length) ubxState = UBXSTATE_CKA; // switch to next state if all data have been received
}
else // rx buffer overrun
{
ubxState = UBXSTATE_IDLE;
}
break;
 
case UBXSTATE_LEN1: // 1st message length byte
msglen = (uint16_t)c; // lowbyte first
cka += c;
ckb += cka;
ubxState = UBXSTATE_LEN2;
break;
 
case UBXSTATE_LEN2: // 2nd message length byte
msglen += ((uint16_t)c)<<8; // high byte last
cka += c;
ckb += cka;
// if the old data are not processed so far then break parsing now
// to avoid writing new data in ISR during reading by another function
if ( *ubxSp == NEWDATA )
{
ubxState = UBXSTATE_IDLE;
Update_GPSData(); //update GPS info respectively
}
else // data invalid or allready processd
{
*ubxSp = INVALID; // mark invalid during buffer filling
ubxState = UBXSTATE_DATA;
}
break;
case UBXSTATE_CKA:
if (c == cka) ubxState = UBXSTATE_CKB;
else
{
ubxState = UBXSTATE_IDLE;
}
break;
 
case UBXSTATE_DATA: // collecting data
if (ubxP < ubxEp)
{
*ubxP++ = c; // copy curent data byte if any space is left
cka += c;
ckb += cka;
if (--msglen == 0) ubxState = UBXSTATE_CKA; // switch to next state if all data was read
}
else // rx buffer overrun
{
ubxState = UBXSTATE_IDLE;
}
break;
case UBXSTATE_CKB:
if (c == ckb)
{ // checksum is ok
 
case UBXSTATE_CKA:
if (c == cka) ubxState = UBXSTATE_CKB;
else
{
*ubxSp = INVALID;
ubxState = UBXSTATE_IDLE;
}
break;
switch(RxHdr.Class)
{
case UBX_CLASS_NAV:
switch(RxHdr.Id)
{
case UBX_ID_POSLLH: // geodetic position
memcpy((uint8_t*)&UbxPosLlh, RxData, RxHdr.Length);
UbxPosLlh.Status = NEWDATA;
break;
 
case UBXSTATE_CKB:
if (c == ckb)
{
*ubxSp = NEWDATA; // new data are valid
Update_GPSData(); //update GPS info respectively
}
else
{ // if checksum not match then set data invalid
*ubxSp = INVALID;
}
ubxState = UBXSTATE_IDLE; // ready to parse new data
break;
case UBX_ID_VELNED: // velocity vector in tangent plane
memcpy((uint8_t*)&UbxVelNed, RxData, RxHdr.Length);
UbxVelNed.Status = NEWDATA;
break;
 
default: // unknown ubx state
ubxState = UBXSTATE_IDLE;
break;
case UBX_ID_SOL: // navigation solution
memcpy((uint8_t*)&UbxSol, RxData, RxHdr.Length);
UbxSol.Status = NEWDATA;
break;
 
}
DebugOut.Analog[6] = GPSData.NumOfSats;
/* DebugOut.Analog[10] = GPSData.Speed_East;
DebugOut.Analog[9] = GPSData.Speed_North;
DebugOut.Analog[11] = GPSData.Speed_Top;
DebugOut.Analog[13] = GPSData.Position.Longitude;
DebugOut.Analog[14] = GPSData.Position.Latitude;
DebugOut.Analog[15] = GPSData.Position.Altitude;*/
default:
break;
} // EOF switch(Id)
Update_GPSData();
break;
 
default: // any other class
break;
} // EOF switch(class)
 
// check generic msg filter
if(UbxMsg.Status != NEWDATA)
{ // msg buffer is free
if(((UbxMsg.Hdr.Class & UbxMsg.ClassMask) == (RxHdr.Class & UbxMsg.ClassMask)) && ((UbxMsg.Hdr.Id & UbxMsg.IdMask) == (RxHdr.Id & UbxMsg.IdMask)))
{ // msg matches to the filter criteria
UbxMsg.Status = INVALID;
UbxMsg.Hdr.Class = RxHdr.Class;
UbxMsg.Hdr.Id = RxHdr.Id;
UbxMsg.Hdr.Length = RxHdr.Length;
if(UbxMsg.Hdr.Length <= UBX_MSG_DATA_SIZE)
{ // copy data block
memcpy(UbxMsg.Data, RxData, RxHdr.Length);
UbxMsg.Status = NEWDATA;
}
} // EOF filter matches
} // EOF != INVALID
}// EOF crc ok
ubxState = UBXSTATE_IDLE; // ready to parse new data
break;
 
default: // unknown ubx state
ubxState = UBXSTATE_IDLE;
break;
 
}
}
 
/**************************************************************/
/* Create a UBX Message */
/**************************************************************/
uint8_t UBX_CreateMsg(Buffer_t* pBuff, uint8_t* pData, uint16_t Len)
{
uint16_t i;
uint8_t cka = 0, ckb = 0;
// check if buffer is available
if(pBuff->Locked) return(0);
// check if buffer size is sufficient
if(pBuff->Size < 8 + Len) return(0);
// lock the buffer
pBuff->Locked = 1;
// start at begin
pBuff->Position = 0;
pBuff->pData[pBuff->Position++] = UBX_SYNC1_CHAR;
pBuff->pData[pBuff->Position++] = UBX_SYNC2_CHAR;
for(i=0;i<Len;i++)
{
pBuff->pData[pBuff->Position++] = pData[i];
}
// calculate checksum
for(i=2;i<pBuff->Position;i++)
{
cka += pBuff->pData[i];
ckb += cka;
}
pBuff->pData[pBuff->Position++] = cka;
pBuff->pData[pBuff->Position++] = ckb;
pBuff->DataBytes = pBuff->Position;
pBuff->Position = 0; // reset buffer position for transmision
return(1);
}
 
/I2C_Telemetry/trunk/ubx.h
2,31 → 2,32
#define _UBX_H
 
#include <inttypes.h>
#include "buffer.h"
 
 
// Satfix types for GPSData.SatFix
#define SATFIX_NONE 0x00
#define SATFIX_DEADRECKOING 0x01
#define SATFIX_2D 0x02
#define SATFIX_3D 0x03
#define SATFIX_GPS_DEADRECKOING 0x04
#define SATFIX_TIMEONLY 0x05
#define SATFIX_NONE 0x00
#define SATFIX_DEADRECKOING 0x01
#define SATFIX_2D 0x02
#define SATFIX_3D 0x03
#define SATFIX_GPS_DEADRECKOING 0x04
#define SATFIX_TIMEONLY 0x05
// Flags for interpretation of the GPSData.Flags
#define FLAG_GPSFIXOK 0x01 // (i.e. within DOP & ACC Masks)
#define FLAG_DIFFSOLN 0x02 // (is DGPS used)
#define FLAG_WKNSET 0x04 // (is Week Number valid)
#define FLAG_TOWSET 0x08 // (is Time of Week valid)
#define FLAG_GPSFIXOK 0x01 // (i.e. within DOP & ACC Masks)
#define FLAG_DIFFSOLN 0x02 // (is DGPS used)
#define FLAG_WKNSET 0x04 // (is Week Number valid)
#define FLAG_TOWSET 0x08 // (is Time of Week valid)
 
#define INVALID 0x00
#define NEWDATA 0x01
#define PROCESSED 0x02
#define INVALID 0x00
#define NEWDATA 0x01
#define PROCESSED 0x02
 
typedef struct
{
int32_t Longitude; // in 1E-7 deg
int32_t Latitude; // in 1E-7 deg
int32_t Altitude; // in mm
uint8_t Status; // validity of data
int32_t Longitude; // in 1E-7 deg
int32_t Latitude; // in 1E-7 deg
int32_t Altitude; // in mm
uint8_t Status; // validity of data
} __attribute__((packed)) GPS_Pos_t;
 
 
33,23 → 34,25
 
typedef struct
{
GPS_Pos_t Position; // Lat/Lon/Alt
uint8_t Flags; // Status Flags
uint8_t NumOfSats; // number of satelites
uint8_t SatFix; // type of satfix
uint32_t Position_Accuracy; // in cm 3d position accuracy
int32_t Speed_North; // in cm/s
int32_t Speed_East; // in cm/s
int32_t Speed_Top; // in cm/s
uint32_t Speed_Ground; // 2D ground speed in cm/s
int32_t Heading; // 1e-05 deg Heading 2-D (curent flight direction)
uint32_t Speed_Accuracy; // in cm/s 3d velocity accuracy
uint8_t Status; // status of data
uint16_t MsgCycleTime; // time in ms since last gps data
GPS_Pos_t Position; // Lat/Lon/Alt
uint8_t Flags; // Status Flags
uint8_t NumOfSats; // number of satelites
uint8_t SatFix; // type of satfix
uint32_t Position_Accuracy; // in cm 3d position accuracy
int32_t Speed_North; // in cm/s
int32_t Speed_East; // in cm/s
int32_t Speed_Top; // in cm/s
uint32_t Speed_Ground; // 2D ground speed in cm/s
int32_t Heading; // 1e-05 deg Heading 2-D (curent flight direction)
uint32_t Speed_Accuracy; // in cm/s 3d velocity accuracy
uint8_t Status; // status of data
} __attribute__((packed)) gps_data_t;
 
// The data are valid if the GPSData.Status is NEWDATA or PROCESSED.
// To achieve new data after reading the GPSData.Status should be set to PROCESSED.
extern gps_data_t GPSData;
 
extern uint16_t CheckGPSOkay;
 
#define UBX_CLASS_CFG 0x06
75,9 → 78,11
// set Class and Id and correspoinding masks of a message that should be received
extern ubxmsg_t UbxMsg;
 
extern uint16_t UBX_Timeout;
 
extern void UBX_Init(void);
extern void UBX_Parser(uint8_t c);
extern uint8_t UBX_CreateMsg(Buffer_t* pBuff, uint8_t* pData, uint16_t Len);
 
void UBX_Init(void);
void UBX_Parser(uint8_t c);
 
#endif // _UBX_H