⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ephemeris.c

📁 此程序为GPS接收机的源码
💻 C
字号:
// ephemeris.c gpl-gps Satellite navigation message to 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.#include <cyg/kernel/kapi.h>#include <cyg/infra/diag.h>#include <math.h>#include "constants.h"#include "ephemeris.h"#include "gp4020.h"#include "gp4020_io.h"#include "message.h"#include "switches.h"#include "time.h"/****************************************************************************** * Defines ******************************************************************************/// c_2pX == 2^+X, c_2mX == 2^-X#define c_2p4     16.0#define c_2m5     0.03125#define c_2m11    4.8828125e-4#define c_2m19    1.9073486328125e-6#define c_2m20    9.5367431640625e-7#define c_2m21    4.76837158203125e-7#define c_2m23    1.19209289550781e-7   // NaN#define c_2m24    5.96046447753906e-8   // Nan#define c_2m27    7.45058059692383e-9#define c_2m29    1.86264514923096e-9#define c_2m30    9.31322574615479e-10#define c_2m31    4.65661287307739e-10  // NaN#define c_2m33    1.16415321826935E-10#define c_2m38    3.63797880709171e-12  // NaN#define c_2m43    1.13686837721616e-13  // NaN#define c_2m50    8.881784197e-16       // NaN#define c_2m55    2.77555756156289e-17  // NaN// Maximum allowable user range allowable is 8 TODO how man m is this? see BB.#define MAX_URA 8/****************************************************************************** * Globals ******************************************************************************/// Right now we're declaring a message structure per channel, since the// messages come out of locked channels_ready.. but you could argue they should// be in a per-satellite array.ephemeris_t  ephemeris[N_CHANNELS];// Use an array to communicate which subframes we just received to the log#ifdef ENABLE_EPHEMERIS_LOGunsigned char log_eph[N_CHANNELS];#endifcyg_flag_t  ephemeris_channel_flag;cyg_flag_t  ephemeris_subframe_flags[N_CHANNELS];/****************************************************************************** * Statics ******************************************************************************/static msg_copy_t local_msg[N_CHANNELS];        // local copy of the messages./****************************************************************************** * If the channel is reallocated, then clear the ephemeris data for that * channel. Called from allocate.c ******************************************************************************/voidclear_ephemeris( unsigned short ch){    // Clear the ephemeris structure    ephemeris[ch].valid = 0;    // Clear local copies of the nav message    local_msg[ch].have_sf = 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 voidprocess_subframe1( unsigned short ch){    signed   long temp;    unsigned long utemp;    // Map the messages structure to OSGPS's "sf" and make this whole thing    // a bit more readable. TODO remove this eventually.    sf_copy_t * sf = local_msg[ch].sf;    // Update the time with the week number (only done once, further calls    // just return).    utemp = (sf[1-1].word[3-1] >> 14);    set_time_with_weeks( (unsigned short)utemp);    // Get the rest of the ephemerides    utemp = sf[1-1].word[8-1] & 0xffff;    ephemeris[ch].toc = (double)utemp * c_2p4;    // The following variables are signed integers so if the MSB is set,    // sign extend it to 32bits. 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;    ephemeris[ch].tgd = (double)temp * c_2m31;    temp = sf[1-1].word[9-1] >> 16;    if( temp & (1 << 7))        temp |= ~0xff;        ephemeris[ch].af2 = (double)temp * c_2m55;    temp = sf[1-1].word[9-1] & 0xffff;    if( temp & (1 << 15))        temp |= ~0xFFFF;        ephemeris[ch].af1 = (double)temp * c_2m43;    temp = sf[1-1].word[10-1] >> 2;    if( temp & (1 << 21))        temp |= ~0x3FFFFF;    ephemeris[ch].af0 = (double)temp * c_2m31;}static voidprocess_subframe2( unsigned short ch){    unsigned long   ultemp;    long            temp;    // Map the messages structure to OSGPS's "sf" and make this whole thing    // a bit more readable. TODO remove this eventually.    sf_copy_t * sf = local_msg[ch].sf;    temp = sf[2-1].word[3-1] & 0xFFFF;    if( temp & (1 << 15))        temp |= ~0xFFFF;    ephemeris[ch].crs = (double)temp * c_2m5;    temp = sf[2-1].word[4-1] >> 8;    if( temp & (1 << 15))        temp |= ~0xFFFF;    ephemeris[ch].dn = (double)temp * (c_2m43 * PI);    temp = ((sf[2-1].word[4-1] & 0xFF) << 24) | sf[2-1].word[5-1];    ephemeris[ch].ma = (double)temp * (c_2m31 * PI);    temp = sf[2-1].word[6-1] >> 8;    if( temp & (1 << 15))        temp |= ~0xFFFF;    ephemeris[ch].cuc = (double)temp * c_2m29;    temp = ((sf[2-1].word[6-1] & 0xFF) << 24) | sf[2-1].word[7-1];    ephemeris[ch].ecc = (double)temp * c_2m33;    temp = sf[2-1].word[8-1] >> 8;    if( temp & (1 << 15))        temp |= ~0xFFFF;    ephemeris[ch].cus = (double)temp * c_2m29;    ultemp = (((sf[2-1].word[8-1] & 0xFF) << 24) | sf[2-1].word[9-1]);    ephemeris[ch].sqrtA = (double)ultemp * c_2m19;    ultemp = (sf[2-1].word[10-1] >> 8);    ephemeris[ch].toe = (double)ultemp * c_2p4;}static voidprocess_subframe3( unsigned short ch){    long temp;    // Map the messages structure to OSGPS's "sf" and make this whole thing    // a bit more readable. TODO remove this eventually.    sf_copy_t * sf = local_msg[ch].sf;    // 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;    ephemeris[ch].cic = (double)temp * c_2m29;    temp = ((sf[3-1].word[3-1] & 0xFF) << 24) | sf[3-1].word[4-1];    ephemeris[ch].w0 = (double)temp * (c_2m31 * PI);    temp = sf[3-1].word[5-1] >> 8;    if( temp & (1 << 15))        temp |=  ~0xFFFF;    ephemeris[ch].cis = (double)temp * c_2m29;    temp = ((sf[3-1].word[5-1] & 0xFF) << 24) | sf[3-1].word[6-1];    ephemeris[ch].inc0 = (double)temp * (c_2m31 * PI);    temp = sf[3-1].word[7-1] >> 8;    if( temp & (1 << 15))        temp |=  ~0xFFFF;    ephemeris[ch].crc = (double)temp * c_2m5;    temp = ((sf[3-1].word[7-1] & 0xFF) << 24) | sf[3-1].word[8-1];    ephemeris[ch].w = (double)temp * (c_2m31 * PI);    temp = sf[3-1].word[9-1];    if( temp & (1 << 23))        temp |=  ~0xFFFFFF;    ephemeris[ch].omegadot = (double)temp * (c_2m43 * PI);    temp = (sf[3-1].word[10-1] >> 2) & 0x3FFF;    if( temp & (1 << 13))        temp |=  ~0x3FFF;    ephemeris[ch].idot = (double)temp * (c_2m43 * PI);}static voidprocess_subframe4( unsigned short ch){    // Sure, you got subframe 4, why not?}static voidprocess_subframe5( unsigned short ch){    // Sure, you got subframe 5, why not?}/****************************************************************************** * According to the GPS documentation, the ephemerides from subframes 1,2,3 * are to be used as a complete set. This function tests the navigation * messages to see if we can get a valid ephemeris from them. ******************************************************************************/static voidupdate_ephemeris( unsigned short ch){    unsigned short iodc;    unsigned short iode_2;    unsigned short iode_3;    unsigned short ura;    unsigned short health;    // Calculate the `Issue Of Data' Clock (IODC), ephemeris (IODE), user range    // error (URA), and satellite health.    iodc =   (unsigned short)(((local_msg[ch].sf[0].word[2] & 0x3) << 8)                | (local_msg[ch].sf[0].word[7] >> 16));    ura =    (unsigned short)((local_msg[ch].sf[0].word[2] & 0xf00) >> 8);    health = (unsigned short)((local_msg[ch].sf[0].word[2] & 0xfc) >> 2);    iode_2 = (unsigned short)(local_msg[ch].sf[1].word[2] >> 16);    iode_3 = (unsigned short)(local_msg[ch].sf[2].word[9] >> 16);    if( (ura < MAX_URA) && !(health & (1 << 5)) )    {        // The LS 8 bits of the IODC and the two IODE's should match. Although        // it doesn't explicitly say this anywhere, this seems to be the case        // (ICD 20.3.4.4).        if( ((iodc & 0xff) == iode_2) && (iode_2 == iode_3))        {            // Skiddadle if we have valid message data, we've already parsed            // it, and nothing has changed.            if( ephemeris[ch].valid && (ephemeris[ch].iode == iode_2))                return;            ephemeris[ch].prn = messages[ch].prn;            ephemeris[ch].ura = ura;            ephemeris[ch].health = health;            ephemeris[ch].iodc = iodc;            ephemeris[ch].iode = iode_2;            process_subframe1( ch);            process_subframe2( ch);            process_subframe3( ch);            ephemeris[ch].valid = 1;            // If the switch is on, log the ephemeris to the serial port#ifdef ENABLE_EPHEMERIS_LOG            log_eph[ch] = 1;#endif        }    }    // If the MSB of the 6 bit health is set, the satellite's nav message is    // toast - see (ICD 20.3.3.3.1.4). Bad satellite! We'll also call it bad if    // the URA is ever huge. Eventually the allocation thread will notice all    // of this from the almanac data and stop using this satellite.    else        clear_ephemeris( ch);}/****************************************************************************** * Stuff incoming bits from the tracking interrupt into words and subframes in * the messages structure. ******************************************************************************/voidephemeris_thread( CYG_ADDRWORD data) // input 'data' not used{    cyg_flag_value_t channels_ready;    cyg_flag_value_t subframes;    unsigned short   ch;    unsigned short   i;    unsigned short   j;    // There's no way that we're going to get a subframe before this thread    // is first executed, so it's ok to run the flag inits here.    cyg_flag_init( &ephemeris_channel_flag);    for( ch = 0; ch < N_CHANNELS; ch++)        cyg_flag_init( &ephemeris_subframe_flags[0]);    while(1)    {        // Sleep here until the message thread signals there is at least one        // subframe ready.  Clear the ephemeris_channel_flag(s) on wake up, but        // save the value in channels_ready.        channels_ready = cyg_flag_wait( &ephemeris_channel_flag,                         (1 << N_CHANNELS) - 1,   // 0xfff (all channels)                         CYG_FLAG_WAITMODE_OR |   // any flag                         CYG_FLAG_WAITMODE_CLR);  // clear flags        setbits32( GPS4020_GPIO_WRITE, LED5); // DEBUG        // OK we're awake, process the messages        for( ch = 0; ch < N_CHANNELS; ++ch)        {            if (channels_ready & (1 << ch))            {                // Find out which subframes are new (nonblocking)                // TODO Don't clear bits here, do it at end.                subframes = cyg_flag_poll( &ephemeris_subframe_flags[ch],                                           0x01f, // 5 possible subframes                                           CYG_FLAG_WAITMODE_OR                                           | CYG_FLAG_WAITMODE_CLR);                // Grab local copies of all incoming subframes                for( i = 0; i < NUM_SUBFRAMES; ++i)                {                    if( subframes & (1 << i))                    {                        // If we have all 10 words, copy over the message                        if( messages[ch].sf[i].valid == 0x3ff)                        {                            for( j = 0; j < NUM_WORDS; ++j)                            {                                local_msg[ch].sf[i].word[j] =                                        messages[ch].sf[i].word[j];                            }                            local_msg[ch].have_sf |= (1 << i);                        }                    }                }                // If we have all of the necessary message subframes, parse                // the messages for ephemeris. Subframe 4 and 5 are handled                // seperately.                if( (local_msg[ch].have_sf & 7) == 7)                    update_ephemeris( ch);                // TODO implement parsing of subframes 4                if( local_msg[ch].have_sf & (1 << 3))                    process_subframe4( ch);                // TODO implement parsing of subframes 5                if( local_msg[ch].have_sf & (1 << 4))                   process_subframe5( ch);            }        }        clearbits32( GPS4020_GPIO_WRITE, LED5); // DEBUG    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -