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

📄 sync.c

📁 GPS导航定位程序
💻 C
字号:
#include "includes.h"

/****************************************************************************    
* Function: void ProcessDataBit(register chanstruc _ds *CHPTR, unsigned dbit,
*                               unsigned _20ms_epoch)
*
* Stores the message data bits from each satellite and performs frame sync
* if this has not already been achieved. If frame sync has been achieved
* then monitors when a complete data frame has been received and dispatches
* it for processing.
*
* Input: CHPTR - pointer to the channel structure for the SV concerned.
*        dbit - the data bit.
*        _20ms_epoch - the 20ms epoch count.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void ProcessDataBit(register chanstruc _ds *CHPTR, unsigned dbit,
		    unsigned _20ms_epoch)
{
    unsigned long dataTIC;
    unsigned long subframe[FRAME_SIZE_PLUS_2];

    dataTIC = TIC-12;  /* SF being parsed ended 1.2 seconds (60 bits) ago. */

    StoreData(CHPTR,dbit);

    /* If frame sync has been achieved then see if a complete frame has
       been logged. */

    if(CHPTR->FrameSync==TRUE) 
    {
	CHPTR->BitNumber = (CHPTR->BitNumber+1)%300; 
	if(CHPTR->BitNumber==0)
	{
	    if(ValidFrameFormat(CHPTR,subframe))
	    {
		Checkpoint("ProcessDataBit",1);
		EmitSubframe(CHPTR,subframe,dataTIC); 
	    }
	}
    }

    /* Else attempt frame sync. */

    if(CHPTR->bitlk==TRUE && CHPTR->FrameSync==FALSE)
	FrameSync(CHPTR,_20ms_epoch);
}

/****************************************************************************    
* Function: void StoreData(register chanstruc _ds *CHPTR, unsigned dbit)
*
* Stores message data bits for each satellite into separate arrays.
*
* Input: CHPTR - pointer to the channel structure for the SV concerned.
*        dbit - the data bit.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void StoreData(register chanstruc _ds *CHPTR, unsigned dbit)
{
    int dataword;
    int feedbit;

    /* Each word in wordbuff is composed of: 
       Bits 0 to 29 = the GPS data word
       Bits 30 to 31 = 2 LSBs of the GPS word ahead. */ 

    for(dataword=0;dataword<=(FRAME_SIZE_PLUS_2-2);dataword++)
    {
	/* Shift the data word 1 place to the left. */

	CHPTR->wordbuff[dataword] <<= 1;

	/* Add the MSB of the following GPS word (bit 29 of a wordbuff
	   word). */

	feedbit = (CHPTR->wordbuff[dataword+1]>>29)&0x0001;
	CHPTR->wordbuff[dataword] += feedbit;
    }

    /* The bit added for the 12th word is the new data bit. */

    CHPTR->wordbuff[FRAME_SIZE_PLUS_2-1] <<= 1;
    CHPTR->wordbuff[FRAME_SIZE_PLUS_2-1] += dbit;
}

/****************************************************************************    
* Function: void BitSync(register chanstruc _ds *CHPTR, int _1ms_epoch)
*
* Performs data bit synchronisation.This occurs when the 1ms epoch counter
* is zero at the start of each data bit. A running sum of the inphase
* correlation at each of the possible 20 1ms epoch settings is maintained.
* The best is selected and the 1ms epoch is slewed so that an epoch count of
* zero corresponds to this position. If the best position is constant for
* a fixed period then bit lock is declared.
*
* Input: CHPTR - pointer to the channel structure for the SV concerned.
*        _1ms_epoch - the 1ms epoch count.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void BitSync(register chanstruc _ds *CHPTR, int _1ms_epoch)
{
    int epoch_counter;

    /* Update the corresponding bit integral. */

    CHPTR->DBINTEG[_1ms_epoch]    
      += (long)(labs(CHPTR->IPSUM20)-CHPTR->DBINTEG[_1ms_epoch])>>6;

    /* If a 1ms epoch slew is pending then don't bother attempting sync. */

    if(CHPTR->_1MS_EPOCH_SLEW==0)
    {
	/* If the 1ms epoch counter is zero and 2000 (2s) worth of data bit
	   integrations have occurred. */

	if((_1ms_epoch==0) && (CHPTR->nDBINTEG>=2000))
	{
	    /* If the best epoch position is non-zero then a slew of the
	       1ms epoch counter is needed. */

	    if(CHPTR->BESTEPOCH!=0)
	    {
		/* The slew so that the best epoch position will 
		   correspond to the 1ms epoch counter equal to zero. */

		CHPTR->_1MS_EPOCH_SLEW = 20 - CHPTR->BESTEPOCH;

		/* Restart the data bit integrations for epoch setting. */

		for(epoch_counter=0;epoch_counter<20;++epoch_counter)
		    CHPTR->DBINTEG[epoch_counter]=0;

		CHPTR->nDBINTEG=0;                 /* Integration counter. */
		CHPTR->bitlk=0;                            /* No bit lock. */
		CHPTR->FrameSync = FALSE;                /* No frame sync. */
		CHPTR->FrameSyncAndTIC = FALSE;
	    }

	    /* The best epoch position is now zero and the best sum the
	       current integration value. */

	    CHPTR->BESTEPOCH = 0;
	    CHPTR->BESTSUM = CHPTR->DBINTEG[_1ms_epoch];
	}
	else                             /* The 1ms epoch counter is != 0. */
	{
	    /* If the current integrated data bit value is better than the
	       current best then change the best epoch position and the sum
	       at this epoch. */

	    if(labs(CHPTR->DBINTEG[_1ms_epoch]) > CHPTR->BESTSUM)
	    {
		CHPTR->BESTEPOCH = _1ms_epoch;
		CHPTR->BESTSUM = CHPTR->DBINTEG[_1ms_epoch];
	    }
	}

	/* If the best epoch position has not changed for 1000 readings (1s)
	   then declare bit lock at this position. */
	
	if(CHPTR->nDBINTEG < 2000L)
	    CHPTR->nDBINTEG++;
	else
	    CHPTR->bitlk=TRUE;

    }                                           /* If 1ms epoch slew == 0. */
}

/****************************************************************************    
* Function: void FrameSync(register chanstruc _ds *CHPTR,
*                          unsigned _20ms_epoch)
*
* Performs sync to the message frame. Frame sync is declared when (i) the
* first 2 words pass the parity check, (ii) the preamble is detected,
* (iii) the subframe ID is valid and (iv) the zero bits are present. When the 
* above conditions are valid then the first 2 words of a frame have been
* received - the 20ms epoch counter at this point should 10 (last bit of
* word 2).
*
* Input: CHPTR - pointer to the channel structure for the SV concerned.
*        _20ms_epoch - the 20ms epoch count.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void FrameSync(register chanstruc _ds *CHPTR, unsigned _20ms_epoch)
{
    int preamble;              /* The TLM word preamble sequence 10001011. */
    int sid;                                  /* The subframe ID (1 to 5). */
    int zerobits;            /* The zero bits (the last 2 bits of word 2). */

    unsigned long word0,word1;

    word0 = CHPTR->wordbuff[FRAME_SIZE_PLUS_2-2];
    word1 = CHPTR->wordbuff[FRAME_SIZE_PLUS_2-1];

    /* Extract the preamble. */

    preamble = (int)(word0>>22)&0x00FF;

    /* Extract the subframe ID. */

    sid = (int)(word1>>8)&0x0007;

    /* Extract the zero bits. */

    zerobits = (int)word1&0x0003;

    /* Invert the extracted data according to bit 30 of the previous word. */

    if(word0&0x40000000L)
    {
	preamble ^= 0x00FF;
	zerobits ^= 0x0003;
    }
    if(word1&0x40000000L)
	sid ^= 0x0007;

    /* Check that the preamble, subframe and zero bits are ok. */

    if(preamble!=PREAMBLE)
	return;

    /* Check if the subframe ID is ok. */

    if(sid<1 || sid>5)
	return;

    /* Check that the zero bits are ok. */

    if(zerobits!=0)
	return;

    /* Check that the 2 most recently logged words pass parity. Have to first 
       invert the data bits according to bit 30 of the previous word. */

    if(word0&0x40000000L)
	word0 ^= 0x3FFFFFC0L;

    if(word1&0x40000000L)
	word1 ^= 0x3FFFFFC0L;

    if(ParityCheck(word0)==FALSE || ParityCheck(word1)==FALSE) 
	return;

    /* All the data matches up, therefore all that needs to be done is
       to set the 20ms epoch counter to its correct value. */

    if(_20ms_epoch!=10)
	CHPTR->_20MS_EPOCH_SLEW = 50 - ((40+_20ms_epoch)%50);
    else if(CHPTR->_20MS_EPOCH_SLEW==0)
    {
	CHPTR->FrameSync = TRUE;
	CHPTR->BitNumber = 0; 
    }
}

/****************************************************************************    
* Function: int ValidFrameFormat(register chanstruc _ds *CHPTR,
*                                unsigned long *subframe)
*
* Validates that the frame format is ok.
*
* Input: CHPTR - pointer to the channel structure for the SV concerned.
*        subframe - pointer to the subframe data.
*
* Output: None.
*
* Return Value: TRUE if format is good.
****************************************************************************/
int ValidFrameFormat(register chanstruc _ds *CHPTR, unsigned long *subframe)
{
    int preamble,next_preamble;
    int zerobits,next_zerobits;
    int sid,next_sid;
    int wordcounter;
    int parity_errors;

    for(wordcounter=0;wordcounter<FRAME_SIZE_PLUS_2;wordcounter++)
	subframe[wordcounter] = CHPTR->wordbuff[wordcounter];
    
    /* Extract the preamble. */

    preamble = (int)(subframe[0]>>22)&0x00FF;

    /* Extract the subframe ID. */

    sid = (int)(subframe[1]>>8)&0x0007;

    /* Extract the zero bits. */

    zerobits = (int)subframe[1]&0x0003;

    /* Invert the extracted data according to bit 30 of the previous word. */

    if(subframe[0]&0x40000000L)
    {
	preamble ^= 0x00FF;
	zerobits ^= 0x0003;
    }
    if(subframe[1]&0x40000000L)
	sid ^= 0x0007;

    /* Check that the preamble, subframe and zero bits are ok. */

    if(preamble!=PREAMBLE)
	return(FALSE);

    if(sid<1 || sid>5)
	return(FALSE);

    if(zerobits!=0)
	return(FALSE);

    /* Extract the next preamble (10001011). */

    next_preamble = (int)(subframe[FRAME_SIZE_PLUS_2-2]>>22)&0x00FF;
    
    /* Extract the next subframe ID. */

    next_sid = (int)(subframe[FRAME_SIZE_PLUS_2-1]>>8)&0x0007;

    /* Extract the next zero bits. */

    next_zerobits = (int)(subframe[FRAME_SIZE_PLUS_2-1]&0x0003);

    /* Invert the extracted data according to bit 30 of the previous word. */

    if(subframe[FRAME_SIZE_PLUS_2-2]&0x40000000L)
    {
	next_preamble ^= 0x00FF;
	next_zerobits ^= 0x0003;
    }
    if(subframe[FRAME_SIZE_PLUS_2-1]&0x40000000L)
	next_sid ^= 0x0007;

    /* Check that the preamble, subframe and zero bits are ok. */

    if(next_preamble!=PREAMBLE)       
	return(FALSE);

    if(next_sid<1 || next_sid>5)
	return(FALSE);

    if(next_zerobits!=0)
	return(FALSE);

    /* Check that the subframe IDs are consistent. */

    if((next_sid-sid)!=1 && (next_sid-sid)!=-4)
	return(FALSE);

    /* Check that all 12 words have correct parity. Have to first 
       invert the data bits according to bit 30 of the previous word. */

    parity_errors = 0;

    for(wordcounter=0;wordcounter<FRAME_SIZE_PLUS_2;wordcounter++)
    {
	if(subframe[wordcounter]&0x40000000L)
	    subframe[wordcounter] ^= 0x3FFFFFC0L;
    }
    for(wordcounter=0;wordcounter<FRAME_SIZE_PLUS_2;wordcounter++)
    {
	if(ParityCheck(subframe[wordcounter])==FALSE)
	    parity_errors++;
    }

    if(parity_errors!=0)
	return(FALSE);
    
    return(TRUE);
}

/****************************************************************************    
* Function: int ParityCheck(unsigned long gpsword)
*
* Checks the parity of a GPS data word.
*
* Input: gpsword - the word to be checked.
*
* Output: None.
*
* Return Value: TRUE if parity is good.
****************************************************************************/
int ParityCheck(unsigned long gpsword)
{
    unsigned long d1,d2,d3,d4,d5,d6,d7,t,parity;

    /* XOR as many bits in parallel as possible.  The magic constants pick
       up bits which are to be XOR'ed together to implement the GPS parity
       check algorithm described in ICD-GPS-200.  This avoids lengthy shift-
       and-xor loops. */

    d1 = gpsword & 0xFBFFBF00L;
    d2 = _lrotl(gpsword,1) & 0x07FFBF01L;
    d3 = _lrotl(gpsword,2) & 0xFC0F8100L;
    d4 = _lrotl(gpsword,3) & 0xF81FFE02L;
    d5 = _lrotl(gpsword,4) & 0xFC00000EL;
    d6 = _lrotl(gpsword,5) & 0x07F00001L;
    d7 = _lrotl(gpsword,6) & 0x00003000L;

    t = d1 ^ d2 ^ d3 ^ d4 ^ d5 ^ d6 ^ d7;

    /* Now XOR the 5 6-bit fields together to produce the 6-bit
       final result. */

    parity = t ^ _lrotl(t,6) ^ _lrotl(t,12) ^ _lrotl(t,18) ^ _lrotl(t,24);
    parity = parity & 0x3F;
    if(parity == (gpsword&0x3F))
	return(TRUE);
    else
	return(FALSE);
}

/****************************************************************************
*
* Function: void EmitSubframe(register chanstruc _ds *CHPTR,
*                             unsigned long *subframe,unsigned long dataTIC)
*
* Emits the valid subframe for processing by the subframe processing
* functions.
*
* Input: CHPTR - A pointer to the channel structure of the channel in
*                question. This data structure must reside in DGROUP.
*        subframe - Pointer to 12 subframe words.      
*        dataTIC - The TIC at the end of the last subframe.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void EmitSubframe(register chanstruc _ds *CHPTR, unsigned long *subframe,
		  unsigned long dataTIC)
{
    int i;

    /* Emit the current subframe (not including the TLM and HOW from the next
       subframe) if we have frame sync. */

    CHPTR->BadDataCntr = 0;       /* Reset errors-since-good-data counter. */

    /* Check to make sure that the subframe for this satellite hasn't
       already been sent because the satellite is being tracked on more than
       one channel. */

    if(dataTIC - TimeOfLastSubframe[CHPTR->SV] < 10)
	return;

    if(SfPending<MAXCHANNELS)
    {
      for(i=0; i<10; ++i)
	  sfbuff[csf].subframe[i] = subframe[i];
      sfbuff[csf].SV = CHPTR->SV;
      sfbuff[csf].dataTIC = dataTIC;
      if(++csf >= MAXCHANNELS)
	  csf=0;
      SfPending++;
      TimeOfLastSubframe[CHPTR->SV] = dataTIC;
    }
    else
    {
	/* No room in the buffer, increment the missed subframe count. */

	misssf++;
    }
}

⌨️ 快捷键说明

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