Home | History | Annotate | Line # | Download | only in clockstuff
      1  1.6  christos /*	$NetBSD: propdelay.c,v 1.6 2020/05/25 20:47:19 christos Exp $	*/
      2  1.1    kardel 
      3  1.1    kardel /* propdelay.c,v 3.1 1993/07/06 01:05:24 jbj Exp
      4  1.1    kardel  * propdelay - compute propagation delays
      5  1.1    kardel  *
      6  1.1    kardel  * cc -o propdelay propdelay.c -lm
      7  1.1    kardel  *
      8  1.1    kardel  * "Time and Frequency Users' Manual", NBS Technical Note 695 (1977).
      9  1.1    kardel  */
     10  1.1    kardel 
     11  1.1    kardel /*
     12  1.1    kardel  * This can be used to get a rough idea of the HF propagation delay
     13  1.1    kardel  * between two points (usually between you and the radio station).
     14  1.1    kardel  * The usage is
     15  1.1    kardel  *
     16  1.1    kardel  * propdelay latitudeA longitudeA latitudeB longitudeB
     17  1.1    kardel  *
     18  1.1    kardel  * where points A and B are the locations in question.  You obviously
     19  1.1    kardel  * need to know the latitude and longitude of each of the places.
     20  1.1    kardel  * The program expects the latitude to be preceded by an 'n' or 's'
     21  1.1    kardel  * and the longitude to be preceded by an 'e' or 'w'.  It understands
     22  1.1    kardel  * either decimal degrees or degrees:minutes:seconds.  Thus to compute
     23  1.1    kardel  * the delay between the WWVH (21:59:26N, 159:46:00W) and WWV (40:40:49N,
     24  1.1    kardel  * 105:02:27W) you could use:
     25  1.1    kardel  *
     26  1.1    kardel  * propdelay n21:59:26 w159:46 n40:40:49 w105:02:27
     27  1.1    kardel  *
     28  1.1    kardel  * By default it prints out a summer (F2 average virtual height 350 km) and
     29  1.1    kardel  * winter (F2 average virtual height 250 km) number.  The results will be
     30  1.1    kardel  * quite approximate but are about as good as you can do with HF time anyway.
     31  1.1    kardel  * You might pick a number between the values to use, or use the summer
     32  1.1    kardel  * value in the summer and switch to the winter value when the static
     33  1.1    kardel  * above 10 MHz starts to drop off in the fall.  You can also use the
     34  1.1    kardel  * -h switch if you want to specify your own virtual height.
     35  1.1    kardel  *
     36  1.1    kardel  * You can also do a
     37  1.1    kardel  *
     38  1.1    kardel  * propdelay -W n45:17:47 w75:45:22
     39  1.1    kardel  *
     40  1.1    kardel  * to find the propagation delays to WWV and WWVH (from CHU in this
     41  1.1    kardel  * case), a
     42  1.1    kardel  *
     43  1.1    kardel  * propdelay -C n40:40:49 w105:02:27
     44  1.1    kardel  *
     45  1.1    kardel  * to find the delays to CHU, and a
     46  1.1    kardel  *
     47  1.1    kardel  * propdelay -G n52:03:17 w98:34:18
     48  1.1    kardel  *
     49  1.1    kardel  * to find delays to GOES via each of the three satellites.
     50  1.1    kardel  */
     51  1.1    kardel 
     52  1.2  christos #ifdef HAVE_CONFIG_H
     53  1.2  christos # include <config.h>
     54  1.2  christos #endif
     55  1.1    kardel #include <stdio.h>
     56  1.1    kardel #include <string.h>
     57  1.1    kardel 
     58  1.1    kardel #include "ntp_stdlib.h"
     59  1.1    kardel 
     60  1.1    kardel extern	double	sin	(double);
     61  1.1    kardel extern	double	cos	(double);
     62  1.1    kardel extern	double	acos	(double);
     63  1.1    kardel extern	double	tan	(double);
     64  1.1    kardel extern	double	atan	(double);
     65  1.1    kardel extern	double	sqrt	(double);
     66  1.1    kardel 
     67  1.1    kardel #define	STREQ(a, b)	(*(a) == *(b) && strcmp((a), (b)) == 0)
     68  1.1    kardel 
     69  1.1    kardel /*
     70  1.1    kardel  * Program constants
     71  1.1    kardel  */
     72  1.1    kardel #define	EARTHRADIUS	(6370.0)	/* raduis of earth (km) */
     73  1.1    kardel #define	LIGHTSPEED	(299800.0)	/* speed of light, km/s */
     74  1.1    kardel #define	PI		(3.1415926536)
     75  1.1    kardel #define	RADPERDEG	(PI/180.0)	/* radians per degree */
     76  1.1    kardel #define MILE		(1.609344)      /* km in a mile */
     77  1.1    kardel 
     78  1.1    kardel #define	SUMMERHEIGHT	(350.0)		/* summer height in km */
     79  1.1    kardel #define	WINTERHEIGHT	(250.0)		/* winter height in km */
     80  1.1    kardel 
     81  1.1    kardel #define SATHEIGHT	(6.6110 * 6378.0) /* geosync satellite height in km
     82  1.1    kardel 					     from centre of earth */
     83  1.1    kardel 
     84  1.1    kardel #define WWVLAT  "n40:40:49"
     85  1.1    kardel #define WWVLONG "w105:02:27"
     86  1.1    kardel 
     87  1.1    kardel #define WWVHLAT  "n21:59:26"
     88  1.1    kardel #define WWVHLONG "w159:46:00"
     89  1.1    kardel 
     90  1.1    kardel #define CHULAT	"n45:17:47"
     91  1.1    kardel #define	CHULONG	"w75:45:22"
     92  1.1    kardel 
     93  1.1    kardel #define GOES_UP_LAT  "n37:52:00"
     94  1.1    kardel #define GOES_UP_LONG "w75:27:00"
     95  1.1    kardel #define GOES_EAST_LONG "w75:00:00"
     96  1.1    kardel #define GOES_STBY_LONG "w105:00:00"
     97  1.1    kardel #define GOES_WEST_LONG "w135:00:00"
     98  1.1    kardel #define GOES_SAT_LAT "n00:00:00"
     99  1.1    kardel 
    100  1.1    kardel char *wwvlat = WWVLAT;
    101  1.1    kardel char *wwvlong = WWVLONG;
    102  1.1    kardel 
    103  1.1    kardel char *wwvhlat = WWVHLAT;
    104  1.1    kardel char *wwvhlong = WWVHLONG;
    105  1.1    kardel 
    106  1.1    kardel char *chulat = CHULAT;
    107  1.1    kardel char *chulong = CHULONG;
    108  1.1    kardel 
    109  1.1    kardel char *goes_up_lat = GOES_UP_LAT;
    110  1.1    kardel char *goes_up_long = GOES_UP_LONG;
    111  1.1    kardel char *goes_east_long = GOES_EAST_LONG;
    112  1.1    kardel char *goes_stby_long = GOES_STBY_LONG;
    113  1.1    kardel char *goes_west_long = GOES_WEST_LONG;
    114  1.1    kardel char *goes_sat_lat = GOES_SAT_LAT;
    115  1.1    kardel 
    116  1.1    kardel int hflag = 0;
    117  1.1    kardel int Wflag = 0;
    118  1.1    kardel int Cflag = 0;
    119  1.1    kardel int Gflag = 0;
    120  1.1    kardel int height;
    121  1.1    kardel 
    122  1.4  christos char const *progname;
    123  1.1    kardel 
    124  1.1    kardel static	void	doit		(double, double, double, double, double, char *);
    125  1.1    kardel static	double	latlong		(char *, int);
    126  1.1    kardel static	double	greatcircle	(double, double, double, double);
    127  1.1    kardel static	double	waveangle	(double, double, int);
    128  1.1    kardel static	double	propdelay	(double, double, int);
    129  1.1    kardel static	int	finddelay	(double, double, double, double, double, double *);
    130  1.1    kardel static	void	satdoit		(double, double, double, double, double, double, char *);
    131  1.1    kardel static	void	satfinddelay	(double, double, double, double, double *);
    132  1.1    kardel static	double	satpropdelay	(double);
    133  1.1    kardel 
    134  1.1    kardel /*
    135  1.1    kardel  * main - parse arguments and handle options
    136  1.1    kardel  */
    137  1.1    kardel int
    138  1.1    kardel main(
    139  1.1    kardel 	int argc,
    140  1.1    kardel 	char *argv[]
    141  1.1    kardel 	)
    142  1.1    kardel {
    143  1.1    kardel 	int c;
    144  1.1    kardel 	int errflg = 0;
    145  1.1    kardel 	double lat1, long1;
    146  1.1    kardel 	double lat2, long2;
    147  1.1    kardel 	double lat3, long3;
    148  1.1    kardel 
    149  1.2  christos 	init_lib();
    150  1.2  christos 
    151  1.1    kardel 	progname = argv[0];
    152  1.1    kardel 	while ((c = ntp_getopt(argc, argv, "dh:CWG")) != EOF)
    153  1.1    kardel 	    switch (c) {
    154  1.1    kardel 		case 'd':
    155  1.1    kardel 		    ++debug;
    156  1.1    kardel 		    break;
    157  1.1    kardel 		case 'h':
    158  1.1    kardel 		    hflag++;
    159  1.1    kardel 		    height = atof(ntp_optarg);
    160  1.1    kardel 		    if (height <= 0.0) {
    161  1.1    kardel 			    (void) fprintf(stderr, "height %s unlikely\n",
    162  1.1    kardel 					   ntp_optarg);
    163  1.1    kardel 			    errflg++;
    164  1.1    kardel 		    }
    165  1.1    kardel 		    break;
    166  1.1    kardel 		case 'C':
    167  1.1    kardel 		    Cflag++;
    168  1.1    kardel 		    break;
    169  1.1    kardel 		case 'W':
    170  1.1    kardel 		    Wflag++;
    171  1.1    kardel 		    break;
    172  1.1    kardel 		case 'G':
    173  1.1    kardel 		    Gflag++;
    174  1.1    kardel 		    break;
    175  1.1    kardel 		default:
    176  1.1    kardel 		    errflg++;
    177  1.1    kardel 		    break;
    178  1.1    kardel 	    }
    179  1.1    kardel 	if (errflg || (!(Cflag || Wflag || Gflag) && ntp_optind+4 != argc) ||
    180  1.1    kardel 	    ((Cflag || Wflag || Gflag) && ntp_optind+2 != argc)) {
    181  1.1    kardel 		(void) fprintf(stderr,
    182  1.1    kardel 			       "usage: %s [-d] [-h height] lat1 long1 lat2 long2\n",
    183  1.1    kardel 			       progname);
    184  1.1    kardel 		(void) fprintf(stderr," - or -\n");
    185  1.1    kardel 		(void) fprintf(stderr,
    186  1.1    kardel 			       "usage: %s -CWG [-d] lat long\n",
    187  1.1    kardel 			       progname);
    188  1.1    kardel 		exit(2);
    189  1.1    kardel 	}
    190  1.1    kardel 
    191  1.1    kardel 
    192  1.1    kardel 	if (!(Cflag || Wflag || Gflag)) {
    193  1.1    kardel 		lat1 = latlong(argv[ntp_optind], 1);
    194  1.1    kardel 		long1 = latlong(argv[ntp_optind + 1], 0);
    195  1.1    kardel 		lat2 = latlong(argv[ntp_optind + 2], 1);
    196  1.1    kardel 		long2 = latlong(argv[ntp_optind + 3], 0);
    197  1.1    kardel 		if (hflag) {
    198  1.1    kardel 			doit(lat1, long1, lat2, long2, height, "");
    199  1.1    kardel 		} else {
    200  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)SUMMERHEIGHT,
    201  1.1    kardel 			     "summer propagation, ");
    202  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)WINTERHEIGHT,
    203  1.1    kardel 			     "winter propagation, ");
    204  1.1    kardel 		}
    205  1.1    kardel 	} else if (Wflag) {
    206  1.1    kardel 		/*
    207  1.1    kardel 		 * Compute delay from WWV
    208  1.1    kardel 		 */
    209  1.1    kardel 		lat1 = latlong(argv[ntp_optind], 1);
    210  1.1    kardel 		long1 = latlong(argv[ntp_optind + 1], 0);
    211  1.1    kardel 		lat2 = latlong(wwvlat, 1);
    212  1.1    kardel 		long2 = latlong(wwvlong, 0);
    213  1.1    kardel 		if (hflag) {
    214  1.1    kardel 			doit(lat1, long1, lat2, long2, height, "WWV  ");
    215  1.1    kardel 		} else {
    216  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)SUMMERHEIGHT,
    217  1.1    kardel 			     "WWV  summer propagation, ");
    218  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)WINTERHEIGHT,
    219  1.1    kardel 			     "WWV  winter propagation, ");
    220  1.1    kardel 		}
    221  1.1    kardel 
    222  1.1    kardel 		/*
    223  1.1    kardel 		 * Compute delay from WWVH
    224  1.1    kardel 		 */
    225  1.1    kardel 		lat2 = latlong(wwvhlat, 1);
    226  1.1    kardel 		long2 = latlong(wwvhlong, 0);
    227  1.1    kardel 		if (hflag) {
    228  1.1    kardel 			doit(lat1, long1, lat2, long2, height, "WWVH ");
    229  1.1    kardel 		} else {
    230  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)SUMMERHEIGHT,
    231  1.1    kardel 			     "WWVH summer propagation, ");
    232  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)WINTERHEIGHT,
    233  1.1    kardel 			     "WWVH winter propagation, ");
    234  1.1    kardel 		}
    235  1.1    kardel 	} else if (Cflag) {
    236  1.1    kardel 		lat1 = latlong(argv[ntp_optind], 1);
    237  1.1    kardel 		long1 = latlong(argv[ntp_optind + 1], 0);
    238  1.1    kardel 		lat2 = latlong(chulat, 1);
    239  1.1    kardel 		long2 = latlong(chulong, 0);
    240  1.1    kardel 		if (hflag) {
    241  1.1    kardel 			doit(lat1, long1, lat2, long2, height, "CHU ");
    242  1.1    kardel 		} else {
    243  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)SUMMERHEIGHT,
    244  1.1    kardel 			     "CHU summer propagation, ");
    245  1.1    kardel 			doit(lat1, long1, lat2, long2, (double)WINTERHEIGHT,
    246  1.1    kardel 			     "CHU winter propagation, ");
    247  1.1    kardel 		}
    248  1.1    kardel 	} else if (Gflag) {
    249  1.1    kardel 		lat1 = latlong(goes_up_lat, 1);
    250  1.1    kardel 		long1 = latlong(goes_up_long, 0);
    251  1.1    kardel 		lat3 = latlong(argv[ntp_optind], 1);
    252  1.1    kardel 		long3 = latlong(argv[ntp_optind + 1], 0);
    253  1.1    kardel 
    254  1.1    kardel 		lat2 = latlong(goes_sat_lat, 1);
    255  1.1    kardel 
    256  1.1    kardel 		long2 = latlong(goes_west_long, 0);
    257  1.1    kardel 		satdoit(lat1, long1, lat2, long2, lat3, long3,
    258  1.1    kardel 			"GOES Delay via WEST");
    259  1.1    kardel 
    260  1.1    kardel 		long2 = latlong(goes_stby_long, 0);
    261  1.1    kardel 		satdoit(lat1, long1, lat2, long2, lat3, long3,
    262  1.1    kardel 			"GOES Delay via STBY");
    263  1.1    kardel 
    264  1.1    kardel 		long2 = latlong(goes_east_long, 0);
    265  1.1    kardel 		satdoit(lat1, long1, lat2, long2, lat3, long3,
    266  1.1    kardel 			"GOES Delay via EAST");
    267  1.1    kardel 
    268  1.1    kardel 	}
    269  1.1    kardel 	exit(0);
    270  1.1    kardel }
    271  1.1    kardel 
    272  1.1    kardel 
    273  1.1    kardel /*
    274  1.1    kardel  * doit - compute a delay and print it
    275  1.1    kardel  */
    276  1.1    kardel static void
    277  1.1    kardel doit(
    278  1.1    kardel 	double lat1,
    279  1.1    kardel 	double long1,
    280  1.1    kardel 	double lat2,
    281  1.1    kardel 	double long2,
    282  1.1    kardel 	double h,
    283  1.1    kardel 	char *str
    284  1.1    kardel 	)
    285  1.1    kardel {
    286  1.1    kardel 	int hops;
    287  1.1    kardel 	double delay;
    288  1.1    kardel 
    289  1.1    kardel 	hops = finddelay(lat1, long1, lat2, long2, h, &delay);
    290  1.1    kardel 	printf("%sheight %g km, hops %d, delay %g seconds\n",
    291  1.1    kardel 	       str, h, hops, delay);
    292  1.1    kardel }
    293  1.1    kardel 
    294  1.1    kardel 
    295  1.1    kardel /*
    296  1.1    kardel  * latlong - decode a latitude/longitude value
    297  1.1    kardel  */
    298  1.1    kardel static double
    299  1.1    kardel latlong(
    300  1.1    kardel 	char *str,
    301  1.1    kardel 	int islat
    302  1.1    kardel 	)
    303  1.1    kardel {
    304  1.1    kardel 	register char *cp;
    305  1.1    kardel 	register char *bp;
    306  1.1    kardel 	double arg;
    307  1.1    kardel 	double divby;
    308  1.1    kardel 	int isneg;
    309  1.1    kardel 	char buf[32];
    310  1.1    kardel 	char *colon;
    311  1.1    kardel 
    312  1.1    kardel 	if (islat) {
    313  1.1    kardel 		/*
    314  1.1    kardel 		 * Must be north or south
    315  1.1    kardel 		 */
    316  1.1    kardel 		if (*str == 'N' || *str == 'n')
    317  1.1    kardel 		    isneg = 0;
    318  1.1    kardel 		else if (*str == 'S' || *str == 's')
    319  1.1    kardel 		    isneg = 1;
    320  1.1    kardel 		else
    321  1.1    kardel 		    isneg = -1;
    322  1.1    kardel 	} else {
    323  1.1    kardel 		/*
    324  1.1    kardel 		 * East is positive, west is negative
    325  1.1    kardel 		 */
    326  1.1    kardel 		if (*str == 'E' || *str == 'e')
    327  1.1    kardel 		    isneg = 0;
    328  1.1    kardel 		else if (*str == 'W' || *str == 'w')
    329  1.1    kardel 		    isneg = 1;
    330  1.1    kardel 		else
    331  1.1    kardel 		    isneg = -1;
    332  1.1    kardel 	}
    333  1.1    kardel 
    334  1.1    kardel 	if (isneg >= 0)
    335  1.1    kardel 	    str++;
    336  1.1    kardel 
    337  1.1    kardel 	colon = strchr(str, ':');
    338  1.1    kardel 	if (colon != NULL) {
    339  1.1    kardel 		/*
    340  1.1    kardel 		 * in hhh:mm:ss form
    341  1.1    kardel 		 */
    342  1.1    kardel 		cp = str;
    343  1.1    kardel 		bp = buf;
    344  1.1    kardel 		while (cp < colon)
    345  1.1    kardel 		    *bp++ = *cp++;
    346  1.1    kardel 		*bp = '\0';
    347  1.1    kardel 		cp++;
    348  1.1    kardel 		arg = atof(buf);
    349  1.1    kardel 		divby = 60.0;
    350  1.1    kardel 		colon = strchr(cp, ':');
    351  1.1    kardel 		if (colon != NULL) {
    352  1.1    kardel 			bp = buf;
    353  1.1    kardel 			while (cp < colon)
    354  1.1    kardel 			    *bp++ = *cp++;
    355  1.1    kardel 			*bp = '\0';
    356  1.1    kardel 			cp++;
    357  1.1    kardel 			arg += atof(buf) / divby;
    358  1.1    kardel 			divby = 3600.0;
    359  1.1    kardel 		}
    360  1.1    kardel 		if (*cp != '\0')
    361  1.1    kardel 		    arg += atof(cp) / divby;
    362  1.1    kardel 	} else {
    363  1.1    kardel 		arg = atof(str);
    364  1.1    kardel 	}
    365  1.1    kardel 
    366  1.1    kardel 	if (isneg == 1)
    367  1.1    kardel 	    arg = -arg;
    368  1.1    kardel 
    369  1.1    kardel 	if (debug > 2)
    370  1.1    kardel 	    (void) printf("latitude/longitude %s = %g\n", str, arg);
    371  1.1    kardel 
    372  1.1    kardel 	return arg;
    373  1.1    kardel }
    374  1.1    kardel 
    375  1.1    kardel 
    376  1.1    kardel /*
    377  1.1    kardel  * greatcircle - compute the great circle distance in kilometers
    378  1.1    kardel  */
    379  1.1    kardel static double
    380  1.1    kardel greatcircle(
    381  1.1    kardel 	double lat1,
    382  1.1    kardel 	double long1,
    383  1.1    kardel 	double lat2,
    384  1.1    kardel 	double long2
    385  1.1    kardel 	)
    386  1.1    kardel {
    387  1.1    kardel 	double dg;
    388  1.1    kardel 	double l1r, l2r;
    389  1.1    kardel 
    390  1.1    kardel 	l1r = lat1 * RADPERDEG;
    391  1.1    kardel 	l2r = lat2 * RADPERDEG;
    392  1.1    kardel 	dg = EARTHRADIUS * acos(
    393  1.1    kardel 		(cos(l1r) * cos(l2r) * cos((long2-long1)*RADPERDEG))
    394  1.1    kardel 		+ (sin(l1r) * sin(l2r)));
    395  1.1    kardel 	if (debug >= 2)
    396  1.1    kardel 	    printf(
    397  1.1    kardel 		    "greatcircle lat1 %g long1 %g lat2 %g long2 %g dist %g\n",
    398  1.1    kardel 		    lat1, long1, lat2, long2, dg);
    399  1.1    kardel 	return dg;
    400  1.1    kardel }
    401  1.1    kardel 
    402  1.1    kardel 
    403  1.1    kardel /*
    404  1.1    kardel  * waveangle - compute the wave angle for the given distance, virtual
    405  1.1    kardel  *	       height and number of hops.
    406  1.1    kardel  */
    407  1.1    kardel static double
    408  1.1    kardel waveangle(
    409  1.1    kardel 	double dg,
    410  1.1    kardel 	double h,
    411  1.1    kardel 	int n
    412  1.1    kardel 	)
    413  1.1    kardel {
    414  1.1    kardel 	double theta;
    415  1.1    kardel 	double delta;
    416  1.1    kardel 
    417  1.1    kardel 	theta = dg / (EARTHRADIUS * (double)(2 * n));
    418  1.1    kardel 	delta = atan((h / (EARTHRADIUS * sin(theta))) + tan(theta/2)) - theta;
    419  1.1    kardel 	if (debug >= 2)
    420  1.1    kardel 	    printf("waveangle dist %g height %g hops %d angle %g\n",
    421  1.1    kardel 		   dg, h, n, delta / RADPERDEG);
    422  1.1    kardel 	return delta;
    423  1.1    kardel }
    424  1.1    kardel 
    425  1.1    kardel 
    426  1.1    kardel /*
    427  1.1    kardel  * propdelay - compute the propagation delay
    428  1.1    kardel  */
    429  1.1    kardel static double
    430  1.1    kardel propdelay(
    431  1.1    kardel 	double dg,
    432  1.1    kardel 	double h,
    433  1.1    kardel 	int n
    434  1.1    kardel 	)
    435  1.1    kardel {
    436  1.1    kardel 	double phi;
    437  1.1    kardel 	double theta;
    438  1.1    kardel 	double td;
    439  1.1    kardel 
    440  1.1    kardel 	theta = dg / (EARTHRADIUS * (double)(2 * n));
    441  1.1    kardel 	phi = (PI/2.0) - atan((h / (EARTHRADIUS * sin(theta))) + tan(theta/2));
    442  1.1    kardel 	td = dg / (LIGHTSPEED * sin(phi));
    443  1.1    kardel 	if (debug >= 2)
    444  1.1    kardel 	    printf("propdelay dist %g height %g hops %d time %g\n",
    445  1.1    kardel 		   dg, h, n, td);
    446  1.1    kardel 	return td;
    447  1.1    kardel }
    448  1.1    kardel 
    449  1.1    kardel 
    450  1.1    kardel /*
    451  1.1    kardel  * finddelay - find the propagation delay
    452  1.1    kardel  */
    453  1.1    kardel static int
    454  1.1    kardel finddelay(
    455  1.1    kardel 	double lat1,
    456  1.1    kardel 	double long1,
    457  1.1    kardel 	double lat2,
    458  1.1    kardel 	double long2,
    459  1.1    kardel 	double h,
    460  1.1    kardel 	double *delay
    461  1.1    kardel 	)
    462  1.1    kardel {
    463  1.1    kardel 	double dg;	/* great circle distance */
    464  1.1    kardel 	double delta;	/* wave angle */
    465  1.1    kardel 	int n;		/* number of hops */
    466  1.1    kardel 
    467  1.1    kardel 	dg = greatcircle(lat1, long1, lat2, long2);
    468  1.1    kardel 	if (debug)
    469  1.1    kardel 	    printf("great circle distance %g km %g miles\n", dg, dg/MILE);
    470  1.1    kardel 
    471  1.1    kardel 	n = 1;
    472  1.1    kardel 	while ((delta = waveangle(dg, h, n)) < 0.0) {
    473  1.1    kardel 		if (debug)
    474  1.1    kardel 		    printf("tried %d hop%s, no good\n", n, n>1?"s":"");
    475  1.1    kardel 		n++;
    476  1.1    kardel 	}
    477  1.1    kardel 	if (debug)
    478  1.1    kardel 	    printf("%d hop%s okay, wave angle is %g\n", n, n>1?"s":"",
    479  1.1    kardel 		   delta / RADPERDEG);
    480  1.1    kardel 
    481  1.1    kardel 	*delay = propdelay(dg, h, n);
    482  1.1    kardel 	return n;
    483  1.1    kardel }
    484  1.1    kardel 
    485  1.1    kardel /*
    486  1.1    kardel  * satdoit - compute a delay and print it
    487  1.1    kardel  */
    488  1.1    kardel static void
    489  1.1    kardel satdoit(
    490  1.1    kardel 	double lat1,
    491  1.1    kardel 	double long1,
    492  1.1    kardel 	double lat2,
    493  1.1    kardel 	double long2,
    494  1.1    kardel 	double lat3,
    495  1.1    kardel 	double long3,
    496  1.1    kardel 	char *str
    497  1.1    kardel 	)
    498  1.1    kardel {
    499  1.1    kardel 	double up_delay,down_delay;
    500  1.1    kardel 
    501  1.1    kardel 	satfinddelay(lat1, long1, lat2, long2, &up_delay);
    502  1.1    kardel 	satfinddelay(lat3, long3, lat2, long2, &down_delay);
    503  1.1    kardel 
    504  1.1    kardel 	printf("%s, delay %g seconds\n", str, up_delay + down_delay);
    505  1.1    kardel }
    506  1.1    kardel 
    507  1.1    kardel /*
    508  1.1    kardel  * satfinddelay - calculate the one-way delay time between a ground station
    509  1.1    kardel  * and a satellite
    510  1.1    kardel  */
    511  1.1    kardel static void
    512  1.1    kardel satfinddelay(
    513  1.1    kardel 	double lat1,
    514  1.1    kardel 	double long1,
    515  1.1    kardel 	double lat2,
    516  1.1    kardel 	double long2,
    517  1.1    kardel 	double *delay
    518  1.1    kardel 	)
    519  1.1    kardel {
    520  1.1    kardel 	double dg;	/* great circle distance */
    521  1.1    kardel 
    522  1.1    kardel 	dg = greatcircle(lat1, long1, lat2, long2);
    523  1.1    kardel 
    524  1.1    kardel 	*delay = satpropdelay(dg);
    525  1.1    kardel }
    526  1.1    kardel 
    527  1.1    kardel /*
    528  1.1    kardel  * satpropdelay - calculate the one-way delay time between a ground station
    529  1.1    kardel  * and a satellite
    530  1.1    kardel  */
    531  1.1    kardel static double
    532  1.1    kardel satpropdelay(
    533  1.1    kardel 	double dg
    534  1.1    kardel 	)
    535  1.1    kardel {
    536  1.1    kardel 	double k1, k2, dist;
    537  1.1    kardel 	double theta;
    538  1.1    kardel 	double td;
    539  1.1    kardel 
    540  1.1    kardel 	theta = dg / (EARTHRADIUS);
    541  1.1    kardel 	k1 = EARTHRADIUS * sin(theta);
    542  1.1    kardel 	k2 = SATHEIGHT - (EARTHRADIUS * cos(theta));
    543  1.1    kardel 	if (debug >= 2)
    544  1.1    kardel 	    printf("Theta %g k1 %g k2 %g\n", theta, k1, k2);
    545  1.1    kardel 	dist = sqrt(k1*k1 + k2*k2);
    546  1.1    kardel 	td = dist / LIGHTSPEED;
    547  1.1    kardel 	if (debug >= 2)
    548  1.1    kardel 	    printf("propdelay dist %g height %g time %g\n", dg, dist, td);
    549  1.1    kardel 	return td;
    550  1.1    kardel }
    551