www.pudn.com > opengpssim.zip > ogsnavdecode.c


/* ************************************************************************ 
   *                                                                      *
   *                          GPS Simulation                              *
   *                                                                      *
   * -------------------------------------------------------------------- *
   *                                                                      *
   *    Module:   ogsnavdecode.cpp                                        *
   *                                                                      *
   *   Version:   0.1                                                     *
   *                                                                      *
   *      Date:   02.03.02                                                *
   *                                                                      *
   *    Author:   C. Kelley, G. Beyerle                                   *
   *                                                                      *
   * -------------------------------------------------------------------- *
   *                                                                      *
   * Copyright (C) 2001,2002  C. Kelley, G. Beyerle                       *
   *                                                                      *
   * This program is free software; you can redistribute it and/or modify *
   * it under the terms of the GNU General Public License as published by *
   * the Free Software Foundation; either version 2 of the License, or    *
   * (at your option) any later version.                                  *
   *                                                                      *
   * This program is distributed in the hope that it will be useful,      *
   * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
   * GNU General Public License for more details.                         *
   *                                                                      *
   * You should have received a copy of the GNU General Public License    *
   * along with this program; if not, write to the Free Software          *
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
   *                                                                      *
   * -------------------------------------------------------------------- *
   *                                                                      *
   * The files 'gpsfuncs.cpp', 'gpsrcvr.cpp' and 'gp2021.cpp' are modi-   *
   * fied versions of the files with the same name from Clifford Kelley's * 
   * OpenSourceGPS distribution. The unmodified files can be obtained     *
   * from http://www.home.earthlink.net/~cwkelley                         *
   *                                                                      *
   * -------------------------------------------------------------------- *
   *                                                                      *
   *                      Navigation data decoding                        *
   *                                                                      *
   ************************************************************************ */

/* ******************************* changes ********************************

   dd.mm.yy -

   ************************************************************************ */

/* ------------------------------- includes ------------------------------- */

#include 
#include 
#include 
#include 
#include 

#define OSGLIBRY_H

#include "ogsdefine.h"
#include "ogsstructs.h"
#include "ogsextern.h"
#include "ogslibrary.h"

/* ------------------------------- defines -------------------------------- */

/* ------------------------------- globals -------------------------------- */

/* -------------------------- prototypes (global) ------------------------- */

static int exor_long( unsigned long x);

/* ------------------------------ procedures ------------------------------ */


//
//  printf content of sf[][]
//
static void print_sf( unsigned long sf[6][11])
{
  int i, sfr, word;
  unsigned long scale;

  for ( sfr=1; sfr<=5; sfr++)
  {
    printf( "--- subframe %d ---\n", sfr);
    for ( word=1; word<=10; word++)
    {
      printf( " %08x", sf[sfr][word]);
      if (( word % 5) == 0)
        printf( "\n");
    }  
  }
  getchar();

  return;
}

//
//  copy frame buffer sf[][] to 1500 byte nav msg array
//
static void copy_sf_to_msg( unsigned long sf[6][11], char msg[])
{
  int i, j, sfr, word;
  unsigned long scale;

  j=0;
  for ( sfr=1; sfr<=5; sfr++)
  {
    for ( word=1; word<=10; word++)
    {
      scale = 0x1L << 29; 

      for ( i=0; i<30; i++)
      {

//        if ( message[j%1500] == !invert)
//          sf[sfr][word] += scale;

        if ( sf[sfr][word] & scale)
          msg[j%1500] = 1;
        else  
          msg[j%1500] = -1;

        scale = scale >> 1;
        j++;
      }
    }
  }

  return;
}

//
//  xor all 32 bits in a long variable (b31^b30^b29^...^b2^b1^b0)
//
static int exor_long( unsigned long x)
{
  char i;
  int res = 0;

  for ( i=0; i<32; i++)
  {
    res = res ^ (x & 0x1);
    x = x >> 1;
  }
  return res;
}

#if 0
inline double frem( double x, double y)
{
  double res;

  if ( x >= 0.0)
    res = fmod( x, y);
  else
    res = -fmod( -x, y);    
  return res;
}
#endif

/*******************************************************************************
FUNCTION parity_check()
RETURNS  None.

PARAMETERS
  subrame array

PURPOSE
  check parity and remove parity bits from frame buffer sf[][]

WRITTEN BY
  Clifford Kelley

*******************************************************************************/

static void parity_check( unsigned long sf[6][11])
{
  long pb1 = 0x3b1f3480L,    // just bits 6-29 (GPS bits 1-24)
       pb2 = 0x1d8f9a40L, 
       pb3 = 0x2ec7cd00L,
       pb4 = 0x1763e680L, 
       pb5 = 0x2bb1f340L, 
       pb6 = 0x0b7a89c0L;
  int  parity, m_parity;
  int  d29 = 0, d30 = 0, sfm, word, 
       b_1, b_2, b_3, b_4, b_5, b_6;
  int  err_bit;

  for ( sfm = 1; sfm <= 5; sfm++)
  {
    p_error[sfm] = 0;
    for ( word=1; word<=10; word++)
    {

//  transmitted parity
      m_parity = (int)( sf[sfm][word] & 0x3f);

//  calculate parity
      b_1 = parity_exor_7to30( d29,     sf[sfm][word] & pb1) << 5;
      b_2 = parity_exor_7to30( d30,     sf[sfm][word] & pb2) << 4;
      b_3 = parity_exor_7to30( d29,     sf[sfm][word] & pb3) << 3;
      b_4 = parity_exor_7to30( d30,     sf[sfm][word] & pb4) << 2;
      b_5 = parity_exor_7to30( 0,       sf[sfm][word] & pb5) << 1;
      b_6 = parity_exor_7to30( d29^d30, sf[sfm][word] & pb6);

      parity  = b_1+b_2+b_3+b_4+b_5+b_6;

//      printf("sf[%d][%d] = %x", sfm, word, sf[sfm][word]);
//      printf(", m_parity = %x", m_parity);
//      printf(", parity   = %x\n", parity);
//      getchar();

      if ( parity != m_parity)
        err_bit = 1;
      else  
      {
        err_bit = 0;
//        printf( "parity check passed.\n");
      }  

      p_error[sfm] = (p_error[sfm] << 1) + err_bit;

      if ( d30 == 1) 
        sf[sfm][word] = 0x3fffffc0L & ~sf[sfm][word];
//        sf_noparity[sfm][word] = 0x3fffffc0L & ~sf[sfm][word];

      sf[sfm][word] = sf[sfm][word] >> 6;   // remove 6 parity bits
//      sf_noparity[sfm][word] = sf[sfm][word] >> 6;   // remove 6 parity bits

      d29 = (m_parity & 0x2) >> 1;
      d30 = m_parity & 0x1;
    }
  }
  return;
}

/*******************************************************************************
FUNCTION decode_navmsg()
RETURNS  None.

PARAMETERS

PURPOSE
  This function assembles and decodes the 1500 bit nav message
  into almanac and ephemeris messages

WRITTEN BY
  Clifford Kelley
  Modifications by G. Beyerle

*******************************************************************************/

void decode_navmsg( unsigned long sf[6][11], NAVDATA *nav)
{
  int i, j, k;
  static int i4page, i5page;   // GB: int inserted
  int   i4data, i5data, isv;
  int   i4p, i5p;
  unsigned long tmpulng;
  long  tmplng;
  char  tmpchr;
  int  tmpint;
  unsigned int tmpuint;
  float d_toe;

//
//    assemble the bits into subframes and words
//

//  d_toe = clock_tow - gps_eph[prn].toe;

//  if (d_toe > 302400.0) 
//    d_toe = d_toe - 604800.0;
//  else if ( d_toe < -302400.0)
//    d_toe = d_toe + 604800.0;

//  if ( gps_eph[prn].valid == 0 || 
//       (almanac_valid == 0 && almanac_flag == 0) || 
//       fabs( d_toe) > 7200.0)

//  pattern = (int)( (sf[1][1] >> 22) & 0xff);
//  printf( "pattern = %x", pattern); 

//    for (i=0; i<300;i++)
//      printf( "%d", Hist[i]); 

//  getchar();

//
//   EPHEMERIS DECODE subframes 1, 2, 3
//
//  subframe 1
//

//  k = 1;
//  while (!((p_error[1]==0 || p_error[1]==0x200) && 
//       p_error[2]==0 && p_error[3]==0))
//  {
//    
//    copy_msg_to_sf( message, k);
//  
//    parity_check(); // check the parity of the 1500 bit message
//
//    printf("(%d) perr[1] = 0x%x perr[2] = 0x%x perr[3] = 0x%x\n", 
//      k, p_error[1], p_error[2], p_error[3]);
//
//    k += 1;
//  }

// check the parity of the 1500 bit message and strip 6 parity bits
  parity_check( sf); 

//  printf("perr[1] = 0x%x, perr[2] = 0x%x, perr[3] = 0x%x, perr[4] = 0x%x, perr[5] = 0x%x\n", 
//    p_error[1], p_error[2], p_error[3], p_error[4], p_error[5]);
//  printf("*** copy sf_noparity[][] to sf[][] ***\n");
//  getchar();

  if (( p_error[1] == 0 || p_error[1] == 0x200) && 
        p_error[2] == 0 && p_error[3] == 0)
  {
#if 0
    printf( "parity check passed!\n");
    printf( "p_error[1] = %x\n", p_error[1]);
    printf( "p_error[2] = %x\n", p_error[2]);
    printf( "p_error[3] = %x\n", p_error[3]);
    getchar();
#endif

// was:
//    nav->sf1how       = (long)( (sf[1][2] & 0xffff80) >> 7);

    nav->sf1how       = (long)( (sf[1][2] & 0xfffffc) >> 2);
    nav->sf2how       = (long)( (sf[2][2] & 0xfffffc) >> 2);
    nav->sf3how       = (long)( (sf[3][2] & 0xfffffc) >> 2);
    nav->sf4how       = (long)( (sf[4][2] & 0xfffffc) >> 2);
    nav->sf5how       = (long)( (sf[5][2] & 0xfffffc) >> 2);

    nav->sf4svid      = (int)( (sf[4][3] & 0x3f0000) >> 16);
    nav->sf5svid      = (int)( (sf[5][3] & 0x3f0000) >> 16);

    if ( nav->sf4svid >= 0 && nav->sf4svid < 64)
      nav->sf4pageno  = satid2page[nav->sf4svid];
    else  
      nav->sf4pageno  = -1;

    if ( nav->sf5svid >= 0 && nav->sf5svid < 64)
      nav->sf5pageno  = satid2page[nav->sf5svid];
    else  
      nav->sf5pageno  = -1;

#if 0
    printf("\n");
    printf("nav->sf4pageno = %d\n", nav->sf4pageno);
    printf("nav->sf4svid   = %d\n", nav->sf4svid);
    printf("nav->sf5pageno = %d\n", nav->sf5pageno);
    printf("nav->sf5svid   = %d\n", nav->sf5svid);
//    printf("sf[4][2] = %08x\n", sf[4][2]);
//    printf("sf[5][2] = %08x\n", sf[5][2]);
    getchar();
#endif

    nav->eph.valid = 0;

//    iodct=iodc & 0xff;
//    iode=sf[2][3]  >> 16;
//    idoe=sf[3][10] >> 16;
//    if ( iodct != iode || iodct!= idoe || iode != idoe || gps_eph[prn].sqra==0.0)
//    
    nav->eph.how       = (long)( sf[1][2] >> 2);
    nav->eph.sfid      = (int)( (sf[1][2] & 0x1c) >> 2);
    tmplng             = (long)( (sf[1][2] & 0xffff80) >> 7);
    nav->eph.tow       = tmplng * 6 - 6;   // z-count/4 -> week seconds
    nav->eph.asflag    = (int)( (sf[1][2] & 0x20) >> 5);
    nav->eph.alertflag = (int)( (sf[1][2] & 0x40) >> 6);

    nav->eph.week   = (int)( sf[1][3] >> 14);
//      icapl2              = ( sf[1][3] & 0x3000 ) >> 12;
    nav->eph.ura    = (int)(( sf[1][3] & 0xF00 ) >> 8);
    nav->eph.health = (int)(( sf[1][3] & 0xFC ) >> 2);
    tmpint          = (int)(((sf[1][3] & 0x3) << 8 ) | ((sf[1][8] & 0xFF0000L) >> 16));
    nav->eph.iodc   = tmpint;
    tmpint          = (int)( sf[1][7] & 0xFF);
    nav->eph.tgd    = tmpint * pow( 2.0, -31.0);
    tmpuint         = (int)( sf[1][8] & 0xFFFF);
    nav->eph.toc    = tmpuint * 16.0;
    tmpint          = (int)( sf[1][9] >> 16);
    nav->eph.af2    = tmpint * pow( 2.0, -55.0);
    tmpint          = (int)( sf[1][9] & 0xFFFF);
    nav->eph.af1    = tmpint * pow( 2.0, -43.0);
    tmplng          = sf[1][10] >> 2;
    if ( bit_test_long( tmplng, 22)) 
      tmplng |= 0xFFC00000L;
    nav->eph.af0    = tmplng * pow( 2.0, -31.0);
//
//   subframe 2
//
    tmpint            = (int)(sf[2][3] & 0xFFFF);
    nav->eph.crs      = tmpint * pow( 2.0, -5.0);
    tmplng            = (long)( (sf[2][4] >> 8) & 0xffff);
    nav->eph.dn       = tmplng * pow( 2.0, -43.0) * pi;
    tmplng            = ((sf[2][4] & 0xFF) << 24) | sf[2][5];
    nav->eph.ma       = tmplng * pow( 2.0, -31.0) * pi;
    tmpint            = (int)( sf[2][6] >> 8);
    nav->eph.cuc      = tmpint * pow( 2.0, -29.0);
    tmpulng           = ((sf[2][6] & 0xFF) << 24) | sf[2][7];
    nav->eph.ety      = tmpulng * pow( 2.0, -33.0);
    tmpint            = (int)( sf[2][8] >> 8);
    nav->eph.cus      = tmpint * pow( 2.0, -29.0);
    tmpulng           = (((sf[2][8] & 0xFF) << 24) | sf[2][9]);
    nav->eph.sqra     = tmpulng * pow( 2.0, -19.0);
    if ( nav->eph.sqra > 0.0) 
      nav->eph.wm     = 19964981.84 / pow( nav->eph.sqra, 3);
    tmpuint           = (int)(sf[2][10] >> 8);
    nav->eph.toe      = tmpuint * 16.0;
//      fif=(sf[2][10] & 0x80) >> 7;
//
// subframe 3
//
    tmpint            = (int)( sf[3][3] >> 8);
    nav->eph.cic      = tmpint * pow( 2.0, -29.0);
    tmpint            = (int)(sf[3][5] >> 8);
    nav->eph.cis      = tmpint * pow( 2.0, -29.0);
    tmplng            = ((sf[3][5] & 0xFF) << 24) | sf[3][6];
    nav->eph.inc0     = tmplng * pow( 2.0, -31.0) * pi;
    tmpulng           = ((sf[3][3] & 0xFF) << 24) | sf[3][4];
    nav->eph.omega0   = tmpulng * pow( 2.0, -31.0) * pi;
    tmpint            = (int)(sf[3][7] >> 8);
    nav->eph.crc      = tmpint * pow( 2.0, -5.0);
    tmplng            = ((sf[3][7] & 0xFF) << 24) | sf[3][8];
    nav->eph.w        = tmplng * pow( 2.0, -31.0) * pi;
    tmplng            = sf[3][9];
    if ( bit_test_long( tmplng, 24)) 
      tmplng |= 0xFF000000L;
    nav->eph.omegadot = tmplng * pow( 2.0, -43.0) * pi;
    tmpint            = (int)( (sf[3][10] & 0xFFFC) >> 2);
    if ( bit_test_long( tmpint, 14)) 
      tmpint |= 0xC000;
    nav->eph.idot     = tmpint * pow( 2.0, -43.0) * pi;
    if ( nav->eph.inc0 != 0.0 && 
         nav->eph.sqra > 5000.0 &&
         nav->eph.ety < .05) 
      nav->eph.valid = 1;
  }
  else
  {
    printf( "parity check failed!\n");
    printf( "p_error[1] = %x\n", p_error[1]);
    printf( "p_error[2] = %x\n", p_error[2]);
    printf( "p_error[3] = %x\n", p_error[3]);
//    getchar();
  }  
  
//
//    ALMANAC DECODE  subframes 4 and 5
//
//    SUBFRAME 4
//
//  Note:  i4page/i5page denotes the satid of subframe4/5
//
//             subframe4 subframe5
//       page    satid    satid
//     ---------------------------
//         1       57        1
//        2-5    25-28     2-5
//         6       57        7
//        8-10   29-32     8-10
//         11      57       11 
//         12      62       12
//       13-15   52-54    13-15
//         16      57       16
//       17-18   55-56    17-18
//       19-20   58-59    19-20
//         21      57       21
//       22-25   60-63      51
//
  if ( p_error[4] == 0 && p_error[5] == 0 && 
       almanac_valid == 0 && almanac_flag == 0)
  {

    nav->sf4how       = (long)( (sf[4][2] & 0xffff80) >> 7);
    nav->sf5how       = (long)( (sf[5][2] & 0xffff80) >> 7);

//    nav->alm.how       = (long)( sf[4][2] >> 2);
//    nav->alm.sfid      = (int)( (sf[4][2] & 0x1c) >> 2);
//    nav->alm.tow       = (long)( (sf[4][2] & 0xffff80) >> 7);
//    nav->alm.asflag    = (int)( (sf[4][2] & 0x20) >> 5);
//    nav->alm.alertflag = (int)( (sf[4][2] & 0x40) >> 6);

    almanac_flag = 1;
//      i4data= sf[4][3] >> 22;
    i4p = (int)((sf[4][3] & 0x3F0000L) >> 16);
    if ( i4p != i4page)
    {
      i4page = i4p;
      if (i4page > 24 && i4page < 33)
      {
        nav->alm.prn       = i4page;
        nav->alm.week      = gps_week;
        tmpuint            = (int)( sf[4][3] & 0x00FFFFL);
        nav->alm.ety       = tmpuint * pow( 2.0, -21.0);
        tmpuint            = (int)( sf[4][4] >> 16);
        nav->alm.toa       = tmpuint * 4096.0;
        tmplng             = sf[4][4] & 0x00FFFFL;
        if (bit_test_long( tmplng, 16)) 
          tmplng |= 0xFFFF0000L;
        nav->alm.inc       = (tmplng * pow( 2.0, -19.0) + 0.3) * pi;
        tmpint             = (int)(sf[4][5] >> 8);
        nav->alm.omegadot  = tmpint * pow( 2.0, -38.0) * pi;
        nav->alm.health    = (int)(sf[4][5] & 0x0000FF);
        tmpulng            = sf[4][6];
        nav->alm.sqra      = tmpulng * pow( 2.0, -11.0);
        if ( nav->alm.sqra > 0.0) 
          nav->alm.w = 19964981.84 / pow( nav->alm.sqra, 3);
        tmplng             = sf[4][7];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->alm.omega0    = tmplng * pow( 2.0, -23.0) * pi;
        tmplng             = sf[4][8];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->alm.w         = tmplng * pow( 2.0, -23.0) * pi;
        tmplng             = sf[4][9];
        if (bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;  
        nav->alm.ma        = tmplng * pow( 2.0, -23.0) * pi;
//          iaaf0=(sf[4][10] >> 13) | (sf[4][10] & 0x1C);  
        tmplng             = (sf[4][10] >> 13) | ((sf[4][10] & 0x1C) >> 2);  // fixed (GB-020217)  
        if ( bit_test_long( tmplng, 11)) 
          tmplng |= 0xFFFFF800L;
        nav->alm.af0       = tmplng * pow( 2.0, -20.0);
        tmplng             = (sf[4][10] | 0xFFE0) >> 5;
        if ( bit_test_long( tmplng, 11)) 
          tmplng |= 0xFFFFF800L;
        nav->alm.af1       = tmplng * pow( 2.0, -38.0);
      }
      else if ( i4page == 55 )
      {
        nav->alm.text_message[0] = (char)( (sf[4][3] & 0x00FF00) >> 8);
        nav->alm.text_message[1] = (char)(  sf[4][3] & 0x0000FF);

        for ( k=1; k<=7; k++)
        {
          nav->alm.text_message[3*k-1] = (char)( sf[4][k+3] >> 16);
          nav->alm.text_message[3*k  ] = (char)( (sf[4][k+3] & 0x00FF00) >>  8);
          nav->alm.text_message[3*k+1] = (char)(  sf[4][k+3] & 0x0000FF);
        }
      }
      else if ( i4page == 56 )
      {
// broadcast ionospheric correction
        tmpchr        = (int)( (sf[4][3] & 0x00FF00) >> 8);
        nav->iono.al0 = tmpchr * pow( 2.0, -30.0);
        tmpchr        = (int)( sf[4][3] & 0x0000FF);
        nav->iono.al1 = tmpchr * pow( 2.0, -27.0);
        tmpchr        = (int)( sf[4][4] >> 16);
        nav->iono.al2 = tmpchr * pow( 2.0, -24.0);
        tmpchr        = (int)( (sf[4][4] & 0x00FF00) >> 8);
        nav->iono.al3 = tmpchr * pow( 2.0, -24.0);
        tmpchr        = (int)( sf[4][4] & 0x0000FF);
        nav->iono.b0  = tmpchr * 2048.0;
        tmpchr        = (int)( sf[4][5] >> 16);
        nav->iono.b1  = tmpchr * 16384.0;
        tmpchr        = (int)( (sf[4][5] & 0x00FF00) >> 8);
        nav->iono.b2  = tmpchr * 65536.0;
        tmpchr        = (int)( sf[4][5] & 0x00FF);
        nav->iono.b3  = tmpchr * 65536.0;
// broadcast UTC data
        tmplng        = sf[4][6];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->utc.a1    = tmplng * pow( 2.0, -50.0);
        tmplng         = (sf[4][7] << 8) | (sf[4][8] >> 16);
        nav->utc.a0    = tmplng * pow( 2.0, -30.0);
        tmpint         = (int)( (sf[4][8] & 0x00FF00) >> 8);
        nav->utc.tot   = tmpint * 4096;
        tmpint         = (int)( sf[4][8] & 0xFF);
        nav->utc.WNt   = tmpint;
        tmpint         = (int)( sf[4][9] >> 16);
        if (tmpint > 128) 
          tmpint |= 0xFF00;
        nav->utc.dtls  = tmpint;
        nav->utc.WNlsf = (int)((sf[4][9] & 0x00FF00) >> 8);
        nav->utc.DN    = (int)(sf[4][9] & 0x0000FF);
//          idtlsf = (int)( sf[4][9] >> 16);
        tmpint         = (int)( sf[4][10] >> 16);   // fixed (GB-020217)
        if ( tmpint > 128) 
          tmpint |= 0xFF00;
        nav->utc.dtlsf = tmpint;
      }
      else if ( i4page == 63 )
      {
        ASV[1]  = (int)( (sf[4][3] & 0x00F000L) >> 12);
        ASV[2]  = (int)( (sf[4][3] & 0x000F00)  >>  8);
        ASV[3]  = (int)( (sf[4][3] & 0x0000F0)  >>  4);
        ASV[4]  = (int)(  sf[4][3] & 0x00000F);
        ASV[5]  = (int)(  sf[4][4] >> 20);
        ASV[6]  = (int)( (sf[4][4] & 0x0F0000L) >> 16);
        ASV[7]  = (int)( (sf[4][4] & 0x00F000)  >> 12);
        ASV[8]  = (int)( (sf[4][4] & 0x000F00)  >>  8);
        ASV[9]  = (int)( (sf[4][4] & 0x0000F0)  >>  4);
        ASV[10] = (int)(  sf[4][4] & 0x00000F);
        ASV[11] = (int)(  sf[4][5] >> 20);
        ASV[12] = (int)( (sf[4][5] & 0x0F0000L) >> 16);
        ASV[13] = (int)( (sf[4][5] & 0x00F000)  >> 12);
        ASV[14] = (int)( (sf[4][5] & 0x000F00)  >>  8);
        ASV[15] = (int)( (sf[4][5] & 0x0000F0)  >>  4);
        ASV[16] = (int)(  sf[4][5] & 0x00000F);
        ASV[17] = (int)(  sf[4][6] >> 20);
        ASV[18] = (int)( (sf[4][6] & 0x0F0000L) >> 16);
        ASV[19] = (int)( (sf[4][6] & 0x00F000)  >> 12);
        ASV[20] = (int)( (sf[4][6] & 0x000F00)  >>  8);
        ASV[21] = (int)( (sf[4][6] & 0x0000F0)  >>  4);
        ASV[22] = (int)(  sf[4][6] & 0x00000F);
        ASV[23] = (int)(  sf[4][7] >> 20);
        ASV[24] = (int)( (sf[4][7] & 0x0F0000L) >> 16);
        ASV[25] = (int)( (sf[4][7] & 0x00F000)  >> 12);
        ASV[26] = (int)( (sf[4][7] & 0x000F00)  >>  8);
        ASV[27] = (int)( (sf[4][7] & 0x0000F0)  >>  4);
        ASV[28] = (int)(  sf[4][7] & 0x00000F);
        ASV[29] = (int)(  sf[4][8] >> 20);
        ASV[30] = (int)( (sf[4][8] & 0x0F0000L) >> 16);
        ASV[31] = (int)( (sf[4][8] & 0x00F000)  >> 12);
        ASV[32] = (int)( (sf[4][8] & 0x000F00)  >>  8);

#if 0
        SVh[25] = (int)( sf[4][8] & 0x00003F);
        if( SVh[25] == 0x3f) 
          nav->gps_alm[25].inc = 0.0;
        SVh[26] = (int)( sf[4][9] >> 18);
        if( SVh[26] == 0x3f) 
          nav->gps_alm[26].inc = 0.0;
        SVh[27] = (int)( (sf[4][9] & 0x03F000L) >> 12);
        if( SVh[27] == 0x3f) 
          nav->gps_alm[27].inc = 0.0;
        SVh[28] = (int)( (sf[4][9] & 0x000FC0) >> 6);
        if( SVh[28] == 0x3f) 
          nav->gps_alm[28].inc = 0.0;
        SVh[29] = (int)( sf[4][9] & 0x00003F);
        if( SVh[29] == 0x3f) 
          nav->gps_alm[29].inc = 0.0;
        SVh[30] = (int)( sf[4][10] >> 18);
        if( SVh[30] == 0x3f) 
          nav->gps_alm[30].inc = 0.0;
        SVh[31] = (int)( (sf[4][10] & 0x03F000L) >> 12);
        if( SVh[31] == 0x3f) 
          nav->gps_alm[31].inc = 0.0;
        SVh[32] = (int)( (sf[4][10] & 0x000FC0) >> 6);
        if( SVh[32] == 0x3f) 
          nav->gps_alm[32].inc = 0.0;
#endif
      }  
    }

//
//    SUBFRAME 5
//
//      i5data= sf[5][3] >> 22;
    i5p = (int)((sf[5][3] & 0x3F0000L) >> 16);
//      chan[ch].page5 = i5p;
    if ( i5page != i5p)
    {
      i5page=i5p;
      if ( i5page == 51 )
      {
#if 0
//       iatoa = (int)((sf[5][3] & 0xFF00) >>8);
//       atoa = iatoa*4096;
        SVh[1] = (int)( sf[5][4] >>18);
        if ( SVh[1] == 0x3f) 
          nav->gps_alm[1].inc = 0.0;
        SVh[2] = (int)( (sf[5][4] & 0x03F000L)>>12);
        if ( SVh[2] == 0x3f) 
          nav->gps_alm[2].inc = 0.0;
        SVh[3] = (int)( (sf[5][4] & 0x000FC0)>>6);
        if ( SVh[3] == 0x3f) 
          nav->gps_alm[3].inc = 0.0;
        SVh[4] = (int)( sf[5][4] & 0x00003F);
        if ( SVh[4] == 0x3f) 
          nav->gps_alm[4].inc = 0.0;
        SVh[5] = (int)( sf[5][5] >>18);
        if ( SVh[5] == 0x3f) 
          nav->gps_alm[5].inc = 0.0;
        SVh[6] = (int)( (sf[5][5] & 0x03F000L)>>12);
        if ( SVh[6] == 0x3f) 
          nav->gps_alm[6].inc = 0.0;
        SVh[7] = (int)( (sf[5][5] & 0x000FC0)>>6);
        if ( SVh[7] == 0x3f) 
          nav->gps_alm[7].inc = 0.0;
        SVh[8] = (int)( sf[5][5] & 0x00003F);
        if ( SVh[8] == 0x3f) 
          nav->gps_alm[8].inc = 0.0;
        SVh[9] = (int)( sf[5][6] >> 18);
        if ( SVh[9] == 0x3f) 
          nav->gps_alm[9].inc = 0.0;
        SVh[10] = (int)( (sf[5][6] & 0x03F000L)>>12);
        if ( SVh[10] == 0x3f) 
          nav->gps_alm[10].inc = 0.0;
        SVh[11] = (int)( (sf[5][6] & 0x000FC0)>>6);
        if ( SVh[11] == 0x3f) 
          nav->gps_alm[11].inc = 0.0;
        SVh[12] = (int)( sf[5][6] & 0x00003F);
        if ( SVh[12] == 0x3f) 
          nav->gps_alm[12].inc = 0.0;
        SVh[13] = (int)( sf[5][7] >>18);
        if ( SVh[13] == 0x3f) 
          nav->gps_alm[13].inc = 0.0;
        SVh[14] = (int)( (sf[5][7] & 0x03F000L)>>12);
        if ( SVh[14] == 0x3f) 
          nav->gps_alm[14].inc = 0.0;
        SVh[15] = (int)( (sf[5][7] & 0x000FC0)>>6);
        if ( SVh[15] == 0x3f) 
          nav->gps_alm[15].inc = 0.0;
        SVh[16] = (int)( sf[5][7] & 0x00003F);
        if ( SVh[16] == 0x3f) 
          nav->gps_alm[16].inc = 0.0;
        SVh[17] = (int)( sf[5][8] >>18);
        if ( SVh[17] == 0x3f) 
          nav->gps_alm[17].inc = 0.0;
        SVh[18] = (int)( (sf[5][8] & 0x03F000L)>>12);
        if ( SVh[18] == 0x3f) 
          nav->gps_alm[18].inc = 0.0;
        SVh[19] = (int)( (sf[5][8] & 0x000FC0)>>6);
        if ( SVh[19] == 0x3f) 
          nav->gps_alm[19].inc = 0.0;
        SVh[20] = (int)( sf[5][8] & 0x00003F);
        if ( SVh[20] == 0x3f) 
          nav->gps_alm[20].inc = 0.0;
        SVh[21] = (int)( sf[5][9] >>18);
        if ( SVh[21] == 0x3f) 
          nav->gps_alm[21].inc = 0.0;
        SVh[22] = (int)( (sf[5][9] & 0x03F000L)>>12);
        if ( SVh[22] == 0x3f) 
          nav->gps_alm[22].inc = 0.0;
        SVh[23] = (int)( (sf[5][9] & 0x000FC0)>>6);
        if ( SVh[23] == 0x3f) 
          nav->gps_alm[23].inc = 0.0;
        SVh[24] = (int)( sf[5][9] & 0x00003F);
        if ( SVh[24] == 0x3f) 
          nav->gps_alm[24].inc = 0.0;
#endif
      }
      else
      {
        nav->alm.prn      = i5page;
        nav->alm.week     = gps_week;
        tmpuint           = (int)(sf[5][3] & 0xFFFF);
        nav->alm.ety      = tmpuint * pow(2.0,-21.0);
        tmpuint           = (int)(sf[5][4] >> 16);
        nav->alm.toa      = tmpuint * 4096.0;
        tmplng            = (int)(sf[5][4] & 0xFFFF);
        nav->alm.inc      = (tmplng * pow(2.0,-19.0) + 0.3)*pi;
        tmpint            = (int)(sf[5][5] >> 8);
        nav->alm.omegadot = tmpint * pow(2.0,-38.0) * pi;
        nav->alm.health   = (int)(sf[5][5] & 0xFF);
        tmpulng           = sf[5][6];
        nav->alm.sqra     = tmpulng * pow(2.0,-11.0);
        if ( nav->alm.sqra > 0.0) 
          nav->alm.w      = 19964981.84 / pow( nav->alm.sqra, 3);
        tmplng = sf[5][7];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->alm.omega0   = tmplng * pow(2.0,-23.0) * pi;
        tmplng            = sf[5][8];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->alm.w        = tmplng * pow(2.0,-23.0) * pi;
        tmplng            = sf[5][9];
        if ( bit_test_long( tmplng, 24)) 
          tmplng |= 0xFF000000L;
        nav->alm.ma       = tmplng * pow(2.0,-23.0) * pi;
        tmplng            = (int)((sf[5][10] >> 13) | (sf[5][10] & 0x1C));
        if ( bit_test_long( tmplng, 11)) 
          tmplng |= 0xF800;
        nav->alm.af0      = tmplng * pow(2.0,-20.0);
        tmplng            = (int)((sf[5][10] & 0xFFE0) >> 5);
        if ( bit_test_long( tmplng, 11)) 
          tmplng |= 0xF800;
        nav->alm.af1      = tmplng * pow(2.0,-38.0);
      }
    }
  }
  return;
}

/* ------------------------------ end of file ----------------------------- */