DECLARE FUNCTION Temperature! (A%, TempType%)
DECLARE FUNCTION ToCentigrade! (A!)
	DEFINT A-Z
	False = 0
	True = NOT False

'============= MEMORY and PROGRAM INITIALIZATION ============================

	Value(0) = 10
	Value(1) = 10
	Value(2) = ToCentigrade!(60)
	Value(3) = ToCentigrade!(85)

	Dig$(3, 2) = "  Digital In 1: "
	Dig$(3, 0) = "Active (0)   "
	Dig$(3, 1) = "Inactive (1) "
	Dig$(2, 2) = "  Digital In 0: "
	Dig$(2, 0) = "Active (0)   "
	Dig$(2, 1) = "Inactive (1) "
	Dig$(1, 2) = " Digital Out 1: "
	Dig$(1, 0) = "Active (0)   "
	Dig$(1, 1) = "Inactive (1) "
	Dig$(0, 2) = " Digital Out 0: "
	Dig$(0, 0) = "Active (0)   "
	Dig$(0, 1) = "Inactive (1) "

	Tickle$(0) = "³"        ' Alive Indicator
	Tickle$(1) = "/"
	Tickle$(2) = "Ä"
	Tickle$(3) = "\"

	'Cmd$ = UCASE$(LTRIM$(RTRIM$(COMMAND$)))    ' For QBX Environment
	Cmd$ = "&H210"                              ' For QBasic Environment

	IF Cmd$ <> "" THEN
		IOBase = VAL(Cmd$)
	ELSE
		IOBase = &H210          ' Default Address
		END IF

	A = INP(IOBase + 2)             ' Read Current Board Status
	IF (A AND &H10) > 0 THEN FanOn = True
	IF (A AND &H20) = 0 THEN Thermostat = True ELSE Thermostat = False

'============= SCREEN SETUP =================================================
	CLS
	PRINT "Environmental Board Test/Setup Utility                     Version 1.00.02"
	PRINT "Copyright 1996 The parvus Corporaation"
	PRINT
	PRINT "        <T>hermostat      <F>an Toggle     <L>ow Temperature"
	PRINT "        <D>egrees Type    <A>ddress        <H>igh Temperature"
	PRINT "        <Q>uit                             <0> Digital Out #0 Toggle"
	PRINT "                                           <1> Digital Out #1 Toggle"
	PRINT
	LOCATE 20, 35
	PRINT " -Press key indicated in <> for action "
	LOCATE 21, 35
	PRINT " -Toggles alternate between two states "
	LOCATE 22, 35
	PRINT " -Status fields are continuously updated"

	OUT IOBase + 1, &H82                ' Continuous Temp Read

'============= MAIN PROGRAM LOOP ============================================
	DO
	A = INP(IOBase + 1)             ' Read Current Board Status
	IF (A AND &H20) > 0 THEN ThermoSAct = True ELSE ThermoSAct = False
	IF ThermoSAct THEN
		IF (A AND &H10) > 0 THEN L$ = "High Temp. Limit  " ELSE L$ = "Low Temp. Limit   "
	ELSE
		L$ = SPACE$(18)
		END IF
	A = INP(IOBase + 2)
	COLOR 1, 7
	LOCATE 20, 1
	FOR I = 0 TO 3
		IF (A AND 2 ^ I) > 0 THEN B = 1 ELSE B = 0
		PRINT Dig$(I, 2) + Dig$(I, B)
		NEXT
	COLOR 7, 0
	   

		 IF FanOn THEN F$ = "Fans Forced On      " ELSE F$ = "Fans Command Off    "
	IF ThermoSAct THEN S$ = "Thermostat Fans On  " ELSE S$ = "Thermostat Fans Off "
	IF Centigrade THEN D$ = "Degrees: Centigrade " ELSE D$ = "Degrees: Fahrenheit "
	IF Thermostat THEN T$ = "Thermostat Enabled  " ELSE T$ = "Thermostat Disabled "
	   
	COLOR 1, 7
	LOCATE 11, 34
	PRINT " Base Address: " + RIGHT$("000" + HEX$(IOBase), 3);
	PRINT "     " + L$ + "  "
	LOCATE 12, 34: PRINT " " + D$ + "  " + F$
	LOCATE 13, 34: PRINT " " + T$ + "  " + S$
	COLOR 7, 0

	COLOR 1, 7
	LOCATE 11, 1
	PRINT "  Register :  +0  +1  +2  +3 "
	PRINT "     Value :";
	FOR I = 0 TO 3
		A = INP(IOBase + I)
		PRINT "  " + RIGHT$("00" + HEX$(A), 2);
		NEXT
	PRINT " "
	PRINT SPACE$(29)
	GOSUB Tickle
	COLOR 7, 0
	   
	COLOR 1, 7
	LOCATE 15, 1
	FOR I = 0 TO 3
		LOCATE 15 + I, 1
		IF I < 4 THEN
		OUT IOBase + 3, I + &H80                ' Select Analog channel
		PRINT " Analog" + STR$(I) + ": ";
		FOR J = 0 TO 100: NEXT                  ' give a little time for conversion
		PRINT RIGHT$("  " + STR$(INP(IOBase + 3)), 3); " ";
		END IF
	   
		IF Value(I) > 255 THEN Bit9 = 1 ELSE Bit9 = 0
		OUT IOBase + 1, &H0                     ' Hold for multi byte write
		OUT IOBase + 0, Value(I) AND &HFF
		OUT IOBase + 1, (I * 2) + &H80 + Bit9 + Change
		S! = TIMER          ' Only wait so long
		DO
			CmdByte = INP(IOBase + 1)
			CmdAddr = (CmdByte \ 2) AND &H3
			DataByte = INP(IOBase + 0)
			IF CmdAddr = I THEN
				IF (CmdByte AND &H80) > 0 THEN
					LOCATE 15 + I, 20
					PRINT " Command" + STR$(I) + ": " + RIGHT$("00" + HEX$(CmdByte), 2); "  Data" + STR$(I) + ": " + RIGHT$("00" + HEX$(DataByte), 2); " ";
					CmdByteH = CmdByte AND &H1
					LOCATE 15 + I, 50
					SELECT CASE I
						CASE 0
						Value(0) = DataByte
						PRINT " Configuration.......: " + RIGHT$("00" + HEX$(Value(0)), 2) + "  "
						CASE 1
						Value(1) = (CmdByteH * 256 + DataByte) AND &H1FF
						PRINT " Current Temperature.:"; RIGHT$("  " + STR$(Temperature(Value(1), Centigrade)), 3) + CHR$(248) + " ";
						CASE 2
						Value(2) = (CmdByteH * 256 + DataByte) AND &H1FF
						PRINT " Low Temp. Setting...:"; RIGHT$("  " + STR$(Temperature(Value(2), Centigrade)), 3) + CHR$(248) + " ";
						CASE 3
						Value(3) = (CmdByteH * 256 + DataByte) AND &H1FF
						PRINT " High Temp. Setting..:"; RIGHT$("  " + STR$(Temperature(Value(3), Centigrade)), 3) + CHR$(248) + " ";
						END SELECT
					END IF
				EXIT DO
			END IF
			IF ABS(TIMER - S!) > .25 THEN       ' Only wait so long
				IF Value(I) > 255 THEN Bit9 = 1 ELSE Bit9 = 0
				OUT IOBase + 1, &H0                     ' Hold for multi byte write
				OUT IOBase + 0, Value(I) AND &HFF
				OUT IOBase + 1, (I * 2) + &H80 + Bit9 + Change
				END IF
			IF ABS(TIMER - S!) > .5 THEN       ' Only wait so long
				LOCATE 9, 1
				IF NOT BeepOnce THEN BEEP: BeepOnce = True
				PRINT "Environmental board may not be present!,  Try address 210, 218, 220, or 228 "
				EXIT DO
			END IF
		LOOP
		PRINT
		NEXT
	Change = 0                  ' No More Changes
	OUT IOBase + 1, &H82        ' Leave On temperature
	COLOR 7, 0
		   
	K$ = INKEY$
	SELECT CASE UCASE$(K$)
		CASE "0"
		A = INP(IOBase + 2)
		OUT IOBase + 2, A XOR &H1
		CASE "1"
		A = INP(IOBase + 2)
		OUT IOBase + 2, A XOR &H2
		CASE "T"
		A = INP(IOBase + 2)
		IF Thermostat THEN
			OUT IOBase + 2, A OR &H20     'turn off thermostat
			Thermostat = False
		ELSE
			OUT IOBase + 2, A AND &HDF      'turn on thermostat
			Thermostat = True
			END IF
		CASE "H"
		LOCATE 9, 1
		PRINT SPACE$(79);
		COLOR 1, 7
		LOCATE 9, 1
		PRINT SPACE$(40);
		LOCATE 9, 1
		IF Centigrade THEN
			INPUT " High Temperature Limit, Degs C: ", A$
			IF A$ <> "" THEN
			A = CINT(VAL(A$) * 2)
			Value(3) = A AND &H1FF
			END IF
		ELSE
			INPUT " High Temperature Limit, Degs F: ", A$
			IF A$ <> "" THEN
			A = CINT(ToCentigrade(VAL(A$)))
			Value(3) = A AND &H1FF
			END IF
			END IF
		COLOR 7, 0
		LOCATE 9, 1
		PRINT SPACE$(79);
		Change = &H40                   ' Mark for change to memory
		CASE "L"
		LOCATE 9, 1
		PRINT SPACE$(79);
		COLOR 1, 7
		LOCATE 9, 1
		PRINT SPACE$(40);
		LOCATE 9, 1
		IF Centigrade THEN
			INPUT " Low Temperature Limit, Degs C: ", A$
			IF A$ <> "" THEN
			A = CINT(VAL(A$) * 2)
			Value(2) = A AND &H1FF
			END IF
		ELSE
			INPUT " Low Temperature Limit, Degs F: ", A$
			IF A$ <> "" THEN
			A = CINT(ToCentigrade!(VAL(A$)))
			Value(2) = A AND &H1FF
			END IF
			END IF
		COLOR 7, 0
		LOCATE 9, 1
		PRINT SPACE$(79);
		Change = &H40                   ' Mark for change to memory
		CASE "D"
		Centigrade = NOT Centigrade
		CASE "A"
		LOCATE 9, 1
		PRINT SPACE$(79);
		COLOR 1, 7
		LOCATE 9, 1
		PRINT SPACE$(40);
		LOCATE 9, 1
		INPUT " Enter Hex Address: ", A$
		COLOR 7, 0
		LOCATE 9, 1
		PRINT SPACE$(79);
		IF A$ <> "" THEN
			IF VAL("&H" + A$) > &H100 THEN
			IOBase = VAL("&H" + A$)
			OUT IOBase + 1, &H82                ' Continuous Temp Read
			END IF
			END IF
		CASE "F"
		A = INP(IOBase + 2)
		IF FanOn THEN
			OUT IOBase + 2, A AND &HEF        'turn off fans
			FanOn = False
		ELSE
			OUT IOBase + 2, A OR &H10      'turn on fans
			FanOn = True
			END IF
		CASE "Q", CHR$(27)
		EXIT DO
		END SELECT
	LOOP
	CLS
	PRINT "Thanks for considering a parvus Product!"
	END

'============= SUPPORT SUBROUTINES ==========================================
Tickle:
	LOCATE 11, 1
	PRINT Tickle$(Tick)
	Tick = Tick + 1: IF Tick > 3 THEN Tick = 0
	RETURN

FUNCTION Temperature! (A, TempType)
	IF A > 255 THEN
	C! = ((512 - A) * -1) / 2
	ELSE
	C! = A / 2
	END IF
	IF TempType THEN            ' Centigrade
	B! = C!
	ELSE
	B! = (C! * (9 / 5)) + 32
	END IF
	Temperature! = CINT(B!)
END FUNCTION

FUNCTION ToCentigrade! (A!)
	B! = CINT(((A! - 32) * (5 / 9)) * 2)
	ToCentigrade! = B!
END FUNCTION

