DESCRIPTION: This patch applies to the raw 2.1.5 release of the PREDICT satellite prediction software, and adds the facility for MultiTrack mode (and the prediction server) to handle up to 32,000 satellites. This does NOT provide this limit elsewhere in the PREDICT software. In particular, SingleTrack mode, along with other modes that require the user to select a particular satellite from those available, can only access one of the first 26 satellites in the list. AUTHOR Riley H Williams LICENSING This patch is released under the GNU General Public Licence, version 2 only. I do NOT release under licence versions that have not yet been written. Index: .version =================================================================== RCS file: /usr/src/CVS/predict/.version,v retrieving revision 1.1 diff -u -5 -r1.1 .version --- .version 28 Feb 2002 22:00:18 -0000 1.1 +++ .version 2 Mar 2002 17:49:43 -0000 @@ -1 +1 @@ -2.1.5 +2.1.5.1 Index: predict.c =================================================================== RCS file: /usr/src/CVS/predict/predict.c,v retrieving revision 1.1 diff -u -5 -r1.1 predict.c --- predict.c 28 Feb 2002 21:58:23 -0000 1.1 +++ predict.c 2 Mar 2002 17:49:44 -0000 @@ -44,13 +44,18 @@ #ifndef PI #define PI 3.141592653589793 #endif +#ifndef MAX_SATELLITES +#define MAX_SATELLITES 32000 +#endif + /* Global Variables */ -struct { char name[25]; +struct satparms { + char name[25]; long catnum; int year; double refepoch; double incl; double raan; @@ -58,20 +63,21 @@ double argper; double meanan; double meanmo; double drag; long orbitnum; - } sat[24]; + } sat[MAX_SATELLITES+1]; -struct { char callsign[10]; +struct qthparms { + char callsign[10]; double stnlat; double stnlong; int stnalt; } qth; char qthfile[50], tlefile[50], temp[80], output[25], serial_port[15], - resave=0, reload_tle=0, netport[6]; + resave=0, reload_tle=0, netport[6], height = 24, width = 80; unsigned char val[256]; int indx, ma256, iaz, iel, isplat, isplong, socket_flag=0, antfd; @@ -89,24 +95,45 @@ /* The following variables are used by the socket server. They are updated in the MultiTrack() and SingleTrack() functions. */ -char visibility_array[24]; +char visibility_array[MAX_SATELLITES]; -float az_array[24], el_array[24], long_array[24], lat_array[24], - footprint_array[24], range_array[24], altitude_array[24], - velocity_array[24], moon_az, moon_el, sun_az, sun_el; +float az_array[MAX_SATELLITES], el_array[MAX_SATELLITES], + long_array[MAX_SATELLITES], lat_array[MAX_SATELLITES], + footprint_array[MAX_SATELLITES], range_array[MAX_SATELLITES], + altitude_array[MAX_SATELLITES], velocity_array[MAX_SATELLITES], + moon_az, moon_el, sun_az, sun_el; -double doppler100[24], nextevent[24]; +double doppler100[MAX_SATELLITES], nextevent[MAX_SATELLITES]; -long aos_array[24], orbitnum_array[24]; +long aos_array[MAX_SATELLITES], orbitnum_array[MAX_SATELLITES]; unsigned short portbase=0; /******************** Program functions begin below ************************/ +void setscreen() +{ + unsigned long temp; + char *ptr; + + ptr = getenv("COLUMNS"); + if (ptr != NULL) { + temp = strtoul(ptr,&ptr,10); + if (!*ptr) + width = temp; + } + ptr = getenv("LINES"); + if (ptr != NULL) { + temp = strtoul(ptr,&ptr,10); + if (!*ptr) + height = temp; + } +} + void bailout(string) char *string; { /* This function quits ncurses, resets and "beeps" the terminal, and displays an error message (string) @@ -119,10 +146,65 @@ refresh(); endwin(); fprintf(stderr,"*** predict: %s!\n",string); } +long DayNum(m,d,y) +int m, d, y; +{ + /* This function calculates the day number from m/d/y. */ + + long dn; + double mm, yy; + + if (m<3) + { + y--; + m+=12; + } + + yy=(double)y; + mm=(double)m; + dn=(long)(floor(365.25*(yy-80.0))-floor(19.0+yy/100.0)+floor(4.75+yy/400.0)-16.0); + dn+=d+30*m+(long)floor(0.6*mm-0.3); + return dn; +} + +double CurrentDaynum() +{ + /* Read the system clock and return the number + of days since 31Dec79 00:00:00 UTC (daynum 0) */ + + struct timeb tptr; + int x; + + x=ftime(&tptr); + + return ((((double)tptr.time+0.001*(double)tptr.millitm)/86400.0)-3651.0); +} + +char Decayed(x,time) +int x; +double time; +{ + /* This function returns a 1 if it appears that the satellite + pointed to by 'x' has decayed at the time of 'time'. + If 'time' is 0.0, then the current date/time is used. */ + + double satepoch; + + if (time==0.0) + time=CurrentDaynum(); + + satepoch=DayNum(1,0,sat[x].year)+sat[x].refepoch; + + if (satepoch+((16.666666-sat[x].meanmo)/(10.0*fabs(sat[x].drag))) < time) + return 1; + else + return 0; +} + void TrackDataOut(antfd, elevation, azimuth) int antfd; double elevation, azimuth; { /* This function sends Azimuth and Elevation data @@ -225,11 +307,17 @@ /* Get datagram from socket port */ if (recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&fsin,&alen) < 0) exit(-1); /* Parse the command in the datagram */ - if (strncmp("GET_SAT",buf,7)==0) + if (!strncmp("GET_MAXSATS",buf,11)) + { + sprintf(buff,"%lu\n",(unsigned long)MAX_SATELLITES); + sendto(sock,buff,strlen(buff),0,(struct sockaddr*)&fsin,sizeof(fsin)); + } + + if (!strncmp("GET_SAT",buf,7)) { /* Parse "buf" for satellite name */ for (i=0; buf[i]!=32 && buf[i]!=0 && i<39; i++); for (j=++i; buf[j]!='\n' && buf[j]!=0 && (j-i)<25; j++) @@ -237,13 +325,13 @@ satname[j-i]=0; /* Do a simple search for the matching satellite name */ - for (i=0; i<24; i++) + for (i=0; i==--",version); + mvprintw(3,(width-strlen(Buffer))/2,Buffer); + mvprintw(4,(width-60)/2,"%60s"," "); + mvprintw(4,(width-21)/2,"By John A. Magliacane"); + mvprintw(5,(width-60)/2,"%60s"," "); + mvprintw(5,(width-37)/2,"KD2BD Software -- Copyright 1991-2002"); + mvprintw(6,(width-60)/2,"%60s"," "); } void AnyKey() { - mvprintw(23,24,"<< Press Any Key To Continue >>"); + mvprintw(height-2,24,"<< Press Any Key To Continue >>"); refresh(); getch(); } double FixAngle(x) @@ -634,27 +727,27 @@ fd=fopen(tlefile,"r"); if (fd!=NULL) { - while (x<24 && feof(fd)==0) + while (x= epoch in data file @@ -947,10 +1040,12 @@ line2[25]='.'; /* Copy TLE data into the sat data structure */ sat[i].year=atoi(SubString(line1,18,19)); + if (line1[18]<'5') + sat[i].year+=100; sat[i].refepoch=atof(SubString(line1,20,31)); sat[i].incl=atof(SubString(line2,8,15)); sat[i].raan=atof(SubString(line2,17,24)); sat[i].eccn=atof(SubString(line2,25,32)); sat[i].argper=atof(SubString(line2,34,41)); @@ -990,14 +1085,14 @@ { if (savecount==1) mvprintw(19,21," Only 1 satellite was updated."); else { - if (savecount==24) + if (savecount==MAX_SATELLITES) mvprintw(19,21," All satellites were updated!"); else - mvprintw(19,21,"%3u out of 24 satellites were updated.",savecount); + mvprintw(19,21,"%3u out of %u satellites were updated.",savecount,MAX_SATELLITES); } } refresh(); } @@ -1060,49 +1155,10 @@ while (key<'A' || key>'X'); return(key-'A'); } -long DayNum(m,d,y) -int m, d, y; -{ - /* This function calculates the day number from m/d/y. */ - - long dn; - double mm, yy; - - if (m<3) - { - y--; - m+=12; - } - - /* Correct for Y2K... */ - - if (y<=50) - y+=100; - - yy=(double)y; - mm=(double)m; - dn=(long)(floor(365.25*(yy-80.0))-floor(19.0+yy/100.0)+floor(4.75+yy/400.0)-16.0); - dn+=d+30*m+(long)floor(0.6*mm-0.3); - return dn; -} - -double CurrentDaynum() -{ - /* Read the system clock and return the number - of days since 31Dec79 00:00:00 UTC (daynum 0) */ - - struct timeb tptr; - int x; - - x=ftime(&tptr); - - return ((((double)tptr.time+0.001*(double)tptr.millitm)/86400.0)-3651.0); -} - char *Daynum2String(daynum) double daynum; { /* This function takes the given epoch as a fractional number of days since 31Dec79 00:00:00 UTC and returns the corresponding @@ -1122,20 +1178,25 @@ for (x=0; x<=3; output[x]=timestr[x], x++); output[4]=timestr[8]; output[5]=timestr[9]; - output[6]=timestr[4]; - output[7]=timestr[5]; - output[8]=timestr[6]; - output[9]=timestr[22]; - output[10]=timestr[23]; - output[11]=' '; - for (x=12; x<=19; output[x]=timestr[x-1], x++); + output[7]=timestr[4]; + output[8]=timestr[5]; + output[9]=timestr[6]; + + output[11]=timestr[20]; + output[12]=timestr[21]; + output[13]=timestr[22]; + output[14]=timestr[23]; - output[20]=0; + output[6] = output[10] = output[15] = ' '; + + for (x=16; x<=23; output[x]=timestr[x-5], x++); + + output[24]=0; return output; } double GetStartTime() { @@ -1164,11 +1225,11 @@ attrset(COLOR_PAIR(4)|A_BOLD); printw("\t\t Format: %s -or- ",string); string[7]=0; printw("%s",string); attrset(COLOR_PAIR(2)|A_BOLD); - mvprintw(21,30,"Default is `NOW'"); + mvprintw(height-4,30,"Default is `NOW'"); attrset(COLOR_PAIR(3)|A_BOLD); mvprintw(13,1,"Enter Start Date & Time >> "); curs_set(1); refresh(); echo(); @@ -1252,10 +1313,12 @@ exit(-1); } /* Decode Year */ yy=10*(line[5]-'0')+line[6]-'0'; + if (line[5]<'5') + yy+=100; /* Decode Time */ for (x=8; x<16; x++) string[x-8]=line[x]; @@ -1266,10 +1329,36 @@ s=10*(line[14]-'0')+line[15]-'0'; return ((double)DayNum(mm,dd,yy)+((h/24.0)+(m/1440.0)+(s/86400.0))); } +void dms(degrees,d,m,c,s) +double degrees; +int *d,*m; +char *c, *s; +{ + long minutes; + + minutes = (120.0 * degrees); + if (minutes<0) { + minutes--; + minutes/=2; + *m=(-minutes)%60; + if (c && s) { + *c=s[0]; + minutes=-minutes; + } + } else { + minutes++; + minutes/=2; + if (c && s && *s) + *c=s[1]; + *m=minutes%60; + } + *d = minutes / 60; +} + char FindSun(daynum,display) double daynum; char display; { /* This function calculates the position of the Sun. @@ -1286,11 +1375,11 @@ double c, ms, t1, t2, t3, ew, e, n, si, co, ra, gh, lh, gm, de, se, gs, dc, el[2], az[2], lat[2], lon[2], horizon_angle, yr; - int x; + int d, m, x; /* Calculate the year from "daynum" */ t1=(double)(long)(daynum-39410.0); t2=floor((t1+32044.75)/36524.25); @@ -1360,15 +1449,19 @@ sun_el=el[0]/deg2rad; if (display) { attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(20,5," Sun "); - mvprintw(21,5,"---------"); + mvprintw(height-5,1," Sun "); + mvprintw(height-4,1,"~~~~~~~~~"); + mvprintw(height-3,1,"Az"); + mvprintw(height-2,1,"El"); attrset(COLOR_PAIR(3)|A_BOLD); - mvprintw(22,5,"%-7.2fAz",sun_az); - mvprintw(23,4,"%+-6.2f El",sun_el); + dms(sun_az,&d,&m,NULL,NULL); + mvprintw(height-3,4,"%3d°%2d",d,m); + dms(sun_el,&d,&m,NULL,NULL); + mvprintw(height-2,4,"%+3d°%2d",d,m); } /* ak = altitude of the satellite in km */ /* The sky is dark enough to see large satellites @@ -1393,10 +1486,12 @@ double daynum; { double t1, t2, t3, ew, en, e, n, si, co, ra, gh, lh, gm, de, se, gs, dc, el, az, mm, yr, ro; + int d, m; + gm=24.0*(daynum-floor(daynum)); ew=FixAngle(1.134193+daynum*0.229971506); mm=FixAngle(1.319238+daynum*0.228027135); t1=FixAngle(6.217512+daynum*0.01720196977); t2=2.0*FixAngle(2.550677+daynum*0.212768711); @@ -1456,15 +1551,19 @@ moon_az=az/deg2rad; moon_el=el/deg2rad; attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(20,65," Moon "); - mvprintw(21,65,"---------"); + mvprintw(height-5,width-10," Moon "); + mvprintw(height-4,width-10,"~~~~~~~~~"); + mvprintw(height-3,width-10,"Az"); + mvprintw(height-2,width-10,"El"); attrset(COLOR_PAIR(3)|A_BOLD); - mvprintw(22,65,"%-7.2fAz",moon_az); - mvprintw(23,64,"%+-6.2f El",moon_el); + dms(moon_az,&d,&m,NULL,NULL); + mvprintw(height-3,width-7,"%3d°%2d",d,m); + dms(moon_el,&d,&m,NULL,NULL); + mvprintw(height-2,width-7,"%+3d°%2d",d,m); } double PreCalc(daynum) double daynum; { @@ -1472,16 +1571,10 @@ calculations prior to tracking or prediction. */ epoch=DayNum(1,0,sat[indx].year)+sat[indx].refepoch; age=daynum-epoch; yr=(float)sat[indx].year; - - /* Do the Y2K thing... */ - - if (yr<=50.0) - yr+=100.0; - t1=yr-1.0; df=366.0+floor(365.25*(t1-80.0))-floor(t1/100.0)+floor(t1/400.0+0.75); t1=(df+29218.5)/36525.0; t1=6.6460656+t1*(2400.051262+t1*2.581e-5); se=t1/24.0-yr; @@ -1622,32 +1715,10 @@ else return 0; } } -char Decayed(x,time) -int x; -double time; -{ - /* This function returns a 1 if it appears that the - satellite pointed to by 'x' has decayed at the - time of 'time'. If 'time' is 0.0, then the - current date/time is used. */ - - double satepoch; - - if (time==0.0) - time=CurrentDaynum(); - - satepoch=DayNum(1,0,sat[x].year)+sat[x].refepoch; - - if (satepoch+((16.666666-sat[x].meanmo)/(10.0*fabs(sat[x].drag))) < time) - return 1; - else - return 0; -} - char Geostationary(x) int x; { /* This function returns a 1 if the satellite pointed to by "x" appears to be in a geostationary orbit */ @@ -1825,15 +1896,15 @@ if (buffer[0]=='\n') printw("\n"); if (fd==NULL) - mvprintw(23,63," "); + mvprintw(height-2,63," "); else - mvprintw(23,63,"Log = ON"); + mvprintw(height-2,63,"Log = ON"); - mvprintw(23,6,"More? [y/n] >> "); + mvprintw(height-2,6,"More? [y/n] >> "); curs_set(1); refresh(); while (ans==0) { @@ -1872,11 +1943,11 @@ } fd=fopen(temp,"a"); fprintf(fd,"%s%s%s\n",head1,head2,head3); fprintf(fd,"%s",buffer); - mvprintw(23,63,"Log = ON"); + mvprintw(height-2,63,"Log = ON"); move(23,21); refresh(); } else if (fd!=NULL) @@ -1884,12 +1955,12 @@ if (key=='L' || key=='N') { fprintf(fd,"%s\n\n",buffer); fclose(fd); fd=NULL; - mvprintw(23,63," "); - move(23,21); + mvprintw(height-2,63," "); + move(height-2,21); refresh(); } else fprintf(fd,"%s",buffer); @@ -2009,11 +2080,11 @@ if (mode=='v') { nodelay(stdscr,TRUE); attrset(COLOR_PAIR(4)); - mvprintw(23,6," Calculating... Press [ESC] To Quit"); + mvprintw(height-2,6," Calculating... Press [ESC] To Quit"); /* Allow a way out if this should continue forever... */ if (getch()==27) @@ -2154,11 +2225,11 @@ mvprintw(18,21,"Perigee Altitude"); mvprintw(19,21,"Anomalistic Period"); mvprintw(20,21,"Nodal Period"); attrset(COLOR_PAIR(2)|A_BOLD); - mvprintw(7,40,": %02d %.8f",sat[x].year,sat[x].refepoch); + mvprintw(7,40,": %04d/%.8f",sat[x].year,sat[x].refepoch); mvprintw(8,40,": %.4f deg",sat[x].incl); mvprintw(9,40,": %.4f deg",sat[x].raan); mvprintw(10,40,": %g",sat[x].eccn); mvprintw(11,40,": %.4f deg",sat[x].argper); mvprintw(12,40,": %.4f deg",sat[x].meanan); @@ -2210,11 +2281,11 @@ attrset(COLOR_PAIR(2)|A_BOLD); mvprintw(8,42,"%s",sat[x].name); mvprintw(9,42,"%ld",sat[x].catnum); - mvprintw(10,42,"%02d %.8f",sat[x].year,sat[x].refepoch); + mvprintw(10,42,"%04d/%.8f",sat[x].year,sat[x].refepoch); mvprintw(11,42,"%.4f",sat[x].incl); mvprintw(12,42,"%.4f",sat[x].raan); mvprintw(13,42,"%g",sat[x].eccn); mvprintw(14,42,"%.4f",sat[x].argper); mvprintw(15,42,"%.4f",sat[x].meanan); @@ -2233,11 +2304,11 @@ sprintf(temp,"%ld",sat[x].catnum); if (KbEdit(43,10)) sscanf(temp,"%ld",&sat[x].catnum); - sprintf(temp,"%02d %4.8f",sat[x].year,sat[x].refepoch); + sprintf(temp,"%04d %4.8f",sat[x].year,sat[x].refepoch); if (KbEdit(43,11)) sscanf(temp,"%d %lf",&sat[x].year,&sat[x].refepoch); sprintf(temp,"%4.4f",sat[x].incl); @@ -2308,30 +2379,30 @@ printw("\n\t\t\tStation Longitude:"); printw("\n\t\t\tStation Altitude :"); attrset(COLOR_PAIR(2)|A_BOLD); mvprintw(11,43,"%s",qth.callsign); - mvprintw(12,43,"%g",qth.stnlat); - mvprintw(13,43,"%g",qth.stnlong); + mvprintw(12,43,"%+16.12f",qth.stnlat); + mvprintw(13,43,"%16.12f",qth.stnlong); mvprintw(14,43,"%d",qth.stnalt); refresh(); sprintf(temp,"%s",qth.callsign); mvprintw(18,20,"Enter the callsign of your ground station"); if (KbEdit(44,12)) strncpy(qth.callsign,temp,7); - sprintf(temp,"%g",qth.stnlat); + sprintf(temp,"%+16.12f",qth.stnlat); mvprintw(18,10,"Enter your latitude in decimal degrees NORTH (south=negative)"); if (KbEdit(44,13)) sscanf(temp,"%lf",&qth.stnlat); - sprintf(temp,"%g",qth.stnlong); + sprintf(temp,"%16.12f",qth.stnlong); mvprintw(18,10,"Enter your longitude in decimal degrees WEST (east=negative) "); if (KbEdit(44,14)) sscanf(temp,"%lf",&qth.stnlong); @@ -2357,95 +2428,106 @@ /* This function tracks a single satellite in real-time until 'Q' or ESC is pressed. x represents the index of the satellite being tracked. If speak=='T', then the speech routines are enabled. */ - int ans, oldaz=0, oldel=0; + int ans, oldaz=0, oldel=0, pos=(width-60)/2, d, m; - char going_or_coming=0, command[80], oncethru=0, + char going_or_coming=0, command[80], oncethru=0, u, alarm=0, geostationary=0, aoshappens=0, decayed=0; double pl146=0.0, pl435=0.0, old_clock=0.0, old_range=0.0, dp=0.0, dt=0.0, doppler146=0.0, doppler435=0.0, fraction=0.0, oldtime=0.0, nextaos=0.0, lostime=0.0, - aoslos=0.0; + aoslos=0.0, doppler999=0.0, pl999; curs_set(0); bkgdset(COLOR_PAIR(3)); clear(); refresh(); attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); - mvprintw(1,15," "); - mvprintw(2,15," PREDICT Real-Time Tracking Mode "); - mvprintw(3,15," Tracking: %-10sOn: ",Abbreviate(sat[x].name,9)); - mvprintw(4,15," "); + mvprintw(0,pos,"%60s",""); + mvprintw(4,pos+48," Orbit "); + mvprintw(8,pos+48," Status "); + mvprintw(0,pos+1,"PREDICT Real-Time Tracking Mode "); attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(6,20,"SATELLITE ALTITUDE SLANT RANGE"); - mvprintw(7,20,"--------- -------- -----------"); - mvprintw(8,20," . mi mi"); - mvprintw(9,20," W. km km"); - mvprintw(11,20,"DIRECTION VELOCITY DOPPLER SHIFT"); - mvprintw(12,20,"--------- -------- -------------"); - mvprintw(13,20," Az mi 146: Hz"); - mvprintw(14,20," El km 435: Hz"); - mvprintw(16,20,"PATH - LOSS FOOTPRINT ORBITAL PHASE"); - mvprintw(17,20,"----------- --------- -------------"); - mvprintw(18,20,"146: dB mi (360)"); - mvprintw(19,20,"435: dB km (256)"); + printw(" "); + + mvprintw(2,pos,"Satellite:"); + mvprintw(4,pos,"Location:"); + mvprintw(5,pos,"Direction:"); + mvprintw(7,pos,"Altitude:"); + mvprintw(8,pos,"Slant Range:"); + mvprintw(9,pos,"Footprint:"); + mvprintw(11,pos,"Velocity:"); + mvprintw(13,pos,"Phase:"); + mvprintw(15,pos+16,"146 MHz"); + mvprintw(16,pos+16,"~~~~~~~"); + mvprintw(15,pos+32,"435 MHz"); + mvprintw(16,pos+32,"~~~~~~~"); + mvprintw(15,pos+48,"1 GHz"); + mvprintw(16,pos+48,"~~~~~"); + mvprintw(17,pos,"Doppler:"); + mvprintw(17,pos+25,"kHz"); + mvprintw(17,pos+41,"kHz"); + mvprintw(17,pos+57,"kHz"); + mvprintw(18,pos,"Path Loss:"); + mvprintw(18,pos+25,"dB"); + mvprintw(18,pos+41,"dB"); + mvprintw(18,pos+57,"dB"); attrset(COLOR_PAIR(3)|A_BOLD); - mvprintw(21,22,"Orbit Number:"); - if (strcmp("/dev/null\0",serial_port)) - { - attrset(COLOR_PAIR(3)|A_BOLD); - mvprintw(24,22,"Tracking data sent to: %s ",serial_port); - } + mvprintw(2,pos+16,sat[x].name); halfdelay(2); PreCalc(CurrentDaynum()); aoshappens=AosHappens(indx); geostationary=Geostationary(indx); decayed=Decayed(indx,0.0); - do - { + if (strcmp("/dev/null\0",serial_port)) + mvprintw(22,pos+12,"Tracking data sent to: %s ",serial_port); + + do { + attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); daynum=CurrentDaynum(); - mvprintw(3,41,"%s",Daynum2String(daynum)); + mvprintw(0,pos+35,"%s",Daynum2String(daynum)); + Calc(); - attrset(COLOR_PAIR(2)|A_BOLD); + mvprintw(5,pos+48," %7ld ",rv); - if (ssplat>=0.0) - { - mvprintw(8,20,"%-6.2f",ssplat); - attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(8,27,"N"); - } + attrset(COLOR_PAIR(3)|A_BOLD); - else - { - mvprintw(8,20,"%-6.2f",-ssplat); - attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(8,27,"S"); - } + dms(ssplat,&d,&m,&u,"SN"); + mvprintw(4,pos+16,"%3d°%2u' %c",d,m,u); + dms(-ssplong,&d,&m,&u,"WE"); + mvprintw(4,pos+32,"%3d°%2u' %c",d,m,u); + + dms(elevation,&d,&m,NULL,NULL); + mvprintw(5,pos+16,"%+3d°%2u El",d,m); + dms(azimuth,&d,&m,NULL,NULL); + mvprintw(5,pos+32,"%3u°%2u Az",d,m); + + mvprintw(7,pos+16,"%7.0f km",ak); + mvprintw(7,pos+32,"%7.0f miles",am); + mvprintw(8,pos+16,"%7.0f km",rk); + mvprintw(8,pos+32,"%7.0f miles",rm); + mvprintw(9,pos+16,"%7.0f km",fk); + mvprintw(9,pos+32,"%7.0f miles",fm); - attrset(COLOR_PAIR(2)|A_BOLD); - mvprintw(8,34,"%0.f ",am); - mvprintw(9,34,"%0.f ",ak); - mvprintw(8,47,"%-5.0f",rm); - mvprintw(9,47,"%-5.0f",rk); - mvprintw(9,20,"%-7.2f",ssplong); - mvprintw(13,20,"%-7.2f",azimuth); - mvprintw(14,19,"%+-6.2f",elevation); - mvprintw(13,34,"%0.f ",vm); - mvprintw(14,34,"%0.f ",vk); + mvprintw(11,pos+16,"%8.1f km/h",vk); + mvprintw(11,pos+32,"%8.1f MPH",vm); + + mvprintw(13,pos+16,"%3.0f/256",256.0*q); + mvprintw(13,pos+32,"%3.0f/360",360.0*q); /* Send data to serial port antenna tracker */ if (elevation>=0.0 && (strcmp("/dev/null\0",serial_port))) { @@ -2461,41 +2543,44 @@ dp=(rk*1000.0)-old_range; if (dt>0.0) { fraction=-((dp/dt)/299792458.0); - doppler146=fraction*146.0e6; - doppler435=fraction*435.0e6; + doppler146=fraction*146.0e3; + doppler435=fraction*435.0e3; + doppler999=fraction*1e6; old_clock=86400.0*daynum; old_range=rk*1000.0; } if (elevation>=0.0) { pl146=75.6870571232+(20.0*log10(rk)); pl435=pl146+9.482728; - mvprintw(18,25,"%0.f",pl146); - mvprintw(19,25,"%0.f",pl435); + pl999=pl146+25.0; + mvprintw(18,pos+16,"%8.2f",pl146); + mvprintw(18,pos+32,"%8.2f",pl435); + mvprintw(18,pos+48,"%8.2f",pl999); if (alarm==0) { beep(); alarm=1; } if (oncethru && dt>0.0) { - mvprintw(13,50,"%+5.0f",doppler146); - mvprintw(14,49,"%+6.0f",doppler435); - - if (doppler435>0.0) - going_or_coming='+'; - else - going_or_coming='-'; + mvprintw(17,pos+16,"%+8.3f",doppler146); + mvprintw(17,pos+32,"%+8.3f",doppler435); + mvprintw(17,pos+48,"%+8.3f",doppler999); - if (speak=='T' && soundcard && (CurrentDaynum()-oldtime)>(0.00003*sqrt(ak))) + if (speak=='T' && soundcard && (CurrentDaynum()-oldtime)>(sqrt(ak)*3e-5)) { + if (doppler435>0.0) + going_or_coming='+'; + else + going_or_coming='-'; sprintf(command,"%svocalizer/vocalizer %.0f %.0f %c &",predictpath,azimuth,elevation,going_or_coming); system(command); oldtime=CurrentDaynum(); going_or_coming=0; } @@ -2503,84 +2588,84 @@ } } else { - mvprintw(18,25,"---"); - mvprintw(19,25,"---"); - mvprintw(13,50,"-----"); - mvprintw(14,49," ----- "); + mvprintw(17,pos+16,"%-44s","Not applicable"); + mvprintw(18,pos+16,"%-44s","Not applicable"); lostime=0.0; alarm=0; } - mvprintw(18,34,"%0.f ",fm); - mvprintw(19,34,"%0.f ",fk); - mvprintw(18,45,"%-5.0f",q*360.0); - mvprintw(19,45,"%-5.0f",q*256.0); - attrset(COLOR_PAIR(3)|A_BOLD); - mvprintw(21,36,"%ld",rv); - mvprintw(23,22,"Spacecraft is currently "); switch (FindSun(CurrentDaynum(),1)) { case '*': - mvprintw(23,46,"in sunlight"); + attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); + mvprintw(9,pos+48," Sunlight "); visibility_array[indx]='D'; break; case '+': + attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); if (elevation>0.0) { - mvprintw(23,46,"visible "); + mvprintw(9,pos+48," Visible "); visibility_array[indx]='V'; } else { - mvprintw(23,46,"in sunlight"); + mvprintw(9,pos+48," Sunlight "); visibility_array[indx]='D'; } break; case ' ': - mvprintw(23,46,"in eclipse "); + attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); + mvprintw(9,pos+48," Eclipsed "); visibility_array[indx]='N'; break; } - if (geostationary==1 && elevation>=0.0) - { - mvprintw(22,22,"Satellite orbit is geostationary"); - aoslos=-3651.0; - } + attrset(COLOR_PAIR(3)|A_BOLD); - if (geostationary==1 && elevation<0.0) + if (geostationary) { - mvprintw(22,22,"This satellite never reaches AOS"); + if (elevation>=0.0) + mvprintw(22,(width-32)/2,"Satellite orbit is geostationary"); + else + mvprintw(22,(width-32)/2,"This satellite never reaches AOS"); aoslos=-3651.0; } - if (aoshappens==0 || decayed==1) + if (decayed || !aoshappens) { - mvprintw(22,22,"This satellite never reaches AOS"); + mvprintw(22,(width-32)/2,"This satellite never reaches AOS"); aoslos=-3651.0; } - if (elevation>=0.0 && geostationary==0 && decayed==0 && daynum>lostime) + if (!geostationary && !decayed) { - lostime=FindLOS2(); - mvprintw(22,22,"LOS at: %s UTC ",Daynum2String(lostime)); - aoslos=lostime; - } + if (elevation>=0.0 && daynum>lostime) + { + lostime=FindLOS2(); + mvprintw(20,pos,"%60s",""); + sprintf(command,"LOS at %s UTC",Daynum2String(lostime)); + mvprintw(20,(width-strlen(command))/2,command); + aoslos=lostime; + } - else if (elevation<0.0 && geostationary==0 && decayed==0 && aoshappens==1 && daynum>nextaos) - { - daynum+=0.003; /* Move ahead slightly... */ - nextaos=FindAOS(); - mvprintw(22,22,"Next AOS: %s UTC",Daynum2String(nextaos)); - aoslos=nextaos; + else if (elevation<0.0 && aoshappens && daynum>nextaos) + { + daynum+=0.003; /* Move ahead slightly */ + nextaos=FindAOS(); + mvprintw(20,pos,"%60s",""); + sprintf(command,"Next AOS at %s UTC",Daynum2String(nextaos)); + mvprintw(20,(width-strlen(command))/2,command); + aoslos=nextaos; + } } FindMoon(CurrentDaynum()); /* This is where the variables for the socket server are updated. */ @@ -2608,24 +2693,24 @@ if (ans=='t') oldtime=0.0; oncethru=1; - /* If we receive a RELOAD_TLE command through the - socket connection, reload the TLE file, and run - through the preliminary orbital calculations - again to get everything up to date */ + /* If we receive a RELOAD_TLE command through the socket + connection, reload the TLE file, and run through the + preliminary orbital calculations again to get everything + up to date */ if (reload_tle || ans=='r') { if (ReadDataFiles()&2) PreCalc(CurrentDaynum()); reload_tle=0; } - } while (ans!='q' && ans!=27); + } while (ans!='q' && ans!=27 && ans!=13); cbreak(); } void MultiTrack() @@ -2633,32 +2718,63 @@ /* This function tracks all satellites in the program's database simultaneously until 'Q' or ESC is pressed. Satellites in range are HIGHLIGHTED. Coordinates for the Sun and Moon are also displayed. */ - int x, y, z, ans; + long ans, max, x, y, z; + + int cols, d1, d2, m1, m2, p; - unsigned char satindex[24], inrange[24], sunstat=0, ok2predict[24]; + unsigned char satindex[MAX_SATELLITES], inrange[MAX_SATELLITES], + sunstat=0, ok2predict[MAX_SATELLITES], Temp[80]; - double aos[24], aos2[24], temptime, nextcalctime=0.0, dt[24], - dp[24], old_clock[24], old_range[24], fraction[24], - doppler[24], los[24], aoslos[24]; + double aos[MAX_SATELLITES], aos2[MAX_SATELLITES], temptime, + nextcalctime=0.0, dt[MAX_SATELLITES], + dp[MAX_SATELLITES], old_clock[MAX_SATELLITES], + old_range[MAX_SATELLITES], fraction[MAX_SATELLITES], + doppler[MAX_SATELLITES], los[MAX_SATELLITES], + aoslos[MAX_SATELLITES]; + + cols=(width+1)/40; + + sprintf(Temp,"Current Date/Time: %s",Daynum2String(0,1)); + p=(width-strlen(Temp))/2; curs_set(0); attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); clear(); refresh(); - printw(" "); - printw(" PREDICT Real-Time Multi-Tracking Mode "); - printw(" Current Date/Time: "); - printw(" "); + mvprintw(0,(width-60)/2,"%60s",""); + mvprintw(0,(width-37)/2,"PREDICT Real-Time Multi-Tracking Mode"); + mvprintw(1,(width-60)/2,"%60s",""); + mvprintw(2,(width-60)/2,"%60s",""); + mvprintw(2,p,Temp); + p+=19; + + dms(qth.stnlat,&d1,&m1,Temp+70,"SN"); + dms(-qth.stnlong,&d2,&m2,Temp+71,"WE"); + + sprintf(Temp,"%s is at %u°%u' %c, %u°%u' %c, altitude %d metres.", + Abbreviate(qth.callsign,15),d1,m1,Temp[70], + d2,m2,Temp[71],qth.stnalt); + mvprintw(3,(width-60)/2,"%60s",""); + mvprintw(3,(width-strlen(Temp))/2,Temp); + + sprintf(Temp,"%%%us",width); attrset(COLOR_PAIR(2)|A_REVERSE); - printw(" Satellite Az El Lat Long Range | Satellite Az El Lat Long Range "); + mvprintw(5,0,Temp," "); + mvprintw(5,0," Satellite Az El Lat Long Range "); + for (x=1; xMAX_SATELLITES) + max=MAX_SATELLITES; - for (x=0; x<24; x++) + for (x=0; x MAX_SATELLITES) + continue; - else - { - x=1; - indx=y; - } + x=40*(z%cols); if (sat[indx].meanmo!=0.0 && Decayed(indx,0.0)!=1) { daynum=CurrentDaynum(); PreCalc(daynum); @@ -2735,11 +2845,15 @@ case ' ': sunstat='N'; break; } - mvprintw(y+6,x,"%-10s%3.0f %+3.0f %3.0f %3.0f %6.0f %c", Abbreviate(sat[indx].name,9),azimuth,elevation,ssplat,ssplong,rk,sunstat); + mvprintw(y+6,x, + "%-10s %3.0f %+3.0f %3.0f %3.0f %6.0f %c", + Abbreviate(sat[indx].name,10), + azimuth,elevation,ssplat,ssplong, + rk,sunstat); if (socket_flag) { az_array[indx]=azimuth; el_array[indx]=elevation; @@ -2789,48 +2903,62 @@ } if (Decayed(indx,0.0)) { attrset(COLOR_PAIR(2)); - mvprintw(y+6,x,"%-10s---------- Decayed ---------", Abbreviate(sat[indx].name,9)); + mvprintw(y+6,x,"%-10s---------- Decayed ---------", + Abbreviate(sat[indx].name,9)); } } attrset(COLOR_PAIR(6)|A_REVERSE|A_BOLD); daynum=CurrentDaynum(); - mvprintw(2,39,"%s",Daynum2String(daynum)); + mvprintw(2,37,"%s",Daynum2String(daynum)); if (daynum>nextcalctime) { /* Bubble sort the AOS times */ - for (z=22; z>=0; z--) - for (y=0; y<=z; y++) - if (aos2[y]>=aos2[y+1]) + for (z=MAX_SATELLITES; z>0; z--) + for (y=1; y=aos2[y]) { temptime=aos2[y]; - aos2[y]=aos2[y+1]; - aos2[y+1]=temptime; + aos2[y]=aos2[y-1]; + aos2[y-1]=temptime; x=satindex[y]; - satindex[y]=satindex[y+1]; - satindex[y+1]=x; + satindex[y]=satindex[y-1]; + satindex[y-1]=x; } /* Display list of upcoming passes */ attrset(COLOR_PAIR(4)|A_BOLD); - mvprintw(19,31,"Upcoming Passes"); - mvprintw(20,31,"---------------"); +#ifdef SHOW_DURATION + mvprintw(height-6,(width-50)/2,"Satellite Name Signal Acquisition Duration"); + mvprintw(height-5,(width-50)/2,"~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~"); +#else + mvprintw(height-6,(width-40)/2,"Satellite Name Signal Acquisition "); + mvprintw(height-5,(width-40)/2,"~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~"); +#endif attrset(COLOR_PAIR(3)|A_BOLD); - for (x=0, y=0, z=-1; x<21 && y!=3; x++) + for (x=0, y=0, z=-1; x86400) { start=now; end=now-1; @@ -3213,11 +3343,11 @@ startstr[y]=0; y++; /* Do a simple search for the matching satellite name */ - for (z=0; z<24; z++) + for (z=0; z