0 IFTIME$="23:59:59"THEN0ELSETS$=TIME$:DS$=DATE$:DS$=LEFT$(DS$,6)+"20"+RIGHT$(DS$,2)'Avoid last second of a day; capture Time & Date strings; formulate 21st century Date string
1 IFPI#THENELSE500'If Pi is defined then pass through to next line, elsewise Pi is not defined (i.e., resolved as zero) because initial assignment of constants and variables has not been made -- go make those initial assignments
2 YR%=VAL(RIGHT$(DS$,4)):LY%=1-SGN(YR%MOD400):IF0=LY%THENLY%=SGN(YR%MOD100)*(1-SGN(YR%MOD4))
3 MN%=VAL(LEFT$(DS$,2)):DY%=365+VAL(MID$(DS$,4)):IF(LY%*MN%)>2THENDY%=DY%+1
4 ON13-MN%GOTO16,15,14,13,12,11,10,9,8,7,6,5
5 DY%=DY%-31'reduce by 365;enter here for January
6 DY%=DY%-28'reduce by 334;enter here for February
7 DY%=DY%-31'reduce by 306;enter here for March
8 DY%=DY%-30'reduce by 275;enter here for April
9 DY%=DY%-31'reduce by 245;enter here for May
10 DY%=DY%-30'reduce by 214;enter here for June
11 DY%=DY%-31'reduce by 184;enter here for July
12 DY%=DY%-31'reduce by 153;enter here for August
13 DY%=DY%-30'reduce by 122;enter here for September
14 DY%=DY%-31'reduce by 092;enter here for October
15 DY%=DY%-30'reduce by 061;enter here for November
16 DY%=DY%-31'reduce by 031;enter here for December
20 T0#=2*PI#*DY%/(365+LY%)'Temporal factor 0
21 T1#=T0#+4.8718'Temporal factor 1
30 SD#=0.322003-22.9711*COS(T0#)-0.357898*COS(2*T0#)-0.14398*COS(3*T0#)+3.94638*SIN(T0#)+0.019334*SIN(2*T0#)+0.05928*SIN(3*T0#)'Solar Declination (in degrees)
31 SD#=SD#*DR#'Solar Declination expression now in radians
40 ET#=5.0323-430.837*COS(T1#)+12.5024*COS(2*T1#)+18.25*COS(3*T1#)-100.976*SIN(T1#)+595.275*SIN(2*T1#)+3.6858*SIN(3*T1#)-12.47*SIN(4*T1#)'Equation of Time (in seconds)
50 LA#=LT#*DR#'LAtitude (in radians)
57 TD!=TZ!'Time Differential (in hours) with respect to Universal Time Coordinated (UTC)
58 IF-12>TD!THENTD!=TD!+24'compensate (only once) if more negative than -12
59 IFTD!>+12THENTD!=TD!-24'compensate (only once) if more positive than +12
60 UC#=-TD!+VAL(LEFT$(TS$,2))+VAL(MID$(TS$,4))/60+VAL(RIGHT$(TS$,2))/3600'Universal time-of-day Coordinated (in hours)
69 IFUC#=>24THENUC#=UC#-24ELSEIF-1=SGN(UC#)THENUC#=UC#+24'compensate (once only) if +24 or more positive, else compensate (once only) if -24 or less negative
70 HA#=LG#+PI#/12*(ET#/3600+UC#)-PI#'Hour Angle (in radians)
80 'Calculation of AL# follows. Sine of AL# is computed, and then its ArcSine (i.e., inverse sine) produces AL#
81 SL#=SIN(SD#)*SIN(LA#)+COS(SD#)*COS(LA#)*COS(HA#)'Sine of aLtitude angle of sun
88 'ArcSine (i.e., ArcSIN) is not provided in Tandy BASIC. ArcSine is found via BASIC equivalent statements where the ArcSine of unitless number, such as UN#, is equal to ATN ( UN# / SQR( 1 - UN# * UN#) )
89 AL#=ATN(SL#/SQR(1-SL#^2))'ALtitude angle of sun, which is the true angle rather than the visible angle that results from atmospheric refraction (in radians)
90 'Calculation of AZ# follows. Cosine of AZ# is computed, and then its ArcCosine (i.e., inverse Cosine) produces AZ#
91 CZ#=(SIN(SD#)*COS(LA#)-COS(SD#)*SIN(LA#)*COS(HA#))/COS(AL#)'Cosine of AZ#
92 'To avoid the FC Error in the subsequent SQR() function, the value of CZ# must not exceed positive 1 (or apparent threshold of 1.00000000000004999..999)
93 'A guard may be placed here to: adjust the CZ# value to 1.0 in all cases of excess, or allow trivial excess to trigger an Error response.
94 ' IF CZ# > 1 THEN CZ# = 1 'Adjust to 1.0 in all cases
95 ' IF CZ# > 1 THEN IF CZ# <= 1+1/3D13 THEN CZ# = CZ# ELSE ERROR 17 'CN Can't Continue
96 ' IF CZ# > 1 THEN IF CZ# <= 1+1/3D13 THEN CZ# = CZ# ELSE ERROR 50 'IE Internal Error
97 ' IF CZ# > 1 THEN IF CZ# <= 1+1/3D13 THEN CZ# = CZ# ELSE ERROR 255'UE Undefined Error
98 'ArcCosine (i.e., ArcCOS) is not provided in Tandy BASIC. ArcCosine is found via BASIC equivalent statements where the ArcCosine of a unitless number, such as UN#, is equal to -ATN ( UN# / SQR( 1 - UN# * UN#) ) + PI# / 2
99 AZ#=-ATN(CZ#/SQR(1-CZ#^2))+PI#/2'Calculate AZimuth angle of sun (in radians)
100 IFSGN(HA#)>-1THENAZ#=2*PI#-AZ#'Compensate Azimuth due to a positive hour angle
110 PRINT@0,USING"Date \ \ Time \ \";DS$,TS$;
111 PRINTUSING"Equation of Time +##min ##sec";ET#/60MOD60,ABS(ET#-60*(ET#/60MOD60));
112 PRINTUSING"Sun Declined +##.###########"+CHR$(166);SD#*RD#;
113 GOSUB301:PRINTUSING"Sun Altitude +##.###########"+CHR$(166);RL#;
114 PRINTUSING"Sun Azimuth"+CHR$(149)+" ###.###########"+CHR$(166);AZ#*RD#;
115 PRINTUSING"Lt+##.######"+CHR$(166)+" Lng+###.######"+CHR$(166);LT#,LG#*RD#;
116 PRINTUSING"Hour Angle +###.###########"+CHR$(166);HA#*RD#;
120 GOSUB290'Display command line
220 LINE-(XO%,YO%),0'erase prior shadow-line
230 IFSGN(RL#)<0THEN250'atmospheric refraction compensated (i.e., optic) altitude of sun is below the horizon
240 Y%=YO%+R%*COS(AZ#):LINE-(XO%-R%*SIN(AZ#),Y%),1'draw shadow-line
241 IFS%THENBEEP'If sound is allowed, beep to notify that shadow-line has changed
250 IFPEEK(65450)=0THENIFLEFT$(TIME$,7)=LEFT$(TS$,7)THEN250ELSE0ELSEK$=INKEY$'Stay here until operator makes a keystrike or a new 10-second interval commences. Go back upon new interval for update; capture keystrike and proceed forward.
251 V%=INT((1+INSTR("QqGgUuEeSs",K$))/2):IFV%=0THENSOUND11838,50:GOTO250'If not valid keystrike then loop back
252 SOUNDV%*1920,5:ONV%GOTO254,258,255,280,253'5-way branch based on valid keystrike
253 S%=1:GOSUB290:GOTO250'Sound
254 S%=0:GOSUB290:GOTO250'Quiet
255 PRINT@0,;:FORY%=1TOPEEK(-2501):PRINTSPACE$(PEEK(-2500));:NEXT:PRINT@0,;'Equivalent CLS for any screen width; reuses variable Y%
256 PRINT"Time zone displacement with":PRINT"respect to Universal Time":PRINTUSING"Coordinated (UTC) is +##.##";TZ!:PRINT"hours. This can be changed":PRINT"by editing line 540, where a"
257 PRINT"RESTORE7nn phrase points to":PRINT"a line of DATA in the range":PRINT"of 701 through 797. MRG700.DO";:GOSUB260:GOTO250'UTC+/-
258 CLS:LINE(XO%,YO%-R%)-(XO%,YO%+R%):LINE(XO%-R%,YO%)-(XO%+R%,YO%),1
259 PRINT"Center the gnomon exactly on the crosshair target that is seen in right-hand panel. It must stand perfectly upright on the LCD glass. During use the laptop must be placed so that the LCD glass is level.";:GOSUB260:CLS:GOTO594
260 FORY%=0TO32766:NEXT:RETURN'Dwell a short time
280 GOSUB409:GOSUB411:END'Enable scroll, set screen width to 40-column, and end program interpretation
290 'Subroutine to display appropriate line of command keystrikes
291 GOSUB408:PRINT@7*PEEK(-2500),;'Disable scrool, set print position to bottommost line of LCD
292 IFS%THENPRINT"[Q]uiet ";:ELSEPRINT"[S]ound ";'
293 PRINT"[G]nomon [U]TC"CHR$(141)" [E]nd";'
299 RETURN
300 'Subroutine to determine the visual sun altitude based on average conditions of atmospheric refraction
301 RL#=AL#*RD#'Refracted aLtitude (in degrees) is based on true ALtitude angle of sun
302 IFRL#>85THEN309'No compensation for 85 degrees < true sun altitude
303 TR#=TAN(RL#*DR#)'Tangent of Refracted altitude
304 IFRL#>05THENRL#=RL#+(58.1/TR#-0.07/TR#^3+0.000086/TR#^5)/3600:GOTO309'Compensation for 05 degrees < true sun altitude <= 85 degrees
305 IFRL#>-0.575THENRL#=RL#+(1735-518.2*RL#+103.4*RL#^2-12.79*RL#^3+0.722*RL#^4)/3600:GOTO309'Compensation for -0.575 degrees < true sun altitude <= 05 degrees
306 IFTR#=0THENRL#=7.0000000000001E-64'To avoid the ?/0 Error in the subsequent TAN() function, if the value of RL# is 0 then it must be adjusted to be as small as possible above the value of 0
307 RL#=RL#+(-20.774/TR#)/3600'Compensation for true sun altitude <= -0.575 degrees
309 RETURN'Atmospheric refraction compensated ALtitude angle of sun (in degrees)
400 'Subroutines for LCD control purposes
406 PRINTCHR$(27)"U";'Disengage LABEL line of screen, then pass to next program line for subroutine completion
407 GOSUB408:PRINT@0,;:FORY%=1TOPEEK(-2501):PRINTSPACE$(PEEK(-2500));:NEXT:PRINT@0,;:GOSUB409:RETURN'Equivalent CLS for any screen width; reuses variable Y%
408 PRINTCHR$(27)"V";:RETURN'Disable scrool, cursor position unchanged
409 PRINTCHR$(27)"W";:RETURN'Enable scroll, cursor position unchanged
410 PRESET(XO%,YO%):RETURN'reset the shadow-line origin pixel, which registers origin
411 POKE-2500,40:RETURN'Set screen width to 40-column
412 POKE-2500,29:RETURN'Set screen width to 29-column
500 'Abort if not M10x laptop, elsewise retain variables TS$ & DS$, but make initial assignment for constants and other variables in a forced order (using dummy values if necessary) for sake of high-speed interpretation
501 IFPEEK(72)THENBEEP:PRINT"This program is valid for Model 100 and Model 102 laptops only.":STOP:MENU
502 PI#=2*ATN(3D13)'Forced order assignment. Constant Pi approximation for all laptop Models (100/102/200) based on value of 3D13 being a sufficiently close approximation to infinity
503 DR#=PI#/180'Forced order assignment. Constant Degrees-to-Radians angular unit conversion factor
504 RD#=180/PI#'Forced order assignment. Constant Radians-to-Degrees angular unit conversion factor
505 YR%=0:LY%=0'Forced order assignment by dummy value. Variables YeaR number & LeapYear_flag
506 MN%=0:DY%=0'Forced order assignment by dummy value. Variables MoNth number & Day-of-Year number
507 T0#=0:T1#=0'Forced order assignment by dummy value. Variables Temporal_factor_0 & Temporal_factor_1
508 TD!=0'Forced order assignment by dummy value. Constant Time_Differential
509 UC#=0'Forced order assignment by dummy value. Variable Universal_time-of-day_Coordinated
510 SD#=0'Forced order assignment by dummy value. Variable Solar Declination
511 LA#=0'Forced order assignment by dummy value. Variable LAtitude of location (in radians)
512 LG#=0'Forced order assignment by dummy value. Constant LonGitude of location
513 HA#=0'Forced order assignment by dummy value. Variable Hour Angle (in radians)
514 SL#=0'Forced order assignment by dummy value. Variable Sine of aLtitude angle of sun (in radians)
515 AL#=0'Forced order assignment by dummy value. Variable ALtitude angle of sun (in radians)
516 CZ#=0'Forced order assignment by dummy value. Variable Cosine of aZimuth of sun
517 AZ#=0'Forced order assignment by dummy value. Variable AZimuth of sun
518 RL#=0'Forced order assignment by dummy value. Variable Refracted aLtitude angle of sun (in degrees)
519 TR#=0'Forced order assignment by dummy value. Variable Tangent of Refracted altitude
520 XO%=208+1:YO%=31'Forced order assignment. Constants X-Origin & Y-Origin
521 R%=YO%-1'Forced order assignment. Constant Radius maximum limit
522 Y%=0'Forced order assignment by dummy value. Variable Y ordinate, and also reused for general purposes
523 ET#=0'Forced order assignment by dummy value. Variable Equation of Time (in seconds)
530 LT#=0'Forced order assignment by dummy value. Constant LaTitude of location (in degrees)
540 RESTORE701:READTZ!'Forced order assignment by default value. Constant Time Zone displacement
550 RESTORE939:READLT#:READLG#:LG#=LG#*DR#'LaTitude (in degrees) & LonGitude (in radians) coordinates of location
560 K$=""'Forced order assignment by dummy value. Variable Keystrike
561 V%=0'Forced order assignment by dummy value. Variable Valid keystrike
562 S%=1'Forced order assignment of default value. Variable Sound: 0=quiet, not0=sound is allowed.
594 GOSUB411'40-column screen width
595 GOSUB406'Disengage LABEL line of screen, disable scroll, perform equivalent CLS
596 PRINT@29,CHR$(152):PRINT@69," ":PRINT@109,"N":PRINT@149,"o":PRINT@189,"r":PRINT@229,"t":PRINT@269,"h":LINE(174,56)-(179,63),0,BF:LINE(176,6)-(176,15),1'place vertical North pointer on screen
597 GOSUB410:LINE-(XO%,YO%),0'register shadow-line origin, nul for the initial shadow-line
598 GOSUB412'29-column screen width
599 GOTO2'Forced order of constants & variables is established, and constant PI# has aquired the value of Pi
600 'Laptop-specific datum
601 DATA -2.3859440304:'LCD screen Angle of Tilt in Tandy M10x laptop as measured by Ron Wiesen (in degrees)
700 'List of Time Zone displacements. In line 540, change the RESTORE line number so it points to the appropriate line in following list. Displacement is +/- whole or fractional hours relative to the Prime Meridian. Range is -12.0 to +12.0.
701 DATA 0:'UTC, Burkina Faso, Canary Is., Cote D' Ivoire, Faroe Is., Gambia, Ghana, Guinea, Guinea Bissau, Iceland, Ireland, Isle of Man, Liberia, Mali, Mauritania, Madeira Is., Morocco, Portugal, Senegal, Shetland Is., Sierra Leone, Togo, U.K.
900 'List of LaTitude (in degrees) & LonGitude (in degrees) coordinates for various folks. In line 550, change the RESTORE line number so it points to the appropriate line in following list.
939 DATA +28.398600,-080.748465:'coordinates for Ron Wiesen [WD8PNL]