Argentine Airglow Spectrometer

BASIC control program (2006 version)

The program manages digital input and output from/to the spectrometer interface, reads input from
SUNDAT.TXT (a list of start and stop times for nocturnal measurements, for each day of the year), and produces the following output files:

Program also reads Real Time Clock, System Software Clock, Printer Port Status signals by direct hardware access. Certain Interrupt Controller Channels (timer tick, keyboard input) are temporarily disabled to insure timing accuracy. Software timing loops are calibrated against real time and so become hardware-independent.

Operation is automatic (mode 0) by default. Other manually selectable modes:

In the following listing, many of the two-character variable names and all numeric labels are still testimony of the original Tandy program version, carried into the PC world unchanged (and bugless!)

For unresolved problems with our server(s), the following listing may appear incomplete

CONST Version$ = "9.1.06(VF2WD)"
'9.1.06: VF2WD: wavelength calib 2005, new coef for useT2,etc..
'18.11.05 RS plot for monit
'9.11.05 count number Z% shown in monit mode
'28.9.05 NeJu%=0  para usar lampara Ne Juergen
'22.9.05 new label "rpt" for manually choosing new option. AT OWN RISK!
'21.9.05 spcfiles (s*.dat) van al \dat; no more than mxspc% are produced
'22.09.04: new limits defined
'25.03.02: 2nd measT2 per block now #7 and #14
'01.11.01: mean%=0 in dark1; monit2 entry if DT, DST modified
'31.10.01: replaced strg comparison (HVon$, Eve$, etc.) by numerics...
'31.10.01: version tested with JMPQ version
'30.10.01: NeJu%=-1, default; varios ajustes (ver "Datos Bicho 2001")
'28.08.01: Obtoff or HVoff status check at entry of subroutines
'          spcfile named correctly
'10.8.01: atras, a los viejos W's hasta se resuelve el prob de los "anchos"
'09.8.01: IF SD > SX OR AC > -330 ... instead of -350
'16.1.01: updated W(); Empty line in log at start, etc.
'02.01.01, VT: Fd updated for each OH pkseekd
'02.01.01: with SPCFILE, etc. 6.1.1: par, par() faltaba
'28.12.00: P0% & constant term ref(T2) updated; ESC logged with date and time
'02.10.99; P0% = 0; "shut" repl by "shutter"
'28.9.99: update "14.9.99(VF2VO)" to include dif F2VN home/hill
'21.5.99: "autosamp" for mode 0
'14.9.99 all HV/obt status changes to LOG
'9.9.99 reordered instructions prior to "START!"; plotRot with LINE
'8.9.99 jm corregido; first REF & P0% to log file; routine CHKDARK
'7.9.99: rutina de backlash (juego muerto, op 7); falta updateo 17.5.99
'02.9.99: VF2VO: reemplazado 2 stops del programa por GOTO emergexit,
'                para una salida segura. ESCAPE in log.
'30.4.99: algunos comentarios de peligro... M$(0)="auto sampling"
'13.4.99: improved P6vsT2 coeffs for useT2 (based on -8.8...18degC)
'13.4.99: display BUG in 8170 removed: edge values displayed correctly
'11.4.99: T2av log format
'9.4.99: HVoff after night with cap on
'        T2av is always output instead of T2
'other previous versions: see older MED.BAS versions!
dark = -50  'dark count criterion dummy init
tdark = -2000
CONST bas% = &H237, bitT1% = 1, bitT2% = 128, ovfl% = 4, L100% = 100
CONST adi1% = bas% + 1, adi2% = bas% + 2, adi3% = bas% + 4, adi4% = bas% + 3
CONST ado1% = bas% + 1, ado2% = bas% + 3, adostp% = bas% + 2
CONST obtoff% = 128, nofchg% = 64, HVEN% = 8, cstart% = 16, rdy% = 64
CONST obtEN% = 255 - obtoff, fchg% = 255 - nofchg, HVoff% = 255 - HVEN, rst% = 255 - cstart
CONST tpd& = 1573040
CONST ticfr# = tpd / 24 / 3600   '18.2 Hz
CONST cspt! = 100 / ticfr 'centiseconds per tick
CONST bda% = &H408   'BIOS data area address
CONST uplim% = 2, lolim% = 4, bolim% = uplim OR lolim, prdy% = 88'printer ready status
DEFINT I-J
ON ERROR GOTO repair
DIM scsc AS STRING * 2, ssec AS STRING * 2, smin AS STRING * 2, shou AS STRING * 2
DIM sday AS STRING * 2, smon AS STRING * 2
DIM CJ AS INTEGER, CR AS INTEGER
DIM wx(13), wy(13)
wx(0) = 618: wy(0) = 186'for Amiga
wx(1) = 319: wy(1) = 199: wx(2) = 639: wy(2) = 199: wx(3) = 719: wy(3) = 347
wx(4) = 639: wy(4) = 399: wx(7) = 319: wy(7) = 199: wx(8) = 639: wy(8) = 199
wx(9) = 639: wy(9) = 349: wx(10) = 639: wy(10) = 349: wx(11) = 639
wy(11) = 479: wx(12) = 639: wy(12) = 479: wx(13) = 319: wy(13) = 199
REDIM DD(5, 1000)
DIM C1(1), C2(1), K1(1), K2(1), ICLOH!(1), ICLO2!(1)
DIM CNO2(1), KNO2(1), ICO2!(1), CNOH(1), KNOH(1), ICOH!(1)
hz% = 20: hz0% = 1: ix = -1: T2av = 999
WIDTH LPRINT 255: dire$ = "c:\binary"
lgd$ = "c:\log\": flog$ = lgd$ + "medir.log"
DIM m$(7): m$(1) = "sampling": m$(0) = "autosamp": m$(2) = "monitoring"
m$(3) = "Neon peaks": m$(4) = "spectrum": m$(5) = "narrow scan"
m$(6) = "OH peaks": m$(7) = "backlash"
DIM LI$(4): LI$(2) = "upper": LI$(4) = "lower"
DIM dow$(7): dow$(1) = "dom": dow$(2) = "lun": dow$(3) = "mar"
dow$(4) = "mie": dow$(5) = "jue": dow$(6) = "vie": dow$(7) = "sab"
st$ = STRING$(11, 42): B6$ = SPACE$(6): B8$ = SPACE$(8): c$ = "COUNT"
L$ = "LIMIT": O$ = "OKAY": F$ = "FILTER ": S$ = "STEPS FROM "
LF% = 14: P0% = 0
DIM S(L100), W(LF%): DT = 5: DTDEF% = 20: back2def% = 20: SX = .005
V% = 9: EM% = 14: Z% = 1: LI% = 0: Tsw = -28: TT = Tsw: LN% = 40
PF% = P0% + 4960
LX% = PF% + 10
SS = 0: DIM K(LF%, 1, 1), prf%(1)
ctspc% = 0: mxspc% = 14
hou0% = -1: day0% = -1: stCO% = -1: stHV% = -1: stobt% = -1
factT1 = 106.987: CO% = 4: sal1% = 255: sal2% = 255
OPEN "c:\frar.bat" FOR OUTPUT AS #1
PRINT #1, "@echo off"
CLOSE #1
OUT &H21, 0 'all hardware interrupts active
DEF SEG = 0: prp% = PEEK(bda) + 256 * PEEK(bda + 1) + 1
CLS                 'prp% is printer port status address
vid% = PEEK(&H410) AND &H30
IF vid% = 0 THEN
	PRINT "EGA(?)"
	IF PEEK(&H487) <> 0 OR PEEK(&H488) <> 0 THEN mode% = 11
END IF
IF vid% = 16 THEN mode% = 1
IF vid% = 32 THEN mode% = 2
IF vid% = 48 THEN mode% = 3
SCREEN mode%
Trang = 210 'rot Temp range, vertical
RSmax = 250
T11 = -45: TO1 = 50: TH1 = 120'lower border
T10 = 30: Tr0(1) = TO1 + Trang: Tr0(0) = TH1 + Trang    'upper border
T1sc = wy(mode%) / (T11 - T10)
Trsc = -wy(mode%) / Trang      'rot temp scale factor for plot
RSsc = -wy(mode%) / RSmax
sal1% = sal1% AND HVoff
GOSUB OUT1: tHV = TIMER  'shutter and HV off by default
GOSUB recd
entry:
IF COMMAND$ = "" THEN
	GOSUB newsc
inco: INPUT "COUNT GATE (CO%; 0-7)"; CO%: IF CO% > 7 THEN GOTO inco
	INPUT "1-norm, 2-monit, 3-Ne peaks, 4-spect, 5-monoc, 6-OH peaks, 7-juego muerto "; op%
ELSE
	log$ = "Automatic program start " + DATE$ + " " + TIME$
END IF
GOSUB rstcnt: GOSUB stcnt
GOSUB initvar1
IF log$ <> "" THEN GOSUB recd
log$ = "Program version V." + Version + ", with P0 =" + STR$(P0%)
del& = 7: GOSUB delay 'init math routines insures correct timing
j1:
OUT &H21, 3
GOSUB inicl: OUT &H70, 0: sec% = INP(&H71)
IF sec% < 89 THEN
	IF (sec% AND 15) <> 9 THEN sec% = sec% + 1 ELSE sec% = sec% + 7
ELSE  'BCD coded seconds treated as if binary
	sec% = 0
END IF
del& = 200000: GOSUB caldel 'del& must be beyond reach during caldel
IF K& = del& + 1 THEN PRINT "machine too fast / RTC clock too slow"
lpms = K& / 1000: PRINT USING "###.# loops per msec "; lpms; : OUT &H21, 0
log$ = log$ + B6$ + STR$(lpms) + " loops per msec": GOSUB recd
del2& = 2.4 * lpms: del1& = 2 * del2&
IF lpms < 3 THEN
	LOCATE 12, 40: PRINT "machine too slow!": SOUND 1500, 10
	del& = 3000 * lpms: GOSUB delay
END IF
GOSUB recd
CV% = CO%: LOCATE 12, 35: PRINT "V."; Version;
LZ% = 2 * LE% + 2
DIM a(6, 3), G%(3), R(EM%), P(EM%), V(V%), E(L100 + 1, EM%), D(LZ% * 14 + 1)
GOSUB chkflt
IF op% = 0 THEN
	IF filt% = 3 THEN GOSUB fchg
	IF filt% = 1 THEN GOSUB fchg  'try to get F2
	IF filt% = 3 THEN log$ = "WRONG " + F$ + "!!!": GOSUB recd 'if power off
END IF
GOSUB initvar2
GOSUB acqT1
IF (erc% AND 16) = 16 THEN FOR i = 1 TO V% - 1: V(i) = 400: NEXT: GOTO normin
FOR i = 1 TO V% - 2: GOSUB acqT1: NEXT
GOSUB evalT1: IF op% <> 2 AND op% <> 0 THEN GOSUB HVdel: GOSUB obtdel 'peligro!
normin: GOSUB newsc: G% = 0
GOSUB acqT1: GOSUB evalT1: LOCATE 1, 1: PRINT CR + 32768!; CJ + 32768!; P, B8$
GOSUB hotPM: GOSUB sync
IF op% = 2 THEN GOTO monit
log$ = CHR$(18) + CHR$(14) + "DATE: " + dat$ + LEFT$(TIME$, 5) + CHR$(15) + " " + m$(op%)
GOSUB recd
SP = 4800: IF MT% = 0 THEN GOSUB range ELSE GOSUB verirep
GOSUB recd
IF MT% = -1 THEN
	IF op% = 0 THEN
		log$ = log$ + "    MOTOR OFF  ": GOSUB recd
		DT = 45
		GOTO monit2                      'no trucho sampling in auto mode
	END IF
END IF
IF op% <= 1 THEN GOTO 2600
IF op% = 2 THEN GOTO monit
IF op% = 3 THEN GOTO neon
IF op% = 4 THEN LE% = 100: GOTO 2600
IF op% = 5 THEN LE% = 100: GOTO monoc
IF op% = 6 THEN GOTO neon
IF op% = 7 THEN GOTO juego
PRINT "illegal mode"; op%: END
2600 RF% = prf%(filn%)
IF filn% = 0 THEN S0 = K(RF%, 0, 0) ELSE S0 = 0
GOSUB measT2: Q = T2: GOSUB measT2
IF ABS(T2 - Q) > .15 THEN GOTO 2600 ELSE T2 = (T2 + Q) / 2
LOCATE 1, 1: PRINT SPACE$(160); : stCO% = -1: stHV% = -1: stobt% = -1
IF MT% = -1 THEN log$ = log$ + "    MOTOR OFF": GOSUB recd
CO% = CV%
log$ = "CO=" + STR$(CO%) + " T1=" + STR$(PC) + " T2=" + STR$(INT(T2av * 100) / 100) + " "
IF op% > 0 THEN GOTO sigamos
GOSUB getsun
hora = TIMER
IF (hora < Eve) AND (hora > Morn) THEN
	GOSUB obtoff
	IF hora < HVtime THEN GOSUB HVoff   'added for early morning HV cutoff
	log$ = log$ + " waiting for the night... " + Eve$ + " - " + Morn$: GOSUB recd
	GOTO monit
END IF
IF (sal1% AND HVEN) <> HVEN THEN GOTO monit
GOSUB useT2: cryf% = 0
IF (sal1% AND obtoff) = obtoff THEN
	GOSUB chkdark
	GOSUB obtdel
	log$ = log$ + TIME$ + ":  sera no necesario? ": GOSUB recd
END IF
sigamos:
GOSUB sync
log$ = log$ + shou + ":" + smin + ":" + ssec: GOSUB recd
IF LE% < 30 THEN
	acpt% = -2: psea% = 0: DP = 0: SD = 0: AC = 0: GOSUB 8270
	pk% = 7: GOSUB chksig
	IF ZA < 3 * dark THEN GOTO monit
ELSE
	IF op% = 4 THEN
		S(1) = 200 '150'20
		FOR i = 2 TO LE%
			NON% = 100 - INT(S(i - 1) * .0165): S(i) = S(i - 1) + NON%
		NEXT
	END IF
END IF
ID = 4: Z% = 1
D(1) = 1: D(0) = 100 * Z(6) + Z(7) + .01 * Z(4)
lote:
IF op% < 2 THEN
	hora$ = TIME$: hora = TIMER
	IF (hora > Morn) AND (hora < Eve) THEN
			GOSUB obtoff
			log$ = log$ + " SUNRISE! " + hora$ + ", " + sday + "." + smon + "." + yea$
			GOSUB recd: GOTO fin
	 END IF
END IF
IF LE% < 30 THEN
	EM% = 2: LOCATE 1, 72: PRINT D(1);
	IF LI% = 0 THEN
		IF Z% = 1 THEN
			IF (INP(prp%) AND 120) = prdy THEN
				LPRINT CHR$(15); "TIME";
				FOR i = 1 TO LE%: LPRINT TAB(12 * i); S(i); : NEXT
				LPRINT TAB(105); "TEMP.OH"; TAB(117); "TEMP.O2";
				LPRINT CHR$(18); CHR$(14); USING "  ## "; D(1);
				LPRINT CHR$(15)
				del& = 1000 * lpms: GOSUB delay
			END IF
			CO% = CV%
		END IF
	END IF
ELSE
	EM% = 14
END IF
GOSUB acqT1: GOSUB evalT1: GOSUB hotPM
IF LE% < 30 THEN LOCATE 1, 76: PRINT LI% + 1
FOR ID = LE% TO 1 STEP -1: SP = S(ID): GOSUB sample: NEXT
IF LE% >= 30 THEN LOCATE 1, 76: PRINT Z% + 1
GOSUB evalT1: GOSUB hotPM
Z% = Z% + 1: IF Z% > EM% THEN GOSUB evalote
FOR ID = 1 TO LE%: SP = S(ID): GOSUB sample: NEXT
IF LE% >= 30 THEN LOCATE 1, 76: PRINT Z% + 1
GOSUB evalT1: GOSUB hotPM
Z% = Z% + 1: IF Z% > EM% THEN GOSUB evalote
GOTO lote

evalote: FOR ID = 1 TO LE%: GOSUB aveE: NEXT
GOSUB csec
FOR i = 1 TO LE%
	IF LE% < 30 THEN j = 2 * i + LI% * LZ% ELSE j = 2 * i
	D(j) = S(i): D(j + 1) = E(i, 0)
NEXT
IF LE% >= 30 THEN GOSUB grablk
IF (INP(prp%) AND 120) = prdy THEN
	LPRINT CHR$(15); shou; smin; "."; ssec; scsc; " ";
	IF LE% < 30 THEN
		FOR i = 1 TO LE%: LPRINT TAB(12 * i); E(i, 0); : NEXT
	ELSE
		LPRINT ""
		FOR i = 1 TO LE%
			LPRINT S(i); ": "; E(i, 0); "+-"; E(i, 1),
			IF LPOS(0) > 105 THEN LPRINT ""
		NEXT
		LPRINT ""
	END IF
END IF
IF LE% >= 30 THEN GOTO 4002
IF ix = -1 THEN GOSUB initbin
ix = ix + 1: foc = 2 ^ (4 - CO%) 'cf. FO!!!
Fd = E(4, 0) * foc
DD(0, ix) = Fd
DD(1, ix) = hou% * 3600! + min% * 60! + sec% - start
IF hou% > 15 THEN DD(1, ix) = DD(1, ix) - 86400
IF Fd < Umb THEN
	P = E(7, 0) - E(5, 0) + C2(filn%) * E(4, 0)
	IF P THEN x = (E(6, 0) - E(4, 0) * C1(filn%)) / P
	DD(2, ix) = (E(1, 0) + E(2, 0) + E(3, 0)) * foc - ICLO2!(filn%) * Fd
	DD(4, ix) = (E(5, 0) + E(6, 0) + E(7, 0)) * foc - ICLOH!(filn%) * Fd
ELSE
	P = E(7, 0) - E(5, 0) + E(4, 0) * KNOH(filn%) + DU2OH(filn%) / foc
	IF P THEN x = (E(6, 0) - E(4, 0) * CNOH(filn%) + DU1OH(filn%)) / P / foc
	DD(2, ix) = (E(1, 0) + E(2, 0) + E(3, 0)) * foc - ICLO2!(filn%) * Umb - ICO2!(filn%) * (Fd - Umb)
	DD(4, ix) = (E(5, 0) + E(6, 0) + E(7, 0)) * foc - ICLOH!(filn%) * Umb - ICOH!(filn%) * (Fd - Umb)
END IF
IF P THEN
	j = 1
	IF x < 0 THEN
		P = -999
	ELSEIF x > 5 THEN
		P = 999
	ELSE
		GOSUB polyn
	END IF
	IF (INP(prp%) AND 120) = prdy THEN LPRINT TAB(105); P;
	GOSUB plTrot
ELSE
	IF (INP(prp%) AND 120) = prdy THEN LPRINT TAB(105); "***";
END IF
IF ABS(P) <> 999 THEN DD(5, ix) = P ELSE DD(5, ix) = 0
LOCATE 3, 75: PRINT USING "######"; DD(4, ix);
LOCATE 4, 75: PRINT USING "######"; DD(2, ix);
LOCATE 5, 75: PRINT USING "######"; DD(0, ix);
FOR i = 1 TO LE%
	LOCATE 6 + i, 75: PRINT USING "######"; E(i, 0);
NEXT i
LOCATE 1, 39: PRINT USING "####.# "; P;
IF Fd <= Umb THEN
	P = E(1, 0) - E(3, 0) + K2(filn%) * E(4, 0)
	IF P THEN x = (E(2, 0) - E(4, 0) * K1(filn%)) / P
ELSE
	P = E(1, 0) - E(3, 0) + E(4, 0) * KNO2(filn%) + DU2O2(filn%) / foc
	IF P THEN x = (E(2, 0) - E(4, 0) * CNO2(filn%) + DU1O2(filn%)) / P / foc
END IF
IF P THEN
	j = 2
	IF x < 0 THEN
		P = -999
	ELSEIF x > 5 THEN
		P = 999
	ELSE
		GOSUB polyn
	END IF
	IF (INP(prp%) AND 120) = prdy THEN LPRINT TAB(117); P: del& = 300 * lpms: GOSUB delay
	GOSUB plTrot
ELSE
	IF (INP(prp%) AND 120) = prdy THEN LPRINT "": del& = 300 * lpms: GOSUB delay
END IF
IF ABS(P) <> 999 THEN DD(3, ix) = P ELSE DD(3, ix) = 0
PRINT USING "####.#"; P;
4002  GOSUB evalT1
IF LE% < 30 THEN
	D(LZ% * (LI% + 1)) = 100 * Z(6) + Z(4)
	D(LZ% * (1 + LI%) + 1) = 100 * Z(3) + Z(2) + .01 * Z(1)
ELSE
	GOSUB verirep
END IF
GOSUB hotPM
IF LE% >= 30 THEN RETURN darkcnt         'after spectrum, monitor
LI% = LI% + 1
IF LI% = 7 THEN GOSUB measT2             'this is new: 25.03.02/upd 03.04.02
IF LI% > 13 THEN
	GOSUB grablk: LI% = 0: GOSUB measT2
	log$ = "T1=" + STR$(PC) + " T2=" + STR$(INT(T2av * 100) / 100) + " "
	GOSUB verirep
	IF op% = 0 AND MT% = -1 THEN RETURN monit
	IF acpt$ <> "*" THEN Fd = E(4, 0): GOSUB 8260 ELSE acpt$ = " "
	GOSUB sync: D(0) = 100 * Z(6) + Z(7) + .01 * Z(4): D(1) = D(1) + 1
END IF
Z% = 1: RETURN

verify: log$ = log$ + "VERIFY REF: "
IF MT% = -1 THEN log$ = log$ + "   MOTOR OFF": GOTO recd
NO% = PF% - PS%: GOSUB MPP
IF (INP(adi4) AND bolim) = uplim THEN
	IF PS% = PF% THEN
		log$ = log$ + "OK": GOSUB recd
		LOCATE 1, 60: PRINT O$ + B8$
	ELSE
		log$ = log$ + STR$(PS% - PF%): GOSUB recd
		LOCATE 1, 60: PRINT "OFFS="; PS% - PF%;
	END IF
	GOTO 7020
END IF
NO% = 1 'advance step by step
FOR atp% = 1 TO 1000
	GOSUB MPP
	IF (INP(adi4) AND bolim) = uplim THEN
		IF PS% <> PF% THEN
			LOCATE 1, 60: PRINT "OFFS="; PS% - PF%;
			log$ = log$ + STR$(PS% - PF%) + " " + S$ + " " + LI$(lim%) + " " + L$
		ELSE
			LOCATE 1, 60: PRINT O$ + B8$
			log$ = log$ + "OK"
		END IF
		GOSUB recd
		GOTO 7020
	END IF
	IF PS% = PF% - LN% THEN
		log$ = log$ + "MORE THAN" + STR$(-LN%) + " " + S$ + " " + LI$(lim%) + " " + L$: GOSUB recd
		LOCATE 1, 60: PRINT "REF>"; -LN%; : GOTO 7020
	END IF
NEXT atp%
MT% = -1: PS% = 0
7020 rfd% = ABS(PS% - PF%)
IF rfd% > 2 THEN VF% = -1 ELSE VF% = 1
IF rfd% > 1 THEN VOK% = -1      'VOK% <>-1 means: ref has always been OK
NO% = FIX(SP - PS%): GOSUB MPP: RETURN

monit:
DT = 5: DST = 2
monit2:
updct% = 0:  pix% = 0
IF op% = 2 THEN CLS
stCO% = -1: stHV% = -1: stobt% = -1 'force screen update
EM% = 14
log$ = CHR$(18) + CHR$(14) + " " + m$(2)
GOSUB recd
TA = Z(3) + 60 * Z(4) - DT + DST
8000 GOSUB sync: LOCATE 1, 1
PRINT sday; "."; smon; ". ("; dow$(Z(5)); ") "; shou; ":"; smin; ":"; ssec;
IF Eve$ <> "" THEN LOCATE 1, 25: PRINT Eve$; " - "; Morn$;
GOSUB watchcnt
mi% = Z(3) + 60 * Z(4)
IF (mi% < TA + DT) AND (mi% >= TA) THEN GOTO 8003
updct% = updct% + 1
IF updct% > back2def% THEN DT = DTDEF%: updct% = 0
TA = mi%: GOSUB measT2
IF log$ <> "" THEN GOSUB recd
IF (INP(prp%) AND 120) = prdy THEN
	LPRINT CHR$(15);
	LPRINT USING shou + ":" + smin + " ###.## " + c$ + ":######.## +-####.# (CO=#) T2:###.##"; PC; RS; VR; CO%; T2av
	del& = 500 * lpms: GOSUB delay
END IF
OPEN flog$ FOR APPEND AS #4
PRINT #4, USING shou + ":" + smin + " ###.## ######.## +-####.# (CO=#) T2:###.##"; PC; RS; VR; CO%; T2av
CLOSE #4
CO% = CV%
8003 IF hot% = 0 THEN IF PC > TT THEN GOSUB HVoff: hot% = 1: GOSUB obtoff
IF hot% = 1 AND ovf% = 0 THEN
	IF PC < Tsw - 1 THEN
		hot% = 0
		IF hidark% = 1 THEN
			IF TIMER < thid THEN thid = thid - 86399
			IF TIMER > thid + 1800 THEN IF op% > 0 THEN GOSUB HVdel
		ELSE
			IF HVovf% = 0 THEN IF op% > 0 THEN GOSUB HVdel
		END IF
		IF (sal1% AND HVEN) = HVEN THEN
			TT = Tsw
			IF op% <> 0 AND op% <> 2 THEN GOTO normin
		END IF
	 END IF
END IF
IF Eve$ = "" THEN GOSUB getsun
IF (sal1% AND HVEN) <> HVEN THEN
	hora = TIMER
	IF (op% = 0) AND ((hora > HVtime) OR (hora < Morn)) THEN
		IF PC < Tsw - 1 THEN
			hot% = 0
			IF hidark% = 1 THEN
				IF TIMER < thid THEN thid = thid - 86399
				IF TIMER > thid + 1800 THEN GOSUB HVdel
			ELSE
				IF HVovf% = 0 THEN GOSUB HVdel
			END IF
		END IF
	END IF
END IF
GOSUB acqT1: GOSUB evalT1
PSET (pix%, (PC - T10) * T1sc)
pix% = pix% + 1: IF pix% > wx(mode%) THEN pix% = 0: scr% = scr% + 1
IF scr% = 5 THEN scr% = 0: GOSUB newsc
IF (INP(adi4) AND rdy) <> rdy THEN GOSUB watchcnt: GOTO 8000
GOSUB 720: GOSUB 940
LOCATE 10, 1
PRINT USING "##  ########  "; Z%; ZA;
IF mean% THEN
	mean% = 0
	PRINT USING "AVE: #######.## +- ######.##"; RS; VR
	PRINT B8$;
	IF RS <= RSmax THEN
		PSET (pct%, (RS - RSmax) * RSsc - 75)
		pct% = pct% + 1: IF pct% > wx(mode%) THEN pct% = 0: GOSUB newsc
	END IF
	IF monl% THEN
		log$ = log$ + "DARK COUNT " + STR$(RS) + "+-" + STR$(VR) + "  CO=" + STR$(CO%)
		log$ = log$ + " " + TIME$
		GOSUB recd
		monl% = monl% - 1
		IF monl% = 0 THEN RETURN  'mean-only flag: exit GOSUB monit with mean
	END IF
END IF
GOSUB count: GOSUB measT2
PSET (pix%, (T2av - T10) * T1sc): GOSUB watchcnt
IF in$ = "" THEN in$ = INKEY$
IF in$ = CHR$(27) THEN
	in$ = ""
	log$ = log$ + "ESCAPE from monit " + DATE$ + " " + TIME$
	GOSUB recd
	STOP
END IF
IF UCASE$(in$) = "C" THEN in$ = "": GOSUB CMT
IF in$ = "S" THEN in$ = "": GOSUB set
IF op% > 0 THEN
	IF in$ = "F" THEN
		in$ = ""
		LOCATE 2, 1: PRINT "Searching bckgr pos..."
		IF MT% = 0 THEN GOSUB range
		IF S(4) = 0 THEN GOSUB useT2
		SP = S(4): GOSUB 7020
		log$ = "backgrd pos." + STR$(PS%): GOSUB recd: GOSUB newsc
	END IF
	IF in$ = "P" THEN TA = mi% + 1
	IF in$ = "M" THEN in$ = "": LE% = 7: op% = 0: GOTO normin
END IF
in$ = ""
IF op% > 1 OR hot% = 1 THEN GOTO 8000 'hot% flag inhibits night sampling
hora$ = TIME$: hora = TIMER
IF (hora >= Eve) OR ((hora < Eve) AND (hora < Morn)) THEN
	IF (sal1% AND HVEN) <> HVEN THEN GOTO 8000
	IF MT% = -1 THEN GOSUB range
	IF MT% = -1 THEN GOTO 8000
	GOSUB chkdark
	GOSUB obtdel
	pk% = 7: GOSUB chksig
	IF ZA < 3 * dark THEN GOTO 8000
	log$ = log$ + " START! " + hora$ + ", " + sday + "." + smon + "." + yea$
	GOSUB recd
	LE% = 7: GOTO normin
END IF
IF (sal1% AND obtoff) <> obtoff THEN
	GOSUB HVoff: GOSUB obtoff: cryf% = 0
	log$ = log$ + " soft boot! " + hora$ + ", " + sday + "." + smon + "." + yea$
	GOSUB recd
	SHELL "c:\rebootb"
END IF
GOTO 8000

8060  GOSUB runcnt
8065  GOSUB watchcnt
IF (INP(adi4) AND rdy) = 0 THEN GOTO 8065
GOSUB 720: LOCATE 1, hz% + 7: PRINT ZA; B6$; : SWAP hz%, hz0%: E(ID, Z%) = ZA
RETURN

sample: NO% = FIX(SP - PS%)
8110 GOSUB MPP
8115 LOCATE 1, hz%: PRINT PS%; B8$; : GOSUB 8060: RETURN

8170 IF op% = 7 THEN GOTO jm  'jm
Z% = 1: EM% = 14: SP = S(RF%) + 4 * W(RF%): ID = 8
IF op% <= 1 AND MT% = 1 THEN
	IF RF% <= LE% THEN CO% = 2 ELSE CO% = 0
END IF
GOSUB sample
FOR Z% = 1 TO EM%: NO% = -W(RF%)
	LOCATE 1, 76: PRINT Z%
	FOR ID = 7 TO 0 STEP -1: GOSUB 8110: NEXT
	NO% = W(RF%): Z% = Z% + 1: ID = 0: GOSUB 8115
	LOCATE 1, 76: PRINT Z%
	FOR ID = 1 TO 8: GOSUB 8110: NEXT
	IF Z% < EM% THEN Z% = Z% + 1: ID = 8: GOSUB 8115: Z% = Z% - 1
	GOSUB acqT1
NEXT
Z% = 1: FOR ID = 0 TO 8: GOSUB aveE: NEXT
parab: 'jm
Y1 = 0: X1 = 0: X2 = 0: X3 = 0: X4 = 0: Z1 = 0: Z2 = 0
IF RF% > LE% THEN Fd = 0
FO = Fd / 2 ^ (CV% - CO%)
FOR i = 0 TO 8
	IF E(i, 0) > FO THEN
		E(i, 0) = LOG(E(i, 0) - FO)
	ELSE
		SD = 1000 * SX: DP = 5555: GOTO 8250
	END IF
NEXT
FOR i = 0 TO 8
	YI = E(i, 0): Y1 = Y1 + YI: X1 = X1 + i: I2 = i * i: I3 = I2 * i
	I4 = I3 * i: X2 = X2 + I2: X3 = X3 + I3: X4 = X4 + I4
	Z1 = Z1 + YI * i: Z2 = Z2 + YI * I2
NEXT
XA = X3 - X1 * X2 / 9: XB = X2 - X1 * X1 / 9: XC = X4 - X2 * X2 / 9
XN = XA - XB * XC / XA: KA = Z1 - Z2 * XB / XA + Y1 / 9 * (X2 * XB / XA - X1)
KA = KA / XN: KB = Z2 - KA * XC - Y1 * X2 / 9: KB = KB / XA
KC = Y1 - KA * X2 - KB * X1: KC = KC / 9: YP = KC - KB * KB / 4 / KA
AC = YP / KA: XP = -KB / 2 / KA: SD = 0
FOR i = 0 TO 8
	X2 = i * i
	par = KA * X2 + KB * i + KC
	DY = (E(i, 0) - par) ^ 2: SD = SD + DY
	par(i) = par
NEXT
DP = (XP - 4) * W(RF%)
IF RF% = 12 AND ABS(DP) > 30 THEN NeJu% = -1
8250  IF op% <= 1 THEN CO% = CV%
EM% = 2: RETURN

8260  acpt$ = " ": acpt% = acpt% - 1: SRF0 = S(RF%)
IF (Fd * 2 ^ (4 - CO%) < 1500) OR op% > 1 THEN
	psea% = -1: GOSUB 8170
ELSE
	psea% = 0: DP = 0: SD = 0: AC = 0: GOTO 8270
END IF
parlog:
SS = S(RF%) - INT(S(RF%)): SRF = INT(S(RF%)) + DP
'IF SD > SX OR AC > -350 OR AC < -2000 THEN GOTO 8270
IF SD > SX OR AC > -330 OR AC < -2000 THEN GOTO 8270
acpt% = 0:  S(RF%) = SRF: acpt$ = "*": log$ = log$ + "* ": DP = DP - SS
IF op% <= 1 THEN
	FOR i = 1 TO LE%
		IF i <> RF% THEN
			S(i) = K(i, 0, filn%) + K(i, 1, filn%) * (S(RF%) - S0)
		END IF
	NEXT i
END IF
8270
IF op% <= 1 AND acpt% <= -2 THEN
	GOSUB useT2: log$ = log$ + "$ ": acpt% = 0: acpt$ = "$"
END IF
LOCATE 1, 58: PRINT acpt$;
arg = AC * KA
IF arg < 88 AND arg > 0 THEN expac = EXP(arg) ELSE expac = -99.99999
IF acpt$ = "$" OR psea% = -1 THEN
	IF (INP(prp%) AND 120) = prdy THEN
		LPRINT log$ + "REF#"; RF%; S(RF%); " DP="; DP; " SD="; SD; " WIDTH="; -AC;
		LPRINT "HEIGHT="; expac; : IF op% <= 1 THEN LPRINT ""
	END IF
	OPEN flog$ FOR APPEND AS #4
	PRINT #4, log$ + "REF#"; RF%; S(RF%); DP; SD; -AC; expac; : log$ = ""
	IF op% <= 1 THEN PRINT #4, ""
	CLOSE #4
END IF
LOCATE 15, 74
IF acpt$ <> " " THEN
	PRINT USING "#####.#"; S(RF%) - SRF0;
ELSE
	PRINT SPACE$(7);
END IF
IF psea% = -1 THEN
	LOCATE 16, 74: PRINT USING "#####.#"; DP;
	LOCATE 17, 73: PRINT USING "##.#^^^^"; SD;
	LOCATE 18, 75: PRINT USING "######"; -AC;
ELSE
	LOCATE 16, 74: PRINT SPACE$(7);
	LOCATE 17, 73: PRINT B8$;
	LOCATE 18, 75: PRINT B6$;
END IF
IF op% > 1 THEN IF psea% THEN GOSUB spcfile
RETURN

plTrot:   'rot temps to screen
j = j - 1: G% = G% + 1 - j: IF G% = wx(mode%) THEN G% = 0: GOSUB newsc
IF yvor(j) = 0 THEN
	PSET (G%, (P - Tr0(j)) * Trsc)
ELSE
	LINE (G%, (P - Tr0(j)) * Trsc)-(xvor(j), yvor(j))
END IF
xvor(j) = G%: yvor(j) = (P - Tr0(j)) * Trsc
RETURN

count:
GOSUB runcnt  'runcnt respects CO's explicit value
watchcnt:
IF (INP(adi3) AND ovfl) = 0 THEN RETURN 'do nothing unless ovflow
GOSUB rstcnt: sal1% = (sal1% AND &HF8) OR cstart: OUT ado1, sal1%
'                     note implicit CO=0 !
DO
	IF (INP(adi3) AND ovfl) = ovfl THEN
		GOSUB HVoff: ovf% = 1: GOSUB obtoff: SOUND 3300, 1: RETURN
	END IF
LOOP WHILE (INP(adi4) AND rdy) = 0
GOSUB 720
FOR j = 0 TO CV%: ZA = ZA * 2: CO% = j
	IF ZA > 128000 THEN j = CV%
NEXT
log$ = log$ + "CO=" + STR$(CO%): GOSUB recd
GOTO count

neon:          'Ne or OH peak calibration (one pass, for OH; op%=6)
IF MT% = 0 THEN GOSUB range
LE% = 7: GOSUB sync: NeJu% = -1: IF log$ <> "" THEN GOSUB recd
IF MT% = -1 THEN log$ = "MOTOR OFF": GOSUB recd
LOCATE 1, 1: PRINT SPACE$(160); : stCO% = -1: stHV% = -1: stobt% = -1
IF op% = 6 THEN
	RF% = prf%(filn%): IF S(RF%) = 0 THEN GOSUB measT2: GOSUB useT2
	pk% = 7
ELSE
	IF S(LE% + 1) = 0 THEN
		GOSUB measT2: S(LE% + 1) = T2av
		FOR i = LE% + 1 TO LF%
			S(i) = K(i, 0, filn%) + S(LE% + 1) * K(i, 1, filn%)
		NEXT i
	END IF
	pk% = LE% + 6
END IF
GOSUB chksig
siempre: IF op% = 6 THEN
	FOR RF% = 7 TO 5 STEP -1
		GOSUB pkseekOH
	NEXT RF%
	GOSUB verirep
	FOR RF% = 5 TO 7
		GOSUB pkseekOH
	NEXT RF%
	CV% = 4: CO% = CV%: RF% = 6: op% = 0: GOTO normin
ELSE
	FOR RF% = LF% TO LE% + 1 STEP -1: GOSUB pkseek: NEXT
	GOSUB verirep
	FOR RF% = LE% + 1 TO LF%: GOSUB pkseek: NEXT
	GOSUB verirep
	GOTO siempre
END IF

pkseek:
IF NeJu% AND RF% = 12 THEN RETURN
CN% = CO%
IF RF% = 5 OR RF% = LE% + 4 OR RF% = LE% + 7 THEN CO% = CO% + 1
GOSUB 8260: GOSUB measT2: GOSUB evalT1: GOSUB sync
log$ = "CO=" + STR$(CO%) + " " + shou + ":" + smin + ":" + ssec
log$ = log$ + " T2=" + STR$(INT(T2av * 100) / 100) + " T1=" + STR$(PC): GOSUB recd
CO% = CN%: GOTO hotPM: RETURN

pkseekOH:
ID = 4: SP = S(ID):  Z% = 0
GOSUB sample: Fd = E(4, 0)
GOSUB pkseek
RETURN

T1:
CJ = -32768: cto% = CJ: OUT &H21, 3 'disable keyboard and timer tick
IF (INP(adi4) AND bitT1) <> 0 THEN
	WHILE (INP(adi4) AND bitT1) <> 0
	cto% = cto% + 1: IF cto% > 32766 THEN GOTO emerg1
	WEND
	crit% = 0: GOSUB cou1: CR = CJ: CJ = -32768: crit% = bitT1: GOSUB cou1
ELSE
	WHILE (INP(adi4) AND bitT1) = 0
	cto% = cto% + 1: IF cto% > 32766 THEN GOTO emerg1
	WEND
	crit% = bitT1: GOSUB cou1: CR = CJ: CJ = -32768: crit% = 0: GOSUB cou1
	SWAP CR, CJ
END IF
OUT &H21, 0 'enable all IRQ's
IF (erc% AND 16) = 16 THEN erc% = erc% - 16
RETURN

T2:
CJ = -32768: cto% = CJ: ju = 0: OUT &H21, 3 'disable keyboard and timer tick
IF (INP(adi4) AND bitT2) <> 0 THEN
	WHILE (INP(adi4) AND bitT2) <> 0
	cto% = cto% + 1: IF cto% > 32766 THEN GOTO emerg2
	WEND
	crit% = 0: GOSUB cou2: CR = CJ: CJ = -32768: crit% = bitT2: GOSUB cou2
ELSE
	WHILE (INP(adi4) AND bitT2) = 0
	cto% = cto% + 1: IF cto% > 32766 THEN GOTO emerg2
	WEND
	crit% = bitT2: GOSUB cou2: CR = CJ: CJ = -32768: crit% = 0: GOSUB cou2
	SWAP CR, CJ: ju = 1
END IF
OUT &H21, 0 'enable all IRQ's
IF (erc% AND 32) = 32 THEN erc% = erc% - 32
RETURN

cou1:
WHILE (INP(adi4) AND bitT1) = crit%
	CJ = CJ + 1: IF CJ > 32766 THEN GOTO emerg2
WEND: RETURN

cou2:
WHILE (INP(adi4) AND bitT2) = crit%
	CJ = CJ + 1: IF CJ > 32766 THEN GOTO emerg2
WEND: RETURN

emerg1: erc% = erc% OR 16: CJ = 30000: CR = -28000: GOTO emerg
emerg2: erc% = erc% OR 32: CJ = -5000: CR = -15000
emerg:
OUT &H21, 0: GOSUB HVoff: hot% = 1: GOSUB obtoff: SOUND 2000, 10
RETURN

stcnt: sal1% = sal1% OR cstart: GOTO OUT1  'start count

rstcnt:
sal1% = sal1% AND rst: GOSUB OUT1 'reset
LOCATE 3, 1
erc% = erc% XOR (erc% AND 15) 'delete counter error flags
IF (INP(adi4) AND rdy) <> 0 THEN PRINT "NO ready signal": erc% = erc% OR 1
x% = INP(adi1): IF x% <> 0 THEN PRINT "NO reset in 1st counter"; x%: erc% = erc% OR 2
x% = INP(adi2): IF x% <> 0 THEN PRINT "NO reset in 2nd counter"; x%: erc% = erc% OR 4
x% = INP(adi3) AND 7
IF x% <> 0 THEN PRINT "NO reset in 3rd counter"; x%: erc% = erc% OR 8
' aqui hay que salir, marcando el tipo de error
IF (erc% AND 15) > 0 THEN
	SOUND 2500, 10: t0 = TIMER
	IF t0 > 86394 THEN t0 = t0 - 86400
	WHILE TIMER - t0 < 5: WEND
END IF
RETURN

OUT1: sal1% = (sal1% AND &HF8) OR CO%: OUT ado1, sal1%: GOSUB status
IF al$ <> "" THEN
	log$ = log$ + TIME$ + al$: GOSUB recd
	al$ = ""
END IF
RETURN

OUT2: OUT ado2, sal2%: RETURN

HVdel:
GOSUB sync
WHILE TIMER < tHV + 30
	IF TIMER < tHV THEN tHV = tHV - 86399     'midnight correction
WEND
HVEN:
IF (sal1% AND obtoff) <> obtoff THEN
	SOUND 700, 10: log$ = log$ + " attempt to HVEN with shutter enabled"
	GOSUB recd: RETURN
END IF
IF PC > -20 THEN
	SOUND 4000, 2
	log$ = log$ + " attempt to HVEN with T1=" + STR$(PC) + ">-20"
	GOSUB recd: RETURN
END IF
IF TT > -20 THEN TT = Tsw
sal1% = sal1% OR HVEN: GOSUB rstcnt
sal1% = (sal1% AND &HF8) OR cstart: OUT ado1, sal1%
'       note implicit CO=0 !
DO
	IF (INP(adi3) AND ovfl) = ovfl THEN
		GOSUB HVoff: HVovf% = 1: SOUND 1300, 1
		log$ = log$ + " HVEN aborted because of overflow"
		GOSUB recd: RETURN
	END IF
LOOP WHILE (INP(adi4) AND rdy) = 0
HVovf% = 0
GOSUB 720
IF ZA > 200 THEN
	GOSUB HVoff: hidark% = 1: SOUND 4300, 5
	thid = TIMER
	log$ = log$ + " dark count too high (ZA=" + STR$(ZA) + ")...HVEN aborted."
	GOSUB recd: RETURN
END IF
hidark% = 0: log$ = log$ + TIME$ + " HV EN": GOSUB recd
RETURN

HVoff:
IF (sal1% AND HVEN) <> HVEN THEN RETURN
tHV = TIMER
al$ = " HV off"
sal1% = sal1% AND HVoff: GOTO OUT1
obtoff:
IF (sal1% AND obtoff) = obtoff THEN RETURN
tobt = TIMER
al$ = " shutter off"
sal1% = sal1% OR obtoff: GOTO OUT1

obtdel:
IF (sal1% AND obtoff) <> obtoff THEN RETURN
GOSUB sync
WHILE TIMER < tobt + 20
	IF TIMER < tobt THEN tobt = tobt - 86399     'midnight correction
WEND
obtEN:
IF (sal1% AND obtoff) <> obtoff THEN RETURN
al$ = " shutter EN"
sal1% = sal1% AND obtEN: GOTO OUT1

fchg:
tx = TIMER: sal1% = sal1% AND fchg: GOSUB OUT1
del& = 500 * lpms: GOSUB delay
sal1% = sal1% OR nofchg: GOSUB OUT1: GOSUB chkflt
LOCATE 24, 49: PRINT F$; filt%;
PRINT USING "###.##"; TIMER - tx;
RETURN

MPP:
IF MT% = -1 THEN PS% = PS% + NO%: GOTO exMPP'shortcut if motor off
IF NO% > 0 THEN
	sal1% = sal1% OR 32: IF PS% + NO% > LX% THEN NO% = LX% - PS%
	lim% = 2       'select limit switch
ELSE
	sal1% = sal1% AND 223: IF PS% + NO% < LN% THEN NO% = LN% - PS%
	lim% = 4       'select limit switch
END IF
PS% = PS% + NO%    'expected final position
OUT ado1, sal1%: OUT &H21, 3   'direct access to ado1 saves time
del& = del1&: GOSUB delay: mppcnt% = ABS(NO%)
nxtstp:
IF mppcnt% = 0 THEN GOTO exMPP
IF (INP(adi4) AND lim%) <> 0 GOTO salMPP
OUT adostp, 0: mppcnt% = mppcnt% - 1: GOSUB delay
del& = del2&
GOTO nxtstp
salMPP:
PS% = PS% - SGN(NO%) * mppcnt%
exMPP:
OUT &H21, 0: IF in$ = "" THEN in$ = INKEY$
IF in$ = CHR$(27) THEN
	in$ = ""
	log$ = log$ + "ESCAPE from exMPP " + DATE$ + " " + TIME$
	GOSUB recd
	STOP
END IF
IF UCASE$(in$) = "C" THEN in$ = "": GOSUB CMT
in$ = ""
RETURN

range:
GOSUB 90
IF MT% = 0 THEN
  log$ = log$ + "MT%=0 after gosub 90"
  GOTO emergexit
END IF
IF MT% = -1 THEN RETURN
log$ = LI$(lim%) + " " + L$ + "=" + STR$(PF%) + "; "
NO% = -5100: GOSUB MPP: LOCATE 2, 1: PRINT "range="; PF% - PS%;
log$ = log$ + LI$(lim%) + " " + L$ + "=" + STR$(PS%) + "; "
log$ = log$ + "free scan range=" + STR$(PF% - PS%) + " steps "
PRINT "limits: "; PS%; PF%
GOSUB verirep
RETURN

inicl:
reg% = &HA
DO
	GOSUB rdcmos: by0% = by% AND 128
LOOP WHILE by0% = 0    'wait for clock update
WHILE by0% <> 0
	GOSUB rdcmos: by0% = by% AND 128
WEND                   'wait for clock ready to read
RETURN

rdcmos:
OUT &H70, reg%: by% = INP(&H71): RETURN

clock:
GOSUB inicl
reg% = 4: GOSUB retr: hou% = bo%
reg% = 2: GOSUB retr: min% = bo%
reg% = 0: GOSUB retr: sec% = bo%
IF hou% <> hou0% THEN
	hou0% = hou%
	reg% = 7: GOSUB retr: day% = bo%
	IF day% <> day0% THEN
		reg% = 8: GOSUB retr: mon% = bo%
		reg% = 9: GOSUB retr: yea% = bo%
		reg% = &H32: GOSUB retr
		IF yea% < 80 THEN IF bo% <> 20 THEN bo% = 20
		yea% = bo% * 100 + yea%
	END IF
END IF
RETURN

retr:
GOSUB rdcmos
IF by% < 10 THEN bo% = by% ELSE bo% = 10 * (by% \ 16) + (by% AND 15)
RETURN

sync:
GOSUB clock
tic& = (3600! * hou% + 60! * min% + sec%) * ticfr
DEF SEG = VARSEG(tic&): hi% = PEEK(VARPTR(tic&) + 2)
mi0% = PEEK(VARPTR(tic&) + 1): r0% = PEEK(VARPTR(tic&))
OUT &H21, 3
DEF SEG = 0: POKE &H46E, hi%: POKE &H46D, mi0%: POKE &H46C, r0%
OUT &H21, 0
Z(2) = sec%
IF sec% > 9 THEN ssec = LTRIM$(STR$(sec%)) ELSE ssec = "0" + LTRIM$(STR$(sec%))
Z(3) = min%
IF min% > 9 THEN smin = LTRIM$(STR$(min%)) ELSE smin = "0" + LTRIM$(STR$(min%))
Z(4) = hou%
IF hou% > 9 THEN shou = LTRIM$(STR$(hou%)) ELSE shou = "0" + LTRIM$(STR$(hou%))
Z(1) = 0: scsc = "00"
IF day% <> day0% THEN
	day0% = day%
	Z(6) = day%
	IF day% > 9 THEN sday = LTRIM$(STR$(day%)) ELSE sday = "0" + LTRIM$(STR$(day%))
	Z(7) = mon%
	IF mon% > 9 THEN smon = LTRIM$(STR$(mon%)) ELSE smon = "0" + LTRIM$(STR$(mon%))
	Z(8) = yea%: yea$ = LTRIM$(STR$(yea%))
	GOSUB julian
	Z(5) = ((jd& + 1) MOD 7) + 1
	DATE$ = smon + "-" + sday + "-" + yea$
	dat$ = sday + "." + smon + "." + yea$ + "(" + dow$(Z(5)) + ")"
	log$ = log$ + " " + dat$
END IF
RETURN

julian:
jd& = 367& * yea% - INT(7 * (yea% + INT((mon% + 9) / 12)) / 4) + INT(275 * mon% / 9) + day% + 1721014
RETURN

csec:
OUT &H21, 3
DEF SEG = 0: r1% = PEEK(&H46C): mi1% = PEEK(&H46D): hi1% = PEEK(&H46E)
OUT &H21, 0
w1& = r1%: DEF SEG = VARSEG(w1&)
POKE VARPTR(w1&) + 1, mi1%: POKE VARPTR(w1&) + 2, hi1%
rr& = w1& - tic&
IF rr& < 0 THEN rr& = rr& + tpd
cs% = rr& * cspt
IF cs% >= 100 THEN
	sec% = sec% + cs% \ 100: cs% = cs% MOD 100
	IF sec% > 59 THEN
		min% = min% + sec% \ 60: sec% = sec% MOD 60
		IF min% > 59 THEN
			hou% = hou% + min% \ 60: min% = min% MOD 60
			IF hou% > 23 THEN
				hou% = 0         'new day
			END IF
			Z(4) = hou%
			IF hou% > 9 THEN shou = LTRIM$(STR$(hou%)) ELSE shou = "0" + LTRIM$(STR$(hou%))
		END IF
		Z(3) = min%
		IF min% > 9 THEN smin = LTRIM$(STR$(min%)) ELSE smin = "0" + LTRIM$(STR$(min%))
	END IF
	Z(2) = sec%
	IF sec% > 9 THEN ssec = LTRIM$(STR$(sec%)) ELSE ssec = "0" + LTRIM$(STR$(sec%))
END IF
IF cs% > 9 THEN scsc = LTRIM$(STR$(cs%)) ELSE scsc = "0" + LTRIM$(STR$(cs%))
Z(1) = cs%
RETURN

status:
IF (sal1% AND 7) <> stCO% THEN
	stCO% = sal1% AND 7: LOCATE 24, 1: PRINT "CO="; stCO%;
END IF
IF (sal1% AND HVEN) <> stHV% THEN
	stHV% = sal1% AND HVEN: LOCATE 24, 8: PRINT "HV ";
	IF stHV% <> 0 THEN PRINT "enabled";  ELSE PRINT "OFF    ";
END IF
IF (sal1% AND obtoff) <> stobt% THEN
	stobt% = sal1% AND obtoff:  LOCATE 24, 20: PRINT "shutter ";
	IF stobt% = obtoff THEN PRINT "closed ";  ELSE PRINT "enabled";
END IF
LOCATE 24, 49: PRINT TIME$; " "; : RETURN

spec:
op% = 4: LE% = 100: GOTO normin

norm:
op% = 1: LE% = 7: GOTO normin

CMT: SOUND 500, 5: LOCATE 1, 1
Q$ = "": PRINT CHR$(219); : tget = TIMER
getch:
a$ = INKEY$
IF a$ <> CHR$(13) THEN
	IF a$ <> "" THEN
		tget = TIMER
		IF a$ = CHR$(8) THEN
			Q$ = LEFT$(Q$, LEN(Q$) - 1)
			LOCATE , POS(1) - 1
		ELSE
			PRINT a$; : Q$ = Q$ + a$
		END IF
	END IF
	IF TIMER - tget < 30 THEN GOTO getch
END IF
log$ = log$ + TIME$ + " - " + Q$: LOCATE 1, 1: PRINT SPACE$(160);
GOTO recd

delay:
sec% = -1  'impossible sec% avoids EXIT
caldel:
FOR K& = 1 TO del&
	OUT &H70, 0: IF sec% = INP(&H71) THEN EXIT FOR
NEXT K&
RETURN

recd:
IF (INP(prp%) AND 120) = prdy THEN LPRINT log$
IF recd% = 0 THEN
	OPEN flog$ FOR APPEND AS #4
	IF LOF(4) > 20000 THEN
		CLOSE #4
		GOSUB sync
		NAME flog$ AS lgd$ + "m" + RIGHT$(yea$, 2) + smon + sday + ".log"
	ELSE
		CLOSE #4
	END IF
	recd% = -1
END IF
OPEN flog$ FOR APPEND AS #4: PRINT #4, log$: CLOSE #4
log$ = ""
RETURN

monoc:
CO% = 0: ZAMIN = 150
	S(1) = 20
	FOR i = 2 TO LE%
		NON% = 100 - INT(S(i - 1) * .0165): S(i) = S(i - 1) + NON%
	NEXT
nextin: INPUT "center position"; po0%
IF po0% < 0 OR po0% > PF% THEN GOTO nextin
IF po0% <> 0 THEN
	log$ = log$ + "center pos:" + STR$(po0%): GOSUB recd
	FOR i = 1 TO LE%
		IF S(i) > po0% THEN ID = i - 1: GOTO max
	NEXT i
	ID = LE% - 1
	GOTO max
END IF
FOR ID = LE% TO 1 STEP -1
	SP = S(ID): GOSUB sample
	IF ZA > ZAMIN THEN
		IF ZA < ZA0 THEN GOTO max ELSE ZA0 = ZA
	END IF
NEXT
GOSUB obtoff
GOTO monit

max:
ID = ID + 1
ILOC = 12: IF ID > ILOC THEN B1 = S(ID - ILOC) ELSE B1 = S(1)
ILOC = 5: IF ID > ILOC THEN B2 = S(ID - ILOC) ELSE B2 = S(1)
ILOC = -5: IF ID < LE% + ILOC THEN B3 = S(ID - ILOC) ELSE B3 = S(LE%)
ILOC = -15: IF ID < LE% + ILOC THEN B4 = S(ID - ILOC) ELSE B4 = S(LE%)
pas = (B2 - B1) / (10 - 1): S(1) = B1
IF pas > 0 THEN
	FOR i = 2 TO 10: S(i) = S(i - 1) + pas: NEXT i
	ini = 11
ELSE
	ini = 2
END IF
IF B4 > B3 THEN
	pas = (B3 - B2) / (91 - ini)
	FOR i = ini TO 90: S(i) = S(i - 1) + pas: NEXT i
	pas = (B4 - B3) / 10: FOR i = 91 TO 100: S(i) = S(i - 1) + pas: NEXT i
ELSE
	pas = (B3 - B2) / 90: FOR i = ini TO 100: S(i) = S(i - 1) + pas: NEXT i
END IF
CO% = CV%
GOTO 2600

90  MT% = 0: PR% = INP(adi4) AND bolim
IF PR% = bolim THEN
	MT% = -1: LOCATE 23, 1: PRINT "BOTH "; L$; "S!"; : GOTO 120
END IF
IF PR% = uplim THEN GOTO 115
100 PS% = 10: NO% = LX%: GOSUB MPP: PS% = PF%
IF (INP(adi4) AND uplim) <> uplim THEN MT% = -1
GOTO 120
115 PS% = LX%: NO% = -40: GOSUB MPP
IF (INP(adi4) AND uplim) <> uplim THEN GOTO 100 ELSE MT% = -1
120  IF MT% = -1 THEN
	LOCATE 24, 37: PRINT "MOTOR OFF";
ELSE
	MT% = 1
	LOCATE 24, 37: PRINT "         ";
END IF
RETURN

polyn: P = a(G%(j), j)
FOR i = G%(j) - 1 TO 0 STEP -1: P = P * x + a(i, j): NEXT: RETURN

hotPM: IF hot% = 0 THEN
	IF PC > TT THEN
		sal1% = (sal1% AND HVoff) OR obtoff: hot% = 1
		GOSUB rstcnt: GOSUB stcnt
		tobt = TIMER: tHV = tobt
		IF LI% > 2 THEN GOSUB grablk: LI% = 0
		RETURN monit
	END IF
END IF
RETURN

acqT1: GOSUB T1: R = factT1 * (CR + 65536! + CJ) / (CR + 32768!)
IF R <= 314 THEN PRINT "T1 GLITCH": SOUND 1800, 10: RETURN
V(L%) = R: L% = L% + 1: IF L% > V% THEN L% = 0
RETURN

evalT1:
KL% = 0: KH% = 0: LO = V(0): hig = LO
FOR K% = 1 TO V%
	IF V(K%) < LO THEN LO = V(K%): KL% = K%
	IF V(K%) > hig THEN hig = V(K%): KH% = K%
NEXT
IF LO = hig THEN RM = V(0): GOTO 700
RM = 0: FOR K% = 0 TO V%
	IF K% = KL% THEN GOTO 685
	IF K% <> KH% THEN RM = RM + V(K%)
685  NEXT
RM = RM / (V% - 1)
700 x = LOG(RM - 314): j = 0: GOSUB polyn
P = 1 / P: PC = .01 * INT(100 * (P - 273.16))
LOCATE 24, 60: PRINT USING "###.##"; PC;
RETURN

'counter status:
720 x% = INP(adi3)
phot& = INP(adi1): DEF SEG = VARSEG(phot&)
POKE VARPTR(phot&) + 1, INP(adi2): POKE VARPTR(phot&) + 2, x% AND 3
IF (x% AND ovfl) = ovfl THEN POKE VARPTR(phot&) + 2, 4
ZA = phot&
RETURN

measT2:
GOSUB T2: Y = (CR + 32768!) / (CJ - CR): x = LOG(Y): j = 3: GOSUB polyn
T2 = INT((1 / P - 273.16) * 100) / 100
IF T2av = 999 THEN T2av = T2 ELSE T2av = (2 * T2av + T2) / 3
LOCATE 24, 70: PRINT USING "###.##"; T2av;
RETURN

880 SQ = 0: SM = 0: FOR i = 1 TO EM%: SM = SM + R(i): NEXT
RS = SM / EM%: FOR i = 1 TO EM%: SQ = SQ + (R(i) - RS) ^ 2: NEXT
VR = SQR(SQ / EM% / (EM% - 1)): RETURN

runcnt:
GOSUB rstcnt                         'OUT ado1, 8 OR 128
IF ((INP(adi3) AND 3) <> 0) OR (INP(adi2) <> 0) OR (INP(adi1) <> 0) THEN
	PRINT st$; " NO RESET! "; st$;
	log$ = log$ + " NO RESET! ": GOSUB recd
	GOSUB 720: PRINT ZA
	IF (erc% AND 15) <> 15 THEN
		IF ZA THEN i = i + 1: IF i > 10 THEN RETURN monit ELSE GOTO runcnt
	END IF
END IF
GOSUB stcnt                          'OUT ado1, 24 OR CO% OR 128
IF (INP(adi4) AND rdy) = rdy THEN
	LOCATE 20, 40: PRINT st$; " NO COUNT START "; st$
	log$ = log$ + " NO COUNT START ": GOSUB recd
	IF (erc% AND 15) <> 15 THEN GOTO runcnt
END IF
IF ID = LE% THEN IF Z% = EM% THEN GOTO sync
IF ID = LE% - 1 THEN GOSUB acqT1   'last chance to read T1 w/o fu-ing csec
RETURN

940 R(Z%) = ZA: P(Z%) = PC: Z% = Z% + 1: IF Z% > EM% THEN GOSUB 730: Z% = 1
RETURN

730 MX = R(1): MN = MX: IL = 1: IH = 1
FOR i = 2 TO EM%
	IF MN > R(i) THEN MN = R(i): IL = i
	IF MX < R(i) THEN MX = R(i): IH = i
NEXT
IF IL = IH THEN GOTO 785
SQ = 0: SM = 0: FOR i = 1 TO EM%
	IF i = IH OR i = IL THEN GOTO 775
	SM = SM + R(i): SQ = SQ + R(i) * R(i)
775  NEXT
RS = SM / (EM% - 2): GOTO 790
785 RS = R(1): VR = 0: GOTO 795
790 VR = SQR((SQ - (EM% - 2) * RS * RS) / (EM% - 2) / (EM% - 3))
795 mean% = -1
RETURN

aveE: FOR i = 1 TO EM%: R(i) = E(ID, i): NEXT: GOSUB 880
IF EM% > 5 THEN IF VR > .1 * RS THEN GOSUB 730
E(ID, 0) = RS: E(ID, 1) = VR: RETURN

grablk:
fou$ = sday + smon + RIGHT$(yea$, 2) + shou + "." + smin + LTRIM$(STR$(CO%))
IF LE% < 30 THEN fs% = 56 * LZ% ELSE fs% = 8 * LE%
CLOSE
DEF SEG = VARSEG(D(0)): BSAVE dire$ + "\" + fou$, VARPTR(D(2)), fs%
log$ = "FILE: " + fou$ + "; " + m$(op%)
IF op% = 0 OR op% = 1 THEN log$ = log$ + STR$(D(1)): GOSUB savebin
GOSUB recd
RETURN

chkflt:
Q% = INP(adi4) AND 24
IF Q% = 8 THEN log$ = F$ + " IR1": filt% = 1: filn% = 0
IF Q% = 16 THEN log$ = F$ + " IR2": filt% = 2: filn% = 1
IF Q% = 24 THEN log$ = F$ + " #3": filt% = 3: filn% = 1
IF Q% = 0 THEN
	del& = 300 * lpms: GOSUB delay
	LOCATE 24, 49: PRINT F$; " changing "; : chgfi% = 1: GOTO chkflt
END IF
GOSUB recd
IF chgfi% = 1 THEN LOCATE 24, 49: PRINT B8$; B8$; : chgfi% = -1
RETURN

newsc:
CLS : stCO% = -1: stHV% = -1: stobt% = -1: GOSUB status: LOCATE 1, 1: RETURN

EN:
GOSUB HVdel: GOTO obtdel

chksig:
SP = S(pk%): ID = 8: CN% = CO%: CO% = 4: GOSUB sample: CO% = CN%
sal1% = (sal1% AND &HF8) OR CO%  'if CO% had been modified, sal1 must know!
IF ZA < 3 * dark THEN
	cry$ = "NO SIGNAL! Tapa cerrada????": LOCATE 2, 1: PRINT cry$;
	IF cryf% = 0 THEN log$ = log$ + " " + cry$: GOSUB recd: cryf% = 1
	SOUND 2490, 10: SOUND 165, 20: SOUND 3950, 50
END IF
RETURN

darkcnt:
Z% = 1: GOSUB obtoff: SOUND 1000, 1
CO% = 4: CV% = CO%: DT = 2: DST = 2: GOTO monit2

dark1:
Z% = 1: mean% = 0: GOSUB obtoff: CO% = 4: CV% = CO%: DT = 10: DST = 10
IF monl% <= 0 THEN monl% = 1
GOTO monit2

fin:
IF LI% > 0 THEN GOSUB grablk
GOSUB newsc: LOCATE 2, 1: PRINT " T  E  R  M  I  N  O   la  noche !";
monl% = 3: GOSUB dark1  'several turns of dark
frar$ = sday + smon + RIGHT$(yea$, 2) + shou
OPEN "c:\frar.bat" FOR OUTPUT AS #1
PRINT #1, "rar m -rr d:\results\" + frar$ + " " + dire$
PRINT #1, "vopt c:"
CLOSE #1
GOSUB HVoff
NO% = -PS%: GOSUB MPP'parking at normal incidence; 22.9.04
SHELL "c:\rebootb"
'no life after boot!

useT2:
S(RF%) = K(0, 0, filn%) + T2av * K(0, 1, filn%)
FOR i = 1 TO LE%
	IF i <> RF% THEN
		S(i) = K(i, 0, filn%) + K(i, 1, filn%) * (S(RF%) - S0)
	END IF
NEXT
RETURN

initbin:
dia$ = sday
IF hou% <= 15 THEN
	dia$ = LTRIM$(STR$(VAL(sday) - 1))
	IF LEN(dia$) = 1 THEN dia$ = "0" + dia$
END IF
fsci$ = "c:\data.sci\prov\p" + dia$ + smon + RIGHT$(yea$, 2) + ".bin"
IF DIR$(fsci$) <> "" THEN
	CLOSE
	DEF SEG = VARSEG(DD(0, 0)): BLOAD fsci$, 0
	range = DD(4, 0): ilast = DD(5, 0): ix = ilast - 1
	IF DD(1, 0) <> 0 AND DD(2, 0) <> 0 THEN
	   start = DD(1, 0) - INT(DD(1, 0) / 100) * 100
	   IF start > 15 THEN start = start - 24!
	   start = start * 3600 + INT(DD(2, 0) / 100) * 60
	   start = start + DD(2, 0) - INT(DD(2, 0) / 100) * 100
	END IF
ELSE
	DD(1, 0) = hou%: DD(2, 0) = min% * 100! + sec%: ix = 0
	start = hou% * 3600! + min% * 60! + sec%
	IF hou% > 15 THEN start = start - 86400
END IF
RETURN

savebin:
DD(4, 0) = DD(1, ix): DD(5, 0) = ix + 1: CLOSE
DEF SEG = VARSEG(DD(0, 0)): BSAVE fsci$, 0, 24 * (ix + 1)
RETURN

repair:
log$ = log$ + " ERROR IN LINE:" + STR$(ERL) + "  Type:" + STR$(ERR)
IF ERR = 6 THEN log$ = log$ + " " + STR$(r0%) + STR$(r1%)
GOSUB recd
SOUND 167, 10: SOUND 250, 10: SOUND 167, 10
RESUME NEXT

getsun:
OPEN "c:\sundat.txt" FOR INPUT AS #1
	WHILE NOT EOF(1)
		LINE INPUT #1, a$
		IF LEFT$(a$, 5) = LEFT$(DATE$, 5) THEN
			Eve$ = MID$(a$, 12, 8): Morn$ = RIGHT$(a$, 8)
			GOTO thatsit
		END IF
	WEND
thatsit:
CLOSE #1
IF Eve$ = "" THEN
	log$ = log$ + "no Sun data available"
	GOTO emergexit
END IF
hora$ = Eve$: GOSUB conv2sec: Eve = hora
HVtime = Eve - 3600 * 4
'time to switch High Voltage on
hora$ = Morn$: GOSUB conv2sec: Morn = hora
RETURN

conv2sec:
hora = 3600! * VAL(LEFT$(hora$, 2)) + 60! * VAL(MID$(hora$, 4, 2)) + VAL(RIGHT$(hora$, 2))
RETURN

verirep: GOSUB verify: IF VF% = -1 THEN GOTO range
RETURN

set:
GOSUB sync: LOCATE 24, 1
INPUT "input new time (hh:mm:ss) and hit Enter to set"; true$
IF LEN(true$) = 8 THEN
	GOSUB csec: prev$ = shou + ":" + smin + ":" + ssec + "." + scsc
	TIME$ = true$
	log$ = log$ + " old time: " + prev$ + "; new time: " + true$
	GOSUB newsc: GOTO recd
END IF
GOSUB newsc: RETURN

initvar1:
READ LE%
prf%(0) = 7: prf%(1) = 6  'LE% + 6, '5 - 7 for airglow, LE%+1 - LE%+7 for Ne
FOR F% = 0 TO 1
	FOR i = 0 TO LF%: FOR j = 0 TO 1: READ K(i, j, F%): NEXT: NEXT
NEXT F%
'F1
DATA 7,4730.43,2.8084,2031.7,2.1,2265.2,1.92941,2477.5,1.793,3261.3
DATA 1.39855,3652.0,1.25264,4281.7,1.07779,4774.0,1
DATA 983.4,12.347,1167.98,.60316,2439.62,.3895,3345.95,.29692,3712.25
DATA .27253,4090.17,.24882,4523.23,.21045
'N3VST2
DATA  2954.9822, 3.996840
'F2 ojo, se refieren ahora a N3, despues se modificaran a prf%(filn%)
'S1VSN3
DATA -1953.0699, 1.374493
'S2VSN3
DATA -1360.2429, 1.250080
'S3VSN3
DATA  -871.4017, 1.154303
'S4VSN3
DATA  651.9126, 0.898848
'S5VSN3
DATA  1311.6655, 0.808404
'S6VSN3
DATA  2265.4609, 0.694083
'S7VSN3
DATA  2993.5865, 0.612715
'N1VSN3
DATA  -4969.0234, 2.121085
'N2VSN3
DATA  -2349.1557, 1.462325
'N3VSN3
DATA 0,1
'N4VSN3
DATA  1376.8963, 0.800048
'N5VSN3
DATA  1904.5043, 0.735643
'N6VSN3
DATA  2430.3990, 0.675511
'N7VSN3
DATA  2993.5865, 0.612715
'conversion to Reference peak:
F% = 1'for F2
iref = prf%(F%): K(0, 1, F%) = K(0, 1, F%) * K(iref, 1, F%)
K(0, 0, F%) = K(0, 0, F%) * K(iref, 1, F%) + K(iref, 0, F%)
K(0, 0, F%) = 4316.484 '(9.1.06)
K(0, 1, F%) = 2.772851  '(9.1.06)
kq1 = K(iref, 1, F%): kq0 = K(iref, 0, F%)
FOR i = 1 TO LF%
	IF i <> LE% + 1 THEN
		K(i, 1, F%) = K(i, 1, F%) / kq1
		K(i, 0, F%) = K(i, 0, F%) - K(i, 1, F%) * kq0
	ELSE
		iref = LE% + 1: kq1 = K(iref, 1, F%): kq0 = K(iref, 0, F%)
	END IF
NEXT i
READ K(LE% + 1, 0, 1), K(LE% + 1, 1, 1)
'N1VST2.1:
DATA  1298.6928, 8.480846
Umb = 800
C1(0) = 1.07426: C2(0) = -.0235163: K1(0) = .870303: K2(0) = .0578625
C1(1) = 1.01563: C2(1) = .0827399: K1(1) = .885753: K2(1) = .0554719
ICLOH!(0) = 3.067797: ICLO2!(0) = 2.609154
ICLOH!(1) = 2.978852: ICLO2!(1) = 2.655499
ICO2!(0) = 2.631356: ICOH!(0) = 3.067797
ICO2!(1) = 2.732946: ICOH!(1) = 3.319233
CNO2(0) = .8771186: KNO2(0) = 4.237288E-02
CNO2(1) = .9187742: KNO2(1) = 4.215922E-02
CNOH(0) = 1.040678: KNOH(0) = -.2135593
CNOH(1) = 1.161092: KNOH(1) = -.3131992
FOR i = 0 TO 1
	DU1O2(i) = (CNO2(i) - K1(i)) * Umb
	DU2O2(i) = (K2(i) - KNO2(i)) * Umb
	DU1OH(i) = (CNOH(i) - C1(i)) * Umb
	DU2OH(i) = (C2(i) - KNOH(i)) * Umb
NEXT i
RETURN

initvar2:
RESTORE Wi
FOR i = 1 TO LF%: READ W(i): NEXT
Wi:
'old:
DATA 50,50,40,30,15,15,14,25,20,12,10,10,10,10
'new, pero...
'DATA 50,50,40,30,24,18,15,52,40,32,24,18,17,15
FOR j = 0 TO 3: IF j = 1 AND filn% = 1 THEN RESTORE ShaF2
IF j = 3 THEN RESTORE calT2
READ G%(j): FOR i = 0 TO G%(j): READ a(i, j): NEXT: NEXT
DATA 3,7.6377125E-4,5.55366104E-4,-3.76855492E-5,1.98012609E-6
DATA 3,40.1392,229.911,-59.6237,6.64293
DATA 3,20.0144,272.093,-82.4147,9.69917
'Shagaev for F2....
ShaF2:
'SHAGOHF2
DATA 4,38.987,208.4552,-68.7006,12.70881,-.9778372
'SHAGO2F2
DATA 6,13.94857,236.0101,-21.88959,-45.82103,26.40504,-6.000724
DATA .5106456
calT2:
DATA 2,3.297524E-3,4.311662E-4,9.858838E-5
RETURN

emergexit:
LOCATE 12, 1
log$ = log$ + CHR$(13) + CHR$(10) + "Error FATAL !"
PRINT STRING$(80, "-")
PRINT log$
PRINT STRING$(80, "-")
GOSUB recd
GOSUB emerg
END

juego:
leadjm% = 200
IF MT% = 0 THEN GOSUB range
LE% = 7: GOSUB sync: NeJu% = -1: IF log$ <> "" THEN GOSUB recd
IF MT% = -1 THEN log$ = "MOTOR OFF": GOSUB recd
LOCATE 1, 1: PRINT SPACE$(160); : stCO% = -1: stHV% = -1: stobt% = -1
IF S(LE% + 1) = 0 THEN
	GOSUB measT2: S(LE% + 1) = T2av
	FOR i = LE% + 1 TO LF%
		S(i) = K(i, 0, filn%) + S(LE% + 1) * K(i, 1, filn%)
	NEXT i
END IF
pk% = LE% + 6
GOSUB chksig
DO
	RF% = 13: GOSUB backlash
	RF% = 10: GOSUB backlash
LOOP

backlash:
GOSUB pkseek
log$ = "backlash "
IF acp1$ = "*" AND acpt$ = "*" THEN
	log$ = log$ + "= " + STR$(DP - dp1) + " steps"
	LOCATE 16, 30: PRINT "backlash ="; : PRINT USING "#####.#"; DP - dp1;
ELSE
	log$ = log$ + " unknown"
	LOCATE 16, 30: PRINT B8$; B8$; B8$;
END IF
GOSUB recd
GOSUB verirep
RETURN

jm:
NO% = S(RF%) + 4 * W(RF%) + leadjm% - PS%: GOSUB MPP
EM% = 14
FOR Z% = 1 TO EM%
	NO% = -leadjm% + W(RF%): GOSUB MPP
	LOCATE 1, 76: PRINT Z%
	NO% = -W(RF%)
	FOR ID = 8 TO 0 STEP -1: GOSUB 8110: NEXT
	Z% = Z% + 1: NO% = -leadjm%: GOSUB MPP
	NO% = leadjm% - W(RF%): GOSUB MPP
	LOCATE 1, 76: PRINT Z%
	NO% = W(RF%)
	FOR ID = 0 TO 8: GOSUB 8110: NEXT
	IF Z% < EM% THEN NO% = leadjm%: GOSUB MPP
	GOSUB acqT1
NEXT
FOR ID = 0 TO 8: GOSUB aveEimpar: NEXT
GOSUB parab: EM% = 14: GOSUB parlog: GOSUB recd
acp1$ = acpt$: S(RF%) = SRF0
dp1 = DP
FOR ID = 0 TO 8: GOSUB aveEpar: NEXT
GOSUB parab: EM% = 14
RETURN

aveEimpar:
EM% = EM% / 2:
FOR i = 1 TO EM%: R(i) = E(ID, 2 * i - 1): NEXT
GOSUB 880
IF EM% > 5 THEN IF VR > .1 * RS THEN GOSUB 730
E(ID, 0) = RS: E(ID, 1) = VR: EM% = 2 * EM%
RETURN

aveEpar:
EM% = EM% / 2:
FOR i = 1 TO EM%: R(i) = E(ID, 2 * i): NEXT
GOSUB 880
IF EM% > 5 THEN IF VR > .1 * RS THEN GOSUB 730
E(ID, 0) = RS: E(ID, 1) = VR: EM% = 2 * EM%
RETURN

chkdark:
now = TIMER
IF tdark > now THEN tdark = tdark - 86400
IF now >= tdark + 1800 THEN
	obt% = (sal1% AND obtoff) 'shutter status
	IF obt% <> obtoff THEN GOSUB obtoff: del& = 500 * lpms: GOSUB delay
	ID = 8: Z% = 0: CN% = CO%: CO% = 4: GOSUB 8060: CO% = CN%
	sal1% = (sal1% AND &HF8) OR CO%: tdark = now
	dark = ZA: log$ = log$ + " dark=" + STR$(dark): GOSUB recd
	IF obt% <> obtoff THEN GOSUB obtdel
END IF
RETURN

spcfile:
IF ctspc% < mxspc% THEN
	fsc$ = "C:\dat\s" + shou + smin + LTRIM$(STR$(RF%)) + ".dat"
	OPEN fsc$ FOR OUTPUT AS #8
	x = INT(SRF0) - 4 * W(RF%) 'corrected ...INT(SRF0)
	FOR ID = 0 TO 8
		'FOR Z% = 1 TO EM%
			'PRINT #8, x, E(ID, Z%)
	   ' NEXT Z%
	   PRINT #8, x, E(ID, 0), 0
	   PRINT #8, x, par(ID), 1
		x = x + W(RF%)
	NEXT ID
	CLOSE #8
	ctspc% = ctspc% + 1
END IF
RETURN

rpt:
RESTORE
FOR i = 0 TO LF%: S(i) = 0: NEXT i
GOTO entry