home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / satel / seesats / seesats.c next >
C/C++ Source or Header  |  1988-11-10  |  31KB  |  1,253 lines

  1. /******************************************************************************
  2.  *
  3.  *    SEESATS.C    - Allows user to "see" where the satellites
  4.  *            are currently located.
  5.  *
  6.  *    Translated from W0SL's ORBITS2.BAS (BASIC) by:
  7.  *
  8.  *        (c) Copyright
  9.  *        November 1985
  10.  *        Rich Bono - NM1D
  11.  *        7 Redfield Circle
  12.  *        Derry, New Hampshire 03038
  13.  *        (603) 432-9002
  14.  *
  15.  *        **** Wild Mean Bits ****
  16.  *
  17.  *    This program in its entirety, or in its parts, is NOT in the public
  18.  *    domain.  My Name/call/copyright must remain in both the source, and
  19.  *    any executable produced from this source or any derivitive of it.
  20.  *    Of course, if you make additions, you may add your name to the end
  21.  *    of the copyright messages.
  22.  *    This source is being made available to others to foster the goodwill
  23.  *    and development of Amateur Radio satelellite operators.  If you make
  24.  *    any changes to this code, either for to port this to another machine
  25.  *    or architechture, you must send me the source for archival reasons,
  26.  *    and so that I can incorporate improvements into the reference copy.
  27.  *
  28.  *
  29.  *
  30.  *    Note:    This program is in such poor shape because it is a
  31.  *        (almost) a direct translation from a BASIC source!  I did all
  32.  *        I could to disolve the spagetti sauce.  With more time, and
  33.  *        revisions, the code will improve....
  34.  *
  35.  *    Revisions:
  36.  *    Ver 1.0        25-Oct-88    localtime() was returning month as
  37.  *                     base 0, needed base 1
  38.  *
  39.  *    Ver 0.9        19-Oct-88    Changed dos ints to calls to time(),
  40.  *                     and localtime()
  41.  *                     also changed for UNIX portability
  42.  *
  43.  *    Ver 0.8        16-Feb-88    Fixed sat loop, so not to repeat
  44.  *                     selected bird
  45.  *
  46.  *    Ver 0.7        13-Feb-88    Changes to read data file routine
  47.  *
  48.  *    Ver 0.6        28-Dec-87    Fixed bug caused by MSC V4.0 float
  49.  *                     logic
  50.  *
  51.  *    Ver 0.5        30-Sep-87    Added paged output mode logic,
  52.  *                     changed abs() to fabs()
  53.  *
  54.  *            22-May-87    Added argument driven loops
  55.  *            20-May-87    Added satelite data display
  56.  *            15-May-87    Changed menu operation to toggle.
  57.  *
  58.  *            06-May-87    Added Version display & concatenated
  59.  *                     data files to use SEESATS.DAT
  60.  *
  61.  *            13-Apr-87    Added prediction algorithms
  62.  *            28-Sep-86    Worked on variable names
  63.  *
  64.  *    Hope to add/change:
  65.  *
  66.  *        Doppler correction, outputs to drive az-el antenna control.
  67.  *        Make bird data into structure.
  68.  *        Get RID of all these *GLOBALS*!!
  69.  *
  70.  *    Notes:
  71.  *
  72.  *    This code was kept as generic as possible, that is, NO terminal
  73.  *    control features were used to allow this to be fairly portable.
  74.  *
  75.  *    Currently compiles with Microsoft-C, see GetAKeyNoEcho() for
  76.  *    possible non-portable code.
  77.  *
  78.  *    Set the FORMSDOS or FORUNIX flag as appropriate
  79.  *
  80.  *    This has been tested under MS-DOS and OS/2
  81.  */
  82.  
  83. #define    VERSION    "1.0"        /* Version as displayed by program    */
  84.  
  85. #include    <stdio.h>
  86. #include    <math.h>
  87. #include    <time.h>
  88. #include    <ctype.h>
  89.  
  90. #define    FORMSDOS    1    /* 1 = for MSDOS or OS/2    */
  91. #define    FORUNIX        0    /* 1 = for UNIX            */
  92.  
  93. /* #define    fopen    fpopen    /* open files with aid of MS-DOS PATH */
  94.  
  95. #define    DATAFILE    "seesats.dat"    /* file that contains station &    */
  96.                     /* bird information        */
  97.  
  98. #define    bool        int
  99. #define    ESC        27        /* Escape key    */
  100. #define    TRUE        (1)
  101. #define    FALSE        (0)
  102. #define abs(a)        (((a) < 0) ? -(a) : (a))
  103. #define    MAXTRACKED    20    /* maximum number of satellites    */
  104.  
  105. /************ GLOBALs ****************/
  106.  
  107. double    pi        = 3.1415926535;    /* P1 value of PI        */
  108. double    pi_2;                /* P2 PI squared        */
  109. double    pi_180;                /* P0 PI/180            */
  110.  
  111. double    one3rd        = 1.0/3.0;    /* one third            */
  112.  
  113. double    e_radius    = 6378.16;    /* R0 Earth's radius        */
  114. double    e_flat        = 298.16;    /* F  1/Earth flattening    */
  115.                     /*         coeficient    */
  116. double    e_gm        =75369793000000.0;/* G0 GM of Earth in         */
  117.                     /*    (Orbits/day)^2/km^3    */
  118.  
  119. double    stn_latitude;            /* L9 station latitude        */
  120. double    stn_longitude;            /* W9 station longitude        */
  121. double    stn_height;            /* H9 station altitude        */
  122. char    stn_call[8+1];            /* C$ station call sign        */
  123. int    stn_utc;            /* Number of hours to change to    */
  124.                     /*  UTC from local time        */
  125.  
  126. int    s_year1[20+1];            /* Y1 siderial year info    */
  127. int    s_year2;            /* X2                */
  128. double    s_year3[20+1];            /* G3                */
  129. double    s_ratio    = 1.0027379093;        /* G1 Sidereal/Solar time    */
  130.                     /*        rate ratio    */
  131.  
  132. char    sat_name[MAXTRACKED+1][10];    /* I$ sat name            */
  133. double    beacon_freq[MAXTRACKED+1];    /* F1                */
  134. double    epoch_orbit[MAXTRACKED+1];    /* K0                */
  135. int    epoch_yr[MAXTRACKED+1];        /* Y3                */
  136. double    epoch_day[MAXTRACKED+1];    /* T0                */
  137. double    raan[MAXTRACKED+1];        /* O0                */
  138. double    inclination[MAXTRACKED+1];    /* I0                */
  139. double    eccentricity[MAXTRACKED+1];    /* E0                */
  140. double    arg_of_perigee[MAXTRACKED+1];    /* W0                */
  141. double    mean_anomoly[MAXTRACKED+1];    /* M0                */
  142. double    mean_motion[MAXTRACKED+1];    /* N0                */
  143. double    decay_rate[MAXTRACKED+1];    /* N1                */
  144.  
  145.  
  146. double    eccent,
  147.     realtime,
  148.     sat_orbit,
  149.     orbit_pi2,
  150.     sat_height,
  151.     this_orbit,
  152.     cos_eccent,
  153.     sin_eccent,
  154.     sat_latitude,
  155.     sat_range,
  156.     sat_longitude,
  157.     cos_s_lon,
  158.     s_lat_pi180,
  159.     sin_s_lon,
  160.     sat_azimuth,
  161.     sin_s_lat,
  162.     sat_elevation,
  163.     s_h_radis,
  164.     cos_s_lat,
  165.     sat_phase,
  166.     stn_x,
  167.     stn_y,
  168.     stn_z;
  169.  
  170. int    max_sats;
  171. int    sider_cnt;
  172.  
  173. struct    {
  174.         int    hour;
  175.         int    minute;
  176.         int    second;
  177.         int    tenth;
  178.     } static_time;
  179.  
  180. struct    {
  181.         int    year;
  182.         int    month;
  183.         int    day;
  184.     } static_date;
  185.  
  186. int    dos_time    = TRUE;    /* when true read dos clock, else increment    */
  187.                 /* clock by min_inc                */
  188. int    min_inc        = 10;    /* number of minutes to increment clock by    */
  189.  
  190. int    in_view        = FALSE;/* when TRUE, only print data is sat is in view    */
  191. int    aos_los        = FALSE;/* when TRUE, only print data at (near) AOS/LOS    */
  192. int    sel_bird    = 0;    /* when not 0, only use selected satelite    */
  193. int    page_mode    = TRUE;    /* when TRUE, give user a page at a time    */
  194.  
  195. /*****************************************************************************
  196.  *
  197.  *    GetAKeyNoEcho() - read one key without echo
  198.  *
  199.  *        if no input available return (0)
  200.  *
  201.  *              else return key
  202.  *
  203.  *     Note: this will not allow the NUL (CTRL-@) character to be input
  204.  *
  205.  */
  206.  
  207. int GetAKeyNoEcho()
  208. {
  209. #if    FORMSDOS
  210.     if(kbhit())
  211.     {
  212.         return(getch());    /* read key without echo */
  213.     }
  214.     else
  215.     {
  216.         return(0);        /* no key to read */
  217.     }
  218.  
  219. #endif    /* FORMSDOS */
  220.  
  221. #if    FORUNIX
  222. #include    <termio.h>
  223.  
  224. struct    termio    tty, savetty;
  225. int    stat;
  226. char    keyin;
  227.  
  228.     if(isatty(fileno(stdin)))
  229.     {
  230.         ioctl(fileno(stdin), TCGETA, &tty); /* read current settings */
  231.  
  232.         savetty = tty;            /* save current settings */
  233.  
  234.         tty.c_lflag &= ~ (ICANON|ECHO);    /* allow read of char without echo */
  235.         tty.c_cc[VMIN] = 0;            /* allow read without blocking */
  236.         tty.c_cc[VTIME] = 0;        /* no input timer */
  237.  
  238.         ioctl(fileno(stdin), TCSETA, &tty); /* set new parameters */
  239.     }
  240.  
  241.     stat = read(fileno(stdin), &keyin, 1); /* read one character */
  242.  
  243.     if(isatty(fileno(stdin)))
  244.     {
  245.         ioctl(fileno(stdin), TCSETA, &savetty); /* restore previous settings */
  246.     }
  247.  
  248.     return(stat ? ((int) keyin) : 0);    /* return key read if any, else return 0 */
  249.  
  250. #endif    /* FORUNIX */
  251.  
  252. } /* end of GetAKeyNoEcho() */
  253.  
  254. /****************************************************************************/
  255. main(argc, argv)
  256. int    argc;
  257. char    *argv[];
  258. {
  259.  
  260. FILE        *fp, *fopen();
  261. int        hour(), minute(), second(), day(), month(), year();
  262. int        status;
  263. int        loops;            /* number of loops to perform    */
  264. int        forever;        /* flag, is loops decremented?    */
  265. char        *date();
  266. char        buffer[132];
  267. register    sat_number;
  268.  
  269.     printf("\nSeesats  version %s - (c) Copyright 1985 - By Rich Bono, NM1D.\n\n", VERSION);
  270.  
  271.  
  272.     /*********************************/
  273.     /* read earth station parameters */
  274.     /*********************************/
  275.  
  276.     fp = fopen(DATAFILE,"r");
  277.  
  278.     if(!fp)
  279.      {
  280.          fprintf(stderr, "\nFile %s missing!\n\n", DATAFILE);
  281.          exit(1);
  282.      }
  283.  
  284.     do    /* eat any comment lines, output note lines */
  285.     {
  286.          fgets(buffer, sizeof(buffer), fp);
  287.  
  288.         if(buffer[0] == '|')    /* output lines that begin with | */
  289.         {            /* to stdout              */
  290.             printf("%s", &buffer[1]);
  291.         }
  292.  
  293.     } while (buffer[0] == ';' || buffer[0] == '|');
  294.  
  295.     if( 5 != sscanf(buffer, "%lf %lf %lf %s %d",
  296.                 &stn_latitude, &stn_longitude, &stn_height,
  297.                 stn_call, &stn_utc)
  298.       )
  299.      {
  300.          fprintf(stderr,"\nError reading file %s for earth station information!\n\n", DATAFILE);
  301.  
  302.         fprintf(stderr,"Should be latitude longitude height station ID and UTC correction\n");
  303.         fprintf(stderr,"%lf %lf %lf %s %d\n",
  304.             &stn_latitude, &stn_longitude, &stn_height,stn_call, stn_utc);
  305.  
  306.  
  307.         fclose(fp);
  308.          exit(1);
  309.      }
  310.  
  311.     fprintf(stderr,"Earth location data entered for '%s'.\n\n", stn_call);
  312.  
  313.     /************************/
  314.     /* initialize constants    */
  315.     /************************/
  316.  
  317.     pi_2        = 2.0 * pi;
  318.     pi_180        = pi / 180.0;
  319.     e_flat        = 1.0 / e_flat;
  320.     s_lat_pi180    = stn_latitude * pi_180;
  321.     sin_s_lat    = sin(s_lat_pi180);
  322.     cos_s_lat    = cos(s_lat_pi180);
  323.     sin_s_lon    = sin( -stn_longitude * pi_180);
  324.     cos_s_lon    = cos(stn_longitude * pi_180);
  325.     s_h_radis    = e_radius * ( 1.0 - (e_flat / 2.0) + (e_flat / 2.0) * cos(2.0 * s_lat_pi180)) + stn_height / 1000.0;
  326.     s_lat_pi180    = atan( ((1.0 - e_flat)*(1.0 - e_flat)) * sin_s_lat / cos_s_lat);
  327.     stn_z        = s_h_radis * sin(s_lat_pi180);
  328.     stn_x        = s_h_radis * cos(s_lat_pi180) * cos_s_lon;
  329.     stn_y        = s_h_radis * cos(s_lat_pi180) * sin_s_lon;
  330.  
  331.     dos_time = TRUE;
  332.  
  333.     settime();    /* initialize time and date structures    */
  334.  
  335.     /**********************************/
  336.     /* Initialize Sidereal time table */
  337.     /**********************************/
  338.  
  339.     for(sider_cnt=1; sider_cnt<20; sider_cnt++)
  340.      {
  341.         s_year1[sider_cnt] = sider_cnt + 1980;
  342.  
  343.         s_year2 = floor( (s_year1[sider_cnt] - 1.0) / 100.0);
  344.  
  345.         s_year3[sider_cnt] = 2.0 - s_year2 + floor(s_year2 / 4.0) +
  346.                 floor(365.25 * (s_year1[sider_cnt]-1.0)) +
  347.                 floor(30.6001 * 14);
  348.  
  349.         s_year3[sider_cnt] = (s_year3[sider_cnt] - 730550.5) / 36525;
  350.  
  351.         s_year3[sider_cnt] = (s_year3[sider_cnt] * (s_year3[sider_cnt] * (s_year3[sider_cnt] *
  352.                 (-7.1759593E-11) + .00000107759259) +
  353.                 100.002139)) + .279057273;
  354.  
  355.         s_year3[sider_cnt] = s_year3[sider_cnt] - floor(s_year3[sider_cnt]);
  356.  
  357.         s_year1[sider_cnt] = s_year1[sider_cnt] - 1900;
  358.      }
  359.  
  360.  
  361.     /*******************************/
  362.     /* initialize satellite matrix */
  363.     /*******************************/
  364.  
  365.     for(max_sats=1; max_sats<=MAXTRACKED; )
  366.      {
  367.          fgets(buffer, sizeof(buffer), fp);
  368.  
  369.         /* skip lines that begin with a ';' or '|' */
  370.         /* output lines that begin with a '|; to stdout */
  371.          if(buffer[0] == ';' || buffer[0] == '|')
  372.            {
  373.                if(buffer[0] == '|')
  374.                {
  375.                    printf("%s",&buffer[1]);
  376.                }
  377.             continue;
  378.           }
  379.  
  380.          status = sscanf(buffer,"%s %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
  381.              sat_name[max_sats],
  382.              &epoch_yr[max_sats],
  383.              &epoch_day[max_sats],
  384.              &inclination[max_sats],
  385.              &raan[max_sats],
  386.              &eccentricity[max_sats],
  387.              &arg_of_perigee[max_sats],
  388.              &mean_anomoly[max_sats],
  389.              &mean_motion[max_sats],
  390.              &decay_rate[max_sats],
  391.              &epoch_orbit[max_sats],
  392.              &beacon_freq[max_sats]
  393.                  );
  394.  
  395.           if(feof(fp) || (status != 12))
  396.            {
  397.                break;
  398.            }
  399.  
  400.           fprintf(stderr,"Data for %2d satellite%s read.\r",max_sats,(max_sats==1?" ":"s"));
  401.  
  402.  
  403. /*
  404.  *         printf("%s %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n",
  405.  *             sat_name[max_sats],
  406.  *             epoch_yr[max_sats],
  407.  *             epoch_day[max_sats],
  408.  *             inclination[max_sats],
  409.  *             raan[max_sats],
  410.  *             eccentricity[max_sats],
  411.  *             arg_of_perigee[max_sats],
  412.  *             mean_anomoly[max_sats],
  413.  *             mean_motion[max_sats],
  414.  *             decay_rate[max_sats],
  415.  *             epoch_orbit[max_sats],
  416.  *             beacon_freq[max_sats]
  417.  *            );
  418.  */
  419.  
  420.  
  421.         if(!((epoch_yr[max_sats] == year()) || (epoch_yr[max_sats] == year()-1)))
  422.          {
  423.              fprintf(stderr, "\nThe elements for satellite #%d (%s) is not from the\n", max_sats, sat_name[max_sats]);
  424.              fprintf(stderr, " current or preceding year.  The current date is %s. Set the\n",date());
  425.              fprintf(stderr, " system date or update the satellite orbital elements.\n");
  426.             exit(1); /* back to menu if any */
  427.          }
  428.  
  429.         max_sats++;
  430.  
  431.      } /* end of for(max_sats=1; max_sats<=MAXTRACKED;) */
  432.  
  433.     if(!page_mode)
  434.     {
  435.         fprintf(stderr, "\n\n Press [ENTER] for menu . . .\n");
  436.     }
  437.     else
  438.     {
  439.         printf("\n");
  440.     }
  441.  
  442.     /********************************/
  443.     /*    Orbit calculation loop    */
  444.     /********************************/
  445.  
  446.     switch(argc)
  447.     {
  448.         default:
  449.         case 1:        /* no command line, set up to run forever */
  450.             dos_time = TRUE;
  451.             loops    = 1;
  452.             forever    = TRUE;
  453.             break;
  454.  
  455.         case 2:
  456.             loops = atoi(argv[1]);    /* get number of loops    */
  457.  
  458.             if(loops > 0)        /* if legal number    */
  459.             {
  460.                 forever = FALSE; /* won't be running long*/
  461.             }
  462.             else
  463.             {
  464.                 forever = TRUE;    /* will never end    */
  465.             }
  466.  
  467.             dos_time = TRUE;    /* be in realtime mode    */
  468.  
  469.             break;
  470.  
  471.     } /* end of switch(argc) */
  472.  
  473.     while(loops)
  474.      {
  475.          if(!dos_time)    /* if not in realtime */
  476.          {
  477.              settime();    /* calculate date & time here */
  478.          }
  479.  
  480.         if(sel_bird)            /* if one bird */
  481.         {
  482.             if(GetAKeyNoEcho())
  483.              {
  484.                   do_command();        /* give menu commands    */
  485.              }
  486.  
  487.             calc_orbit(sel_bird);    /* calculate orbital data */
  488.  
  489.             show_data(sel_bird);    /* show current data    */
  490.         }
  491.         else                /* do all birds    */
  492.         {
  493.             for(sat_number=1;sat_number < max_sats; sat_number++)
  494.              {
  495.                 if(GetAKeyNoEcho())
  496.                  {
  497.                       do_command();        /* give menu commands    */
  498.                  }
  499.  
  500.                 calc_orbit(sat_number);    /* calculate orbital data */
  501.  
  502.                 show_data(sat_number);    /* show current data    */
  503.  
  504.              } /* end for(sat_number=1;sat_number < max_sats; sat_number++) */
  505.         }
  506.  
  507.         if(!forever)        /* if not running forever    */
  508.         {
  509.             loops--;    /* count this loop        */
  510.         }
  511.  
  512.      } /* end while(loops) */
  513.  
  514. }    /* end of main()    */
  515.  
  516. /*****************************************************************************
  517.  *
  518.  *    calc_orbit() - calculate orbital data
  519.  *
  520.  */
  521. calc_orbit(sat_number)
  522. register sat_number;
  523. {
  524. register    loop_cnt;
  525. bool    calc;
  526. int    hour(), minute(), second(), day(), month(), year();
  527. char    *date();
  528. double    c[3+1][2+1];
  529. double    xx,
  530.     yy,
  531.     zz,
  532.     a0,
  533.     c0,
  534.     m0,
  535.     n0,
  536.     o0,
  537.     q0,
  538.     s0,
  539.     w0,
  540.     x_0,
  541.     y_0,
  542.     c1,
  543.     e1,
  544.     m1,
  545.     s1,
  546.     x1,
  547.     y_1,
  548.     z1,
  549.     c2,
  550.     e2,
  551.     g2,
  552.     k2,
  553.     s2,
  554.     r3,
  555.     b5,
  556.     c5,
  557.     m5,
  558.     s5,
  559.     x5,
  560.     y5,
  561.     z5,
  562.     c7,
  563.     g7,
  564.     s7,
  565.     x8,
  566.     y8,
  567.     z8;
  568.  
  569. double    temp;
  570.  
  571.      n0 = mean_motion[sat_number] + 2.0 * (realtime - epoch_day[sat_number]) * decay_rate[sat_number];
  572.      a0 = pow((e_gm / (n0 * n0)), one3rd);
  573.     e2 = 1.0 - eccentricity[sat_number] * eccentricity[sat_number];
  574.     e1 = sqrt(e2);
  575.     q0 = mean_anomoly[sat_number] / 360.0 + epoch_orbit[sat_number];
  576.  
  577.     k2 = 9.95 * pow((e_radius / a0), 3.5) / (e2 * e2);
  578.     s1 = sin(inclination[sat_number] * pi_180);
  579.     c1 = cos(inclination[sat_number] * pi_180);
  580.  
  581.     calc_time(sat_number);    /* update realtime for this bird    */
  582.  
  583.     o0 = raan[sat_number] - (realtime - epoch_day[sat_number]) * k2 * c1;
  584.     s0 = sin(o0 * pi_180);
  585.     c0 = cos(o0 * pi_180);
  586.     w0 = arg_of_perigee[sat_number] + ( realtime - epoch_day[sat_number]) * k2 *
  587.         (2.5 * (c1 * c1) - .5);
  588.     s2 = sin(w0 * pi_180);
  589.     c2 = cos(w0 * pi_180);
  590.     c[1][1] = /*+*/(c2 * c0) - (s2 * s0 * c1);
  591.     c[1][2] = -(s2 * c0) - (c2 * s0 * c1);
  592.     c[2][1] = /*+*/(c2 * s0) + (s2 * c0 * c1);
  593.     c[2][2] = -(s2 * s0) + (c2 * c0 * c1);
  594.     c[3][1] = /*+*/(s2 * s1);
  595.     c[3][2] = /*+*/(c2 * s1);
  596.     this_orbit = (mean_motion[sat_number] + decay_rate[sat_number] * (realtime - epoch_day[sat_number])) *
  597.         (realtime - epoch_day[sat_number]) + q0;
  598.  
  599.     sat_orbit = floor(this_orbit);
  600.     sat_phase = floor((this_orbit-sat_orbit) * 256.0);
  601.     orbit_pi2 = (this_orbit - sat_orbit) * pi_2;
  602.     eccent = orbit_pi2 + eccentricity[sat_number] * sin(orbit_pi2) + .5 *
  603.         (eccentricity[sat_number] * eccentricity[sat_number]) * sin(2.0 * orbit_pi2);
  604.  
  605.     calc = TRUE;
  606.  
  607.     while(calc)    /* calculating */
  608.      {
  609.         sin_eccent = sin(eccent);
  610.         cos_eccent = cos(eccent);
  611.         r3 = 1.0 - eccentricity[sat_number] * cos_eccent;
  612.         m1 = eccent - eccentricity[sat_number] * sin_eccent;
  613.         m5 = m1 - orbit_pi2;
  614.  
  615.         if( fabs(m5) < .000001)
  616.          {
  617.             calc = FALSE;
  618.          }
  619.         else
  620.          {
  621.             eccent = eccent - m5 / r3;
  622.          }
  623.  
  624.      } /* end while(TRUE) calc */
  625.  
  626.     x_0 = a0 * (cos_eccent - eccentricity[sat_number]);
  627.     y_0 = a0 * e1 * sin_eccent;
  628.     sat_height = a0 * r3;
  629.     x1 = x_0 * c[1][1] + y_0 * c[1][2];
  630.  
  631.     y_1 = x_0 * c[2][1] + y_0 * c[2][2];
  632.     z1 = x_0 * c[3][1] + y_0 * c[3][2];
  633.  
  634.     for(loop_cnt = 1; loop_cnt != sider_cnt; loop_cnt++)
  635.      {
  636.         if(epoch_yr[sat_number] == s_year1[loop_cnt])
  637.          {
  638.              g2 = s_year3[loop_cnt];
  639.          }
  640.      }
  641.     g7 = realtime * s_ratio + g2;
  642.     temp = g7;            /* this is to force FWAIT by MSC V4.0! */
  643.     g7 = (g7 - floor(g7)) * pi_2;
  644.     s7 = -sin(g7);
  645.     c7 = cos(g7);
  646.     xx = /*+*/(x1 * c7) - (y_1 * s7);
  647.     yy = /*+*/(x1 * s7) + (y_1 * c7);
  648.     zz = z1;
  649.     x5 = (xx - stn_x);
  650.     y5 = (yy - stn_y);
  651.     z5 = (zz - stn_z);
  652.     sat_range = sqrt(x5 * x5 + y5 * y5 + z5 * z5);
  653.     z8 = /*+*/(x5 * cos_s_lon * cos_s_lat) + (y5 * sin_s_lon * cos_s_lat) + (z5 * sin_s_lat);
  654.     x8 = -(x5 * cos_s_lon * sin_s_lat) - (y5 * sin_s_lon * sin_s_lat) + (z5 * cos_s_lat);
  655.     y8 = /*+*/(y5 * cos_s_lon) - (x5 * sin_s_lon);
  656.     s5 = z8/sat_range;
  657.     c5 = sqrt(1.0 - s5 * s5);
  658.     sat_elevation = atan(s5 / c5) / pi_180;
  659.  
  660.     if(x8 < 0.0)
  661.      {
  662.          sat_azimuth = pi + atan(y8 / x8);
  663.      }
  664.     else
  665.      {
  666.          if(x8 > 0.0 && y8 >= 0.0)
  667.           {
  668.               sat_azimuth = atan(y8/x8);
  669.           }
  670.          else
  671.           {
  672.               if(x8 > 0.0)
  673.                {
  674.                   sat_azimuth = pi_2 + atan(y8/x8);
  675.                }
  676.               else
  677.                {
  678.                    if(y8 < 0.0)
  679.                     {
  680.                         sat_azimuth = 3.0 * pi / 2.0;
  681.                     }
  682.                    else
  683.                     {
  684.                         sat_azimuth = pi / 2.0;
  685.                     }
  686.                }
  687.          }
  688.      }
  689.     sat_azimuth = sat_azimuth / pi_180;
  690.     if(xx < 0.0)
  691.      {
  692.          sat_longitude = pi + atan(yy/xx);
  693.      }
  694.     else
  695.      {
  696.          if(xx > 0.0 && yy >= 0.0)
  697.           {
  698.               sat_longitude = atan(yy/xx);
  699.           }
  700.          else
  701.           {
  702.               if(xx > 0.0)
  703.                {
  704.                    sat_longitude = pi_2 + atan(yy / xx);
  705.                }
  706.               else
  707.                {
  708.                    if(yy < 0.0)
  709.                     {
  710.                         sat_longitude = 3.0 * pi/2.0;
  711.                  }
  712.                 else
  713.                  {
  714.                      sat_longitude = pi / 2.0;
  715.                  }
  716.              }
  717.          }
  718.      }
  719.     sat_longitude = 360.0 - sat_longitude / pi_180;
  720.     b5 = zz / sat_height;
  721.     sat_latitude = atan(b5 / (sqrt(1 - (b5 * b5)))) / pi_180;
  722.  
  723. } /* end of calc_obit() */
  724.  
  725.  
  726. /****************************************************************************
  727.  *
  728.  *    show_data() - show current calculated data
  729.  *
  730.  *    output a header line for each new day, and for each 'page'
  731.  */
  732.  
  733. show_data(sat_number)
  734. register sat_number;
  735. {
  736. char    *stime(), *date();
  737. char    buffer[80];
  738. static    line = 0;
  739. static    oldday = 0;
  740.  
  741.     if(
  742.        (in_view && (sat_elevation < 0.0))
  743.       )
  744.      {
  745.          return;
  746.      }
  747.      
  748.     if((line-- <= 0) || (oldday != day()))
  749.      {
  750.          oldday = day();
  751.  
  752.          line = MAXTRACKED-1;
  753.  
  754.          if(page_mode)
  755.          {
  756.              fprintf(stderr, "\n-- [ENTER] to continue, M for menu -- ");
  757.             fgets(buffer, sizeof(buffer), stdin);
  758.  
  759.             if(tolower(buffer[0])=='m')    /* if user wants back to menu */
  760.             {
  761.                 do_command();        /* handle command    */
  762.                 return;
  763.             }
  764.          }
  765.  
  766.         printf("\nFor %8s, at %7.3f Latitude, %7.3f Longitude, %7.2f M Altitude",
  767.              stn_call,
  768.              stn_latitude,
  769.              stn_longitude,
  770.              stn_height
  771.              );
  772.  
  773.         printf("\nSatellite   Az  El RngKm AltKm   Lat  Long  Orbit   Ph  Beacon %s\n",date());
  774.      }
  775.  
  776.     printf("%-10s %3.0f %3.0f %5.0f %5.0f %5.1f %5.1f %6.0f %4.0f %7.3f  %s\n",
  777.              sat_name[sat_number],        /* Name        */
  778.              sat_azimuth,            /* Azimuth    */
  779.              sat_elevation,            /* Elevation    */
  780.              sat_range,            /* Range_Km    */
  781.              (sat_height - e_radius),    /* Height_Km    */
  782.              sat_latitude,            /* Latitude    */
  783.              sat_longitude,            /* Longitude    */
  784.              sat_orbit,            /* Orbit    */
  785.              sat_phase,            /* Phase    */
  786.              beacon_freq[sat_number],    /* Freq (someday doppler corrected)*/
  787.              stime()
  788.         );
  789.  
  790. } /* end of show_data() */
  791. /*******************************************************************************
  792.  *
  793.  *    show_elements(sat) - display current element data for sat.
  794.  *
  795.  *
  796.  */
  797.  
  798. show_elements(sat)
  799. int    sat;
  800. {
  801.  
  802.     printf("\n");
  803.     printf("Name                : %9s\n",        sat_name[sat]);
  804.     printf("Epoch year          : %9d\n",
  805.         (epoch_yr[sat]<1900 ? epoch_yr[sat] + 1900 : epoch_yr[sat]));
  806.     printf("Epoch day           : %20.10lf\n",    epoch_day[sat]);
  807.     printf("Epoch orbit         : %20.10lf\n",    epoch_orbit[sat]);
  808.     printf("Inclination         : %20.10lf\n",    inclination[sat]);
  809.     printf("RAAN                : %20.10lf\n",    raan[sat]);
  810.     printf("Eccentricity        : %20.10lf\n",    eccentricity[sat]);
  811.     printf("Argument of perigee : %20.10lf\n",    arg_of_perigee[sat]);
  812.     printf("Mean anomoly        : %20.10lf\n",    mean_anomoly[sat]);
  813.     printf("Mean motion         : %20.10lf\n",    mean_motion[sat]);
  814.     printf("Decay rate          : %20.10lf\n",    decay_rate[sat]);
  815.     printf("Beacon frequency    : %20.10lf\n",    beacon_freq[sat]);
  816.     printf("\n");
  817.  
  818. } /* end of show_elements() */
  819.  
  820. /*******************************************************************************
  821.  *
  822.  *    do_command() - Handle any keyboard entries
  823.  *            Present menu.
  824.  *
  825.  */
  826.  
  827. do_command()
  828. {
  829. int    index;
  830. int    cmd_loop;
  831. char    buffer[85];
  832.  
  833.     cmd_loop = TRUE;    /* keep looping until user is done    */
  834.                 /*  with menu                */
  835.     do
  836.     {
  837.  
  838.         fprintf(stderr, "\n\n\t\t\t Current selections:\n");
  839.  
  840. /* the 3 fields for the following are : 10 chars for description, 16 chars data... */
  841.  
  842.         fprintf(stderr,"\nMode is...%-16s  Print...%-16s  Select..%-16s\n",
  843.             (dos_time ? "realtime" : "prediction"),
  844.             (in_view ? "when in view" : "all calculations"),
  845.             (sel_bird ? sat_name[sel_bird] : "all satelites")
  846.             );
  847.         fprintf(stderr,  "Output is.%-16s\n",
  848.             (page_mode ? "paged" : "continuous")
  849.             );
  850.  
  851.         fprintf(stderr, "\n\n\t\t\tSeesats menu -\n\n");
  852.         fprintf(stderr,   "\t\t1   - Mode to %s\n", (dos_time ? "prediction":"realtime"));
  853.         fprintf(stderr,   "\t\t2   - Print %s\n",(in_view ? "all calculations" : "when in view"));
  854.         fprintf(stderr,   "\t\t3   - Select %s\n",(sel_bird ? "all satelites" : "satelite of interest"));
  855.         fprintf(stderr,   "\t\t4   - Print current element data for satelites\n");
  856.         fprintf(stderr,   "\t\t5   - Change output mode to %s\n", (page_mode ? "continuous" : "paged"));
  857.  
  858.         fprintf(stderr, "\n\t\t0 - Quit.\n\n");
  859.  
  860.         fprintf(stderr, "Enter number for desired function ([ENTER] to continue) : ");
  861.  
  862.         fgets(buffer, sizeof(buffer), stdin);
  863.  
  864.          switch(buffer[0])
  865.           {
  866.              case '1':    /* select either realtime or predictions    */
  867.  
  868.                  dos_time = !dos_time;    /* toggle mode    */
  869.  
  870.                 if(dos_time)
  871.                 {
  872.                      fprintf(stderr,"\n\nRunning in realtime . . .\n");
  873.                      settime();
  874.                  }
  875.                  else
  876.                  {
  877.                     fprintf(stderr, "\n\n\nEnter start day, month & year [ENTER = %02d/%02d/%02d ] (dd/mm/yy) : ", 
  878.                         static_date.day, static_date.month, static_date.year-1900);
  879.                         fgets(buffer, sizeof(buffer), stdin);
  880.                     if(strlen(buffer))
  881.                     {
  882.                         sscanf(buffer, "%d/%d/%4d",&static_date.day, &static_date.month, &static_date.year);
  883.                     }
  884.  
  885.                     if(static_date.year < 1900)
  886.                     {
  887.                         static_date.year += 1900;
  888.                     }
  889.  
  890.                     fprintf(stderr, "\nEnter start hour & minute      [ENTER = %02d:%02d ]      (hh:mm) : ",
  891.                         static_time.hour, static_time.minute);
  892.                         static_time.second = 0;
  893.                         static_time.tenth = 0;
  894.  
  895.                     fgets(buffer, sizeof(buffer), stdin);
  896.                     if(strlen(buffer))
  897.                     {
  898.                         sscanf(buffer, "%d:%d", &static_time.hour, &static_time.minute);
  899.                     }
  900.  
  901.                     fprintf(stderr, "\nEnter number of minutes to increment  [ENTER = %3d ]         : ", min_inc);
  902.  
  903.                     fgets(buffer, sizeof(buffer), stdin);
  904.                     if(strlen(buffer))
  905.                     {
  906.                         sscanf(buffer, "%d",&min_inc);
  907.                     }
  908.  
  909.  
  910.                 } /* end of if(dos_time) */
  911.  
  912.                 break;
  913.  
  914.             case '2':    /* select only in view or all calculations    */
  915.  
  916.                 in_view = !in_view;
  917.                 if(in_view)
  918.                 {
  919.                     fprintf(stderr,"\n\nWill show data for satelites only when in view . . .\n");
  920.                 }
  921.                 else
  922.                 {
  923.                     fprintf(stderr,"\n\nWill show all calculated data.\n");
  924.                 }
  925.                 break;
  926.  
  927.             case '3':    /* select bird of interest    */
  928.  
  929.                 if(sel_bird)
  930.                 {
  931.                     sel_bird = 0;
  932.                     fprintf(stderr,"\n\nShow data for all satelites.\n");
  933.  
  934.                 }
  935.                 else
  936.                 {
  937.                     fprintf(stderr, "\n\nSelect from the following list :\n\n");
  938.  
  939.                     do
  940.                     {
  941.                         fprintf(stderr, "\t\t 0 = All the following\n");
  942.  
  943.                         for(index=1; index < max_sats; index++)
  944.                         {
  945.  
  946.                             fprintf(stderr, "\t\t%2d = %s\n",index, sat_name[index]);
  947.                         }
  948.  
  949.                         fprintf(stderr, "\n\n\t\tSelect satelite by number [ENTER = %d] : ", sel_bird);
  950.  
  951.                         fgets(buffer, sizeof(buffer), stdin);
  952.                         if(strlen(buffer))
  953.                         {
  954.                             sscanf(buffer, "%d",&sel_bird);
  955.                         }
  956.  
  957.                     } while ((sel_bird >= max_sats) || (sel_bird < 0));
  958.  
  959.                 } /* end of if(sel_bird) */
  960.  
  961.                 break;
  962.  
  963.             case '4':    /* display element data for bird(s)    */
  964.  
  965.                 fprintf(stderr, "\n\nSelect from the following list to display current element data:\n\n");
  966.  
  967.                 do
  968.                 {
  969.                     fprintf(stderr, "\t\t 0 = All the following\n");    
  970.                     for(index=1; index < max_sats; index++)
  971.                     {
  972.  
  973.                         fprintf(stderr, "\t\t%2d = %s\n",index, sat_name[index]);
  974.                     }
  975.  
  976.                     fprintf(stderr, "\n\n\t\tSelect satelite by number [ENTER = %d] : ", 0);
  977.  
  978.                     fgets(buffer, sizeof(buffer), stdin);
  979.                     if(strlen(buffer))
  980.                     {
  981.                         index=0;
  982.                         sscanf(buffer, "%d",&index);
  983.                     }
  984.                     else
  985.                     {
  986.                         index = 0;
  987.                     }
  988.  
  989.                 } while ((index >= max_sats) || (index < 0));
  990.  
  991.  
  992.                 if(index)
  993.                 {
  994.                     show_elements(index);    /* show current data for selected bird */
  995.                 }                else
  996.                 {
  997.                     for(index=1; index<max_sats; index++)
  998.                     {
  999.                         show_elements(index);    /* show current data for all birds */
  1000.                     }
  1001.                 }
  1002.  
  1003.                 fprintf(stderr, "\n\n\tHit [ENTER] to continue : ");
  1004.                 fgets(buffer, sizeof(buffer), stdin);
  1005.  
  1006.                 break;
  1007.  
  1008.             case '5':    /* select paged or continuous output mode    */
  1009.  
  1010.                 page_mode = !page_mode;
  1011.                 if(page_mode)
  1012.                 {
  1013.                     fprintf(stderr,"\n\nOutput mode changed to continuous output\n");
  1014.                 }
  1015.                 else
  1016.                 {
  1017.                     fprintf(stderr,"\n\nOutput mode changed to paged output\n");
  1018.                 }
  1019.                 break;
  1020.  
  1021.             case '0':
  1022.                 fprintf(stderr, "\n\nSeeSats: done.\n\n");
  1023.                 exit(0);
  1024.                 break;
  1025.  
  1026.              default:
  1027.                  cmd_loop = FALSE;
  1028.                  break;
  1029.  
  1030.           } /* end of switch(buffer[0]) */
  1031.  
  1032.  
  1033.     } while (cmd_loop); /* until done with command loop */
  1034.  
  1035.     if(in_view)    /* if in_view mode, machine may appear dead, tell user    */
  1036.     {
  1037.         fprintf(stderr, "\nNOTE: There will be NOTHING displayed when none are in view!\n");
  1038.     }
  1039.  
  1040.     fprintf(stderr, "\n\n");
  1041.  
  1042.  
  1043. } /* end of do_command() */
  1044.  
  1045. /*********************************************
  1046.  *
  1047.  *    Real time functions
  1048.  *
  1049.  */
  1050. settime()    /* set the static_time structure to the current time    */
  1051. {
  1052. long    l_systemtime;
  1053. struct    tm *st_systemtime;
  1054.  
  1055. extern struct static_time;
  1056.  
  1057. register int    carry;
  1058. static int days_in_mnth[13] =
  1059.             {
  1060.             0,
  1061.             31,
  1062.             28,
  1063.             31,
  1064.             30,
  1065.             30,
  1066.             30,
  1067.             31,
  1068.             31,
  1069.             30,
  1070.             31,
  1071.             30,
  1072.             31
  1073.             };
  1074.  
  1075.     if(dos_time)    /* read DOS clock */
  1076.      {
  1077.          time(&l_systemtime);    /* read the current system time */
  1078.         st_systemtime = localtime(&l_systemtime); /* convert to parts */
  1079.  
  1080.  
  1081.         static_time.hour    = st_systemtime->tm_hour;
  1082.         /* add UTC offset    */
  1083.         static_time.hour    += stn_utc;
  1084.  
  1085.         static_time.minute    = st_systemtime->tm_min;
  1086.         static_time.second    = st_systemtime->tm_sec;
  1087.         static_time.tenth    = 0;
  1088.  
  1089.         /* year should include century, ie: 1988 not 88 */
  1090.         static_date.year    = st_systemtime->tm_year + 1900;
  1091.  
  1092.         /* month should be 1 through 12, 1 = January */
  1093.         static_date.month    = st_systemtime->tm_mon + 1;
  1094.  
  1095.         /* day is day of the month, 1 - 31 */
  1096.         static_date.day        = st_systemtime->tm_mday;
  1097.  
  1098.  
  1099.      }
  1100.     else        /* increment time/date by min_inc */
  1101.      {
  1102.  
  1103.         if((static_date.year % 4) == 0)
  1104.          {
  1105.              days_in_mnth[2] = 29;
  1106.          }
  1107.         else
  1108.          {
  1109.              days_in_mnth[2] = 28;
  1110.          }
  1111.  
  1112.          static_time.tenth    = 0;
  1113.          static_time.second    = 0;
  1114.          static_time.minute    += min_inc;
  1115.      }
  1116.  
  1117.     /* adjust rollover of time if needed */
  1118.  
  1119.      carry            = static_time.minute/60;
  1120.      static_time.minute    %= 60;
  1121.      static_time.hour    += carry;
  1122.      carry            = static_time.hour/24;
  1123.      static_time.hour    %= 24;
  1124.      static_date.day        += carry;
  1125.      carry            = static_date.day/(days_in_mnth[static_date.month]+1);
  1126.      static_date.day        %= (days_in_mnth[static_date.month]+1);
  1127.      if(static_date.day == 0)
  1128.       {
  1129.           static_date.day = 1;
  1130.       }
  1131.      static_date.month    += carry;
  1132.      carry            = static_date.month/13;
  1133.      static_date.month    %= 13;
  1134.      if(static_date.month == 0)
  1135.       {
  1136.           static_date.month = 1;
  1137.       }
  1138.      static_date.year    += carry;
  1139.  
  1140. } /* end of settime() */
  1141.  
  1142.  
  1143. int second()    /* return seconds part of clock    */
  1144. {
  1145. extern struct static_time;
  1146.  
  1147.     return(static_time.second);
  1148. }
  1149.  
  1150. int minute()    /* return minutes part of clock    */
  1151. {
  1152. extern struct static_time;
  1153.  
  1154.     return(static_time.minute);
  1155. }
  1156.  
  1157. int hour()    /* return hours part of clock */
  1158. {
  1159. extern struct static_time;
  1160.  
  1161.     return(static_time.hour);
  1162. }
  1163.  
  1164. int day()    /* return day of month    */
  1165. {
  1166. extern struct static_date;
  1167.  
  1168.     return(static_date.day);
  1169. }
  1170.  
  1171. int month()    /* return month of year    */
  1172. {
  1173. extern struct static_date;
  1174.  
  1175.     return(static_date.month);
  1176. }
  1177.  
  1178. int year()    /* return year        */
  1179. {
  1180. extern struct static_date;
  1181.  
  1182.     return(static_date.year - 1900);
  1183. }
  1184.  
  1185. char *date()    /*return date in string format (ie: 23-Feb-86) */
  1186. {
  1187.  
  1188. static    char    date[20];
  1189. static    char    *mnth[13] = {    "***",
  1190.                 "Jan",
  1191.                 "Feb",
  1192.                 "Mar",
  1193.                 "Apr",
  1194.                 "May",
  1195.                 "Jun",
  1196.                 "Jul",
  1197.                 "Aug",
  1198.                 "Sep",
  1199.                 "Oct",
  1200.                 "Nov",
  1201.                 "Dec"
  1202.              };
  1203.                     
  1204.  
  1205.     sprintf(date,"%02d-%s-%02d",day(),mnth[month()],year());
  1206.  
  1207.     return(date);}
  1208.  
  1209. char *stime()    /*return time in string format (ie: 09:28:32) */
  1210. {
  1211.  
  1212. static    char    time[20];
  1213.  
  1214.     sprintf(time,"%02d:%02d:%02d",hour(),minute(),second());
  1215.  
  1216.     return(time);
  1217. }
  1218.  
  1219. calc_time(sat_number)    /* calculate the new realtime    */
  1220. register sat_number;
  1221. {
  1222.  
  1223.     if(dos_time)    /* if in realtime, update time/date now */
  1224.     {
  1225.         settime();
  1226.     }
  1227.  
  1228.  
  1229.     realtime = floor(30.55 * (((double)month())+2.0)) - 2.0 * ( floor(.1 * (((double)month())+7.0))) - 91.0;
  1230.     if(month() > 2)
  1231.      {
  1232.          if((((double)year())/4.0) == floor(((double)year())/4.0))
  1233.           {
  1234.               realtime += 1.0;
  1235.           }
  1236.      }
  1237.     if(epoch_yr[sat_number] == year() - 1)
  1238.      {
  1239.          realtime += 365.0;
  1240.          if(epoch_yr[sat_number]/4.0 == floor(epoch_yr[sat_number] / 4.0))
  1241.           {
  1242.               realtime += 1.0;
  1243.           }
  1244.      }
  1245.  
  1246.  
  1247.  
  1248.     realtime = realtime + ((double)day()) + (((double)hour())/24.0) + (((double)minute())/1440.0) + (((double)second())/86400.0);
  1249.  
  1250. }
  1251.  
  1252. /* end of seesats.c    */
  1253.