30、GPS L1星历处理实现

\qquad 下面是HD-GR GNSS导航软件的GPS L1星历处理实现代码,入口函数gps_ephemeris_task (…):

// gps_ephemeris.c -- GPS L1 ephemeris processing.

/* 
 * Copyright (C) 2005 Andrew Greenberg
 * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
 * See the "COPYING" file distributed with this software for more information.
 */

/* Namuru GPS receiver project
 * Original : ephemeris.c
 * Modes    : LED handling for debugging commented/replaced
 * version  : V1.0
 * date     : 21st/Dec/2006
 */

/* 
 * HD-GR GNSS receiver project
 * Modes    : Inherited the code of ephemeris.c and ephemeris.h in the Namuru 
 *            GPS receiver project V1.0 and made necessary adjustments to adapt 
 *            to the new RTOS and functions.
 * version  : V1.0
 * date     : xx/xx/2015
 */

#include <io.h>
#include <stdio.h>
#include <math.h>
#include "includes.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "gnsstime.h"
#include "gps_message.h"
#include "gps_ephemeris.h"
#include "gps_almanac.h"

/******************************************************************************
 * Defines
 ******************************************************************************/

/******************************************************************************
 * Globals
 ******************************************************************************/

gps_ephemeris_t g_gps_ephemeris[GPS_MAX_CHANNELS];
gps_ephemeris_t m_gps_ephetable[GPS_MAX_SATELLITES];

unsigned short m_gps_new_almanac = 0;	// 有新历书有待保存标志
int g_gps_alm_savtime = 0;				// 历书上次保存时间(秒)

/******************************************************************************
 * Statics
 ******************************************************************************/

// None

/******************************************************************************
 * Initialize ephemeris table.
 ******************************************************************************/
void gps_initialize_ephetable( void)
{
	unsigned short sv;
	for (sv=0; sv<GPS_MAX_SATELLITES; sv++) {
		m_gps_ephetable[sv].valid = 0;
	}
}

/******************************************************************************
 * If the channel is reallocated, then clear the ephemeris data for that
 * channel. Called from allocate.c
 ******************************************************************************/
void gps_clear_ephemeris(unsigned short ch)
{
	g_gps_ephemeris[ch].valid = 0;
	g_gps_ephemeris[ch].have_subframe = 0;
	g_gps_ephemeris[ch].prn = 0;
}

   
/******************************************************************************
 * Convert subframe bits to ephemeris values.
 *
 * Note that subframes aren't passed up from the message_thread unless they're
 * already considered valid (all parity checks have passed and been removed)
 ******************************************************************************/
static void gps_process_subframe1(unsigned short ch)
{
	signed long temp;
	unsigned long utemp;

	// map the messages structure to OSGPS's "sf"
	gps_subframe_t * sf = m_gps_messages[ch].subframes;
	unsigned short sv = m_gps_messages[ch].prn-1;
    
	// Calculate the `Issue Of Data Clock' (IODC)
	utemp = ((sf[1-1].word[3-1] & 0x3) << 8 ) | (sf[1-1].word[8-1] >> 16);
    
	// Skedaddle if we already have a valid ephemeris and we have this subframe,
	// and the IODC hasn't changed.
	if ((m_gps_ephetable[sv].valid) &&
		(m_gps_ephetable[sv].have_subframe & (1 << 0))&&
		(m_gps_ephetable[sv].iodc == (unsigned short)utemp)) {
		return;
	}
        
	g_gps_ephemeris[ch].iodc = (unsigned short)utemp;
    
	g_gps_ephemeris[ch].ura = (unsigned short)((sf[1-1].word[3-1] & 0xF00) >> 8);
	g_gps_ephemeris[ch].health = (unsigned short)((sf[1-1].word[3-1] & 0xFC) >> 2);

	// According to ICD-GPDS-200C sect. 20.3.3.3.1.4, if the MSB of the 6 bit
	// health is set, the satellite's nav message is toast. Bad satellite!
	if (g_gps_ephemeris[ch].health & (1 << 5)) {
#ifdef GNSS_ENABLE_MUTEX
		OSMutexPend(m_EphTabMutex, 0, &err);
#endif
		m_gps_ephetable[sv].valid = 0;
#ifdef GNSS_ENABLE_MUTEX
		OSMutexPost(m_EphTabMutex);
#endif
		return;
	}
    
	// Grab the PRN for good measure
	g_gps_ephemeris[ch].prn = m_gps_messages[ch].prn;

	// If we haven't already, then update the time with the week number in
	// this subframe. Note that we have NO stinking clue what the true
	// year is because the week is modulo 1024 which is about 20 years.
	// So we'll just guess it's past 2000 :) and before ~ 2020 which
	// means adding 1024 to the current week.
	utemp = (sf[1-1].word[3-1] >> 14) + 1024;
	set_time_with_weeks( (unsigned short)utemp, 0);
    
	// Get the rest of the ephemerides         
	utemp = sf[1-1].word[8-1] & 0xffff;
	g_gps_ephemeris[ch].toc = (double)(utemp << 4);
	//	g_gps_ephemeris[ch].toc = (double)utemp * c_2p4;

	// The following variables are signed integers so if the MSB is set,
	// 'deal 
	// with the sign. Standard sign extending |= 0xFFFFFF00 wasn't
	// working for whatever reason?! Yes, this sucks but the if makes it
	// faster than another multiply, even by -1.
	// TODO try (-((1<<n) - x)) for (x) of (n)bits.
	temp = sf[1-1].word[7-1] & 0xff;
	if (temp & (1 << 7))
		temp |= ~0xff;
	g_gps_ephemeris[ch].tgd = (double)temp * c_2m31;
            
	temp = sf[1-1].word[9-1] >> 16;
	if (temp & (1 << 7))
		temp |= ~0xff;
	g_gps_ephemeris[ch].af2 = (double)temp * c_2m55;

	temp = sf[1-1].word[9-1] & 0xffff;
	if (temp & (1 << 15))
		temp |= ~0xFFFF;
	g_gps_ephemeris[ch].af1 = (double)temp * c_2m43;
            
	temp = sf[1-1].word[10-1] >> 2;
	if (temp & (1 << 21))
		temp |= ~0x3FFFFF;
	g_gps_ephemeris[ch].af0 = (double)temp * c_2m31;
    
	// Got subframe 1
	g_gps_ephemeris[ch].have_subframe |= (1 << 0);
}
        

static void gps_process_subframe2( unsigned short ch)
{
	long temp;
	unsigned long ultemp;
	unsigned short short_temp;

	// map the messages structure to OSGPS's "sf"
	gps_subframe_t * sf = m_gps_messages[ch].subframes;
	unsigned short sv = m_gps_messages[ch].prn-1;

	short_temp = (unsigned short)(sf[2-1].word[3-1] >> 16);

	// If we already have a valid ephemeris, and we have this
	// subframe, and the `Issue Of Data Ephemeris' (IODE) hasn't changed.
	if ((m_gps_ephetable[sv].valid) &&
		(m_gps_ephetable[sv].have_subframe & (1 << 1)) &&
		(m_gps_ephetable[sv].iode1 == short_temp)) {
		return;
	}

	// Some of these data words are signed; check their sign bit and extend
	// as appropriate

	g_gps_ephemeris[ch].iode1 = (unsigned short)short_temp;

	// Grab the PRN for good measure    
	g_gps_ephemeris[ch].prn = m_gps_messages[ch].prn;

	temp = sf[2-1].word[3-1] & 0xFFFF;
	if (temp & (1 << 15))
		temp |= ~0xFFFF;
	g_gps_ephemeris[ch].crs = (double)temp * c_2m5;
    
	temp = sf[2-1].word[4-1] >> 8;
	if (temp & (1 << 15))
		temp |= ~0xFFFF;
	g_gps_ephemeris[ch].dn = (double)temp * (c_2m43 * PI);

	temp = ((sf[2-1].word[4-1] & 0xFF) << 24) | sf[2-1].word[5-1];
	g_gps_ephemeris[ch].ma = (double)temp * (c_2m31 * PI);

	temp = sf[2-1].word[6-1] >> 8;
	if (temp & (1 << 15))
		temp |= ~0xFFFF;
	g_gps_ephemeris[ch].cuc = (double)temp * c_2m29;

	temp = ((sf[2-1].word[6-1] & 0xFF) << 24) | sf[2-1].word[7-1];
	g_gps_ephemeris[ch].ety = (double)temp * c_2m33;

	temp = sf[2-1].word[8-1] >> 8;
	if (temp & (1 << 15))
		temp |= ~0xFFFF;
	g_gps_ephemeris[ch].cus = (double)temp * c_2m29;

	ultemp = (((sf[2-1].word[8-1] & 0xFF) << 24) | sf[2-1].word[9-1]);
	g_gps_ephemeris[ch].sqra = (double)ultemp * c_2m19;
    
	ultemp = (sf[2-1].word[10-1] >> 8);
//	g_gps_ephemeris[ch].toe = (double)ultemp * c_2p4;
	g_gps_ephemeris[ch].toe = (double)(ultemp << 4);

	// Got subframe 2
	g_gps_ephemeris[ch].have_subframe |= (1 << 1);
}
        
            
static void gps_process_subframe3( unsigned short ch)
{
	long temp;
	unsigned short short_temp;

	// map the messages structure to OSGPS's "sf"
	gps_subframe_t * sf = m_gps_messages[ch].subframes;
	unsigned short sv = m_gps_messages[ch].prn-1;

	short_temp  =  (unsigned short)(sf[3-1].word[10-1] >> 16);

	// If we already have a valid ephemeris, we have this subframe,
	// and the IODE hasn't changed.

	if ((m_gps_ephetable[sv].valid) &&
		(m_gps_ephetable[sv].have_subframe & (1 << 3)) &&
		(m_gps_ephetable[sv].iode2 == short_temp)) {
		return;
	}

	// Some of these data words are signed; check their sign bit and extend
	// as appropriate

	g_gps_ephemeris[ch].iode2 = (unsigned short)short_temp;

	// Grab the PRN for good measure    
	g_gps_ephemeris[ch].prn = m_gps_messages[ch].prn;

	// Some of these data words are signed; check their sign bit and extend
	// as appropriate

	temp = sf[3-1].word[3-1] >> 8;
	if (temp & (1 << 15))
		temp |=  ~0xFFFF;
	g_gps_ephemeris[ch].cic = (double)temp * c_2m29;

	temp = ((sf[3-1].word[3-1] & 0xFF) << 24) | sf[3-1].word[4-1];
	g_gps_ephemeris[ch].w0 = (double)temp * (c_2m31 * PI);

	temp = sf[3-1].word[5-1] >> 8;
	if (temp & (1 << 15))
		temp |=  ~0xFFFF;
	g_gps_ephemeris[ch].cis = (double)temp * c_2m29;

	temp = ((sf[3-1].word[5-1] & 0xFF) << 24) | sf[3-1].word[6-1];
	g_gps_ephemeris[ch].inc0 = (double)temp * (c_2m31 * PI);

	temp = sf[3-1].word[7-1] >> 8;
	if (temp & (1 << 15))
		temp |=  ~0xFFFF;
	g_gps_ephemeris[ch].crc = (double)temp * c_2m5;
    
	temp = ((sf[3-1].word[7-1] & 0xFF) << 24) | sf[3-1].word[8-1];
	g_gps_ephemeris[ch].w = (double)temp * (c_2m31 * PI);

	temp = sf[3-1].word[9-1];
	if (temp & (1 << 23))
		temp |=  ~0xFFFFFF;
	g_gps_ephemeris[ch].omegadot = (double)temp * (c_2m43 * PI);
    
	temp = (sf[3-1].word[10-1] >> 2) & 0x3FFF;
	if (temp & (1 << 13))
		temp |=  ~0x3FFF;
	g_gps_ephemeris[ch].idot = (double)temp * (c_2m43 * PI);

	// Got subframe 3
	g_gps_ephemeris[ch].have_subframe |=  (1 << 2);
}

static void gps_process_subframe4( unsigned short ch)
{
	gps_almanac_process_subframe4(ch);

	// Sure, you got subframe 4, why not?
	g_gps_ephemeris[ch].have_subframe |=  (1 << 3);
}
    
static void gps_process_subframe5( unsigned short ch)
{
	gps_almanac_process_subframe5(ch);

	// Sure, you got subframe 5, why not?
	g_gps_ephemeris[ch].have_subframe |=  (1 << 4);
}

void gps_ephemeris_task(OS_FLAGS channels_ready)
{
	INT8U err;
	unsigned short ch, sv;
    OS_FLAGS subframes;
    
	for (ch = 0; ch < GPS_MAX_CHANNELS; ch++) {
		if (channels_ready & (1 << ch)) {
			subframes = OSFlagAccept(m_EphemerisSubframeFlags[ch], 0x01f,
				OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME, &err);

			// Look for subframes to process
			if (subframes & (1 << 0)) {
				gps_process_subframe1(ch);
			}

			if (subframes & (1 << 1)) {
				gps_process_subframe2(ch);
			}

			if (subframes & (1 << 2)) {
				gps_process_subframe3(ch);
			}

			// Almanac decoding
			if (subframes & (1 << 3)) {
				gps_process_subframe4(ch);
			}

			if (subframes & (1 << 4)) {
				gps_process_subframe5(ch);
			}

			// We've processed all available subframes in this channel.
			if (((g_gps_ephemeris[ch].have_subframe & 7) == 7) &&
				(g_gps_ephemeris[ch].ura < 8) &&
				(g_gps_ephemeris[ch].iode2 == g_gps_ephemeris[ch].iode1) &&
				((g_gps_ephemeris[ch].iodc & 0xff) == g_gps_ephemeris[ch].iode1)) {
				// Save g_gps_ephemeris[ch] to m_gps_ephetable[sv]
				sv = g_gps_ephemeris[ch].prn-1;
#ifdef GNSS_ENABLE_MUTEX
				OSMutexPend(m_EphTabMutex, 0, &err);
#endif
				m_gps_ephetable[sv] = g_gps_ephemeris[ch];
				m_gps_ephetable[sv].valid = 1;
#ifdef GNSS_ENABLE_MUTEX
				OSMutexPost(m_EphTabMutex);
#endif
				// Clear g_gps_ephemeris[ch], so as not to save the same results 
				// when the ephemeris is not updated.
				gps_clear_ephemeris(ch);
//					g_gps_ephemeris[ch].valid = 1;
			}
			else {
//					g_gps_ephemeris[ch].valid = 0;
			}
        }
    }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值