'Home control and alarm system using a Metrabyte PDISO-8, ' an 8 channel isolated relay input/output interface PC board. ' ---- With the following revisions ---- ' Autodialer or speaker warning using Aux Alarm on control bit 4. ' Enhanced software testing mode. ' PIR sensors dependent on activation of window/door sensors. ' Four seasons for scheduling lighting control. ' Autoscaling test mode. ' Remote access for screen capture of console menu using SEEMENU.EXE. ' Auto select season. ' 4 sensor temperature monitoring thru game port. ' Optional event logging to printer. ' Individual thermistor calibration. ' PLIX controller for X-10 modules, rev 12, 4-6-95. ' Compile option, shell to LIST for viewing log files, 6-16-95. ' Attic fan (fan9) control via X-10 unit code 9. ' Shortened the time for the autodialer to activate to 45 sec. Radio Shack ' autodialer takes 15 sec to start dial and 15 more before message output. ' Display temperatures upon program startup. ' Attic fan controlled by time, and room temperature if available. ' Revised local and sensor test names, and revised display screen. ' Revised variable names to include underscores. ' RS-232 com1 output to remote display, the unlock sequence and alarm status. ' Compile option, RS-232 com2 or game port temperature input. ' Rearranged text on console display screen. ' Bug fix on cut door wires, now alarms time out for cycling. ' Sensor events recorded and tallied only if door locked or alarming, but ' console menu screen saved for all sensor events. ' Multiple console menu screen saves for all alarmed sensor events. Seemenu revised. ' Remote display includes time and date on a reset. ' Double precision to improve temperature calculatlions. No effect, removed. ' Lights ( F1,F2,F3,F4) can now be tested concurrently, 11-25-96 ' X-10 lights all off at "clear lights", 6-3-97 ' Added another X-10 fan (fan8) control, both fan8 and fan9 controlled by 2nd floor temp, 9-20-97 ' Fixed loss of autotest intermediate temperatures, 11-16-97 ' RS-232 display Welcome message 10 sec after unlock, 11-22-99 ' Lights controlled only when door locked, 11-25-99 ' Aux fluorescent display out com2 duplicates printer output, 12-30-01 ' Bug fix for alarm level 3 to pickup aux output in kitchen, 01-10-02 ' Latest event data from X-10 modules is read, logged and displayed, 01-06-02 ' Bug fix testing fans off-season, so tfan8_on=0, etc. are not valid times, 01-08-02 ' Trying to date stamp RS-232 com2 output and bug fix, 01-10-02 ' Fix bug in get_temp_ini: causing no_ini_flag=1. 04-04-02 ' Major change: Added code to read LM335 voltages with CIO-DAS08/JR A/D channels, ' to get accurate temperature data. 04-09-02 ' Alt-t will toggle screen display for thermister or LM335, 04-09-02 ' Debug of CIO-DAS08 activated when 'simulate I/O" mode is on, 04-09-02 ' Individual calibration for LM335 temperature ic's, 04-19-02 ' Recalc lm335 calibration with HP-48 linear regression, 04-23-02 ' Fixed rd_x10_flag cleared when season changed, 05-01-02 ' When reading x10 line data, temperature sampling interval shortened, 5-20-02 ' Aux fluorescent display includes hr_avg outside LM335 temperature, 10-5-02 ' Aux display now displays most current value from outside LM335, 10-23-02 ' If com2 not available on laptop, com2 ignored, 10-37-02 ' Revised kitchen door message, 6-26-03 ' Added rs232_aux_display2 subroutine to show temp'on computer rm display when temp' log file is written, 2-9-07 'Copyright, (c) Michael Krabach, 1994, 1995, 1996, 1997, 1999, 2001, 2002,2007 'Written in PowerBASIC 3.2 $EVENT OFF rev$="rev 18j " revdate$="02-09-07" '================================================================== 'The I/O output is attached to the interface board as: ' bit 0 living room ' bit 1 kitchen ' bit 2 back room ' bit 3 bedroom ' bit 4 aux alarm, eg. autodialer or speaker warning ' bit 5 bell ' bit 6 horn 1 ' bit 7 horn 2 'The I/O input (sensors) is attached to the interface board as: ' bit 0 kitchen door keylock microswitch ' bit 1 downstairs windows and doors using magnetic reed switches ' bit 2 upstairs windows using magnetic reed switches ' bit 3 upstairs spare room, and bedroom passive PIR sensors ' bit 4 living room passive PIR sensor ' bit 5 dining room passive PIR sensor ' bit 6 kitchen passive PIR sensor ' bit 7 back room passive PIR sensor '================================================================== 'Note any variable dealing with time has been given a prefix t. 'Any variable for temperature monitoring has prefix r. DEFINT a,b,c,d,e,f,h,i,l,n,p,q,s,u,w,x,y 'integer variables DEFSNG o,t,r 'single precision DIM degf(4,4) 'for lm335 temperatures DIM b(4), m(4) 'regress line, counts to ohms at game port DIM rcoefa(4), rcoefb(4), rcoefc(4) 'for Steinhart calibration of thermistors DIM degF1(4), degF2(4), degF3(4), degF4(4) 'for summing temps rd_x10_flag=0 'default does not read x10 line values, alt-x toggle tog_lm335_flag=1 'default reads lm335 ic's, alt-t toggle debug_flag=0 'default not to write to ad_degs.log and ciodas08.log ' compile to = 1 for testing lm335 A/D channels $COM 256 OPEN "COM1:1200,n,8,1,DS,RS,CS,CD" AS #8 LEN=256 'open port1 for I/O ON ERROR RESUME NEXT 'if com2 not available on a laptop OPEN "COM2:1200,n,8,1,DS,RS,CS,CD" AS #9 LEN=256 'open port2 for I/O 'Set up control setpoints for the seasons. GOSUB check_season 'find out what season it is set_season: season$=temp$ 'transfer string SELECT CASE season$ 'User defined setpoints and delay intervals for normal light control. ' Some of these setpoints may be altered by the NEWTIME routine. ' The following setpoints are in 24 hour time (hr.min format). ' Kitchen, backroom, and living room lights are operated twice daily. ' The computer clock needs to be adjusted for Daylight Savings Time. 'Winter setpoint schematic: (EST) '=================================================================== ' 12 hr clock 1 2 3 4 5 6 7 8 9 10 11 12 1am ' 24 hr clock 13 14 15 16 17 18 19 20 21 22 23 24 01 hrs ' normal mode |...|...|...|...|...|...|...|...|...|...|...|...| 'kitchen ?-------------? ?--? 'back rm ?------? ?----------| 'living rm ?------------? ?---| 'bed rm |--? 'clear lights x ' test mode |...|...|...|...|...|...|...|...|...|...|...|...| ' seconds 0 10 20 30 40 50 60 70 80 90 100 110 120 '================================================================== CASE "-Winter-" 'Winter setpoints: tkitch_on=16.00 'kitchen on 4:00 pm tkitch_off=19.30 'kitchen off 7:30 pm tkitch_on2=21.00 'kitchen2 on 9:00 pm tkitch_off2=21.45 'kitchen2 off 9:45 pm tbackrm_on=16.45 'backroom on 4:45 pm tbackrm_off=18.30 'backroom off 6:30 pm tbackrm_on2=20.15 'backroom2 on 8:15 pm tbackrm_off2=23.00 'backroom2 off 11:00 pm tlivrm_on=18.00 'living rm on 6:00 pm tlivrm_off=21.15 'living rm off 9:15 pm tlivrm_on2=22.00 'living rm2 on 10:00 pm time_clear=1.00 'turn off any extraneous lights at 1:00 am tvariation=0.30 'max random variation to setpoint in NEWTIME GOTO cont 'Spring setpoint schematic: (EST) '=================================================================== ' 12 hr clock 1 2 3 4 5 6 7 8 9 10 11 12 1am ' 24 hr clock 13 14 15 16 17 18 19 20 21 22 23 24 01 hrs ' normal mode |...|...|...|...|...|...|...|...|...|...|...|...| 'kitchen ?----------? ?----? 'back rm ?-------? ?-| 'living rm ?------? ?-----| 'bed rm |--? 'clear lights x ' test mode |...|...|...|...|...|...|...|...|...|...|...|...| ' seconds 0 10 20 30 40 50 60 70 80 90 100 110 120 '================================================================== CASE "-Spring-" 'Spring setpoints tkitch_on=17.30 tkitch_off=20.15 tkitch_on2=21.00 tkitch_off2=22.15 tbackrm_on=19.45 tbackrm_off=21.45 tbackrm_on2=22.30 tbackrm_off2=23.00 tlivrm_on=18.45 tlivrm_off=20.30 tlivrm_on2=21.30 time_clear=1.00 tvariation=0.30 GOTO cont 'Summer setpoint schematic: (EDT) '=================================================================== ' 12 hr clock 1 2 3 4 5 6 7 8 9 10 11 12 1am ' 24 hr clock 13 14 15 16 17 18 19 20 21 22 23 24 01 hrs ' normal mode |...|...|...|...|...|...|...|...|...|...|...|...| 'living rm fan |---------| 'attic fan |-------| 'kitchen ?--? ?----? 'back rm ?-----? ?--| 'living rm ?--? ?-| 'bed rm |--? 'clear lights x ' test mode |...|...|...|...|...|...|...|...|...|...|...|...| ' seconds 0 10 20 30 40 50 60 70 80 90 100 110 120 '================================================================== CASE "-Summer-" 'Summer setpoints tkitch_on=20.00 tkitch_off=20.45 tkitch_on2=21.30 tkitch_off2=22.45 tbackrm_on=20.15 tbackrm_off=21.45 tbackrm_on2=22.15 tbackrm_off2=23.00 tlivrm_on=21.15 tlivrm_off=22.00 tlivrm_on2=20.30 time_clear=1.00 tvariation=0.30 tfan8_on=15.00 'livingrm fan time on tfan8_off=17.30 'livingrm fan time off tfan9_on=19.15 'attic fan time on tfan9_off=21.15 'attic fan time off fan_set_point=80 'setpoint temperature to allow fan to turn on GOTO cont 'Fall setpoint schematic: (EDT) '=================================================================== ' 12 hr clock 1 2 3 4 5 6 7 8 9 10 11 12 1am ' 24 hr clock 13 14 15 16 17 18 19 20 21 22 23 24 01 hrs ' normal mode |...|...|...|...|...|...|...|...|...|...|...|...| 'living rm fan |---------| 'attic fan |-------| 'kitchen ?---? ?----? 'back rm ?-----? ?-| 'living rm ?----? ?---| 'bed rm |--? 'clear lights x ' test mode |...|...|...|...|...|...|...|...|...|...|...|...| ' seconds 0 10 20 30 40 50 60 70 80 90 100 110 120 '================================================================== CASE "-Fall-" 'Fall setpoints tkitch_on=19.15 tkitch_off=20.15 tkitch_on2=21.00 tkitch_off2=22.15 tbackrm_on=20.15 tbackrm_off=21.45 tbackrm_on2=22.30 tbackrm_off2=23.00 tlivrm_on=20.00 tlivrm_off=21.15 tlivrm_on2=22.00 time_clear=1.00 tvariation=0.30 tfan8_on=15.00 'livingrm fan time on tfan8_off=17.30 'livingrm fan time off tfan9_on=19.00 'attic fan time on tfan9_off=21.00 'attic fan time off fan_set_point=80 'setpoint temperature to allow fan to turn on cont: 'For all seasons 'User defined delays in seconds referenced to a previous setpoint. tdelay_livrm_off2=10 '2nd living rm off 10 seconds after 2nd back room off tdelay_bedrm_on=8 'bedroom on 8 seconds after 2nd living room off tdelay_bedrm_off=60 'bedroom off (minimum of) 1 minute after light on END SELECT 'User defined alarm delays in seconds for normal operation. twait_bell=5 'delay between event and bell sounding twait_horn1=10 'delay between event and bell and horn sounding twait_horn2=15 'delay between event and all three alarms sounding twait_aux=45 'delay between event and aux alarm (allow pir's to clear) twait_win_bad=60 'delay between event and ignoring window sensors talm_off_delay=300 'delay before shutting off alarms after cleared (5 min) tdown_count_bell=60 'initial starting down-counter for bell repeat sequence ' this number only valid with delay 1 in scan_loop ' note since integer, downcount can only can be <=32000 tread_temp_interval=900 'read house temperatures every 15 minutes, ' to be recorded at 4x interval twin=60 'window of opportunity for setpoint execution '================================================================== 'Test mode setpoints generated from above seasonal setpoints. ' The setpoints are adjusted to seconds from the start of the test. ' This sequence simulates the real control cycles in compressed time. test_kitch_on=INT(makesmall(thrtosec(tkitch_on))) 'kitchen on (F2) test_kitch_off=INT(makesmall(thrtosec(tkitch_off))) 'kitchen off test_kitch_on2=INT(makesmall(thrtosec(tkitch_on2))) 'kitchen on (F2) test_kitch_off2=INT(makesmall(thrtosec(tkitch_off2))) 'kitchen off test_backrm_on=INT(makesmall(thrtosec(tbackrm_on))) 'back room on (F3) test_backrm_off=INT(makesmall(thrtosec(tbackrm_off))) 'back room off test_backrm_on2=INT(makesmall(thrtosec(tbackrm_on2))) 'back room on (F3) test_backrm_off2=INT(makesmall(thrtosec(tbackrm_off2))) 'back room off test_livrm_on=INT(makesmall(thrtosec(tlivrm_on))) 'living rm on (F1) test_livrm_off=INT(makesmall(thrtosec(tlivrm_off))) 'living rm off test_livrm_on2=INT(makesmall(thrtosec(tlivrm_on2))) 'living rm on test_time_clear=INT(makesmall(thrtosec(time_clear)+86400)) 'turn off any lights still on test_variation=INT((tvariation/0.06)+1) 'max random variation to setpoint in NEWTIME test_fan8_on=INT(makesmall(thrtosec(tfan8_on))) 'fan8 on (F4) test_fan8_off=INT(makesmall(thrtosec(tfan8_off))) 'fan8 off test_fan9_on=INT(makesmall(thrtosec(tfan9_on))) 'fan9 on (F4) test_fan9_off=INT(makesmall(thrtosec(tfan9_off))) 'fan9 off 'User defined test delay seconds referenced to a previous setpoint. test_delay_livrm_off2=3 '2nd living rm off 3 sec after 2nd back room off (F1 re F3) test_delay_bedrm_on=3 'bedroom on 3 sec after 2nd living room off (F4 re F1) test_delay_bedrm_off=8 'bedroom off (minimum of) 8 sec after light on (F4 re F4) 'User defined alarm delays in seconds for the test mode. test_wait_bell=5 'delay between event and bell sounding test_wait_horn1=10 'delay between event and bell and horn sounding test_wait_horn2=15 'delay between event and all three alarms sounding test_wait_aux=45 'delay between event and aux alarm test_wait_win_bad=60 'delay between event and ignoring window sensors test_alm_off_delay=10 'delay before shutting off alarms after cleared test_down_count_bell=10 'initial starting down-counter for bell repeat sequence ' this number only valid with delay 1 in scan_loop test_read_temp_interval=7 'read house temperatures every 7 seconds, ' to be recorded at 4x interval test_win=2 'window of opportunity for setpoint execution '================================================================== 'Additional definitions. s$=chr$(10) 'to send line feed to fluorescent display bbase=&h380 'base port address for PDISO-8 I/O card ' note that base &h300 comes up on reboot with bell on! bbase_ad=&h330 'base port address for CIO-DAS08/JR I/O A/D card %AX=1 'Equates for temperature measurments %BX=2 %CX=3 %DX=4 FUNCTION conv2temp! (XX%,i) SHARED PUBLIC SHARED b(), m(), rcoefa(), rcoefb(), rcoefc() ohms=b(i)+m(i)*(XX%) 'for least squares straight line regression ohms2F=(1/(rcoefa(i)+rcoefb(i)*(LOG(ohms))+rcoefc(i)*(LOG(ohms))^3))-459.69 conv2temp!=ohms2F END FUNCTION FUNCTION thrtosec(thrs) 'convert hrs to seconds after midnight thrtosec=INT(thrs)*3600+FRAC(thrs)/0.6*3600 END FUNCTION FUNCTION makesmall(tsecond) 'convert setpoints to interval for test mode makesmall=(tsecond-46800)/360 'starts at 1:00PM END FUNCTION '--------------------------------------------------------------- 'Set up sounds for alarms. PLAY "mb" 'play in background thru buffer bell_sound$= "t240 l64 O4cc.cc.cc.cc." 'a bell sound horn1_sound$="t200 l8 O3gc" 'a horn sound horn2_sound$="t200 l8 O3a-d-" 'another horn sound dial_sound$="t200 l32 O3dgdgdgdg" 'a phone ringing '--------------------------------------------------------------- 'Set up function keys for key trapping. KEY 15, CHR$(&h08, &h02, &h70) 'alt plus !1 KEY KEY 16, CHR$(&h08, &h03, &h70) 'alt plus @2 KEY KEY 17, CHR$(&h08, &h04, &h70) 'alt plus #3 KEY KEY 18, CHR$(&h08, &h05, &h70) 'alt plus $4 KEY KEY 19, CHR$(&h08, &h06, &h70) 'alt plus %5 KEY KEY 20, CHR$(&h08, &h07, &h70) 'alt plus ^6 KEY KEY 21, CHR$(&h08, &h08, &h70) 'alt plus &7 KEY KEY 22, CHR$(&h08, &h09, &h70) 'alt plus *8 KEY KEY 23, CHR$(&h08, &h23, &h70) 'alt plus H key KEY 24, CHR$(&H08, &h0b, &h70) 'alt plus )0 KEY KEY 25, CHR$(&H08, &H24, &H70) 'alt plus J key KEY 26, CHR$(&H08, &H19, &H70) 'alt plus P key KEY 27, CHR$(&H08, &H2D, &H70) 'alt plus X key KEY 28, CHR$(&H08, &H14, &H70) 'alt plus T key KEY 29, CHR$(&H08, &H25, &H70) 'alt plus K key 'limit of useable Keys 30 and 31 reserved for F11 and F12 ON KEY (1) GOSUB test_living 'turn on living room light ON KEY (2) GOSUB test_kitchen 'turn on kitchen light ON KEY (3) GOSUB test_backrm 'turn on back room light ON KEY (4) GOSUB test_bdrm 'turn on bedroom light ON KEY (5) GOSUB test_aux 'turn on aux alarm ON KEY (6) GOSUB test_bell 'turn on bell ON KEY (7) GOSUB test_horn1 'turn on horn 1 ON KEY (8) GOSUB test_horn2 'turn on horn 2 ON KEY (9) GOSUB F9_reset 'turn off all output, and reset flags ON KEY (10) GOSUB shutdown 'exit program ON KEY (11) GOSUB show_log 'show the log file ON KEY (12) GOSUB set_auto_test 'setup auto setpoint test ON KEY (13) GOSUB set_fake_io 'fake I/O test setup ON KEY (14) GOSUB log_lights ON KEY (15) GOSUB bit0_on 'toggle the bit 0 ON KEY (16) GOSUB bit1_on 'etc. ON KEY (17) GOSUB bit2_on ON KEY (18) GOSUB bit3_on ON KEY (19) GOSUB bit4_on ON KEY (20) GOSUB bit5_on ON KEY (21) GOSUB bit6_on ON KEY (22) GOSUB bit7_on ON KEY (23) GOSUB help 'help file ON KEY (24) GOSUB delete_log 'delete the house.log file from menu ON KEY (25) GOSUB help2 'help file ON KEY (26) GOSUB print_events ON KEY (27) GOSUB read_x10 'watch line for x10 events ON KEY (28) GOSUB tog_lm335 'thermister/lm335 screen readings ON KEY (29) GOSUB help3 'help file KEY (1) ON KEY (2) ON KEY (3) ON KEY (4) ON KEY (5) ON KEY (6) ON KEY (7) ON KEY (8) ON KEY (9) ON KEY (10) ON KEY (11) ON KEY (12) ON KEY (13) ON KEY (14) ON KEY (15) ON KEY (16) ON KEY (17) ON KEY (18) ON KEY (19) ON KEY (20) ON KEY (21) ON KEY (22) ON KEY (23) ON KEY (24) ON KEY (25) ON KEY (26) ON KEY (27) ON KEY (28) ON KEY (29) ON '-------------------------------------------------------------------- 'Reset all flags and variables. no_ini_flag=0 'assume that temperature ini data file is available GOSUB get_temp_ini 'get calibration data for temperature measurements 'GOSUB read_rs232 'read temp data from the com1 port, not used GOSUB read_temp 'read temp data from the game port degF1=degF1(q) degF2=degF2(q) degF3=degF3(q) degF4=degF4(q) GOSUB read_lm335 'read temp data from lm335 deg_F1=degf(0,1) deg_F2=degf(0,2) deg_F3=degf(0,3) deg_F4=degf(0,4) CLS 'start with clean screen GOSUB find_plix 'Also is restart point for testing light control. restart: 'reset individual sensor event flags bit_flag1=0 'for sensor on bit1 (bit0 is not a sensor) bit_flag2=0 'for sensor on bit2 bit_flag3=0 'for sensor on bit3 bit_flag4=0 'etc. bit_flag5=0 bit_flag6=0 bit_flag7=0 auto_restart_flag=0 'used to initiate light test only once while in scan_loop talm1a=0 'reset alarm level 1 event start talm1b=0 'reset alarm level 1 event current time talm2a=0 'ditto for alarm level 2 talm2b=0 talm3a=0 'ditto for alarm level 3 talm3b=0 twait=0 'zero time delay to shutoff the alarms tevent=0 'zero common time for all alarm levels for twait test sensor2=255 'set to assume all circuits are closed status$="" 'clear the fluorescent display status2$="" GOSUB rs232_display GOSUB rs232_aux_display 'Set up base light control times for real and test mode. IF auto_test_flag=0 THEN GOSUB tbase ELSE GOSUB test_tbase GOSUB zero 'reset output ports and generate light control times count5=5 'Specific reset to prevent 5 sec delay from causing alarm ' when door is open, while booting computer. 'bug - system alarms when reset with door open cut_flag=0 'door wires are assumed intact GOSUB read_screen 'save a copy of the display screen '================================================================== 'Start of scanning loop $EVENT ON 'start key event checking, during compiling scan_loop: IF alm_level_flag>0 THEN 'slightly faster if before DELAY status$="Alarm Condition. "+tref_time$+" "+tref_date$ GOSUB rs232_display END IF DELAY 1 'timing delay for accurate test timing and cycle_bell 'this also helps prevent bad cursor placement on screen 'Save copy of console display screen to menu.log after a control event. IF oldcount2<>count2 THEN GOSUB read_screen oldcount2=count2 END IF 'Save copy of house temperatures to temp.log periodically. IF loopcount >= temp_interval THEN ' IF tog_lm335_flag=0 THEN 'not used, both thermister and lm335 read, 04-21-02 GOSUB read_temp 'read from game port 'GOSUB read_rs232 'alternate read from external data source, not used ' ELSE GOSUB read_lm335 'read from lm335 board ' END IF loopcount=0 END IF INCR loopcount 'read PLIX for incoming data IF plix_on_flag=1 AND rd_x10_flag=1 THEN GOSUB read_data ELSE GOTO label_2 IF tx_flag=1 THEN 'If new X10 data available, show it. LOCATE 15,5 COLOR 12 PRINT SPC(20) LOCATE 15,5 PRINT hc$;" "; fc$, END IF label_2: IF show_log_flag=1 THEN GOSUB read_log 'show log only at this point in code IF auto_restart_flag=1 THEN GOTO restart 'restart if doing auto test 'Console display screen menu for testing the light and alarm control. COLOR 9 LOCATE 1,5 PRINT "================= HOME CONTROL AND ALARM SYSTEM ==================" COLOR 2 LOCATE 1,73 PRINT rev$ LOCATE 2,73 PRINT revdate$ COLOR 12 LOCATE 1,1 PRINT x10$; 'Display hourly temperature averages on right side of screen. COLOR 7 LOCATE 8,74 PRINT "Hr Avg." IF tog_lm335_flag=0 THEN 'display thermistor temperatures LOCATE 7,74 PRINT "Therm" LOCATE 9,74 PRINT SPC(6); LOCATE 9,74 PRINT degF4;"F"; 'breezeway thermistor LOCATE 10,74 PRINT SPC(6); LOCATE 10,74 PRINT degF3;"F"; '2nd floor thermistor LOCATE 11,74 PRINT SPC(6); LOCATE 11,74 PRINT degF1;"F"; '1st floor thermistor LOCATE 12,74 PRINT SPC(6); LOCATE 12,74 PRINT degF2;"F"; 'basement thermistor ELSE 'display lm335 temperatures LOCATE 7,74 PRINT "LM335" LOCATE 9,74 PRINT SPC(6); LOCATE 9,74 PRINT deg_F1;"F"; 'breezeway lm335 LOCATE 10,74 PRINT SPC(6); LOCATE 10,74 PRINT deg_F2;"F"; '2nd floor lm335 LOCATE 11,74 PRINT SPC(6); LOCATE 11,74 PRINT deg_F3;"F"; '1st floor lm335 LOCATE 12,74 PRINT SPC(6); LOCATE 12,74 PRINT deg_F4;"F"; 'basement lm335 END IF 'Display the menu on left side of screen. LOCATE 15,1 IF rd_x10_flag=1 THEN COLOR 12 PRINT "x10>" ELSE PRINT " " END IF LOCATE 3,5 IF simulate_io_flag=0 THEN COLOR 3 PRINT "-------- TEST MENU ---------" ELSEIF simulate_io_flag=1 THEN COLOR 14 PRINT "-- TEST MENU, FAKE OUTPUT --" LOCATE 2,33 PRINT "A/D debug" END IF COLOR 2 LOCATE 5,5 PRINT "F1 = Test living room light" LOCATE 6,5 PRINT "F2 = Test kitchen light" LOCATE 7,5 PRINT "F3 = Test back room light" LOCATE 8,5 PRINT "F4 = Test bedroom light & fans" LOCATE 9,5 PRINT "F5 = Test aux alarm" LOCATE 10,5 PRINT "F6 = Test bell" LOCATE 11,5 PRINT "F7 = Test horn 1" LOCATE 12,5 PRINT "F8 = Test horn 2" LOCATE 13,5 PRINT "F9 = Clear F1-F8" LOCATE 14,5 PRINT "F10 = Exit program" 'Put more at botton of screen. COLOR 3 'cyan LOCATE 23,29 PRINT "Alt-H,J,K for help" 'When in auto test mode show this at botton of screen. COLOR 13 'magenta IF auto_test_flag=1 THEN LOCATE 21,40 PRINT "Test";count_test;"done" 'display tests completed ELSEIF auto_test_flag=0 THEN LOCATE 21,40 PRINT SPC(14) 'clear test completed LOCATE 22,39 PRINT SPC(24) 'clear temperature line END IF 'Show the cursor key functions at lower right. COLOR 3 LOCATE 20,65 PRINT "--Cursor Pad--" COLOR 10 'light green LOCATE 21,65 PRINT "^"; COLOR 7 PRINT " to view log" COLOR 10 LOCATE 22,65 PRINT "<"; IF auto_test_flag=0 THEN COLOR 7 ELSE COLOR 13 'magenta PRINT " auto test" COLOR 10 LOCATE 23,65 PRINT ">"; IF simulate_io_flag=0 THEN COLOR 7 ELSE COLOR 14 'yellow PRINT " simulate I/O" COLOR 10 LOCATE 24,65 PRINT "v"; IF log_light_flag=0 THEN COLOR 7 ELSE COLOR 10 PRINT " log lights" LOCATE 25,28 IF print_log_flag=1 THEN COLOR 2 ELSE COLOR 0 PRINT "Logging to Printer "; 'When in simulate I/O test mode show following next to house status items. COLOR 14 IF simulate_io_flag=1 THEN LOCATE 4,35 PRINT "Alt" LOCATE 5,36 PRINT "1 = " LOCATE 6,36 PRINT "2 = " LOCATE 7,36 PRINT "3 = " LOCATE 8,36 PRINT "4 = " LOCATE 9,36 PRINT "5 = " LOCATE 10,36 PRINT "6 = " LOCATE 11,36 PRINT "7 = " LOCATE 12,36 PRINT "8 = " ELSEIF simulate_io_flag=0 THEN LOCATE 4,35 PRINT SPC(3) LOCATE 5,36 PRINT SPC(4) LOCATE 6,36 PRINT SPC(4) LOCATE 7,36 PRINT SPC(4) LOCATE 8,36 PRINT SPC(4) LOCATE 9,36 PRINT SPC(4) LOCATE 10,36 PRINT SPC(4) LOCATE 11,36 PRINT SPC(4) LOCATE 12,36 PRINT SPC(4) END IF COLOR 7 '---------------------------------------------- 'Show the random adjustment to the light control. LOCATE 19,5 'required to clean up variable length added values PRINT SPC(25) LOCATE 19,5 'required to clean up variable length added values PRINT "Random time adj. ";added" LOCATE 18,5 PRINT "Daily control events ";count2 COLOR 12 LOCATE 24,2 'display the current time PRINT TIME$;SPC(11); COLOR 2 LOCATE 25,2 PRINT DATE$;" ";season$; COLOR 7 tcheck=TIMER 'the current time check for boolean operations IF auto_test_flag=1 THEN 'display the auto mode time ticks testmark=round(tcheck,0)-round(test_start,0) IF testmark > 160 THEN GOSUB reset_auto_mode 'safety net COLOR 13 LOCATE 24,11 PRINT testmark 'after the time display COLOR 7 END IF '---------------------------------------------- 'Routine to control house lights. IF bit0=0 THEN GOTO label_1 'if the house unlocked, skip light control 'If locking house after light sequencing has begun, no lights on until next set point. 'User must use console (F1, etc.) to activate controlled lights for `lived in' look. 'Only controlled lights will turn off at `tclear'. 'Note there are 2 possible cycles for all items except t4on, t4off, and fans. 'Each setpoint has a window of opportunity to execute control. IF c1onflag=1 AND (tcheck > t1on AND tcheck < (t1on + win)) THEN GOSUB on_living IF c1onflag=1 AND (tcheck > t1on2 AND tcheck < (t1on2 + win)) THEN GOSUB on_living IF c2onflag=1 AND (tcheck > t2on AND tcheck < (t2on + win)) THEN GOSUB on_kitch IF c2onflag=1 AND (tcheck > t2on2 AND tcheck < (t2on2 + win)) THEN GOSUB on_kitch IF c3onflag=1 AND (tcheck > t3on AND tcheck < (t3on + win)) THEN GOSUB on_backrm IF c3onflag=1 AND (tcheck > t3on2 AND tcheck < (t3on2 + win)) THEN GOSUB on_backrm IF c4onflag=1 AND (tcheck > t4on AND tcheck < (t4on + win)) THEN GOSUB on_bdrm IF c1offlag=1 AND (tcheck > t1off AND tcheck < (t1off + win)) THEN GOSUB off_living IF c1offlag=1 AND (tcheck > t1off2 AND tcheck < (t1off2 + win)) THEN GOSUB off_living IF c2offlag=1 AND (tcheck > t2off AND tcheck < (t2off + win)) THEN GOSUB off_kitch IF c2offlag=1 AND (tcheck > t2off2 AND tcheck < (t2off2 + win)) THEN GOSUB off_kitch IF c3offlag=1 AND (tcheck > t3off AND tcheck < (t3off + win)) THEN GOSUB off_backrm IF c3offlag=1 AND (tcheck > t3off2 AND tcheck < (t3off2 + win)) THEN GOSUB off_backrm IF c4offlag=1 AND (tcheck > t4off AND tcheck < (t4off + win)) THEN GOSUB off_bdrm label_1: IF c8onflag=1 AND (tcheck > t8on AND tcheck < (t8on + win)) THEN GOSUB on_fan8 IF c9onflag=1 AND (tcheck > t9on AND tcheck < (t9on + win)) THEN GOSUB on_fan9 IF c8offlag=1 AND (tcheck > t8off AND tcheck < (t8off + win)) THEN GOSUB off_fan8 IF c9offlag=1 AND (tcheck > t9off AND tcheck < (t9off + win)) THEN GOSUB off_fan9 IF clightflag=1 AND (tcheck > tclear AND tcheck < (tclear + win)) THEN GOSUB clear_lights IF clightflag=0 AND (tcheck > (tclear +1.5*win) AND tcheck < (tclear +2*win)) THEN clightflag=1 'reset light flag for next day IF auto_test_flag=1 THEN GOSUB reset_auto_mode END IF '---------------------------------------------------------------- 'Menu header COLOR 3 LOCATE 3,40 IF simulate_io_flag=0 THEN COLOR 3 PRINT "-------- HOUSE STATUS --------- " ELSEIF simulate_io_flag=1 THEN COLOR 14 PRINT "--- HOUSE STATUS, FAKE INPUT ---" END IF COLOR 7 '---------------------------------------------------------------- 'Routines for house sensors. 'read input byte from sensors IF simulate_io_flag=0 THEN sensor=INP(bbase + 1) ELSE sensor=fake_sensor bit0=BIT(sensor,0) bit1=BIT(sensor,1) bit2=BIT(sensor,2) bit3=BIT(sensor,3) bit4=BIT(sensor,4) bit5=BIT(sensor,5) bit6=BIT(sensor,6) bit7=BIT(sensor,7) 'Determine house status message for sensors, whether open or closed. IF bit0=0 THEN GOSUB msg0 ELSE GOSUB msg0a IF bit1=0 THEN GOSUB msg1 ELSE GOSUB msg1a IF bit2=0 THEN GOSUB msg2 ELSE GOSUB msg2a IF bit3=0 THEN GOSUB msg3 ELSE GOSUB msg3a IF bit4=0 THEN GOSUB msg4 ELSE GOSUB msg4a IF bit5=0 THEN GOSUB msg5 ELSE GOSUB msg5a IF bit6=0 THEN GOSUB msg6 ELSE GOSUB msg6a IF bit7=0 THEN GOSUB msg7 ELSE GOSUB msg7a COLOR 7 'restore white from screen messages '--------------------------------------------------- 'When all sensors (excluding keylock) are cleared, reset flags and delay. IF sensor >= 254 THEN alm_level_flag=0 bad_window_flag=0 twait=0 END IF '--------------------------------------------------- 'Determine the status of, and how to handle the kitchen door sensors. IF bit0=1 THEN count5=0 'if kitchen door locked, reset counter 'When door unlocked, wait 5 seconds (scan_loops) before opening door, ' otherwise assume keylock wire and door sensor have been cut at same time. 'Display countdown for 5 seconds after unlocking door, after which it ' is OK to open the kitchen door. 'The serial port com1 output is displayed at kitchen door. 'display_flag sequence is; door locked, flag=0 ' unlocked, wait, flag=1 ' ok to open, flag=2 ' Welcome message, flag=3 COLOR 10 LOCATE 5,69 IF count5=0 THEN PRINT " " 'clear counter in menu status$="WARNING: House alarmed, UNSAFE to enter." IF display_flag=3 THEN GOSUB rs232_display count1=0 'reset sensor event counter when house alarmed END IF display_flag=0 'send output only once to COM port ELSEIF count5>0 AND count5<5 THEN PRINT count5 'show the delay before OK to open door rem status$="WAIT for OK to open the door." status$="WAIT, checking Security Clearance." IF display_flag=0 THEN GOSUB rs232_display display_flag=1 'send output only once to COM port ELSEIF count5=5 THEN PRINT "OK" 'OK to open the door status$="OK to open the door." IF display_flag=1 THEN GOSUB rs232_display display_flag=2 'send output only once to COM port ELSEIF count5=10 THEN PRINT "--" 'display cleared in panel status$="WELCOME to 747 Nate Whipple Hwy" IF display_flag=2 THEN GOSUB rs232_display display_flag=3 'send output only once to COM port END IF COLOR 7 '--------------------------------------------------- 'Determine the alarm level based on the bit setting. 'If door unlocked and have waited 5 seconds, and door wires not cut, ' will skip over alarm routines, but will count 5 more seconds to display ' the welcome message. IF bit0=0 AND count5=10 AND cut_flag=0 THEN GOTO label_4 'If door opened within 4 seconds (scan_loops), get ready for all alarms, ' meanwhile user has 3 sec to close door before alarms. ' But if window sensors timed out, ignore all alarms when opening keylock. ' Note, 1st door violation only clears after normal alarm shutoff delay! ' Any 2nd door violation within this period will setoff all alarms! IF bit0=0 AND bit1=0 AND bad_window_flag=0 AND count5=4 THEN cut_flag=1 INCR count1 'needed because this alarm mode misses 1st event END IF IF bit0=0 THEN INCR count5 'increment door unlock counter IF count5>6 AND cut_flag=0 THEN GOTO label_4 'skip rest of alarm routines after manual door unlocked 5 sec. 'Any open window or door is an alarm level 1. IF (bit1=0 OR bit2=0) THEN alm_level_flag=1 'Any PIR sensor is ignored if activated without alarm level 1. 'Breaking outer sensors and activating inner sensors is an alarm level 2. IF alm_level_flag=1 AND (bit3=0 OR bit4=0 OR bit5=0 OR bit6=0 OR bit7=0) THEN alm_level_flag=2 'If outer sensors inactive, use the inner PIR sensors. IF bad_window_flag=1 AND (bit3=0 OR bit4=0 OR bit5=0 OR bit6=0 OR bit7=0) THEN alm_level_flag=3 'Force alarm level 3 for cut door wires except after bad window timeout, IF cut_flag=1 AND bad_window_flag=0 THEN alm_level_flag=3 IF alm_level_flag=1 THEN GOSUB alm_level1 'just a bell IF alm_level_flag=2 THEN GOSUB alm_level2 'plus horns after delays IF alm_level_flag=3 THEN GOSUB alm_level3 'horns and no delay 'If there is an alarm level active but at least the PIR sensors ' have cleared, set up delay to turn off bell and horns. IF all_clear_flag=0 AND sensor >= 248 THEN twait=TIMER-tevent IF twait > tbasereset THEN GOSUB zero 'after delay reset system ELSEIF all_clear_flag=1 THEN tref=TIMER 'reset the reference time tref_time$=USING$("\ \",TIME$) tref_date$=DATE$ END IF LOCATE 13,65 PRINT SPC(5) 'clear screen space for downcounter IF bad_window_flag=1 THEN 'if window alarm inactive cycle the bell DECR count3 LOCATE 13,65 PRINT count3 'display the countdown for ringing bell IF count3=0 THEN GOSUB cycle_bell 'after specific interval ring bell END IF label_4: '--------------------------------------------------- 'Put alarm information on the screen. GOSUB show_output 'display byte sent to control I/O GOSUB light_stat 'display status of lights IF alm_level_flag=0 AND bit0=1 THEN GOSUB status_ok ELSE GOSUB status_bad COLOR 12 'light red LOCATE 13,40 IF bad_window_flag=1 THEN PRINT "Window sensors inactive. " COLOR 7 LOCATE 13,40 IF bad_window_flag=0 THEN PRINT SPC(25) LOCATE 16,62 PRINT SPC(5) 'clear for next sensor count LOCATE 16,40 PRINT "Alarmed sensor events ";count1 LOCATE 18,40 PRINT "Alarm_level_flag ";alm_level_flag LOCATE 17,40 PRINT "All_clear_flag ";all_clear_flag LOCATE 19,63 PRINT SPC(5) 'clear for next delay number LOCATE 19,40 PRINT "Alarm shutoff delay "; IF tbasereset-ROUND(twait,0)=(0 OR tbasereset) THEN COLOR 7 ELSE COLOR 10 PRINT tbasereset-ROUND(twait,0) 'will be green during countdown COLOR 7 LOCATE 20,18 PRINT SPC(14) 'clean up screen for timer LOCATE 20,5 PRINT "Level 1 timer ";ROUND(talm1a,0);ROUND(talm1b-talm1a,0) LOCATE 21,18 PRINT SPC(14) 'clean up screen for timer LOCATE 21,5 PRINT "Level 2 timer ";ROUND(talm2a,0);ROUND(talm2b-talm2a,0) LOCATE 22,18 PRINT SPC(14) 'clean up screen for timer LOCATE 22,5 PRINT "Level 3 timer ";ROUND(talm3a,0);ROUND(talm3b-talm3a,0) '---------------------------------------------------- 'Determine when sensor status is printed to log files. LOCATE 14,40 'required to clear variable length bin$(sensor) values PRINT SPC(34) LOCATE 14,40 PRINT "Sensor status ";bin$(sensor);" "; bin$(sensor2) IF sensor2 <> sensor THEN GOSUB what_bit 'everytime a sensor changes sensor2=sensor 'save current sensor input for next comparison. '--------------------------------------------------- A$= INKEY$ 'empty keyboard buffer each scan_loop GOTO scan_loop $EVENT OFF '========================================================== ' Subroutines 'Sensor messages for screen output. msg0: COLOR 12 'light red LOCATE 5,40 PRINT "Kitchen Door unlocked. " COLOR 7 RETURN msg0a: COLOR 10 LOCATE 5,40 PRINT "Kitchen Door is locked." COLOR 7 RETURN msg1: IF bit_flag1=0 THEN event1$=TIME$ bit_flag1=1 COLOR 28 LOCATE 6,40 PRINT "Downstairs door/window open at ";event1$ COLOR 7 RETURN msg1a: bit_flag1=0 COLOR 10 LOCATE 6,40 PRINT "Downstairs doors/windows shut. " COLOR 7 RETURN msg2: IF bit_flag2=0 THEN event2$=TIME$ bit_flag2=1 COLOR 28 LOCATE 7,40 PRINT "Upstairs window open at ";event2$ COLOR 7 RETURN msg2a: bit_flag2=0 COLOR 10 LOCATE 7,40 PRINT "Upstairs windows shut. " COLOR 7 RETURN msg3: IF bit_flag3=0 THEN event3$=TIME$ bit_flag3=1 COLOR 28 LOCATE 8,40 PRINT "Motion upstairs at ";event3$ COLOR 7 RETURN msg3a: bit_flag3=0 COLOR 10 LOCATE 8,40 PRINT "Clear upstairs. " COLOR 7 RETURN msg4: IF bit_flag4=0 THEN event4$=TIME$ bit_flag4=1 COLOR 28 LOCATE 9,40 PRINT "Motion in living room at ";event4$ COLOR 7 RETURN msg4a: bit_flag4=0 COLOR 10 LOCATE 9,40 PRINT "Clear in living room. " COLOR 7 RETURN msg5: IF bit_flag5=0 THEN event5$=TIME$ bit_flag5=1 COLOR 28 LOCATE 10,40 PRINT "Motion in dining room at ";event5$ COLOR 7 RETURN msg5a: bit_flag5=0 COLOR 10 LOCATE 10,40 PRINT "Clear in dining room. " COLOR 7 RETURN msg6: IF bit_flag6=0 THEN event6$=TIME$ bit_flag6=1 COLOR 28 LOCATE 11,40 PRINT "Motion in kitchen at ";event6$ COLOR 7 RETURN msg6a: bit_flag6=0 COLOR 10 LOCATE 11,40 PRINT "Clear in kitchen. " COLOR 7 RETURN msg7: IF bit_flag7=0 THEN event7$=TIME$ bit_flag7=1 COLOR 28 LOCATE 12,40 PRINT "Motion in back room at ";event7$ COLOR 7 RETURN msg7a: bit_flag7=0 COLOR 10 LOCATE 12,40 PRINT "Clear in back room. " COLOR 7 RETURN status_bad: COLOR 25 LOCATE 24,21 PRINT " ****** HOUSE UNSECURED ****** " COLOR 7 RETURN status_ok: COLOR 9 LOCATE 24,21 PRINT "--- House Alarmed and Secure ---" COLOR 7 RETURN '------------------------------------------------------------- 'The following outputs are testable by function keys. ' They clear all outputs and turn on only the specific light. ' They do not write to the log file. test_living: 'used for testing only IF simulate_io_flag=1 THEN BIT SET fakeout, 0 ELSE BIT set y, 0 OUT bbase, y GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 5,3 'put mark in front of living room menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=6 'unit code 1 fcode=20 'light on code GOSUB send_to_plix COLOR 12 'light red LOCATE 5,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_kitchen: 'used for testing only IF simulate_io_flag=1 THEN BIT SET fakeout, 1 ELSE BIT set y, 1 OUT bbase, y GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 6,3 'put mark in front of kitchen menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=7 'unit code 2 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 6,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_backrm: 'used for testing only IF simulate_io_flag=1 THEN BIT SET fakeout, 2 ELSE BIT set y, 2 OUT bbase, y GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 7,3 'put mark in front of back room menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=4 'unit code 3 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 7,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_bdrm: 'used for testing only IF simulate_io_flag=1 THEN BIT SET fakeout, 3 ELSE BIT set y, 3 OUT bbase, y GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 8,3 'put mark in front of bed room menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=5 'unit code 4 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 8,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 fan_test_flag=1 'conditional needed when tfan8 and tfan9 is zero off-season 'because zero is recognizes as valid temp not null 'both fan 8 and fan9 are controlled by upstairs temperature, therefore forcing test xdegF3=degF3 'save real upstairs thermistor temperature for attic fan to operate xdeg_F2=deg_F2 'save real upstairs lm335 temperature for attic fan to operate degF3=0 'defeat upstairs thermistor temperature requirement to test fan deg_F2=0 'defeat upstairs lm335 temperature requirement to test fan GOSUB on_fan8 'test the X-10 livingroom fan GOSUB on_fan9 'test the X-10 attic fan degF3=xdegF3 'restore the real upstairs thermistor temperature deg_F2=xdeg_F2 'restore the real upstairs lm335 temperature fan_test_flag=0 RETURN '----------------------------------------------------------------- 'The following test outputs are simultaneously testable. ' They do not write to the log file. test_bell: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 5 ELSE BIT set y, 5 OUT bbase, y IF simulate_io_flag=1 THEN play bell_sound$ GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 10,3 'put mark in front of bell menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=9 'unit code 6 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 10,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_horn1: y=INP(bbase) IF simulate_io_flag=1 THEN BIT set fakeout, 6 ELSE BIT set y, 6 OUT bbase, y IF simulate_io_flag=1 THEN play horn1_sound$ GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 11,3 'put mark in front of bell menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=10 'unit code 7 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 11,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_horn2: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 7 ELSE BIT SET y, 7 OUT bbase, y IF simulate_io_flag=1 THEN play horn2_sound$ GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 12,3 'put mark in front of bell menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=11 'unit code 8 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 12,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN test_aux: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 4 ELSE BIT SET y, 4 OUT bbase, y IF simulate_io_flag=1 THEN play dial_sound$ GOSUB show_output GOSUB light_stat COLOR 14 LOCATE 9,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=8 'unit code 5 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 9,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN '---------------------------------------------------------- 'The following control the lights and write to the logfile. ' Note -- Some do not regenerate the light control setpoints for the ' routines with NEWTIME because it will upset the fixed delay setpoints. ' It can even cause the bedroom light to recycle several times. on_living: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) 'this routine only affects bit0 IF simulate_io_flag=1 THEN BIT SET fakeout, 0 ELSE BIT SET y, 0 OUT bbase, y GOSUB show_output what$="Living room light on." IF log_light_flag=1 THEN GOSUB save_log c1onflag=0 'prevent trying to turn on the light repeatedly c1offlag=1 'allow turning off the light GOSUB light_stat GOSUB new_time 'regenerate all light control setpoints COLOR 14 LOCATE 5,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=6 'unit code 1 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 5,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN off_living: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) 'this routine only affects bit0 IF simulate_io_flag=1 THEN BIT RESET fakeout, 0 ELSE BIT RESET y, 0 OUT bbase, y GOSUB show_output what$="Living room light off." IF log_light_flag=1 THEN GOSUB save_log c1onflag=1 'allow turning on the light c1offlag=0 'prevent trying to turn off the light repeatedly GOSUB light_stat GOSUB new_time 'regenerate all light control setpoints 'setup plix for X-10 unit operation hcode=4 'house code C ucode=6 'unit code 1 fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 5,2 'clear marks in front of test menu PRINT " " RETURN on_kitch: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 1 ELSE BIT SET y, 1 OUT bbase, y GOSUB show_output what$="Kitchen light on." IF log_light_flag=1 THEN GOSUB save_log c2onflag=0 'prevent trying to turn on the light repeatedly c2offlag=1 'allow turning off the light GOSUB light_stat GOSUB new_time 'regenerate all light control setpoints COLOR 14 LOCATE 6,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=7 'unit code 2 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 6,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN off_kitch: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT RESET fakeout, 1 ELSE BIT RESET y, 1 OUT bbase, y GOSUB show_output what$="Kitchen light off." IF log_light_flag=1 THEN GOSUB save_log c2onflag=1 'allow turning on the light c2offlag=0 'prevent trying to turn off the light repeatedly GOSUB light_stat GOSUB new_time 'regenerate all light control setpoints 'setup plix for X-10 unit operation hcode=4 'house code C ucode=7 'unit code 2 fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 6,2 'clear marks in front of test menu PRINT " " RETURN on_backrm: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 2 ELSE BIT SET y, 2 OUT bbase, y GOSUB show_output what$="Backroom light on." IF log_light_flag=1 THEN GOSUB save_log c3onflag=0 'prevent trying to turn on the light repeatedly c3offlag=1 'allow turning off the light GOSUB light_stat GOSUB new_time 'regenerate all light control setpoints COLOR 14 LOCATE 7,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=4 'unit code 3 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 7,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN off_backrm: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT RESET fakeout, 2 ELSE BIT RESET y, 2 OUT bbase, y GOSUB show_output what$="Backroom light off." IF log_light_flag=1 THEN GOSUB save_log c3onflag=1 'allow turning on the light c3offlag=0 'prevent trying to turn off the light repeatedly GOSUB light_stat GOSUB new_time 'setup plix for X-10 unit operation hcode=4 'house code C ucode=4 'unit code 3 fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 7,2 'clear marks in front of test menu PRINT " " RETURN on_bdrm: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 3 ELSE BIT SET y, 3 OUT bbase, y GOSUB show_output what$="Bed room light on." IF log_light_flag=1 THEN GOSUB save_log c4onflag=0 'prevent trying to turn on the light repeatedly c4offlag=1 'allow turning off the light GOSUB light_stat 'GOSUB new_time 'remmed out because not needed COLOR 14 LOCATE 8,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=5 'unit code 4 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 8,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN off_bdrm: INCR count2 'the number of control events LOCATE 18,26 PRINT count2 y=INP(bbase) IF simulate_io_flag=1 THEN BIT RESET fakeout, 3 ELSE BIT RESET y, 3 OUT bbase, y GOSUB show_output what$="Bed room light off." IF log_light_flag=1 THEN GOSUB save_log c4onflag=1 'allow turning on the light c4offlag=0 'prevent trying to turn off the light repeatedly GOSUB light_stat GOSUB new_time 'setup plix for X-10 unit operation hcode=4 'house code C ucode=5 'unit code 4 fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 8,2 'clear marks in front of test menu PRINT " " RETURN '------------------------------------------------------------ 'The following control the alarms and write to the log file. bell: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 5 ELSE BIT SET y, 5 END IF OUT bbase, y IF simulate_io_flag=1 THEN PLAY bell_sound$ END IF GOSUB show_output what$="Bell activated." IF no_bell_flag=0 THEN GOSUB save_log 'write to log file only once no_bell_flag=1 GOSUB light_stat COLOR 14 LOCATE 10,3 'put mark in front of bell menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=9 'unit code 6 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 10,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN plus_horn1: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 5 BIT SET fakeout, 6 ELSE BIT SET y, 5 BIT SET y, 6 END IF OUT bbase, y IF simulate_io_flag=1 THEN PLAY bell_sound$ PLAY horn1_sound$ END IF GOSUB show_output what$="Bell + Horn1 activated." IF no_plus_horn1=0 THEN GOSUB save_log no_plus_horn1=1 GOSUB light_stat COLOR 14 LOCATE 10,3 'put mark in front of test menu PRINT "*" LOCATE 11,3 PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C fcode=20 'light on code ucode=9 'unit code 6 for bell GOSUB send_to_plix ucode=10 'unit code 7 for horn1 GOSUB send_to_plix COLOR 12 'light red IF plix_on_flag=1 THEN LOCATE 10,2 PRINT "x" LOCATE 11,2 PRINT "x" END IF COLOR 7 RETURN plus_horn2: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 5 BIT SET fakeout, 6 BIT SET fakeout, 7 ELSE BIT SET y, 5 BIT SET y, 6 BIT SET y, 7 END IF OUT bbase, y IF simulate_io_flag=1 THEN PLAY bell_sound$ PLAY horn1_sound$ PLAY horn2_sound$ END IF GOSUB show_output what$="Bell + Horn1 + Horn2 activated." IF no_plus_horn2=0 THEN GOSUB save_log no_plus_horn2=1 GOSUB light_stat COLOR 14 LOCATE 10,3 'put mark in front of test menu PRINT "*" LOCATE 11,3 PRINT "*" LOCATE 12,3 PRINT "*" COLOR 7 'setup plix for X-10 unit control hcode=4 'house code C fcode=20 'X-10 on code ucode=9 'unit code 6 for bell GOSUB send_to_plix ucode=10 'unit code 7 for horn1 GOSUB send_to_plix ucode=11 'unit code 8 for horn2 GOSUB send_to_plix COLOR 12 'light red IF plix_on_flag=1 THEN LOCATE 10,2 PRINT "x" LOCATE 11,2 PRINT "x" LOCATE 12,2 PRINT "x" END IF COLOR 7 RETURN aux: y=INP(bbase) IF simulate_io_flag=1 THEN BIT SET fakeout, 4 ELSE BIT SET y, 4 END IF OUT bbase, y IF simulate_io_flag=1 THEN PLAY dial_sound$ END IF GOSUB show_output what$="Aux alarm activated." IF no_aux_flag=0 THEN GOSUB save_log 'write to log file only once no_aux_flag=1 GOSUB light_stat COLOR 14 LOCATE 9,3 'put mark in front of test menu PRINT "*" 'setup plix for X-10 unit control hcode=4 'house code C ucode=8 'unit code 5 fcode=20 'X-10 on code GOSUB send_to_plix COLOR 12 'light red LOCATE 9,2 IF plix_on_flag=1 THEN PRINT "x" COLOR 7 RETURN '----------------------------------------------------------------- 'Misc. routines for system control. shutdown: COLOR 12 'light red LOCATE 23,2 PRINT "Program ended. " LOCATE 25,65 PRINT "(c) M Krabach"; COLOR 7 CLOSE #8 'formal close communication port END RETURN cycle_bell: IF simulate_io_flag=1 THEN y=fakeout BIT SET fakeout, 5 'fake bell ELSE y=INP(bbase) BIT SET y, 5 'turn on bell END IF OUT bbase, y IF simulate_io_flag=1 THEN PLAY bell_sound$ END IF COLOR 14 LOCATE 10,3 'put mark in front of bell menu PRINT "*" COLOR 7 GOSUB show_output what$="Cycle bell." GOSUB save_log GOSUB light_stat 'setup plix for X-10 unit control hcode=4 'house code C fcode=20 'X-10 on code ucode=9 'unit code 6 for bell GOSUB send_to_plix COLOR 12 'light red IF plix_on_flag=1 THEN LOCATE 10,2 PRINT "x" END IF DELAY 3 'allow bell to ring 3 seconds y=INP(bbase) IF simulate_io_flag=1 THEN BIT RESET fakeout, 5 ELSE BIT RESET y, 5 'turn off bell END IF OUT bbase, y 'setup plix for X-10 unit control ucode=9 'unit code 6 for bell fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 10,2 'clear marks in front of bell PRINT " " COLOR 7 GOSUB show_output count3=down_count 'reset down-counter for cycling bell GOSUB light_stat RETURN F9_reset: GOSUB zero GOSUB off_fan8 'only can turn off living rm fan via X-10 signal GOSUB off_fan9 'only can turn off attic fan via X-10 signal count1=0 'reset sensor event counter count2=0 'reset control event counter count5=5 'to prevent bell while using F9 with door open and unlocked cut_flag=0 'keylock and door sensor wires forced intact LOCATE 15,5 PRINT SPC(20) RETURN zero: y=&h0 OUT bbase, y 'reset all control bits fakeout=0 'reset fake sensors all_clear_flag=1 'indicate alarms are all cleared alm_level_flag=0 'reset alarm level twait=0 'prevent negative value on display GOSUB show_output GOSUB blank_stars 'clear control stars on screen count3=down_count 'reset down-counter for cycling bell count5=0 'delay counter before deactivating alarm system via keylock loopcount=0 'reset counter for temp.log q=0 'reset counter for game temperature averaging r=0 'reset counter for lm335 temperature averaging no_bell_flag=0 'reset flags to allow alarms to print to log file once no_plus_horn1=0 no_plus_horn2=0 no_aux_flag=0 GOSUB allow_cycle 'reset toggle flags to enable checking for light control GOSUB new_time 'regenerate all light control setpoints what$="System reset." GOSUB save_log what$="" 'clear string tx_flag=0 'prevent premature tx display reset_time$=USING$("\ \",TIME$) reset_date$=DATE$ status$="System reset. "+reset_time$+" "+reset_date$ GOSUB rs232_display GOSUB light_stat RETURN show_output: 'display what was output to the I/O card. LOCATE 16,5 PRINT SPC(33) LOCATE 16,5 IF simulate_io_flag=0 THEN PRINT "Control byte sent ";bin$(y) ELSEIF simulate_io_flag=1 THEN COLOR 14 PRINT "Control test byte ";bin$(fakeout) COLOR 7 END IF RETURN light_stat: 'display the current status of the I/O card. x=INP(bbase) LOCATE 17,5 PRINT SPC(29) LOCATE 17,5 PRINT "Control status "; IF simulate_io_flag=0 THEN PRINT bin$(x) ELSEIF simulate_io_flag=1 THEN COLOR 14 PRINT "no board I/O" COLOR 7 END IF RETURN '--------------------------------------------------- 'These routines determine when the alarms sequence. alm_level1: IF bad_window_flag=1 THEN RETURN all_clear_flag=0 'indicates there is an alarm condition talm1a=tref 'time this event started talm1b=TIMER 'time into the event IF talm1b-talm1a > tbase6delay THEN GOSUB bell IF talm1b-talm1a > tbase12off THEN bad_window_flag=1 tevent=talm1b 'common event time RETURN alm_level2: all_clear_flag=0 'indicates there is an alarm condition talm2a=tref 'time event started talm2b=TIMER 'time into this event IF talm2b-talm2a > tbase6delay THEN GOSUB bell IF talm2b-talm2a > tbase7delay THEN GOSUB plus_horn1 IF talm2b-talm2a > tbase8delay THEN GOSUB plus_horn2 IF talm2b-talm2a > tbase5delay THEN GOSUB aux tevent=talm2b 'common event time RETURN alm_level3: all_clear_flag=0 'indicates there is an alarm condition talm3a=tref 'time event started talm3b=TIMER 'time into this event 'do not wait, sound bell, horn1 and horn2 GOSUB plus_horn2 IF talm3b-talm3a > tbase5delay AND bit6=0 THEN GOSUB aux 'needs PIR active in kitchen for aux IF talm3b-talm3a > tbase12off THEN bad_window_flag=1 tevent=talm3b 'common event time RETURN '--------------------------------------------------------------- 'Generalize the setpoint control timebases. 'There are 2 cycles for all lights except tbase4on, tbase4off and tbasefanon/off tbase: 'for normal control cycle tbase1on=thrtosec(tlivrm_on) 'living rm on tbase1on2=thrtosec(tlivrm_on2) 'living rm on 2nd time tbase2on=thrtosec(tkitch_on) 'kitchen on tbase2on2=thrtosec(tkitch_on2) 'kitchen on 2nd time tbase3on=thrtosec(tbackrm_on) 'back room on tbase3on2=thrtosec(tbackrm_on2) 'back room on 2nd time tbase4on=tdelay_bedrm_on 'bedroom on after 2nd living rm off tbase8on=thrtosec(tfan8_on) 'livingrm fan on tbase9on=thrtosec(tfan9_on) 'attic fan on tbase1off=thrtosec(tlivrm_off) 'living rm off tbase1off2=tdelay_livrm_off2 '2nd living rm off after 2nd back room off tbase2off=thrtosec(tkitch_off) 'kitchen off tbase2off2=thrtosec(tkitch_off2) 'kitchen off 2nd time tbase3off=thrtosec(tbackrm_off) 'back room off tbase3off2=thrtosec(tbackrm_off2) 'back room off 2nd time tbase4off=tdelay_bedrm_off 'bedroom off after bedroom light on tbase8off=thrtosec(tfan8_off) 'livingrm fan off tbase9off=thrtosec(tfan9_off) 'attic fan off tvar=thrtosec(tvariation) 'max variation of setpoint tbase5delay=twait_aux 'delay between event and aux alarm tbase6delay=twait_bell 'delay between event and bell sounding tbase7delay=twait_horn1 'delay between event and bell and horn sounding tbase8delay=twait_horn2 'delay between event and three alarms sounding tbasereset=talm_off_delay 'delay before reseting system tbase12off=twait_win_bad 'delay between event and ignoring window sensors tclear=thrtosec(time_clear) 'time to turn off all extraneous lights win=twin 'window of opportunity for setpoint execution down_count=tdown_count_bell 'reset down-counter for cycling bell temp_interval=tread_temp_interval 'interval for saving house temperatures RETURN test_tbase: 'for testing control setpoints test_start=TIMER 'all offset from current time tbase1on=test_start+ test_livrm_on 'living rm on tbase1on2=test_start+ test_livrm_on2 'living rm on 2nd time tbase2on=test_start+ test_kitch_on 'kitchen on tbase2on2=test_start+ test_kitch_on2 'kitchen on 2nd time tbase3on=test_start+ test_backrm_on 'back room on tbase3on2=test_start+ test_backrm_on2 'back room on 2nd time tbase4on=test_delay_bedrm_on 'bedroom on after 2nd living rm off tbase8on=test_start+ test_fan8_on 'livingrm fan on tbase9on=test_start+ test_fan9_on 'attic fan on tbase1off=test_start+ test_livrm_off 'living rm off tbase1off2=test_delay_livrm_off2 '2nd living rm off after 2nd back room off tbase2off=test_start+ test_kitch_off 'kitchen off tbase2off2=test_start+ test_kitch_off2 'kitchen off 2nd time tbase3off=test_start+ test_backrm_off 'back room off tbase3off2=test_start+ test_backrm_off2 'back room off 2nd time tbase4off=test_delay_bedrm_off 'bedroom off after bedroom light on tvar=test_variation 'max variation of setpoint tbase8off=test_start+ test_fan8_off 'livingrm fan off tbase9off=test_start+ test_fan9_off 'attic fan off tbase5delay=test_wait_aux 'delay between event and aux alarm tbase6delay=test_wait_bell 'delay between event and bell sounding tbase7delay=test_wait_horn1 'delay between event and bell and horn sounding tbase8delay=test_wait_horn2 'delay between event and three alarms sounding tbasereset=test_alm_off_delay 'delay before reseting system tbase12off=test_wait_win_bad 'delay between event and ignoring window sensors tclear=test_start+ test_time_clear 'time to turn off all extraneous lights win=test_win 'window of opportunity for setpoint execution down_count=test_down_count_bell 'reset down-counter for cycling bell temp_interval=test_read_temp_interval 'interval for saving house temperatures RETURN new_time: RANDOMIZE TIMER 'generate seed for random generator from current time 'Randomize light control setpoint adjustment. ' Note that max random adjustment must be shorter than the nominal ' on/off cycle defined at start of program as user defined variables. added=INT(RND*tvar)+1 'result within 1 to tvar seconds 'Combine to give pseudo random light control setpoint times. ' These are recomputed each time a light is turned on or off ' for each subsequent cycle. This will include the setpoints that are ' based on fixed offsets, eg. t1off2, so watchout when calling new_time. 'The following are independent of prior light cycles. ' These new variables are used to preserve original setpoints. t1on=tbase1on + added 'random living rm on t1on2=tbase1on2 + added 'random living rm on 2nd time t2on=tbase2on + added 'random kitchen on t2on2=tbase2on2 + added 'random kitchen on 2nd time t3on=tbase3on + added 'random back room on t3on2=tbase3on2 + added 'random back room on 2nd time t1off=tbase1off + added 'random living rm off t2off=tbase2off + added 'random kitchen off t2off2=tbase2off2 + added 'random kitchen off 2nd time t3off=tbase3off + added 'random back room off t3off2=tbase3off2 'fixed back room off 2nd time t8on=tbase8on 'fixed livingrm fan on t8off=tbase8off 'fixed livingrm fan off t9on=tbase9on 'fixed attic fan on t9off=tbase9off 'fixed attic fan off ' The following are a fixed sequence, for light control going to bed. t1off2=t3off2 + tbase1off2 '2nd living rm off after 2nd back room off t4on=t1off2 + tbase4on 'bedroom on after 2nd living rm off t4off=t4on + tbase4off +added 'bedroom off after bedroom light on RETURN clear_lights: 'prevent any lights staying on all night y=INP(bbase) BIT RESET y, 0 'turn off bit 0 living rm BIT RESET y, 1 'turn off bit 1 kitchen BIT RESET y, 2 'turn off bit 2 back room BIT RESET y, 3 'turn off bit 3 bedroom OUT bbase, y GOSUB show_output GOSUB light_stat 'Clear X-10 lights hcode=4 'house code C ucode=6 'unit code for living rm fcode=28 'X-10 off code GOSUB send_to_plix hcode=4 'house code C ucode=7 'unit code for kitch fcode=28 'X-10 off code GOSUB send_to_plix hcode=4 'house code C ucode=4 'unit code for back rm fcode=28 'X-10 off code GOSUB send_to_plix hcode=4 'house code C ucode=5 'unit code for bed rm fcode=28 'X-10 off code GOSUB send_to_plix 'Clear X-10 livingrm fan hcode=4 'house code C ucode=11 'unit code 8 for fan fcode=28 'X-10 off code GOSUB send_to_plix 'Clear X-10 attic fan hcode=4 'house code C ucode=14 'unit code 9 for fan fcode=28 'X-10 off code GOSUB send_to_plix LOCATE 5,2 'clear mark in front of living rm menu PRINT " " LOCATE 6,2 'clear mark in front of kitchen menu PRINT " " LOCATE 7,2 'clear marks in front of back room menu PRINT " " LOCATE 8,2 'clear mark in front of bed room menu PRINT " " LOCATE 2,1 'clear fan note from screen PRINT SPC(7) IF log_light_flag=1 THEN 'log the light cycles what$="All lights turned off. " + str$(count2,2)+" cycles" ELSEIF log_light_flag=0 THEN 'do not log the light cycles what$="System OK" END IF clightflag=0 'toggle flag for one operation count2=0 'reset control event counter at end of day GOSUB save_log GOSUB check_season 'check for current season for light control IF temp$ <> season$ THEN GOTO set_season 'change season if different RETURN reset_auto_mode: INCR count_test 'keep track of test runs per pseudo-day GOSUB test_tbase 'reestablish time base for light control GOSUB new_time 'reestablish testable time intervals clightflag=1 'reset toggle flag for one GOSUB clear_lights SOUND 2000,1 RETURN allow_cycle: c1onflag=1 'Control flags enabled to allow toggling on or off each c2onflag=1 ' specific light in conjunction with a specific setpoint. c3onflag=1 c4onflag=1 c8onflag=1 c9onflag=1 c1offlag=1 c2offlag=1 c3offlag=1 c4offlag=1 c8offlag=1 c9offlag=1 clightflag=1 RETURN what_bit: 'only count sensor events when door locked or if alarm exists IF bit0=1 OR alm_level_flag>0 THEN sensor_flag=1 GOSUB read_screen 'save all sensor event conditions to menu.log LOCATE 16,62 PRINT count1 'sensor count bitstat=sensor XOR sensor2 'XOR to determine changed bit bitpattern$=bin$(bitstat) 'give it an alpha pattern LOCATE 15,40 PRINT SPC(27) LOCATE 15,40 PRINT "XOR bit ";bitpattern$ SELECT CASE bitpattern$ CASE "1" IF bit0=1 THEN what$="Kitchen Door locked." ON ERROR RESUME NEXT KILL "menu*.log" END IF IF bit0=0 THEN what$="Kitchen Door UNLOCKED." IF sensor_flag=1 THEN INCR count1 END IF CASE "10" IF bit1=1 THEN what$="Downstairs doors/windows closed." IF bit1=0 THEN what$="Downstairs door/window OPEN." IF sensor_flag=1 THEN INCR count1 END IF CASE "100" IF bit2=1 THEN what$="Upstairs windows closed." IF bit2=0 THEN what$="Upstairs window OPEN." IF sensor_flag=1 THEN INCR count1 END IF CASE "1000" IF bit3=1 THEN what$="Clear upstairs." IF bit3=0 THEN what$="MOTION upstairs." IF sensor_flag=1 THEN INCR count1 END IF CASE "10000" IF bit4=1 THEN what$="Clear in living room." IF bit4=0 THEN what$="MOTION in living room." IF sensor_flag=1 THEN INCR count1 END IF CASE "100000" IF bit5=1 THEN what$="Clear in dining room." IF bit5=0 THEN what$="MOTION in dining room." IF sensor_flag=1 THEN INCR count1 END IF CASE "1000000" IF bit6=1 THEN what$="Clear in kitchen." IF bit6=0 THEN what$="MOTION in kitchen." IF sensor_flag=1 THEN INCR count1 END IF CASE "10000000" IF bit7=1 THEN what$="Clear in back room." IF bit7=0 THEN what$="MOTION in back room." IF sensor_flag=1 THEN INCR count1 END IF END SELECT sensor_flag=0 IF alm_level_flag>0 OR _ 'an alarm condition or bitpattern$ = "1" OR _ 'if keylock status changed or bitpattern$ = "10" OR _ 'downstairs door/window status changed or bitpattern$ = "100" THEN 'or upstairs window status changed GOSUB save_log 'write to log END IF RETURN log_lights: SOUND 1000,1 IF log_light_flag=0 THEN 'do not log the light cycles log_light_flag=1 'log the light cycles ELSEIF log_light_flag=1 THEN log_light_flag=0 END IF RETURN print_events: IF print_log_flag=0 THEN print_log_flag=1 ELSEIF print_log_flag=1 THEN print_log_flag=0 END IF RETURN save_log: 'save to file log and printer log ON ERROR RESUME NEXT 'prevent crash if house.log currently accessed OPEN "house.log" FOR APPEND AS #1 PRINT #1, TIME$;" "; IF print_log_flag=1 THEN LPRINT TIME$;" ";DATE$;" ";what$ IF log_light_flag=1 AND auto_test_flag=1 THEN PRINT #1, "(";testmark;") "; IF log_light_flag=1 THEN PRINT #1, "[";added;"] "; PRINT #1, DATE$;" ";what$ CLOSE #1 status2$=what$ GOSUB rs232_aux_display RETURN show_log: show_log_flag=1 'must do this to keep the cursor consistent RETURN read_log: CLS SHELL "list house.log" 'LIST must be in DOS path cls show_log_flag=0 'clear the show_log flag RETURN 'read_log: 'use this routine if LIST is not in DOS path 'OPEN "house.log" FOR INPUT AS #2 'CLS 'count4=0 'line counter on screen 'LOCATE 1,1 'WHILE NOT EOF(2) 'shows one page at a time ' IF count4=24 THEN GOSUB dopause ' INCR count4 ' INPUT #2, logfile$ ' PRINT logfile$ 'WEND 'CLOSE #2 'GOSUB dopause 'show_log_flag=0 'clear the show_log flag 'RETURN dopause: LOCATE 25,60 COLOR 10 INPUT "ENTER to continue. ",ans$ IF ans$ <> "" THEN GOTO dopause COLOR 7 CLS count4=0 RETURN delete_log: ON ERROR RESUME NEXT KILL "house.log" OPEN "house.log" FOR APPEND AS #1 PRINT #1, TIME$;" ";DATE$;" New alarm log file started." CLOSE #1 ON ERROR RESUME NEXT KILL "temp.log" OPEN "temp.log" FOR APPEND AS #4 WRITE #4, "Ref: basement, 1st floor, 2nd floor, outside." CLOSE #4 ON ERROR RESUME NEXT KILL "menu*.log" RETURN set_auto_test: SOUND 1000,1 IF auto_test_flag=0 THEN 'do not log the light cycles auto_test_flag=1 'log the light cycles ELSEIF auto_test_flag=1 THEN auto_test_flag=0 END IF auto_restart_flag=1 'used to initiate light test once count_test=0 GOSUB blank_stars IF auto_test_flag=1 THEN what$="System in auto test mode. " IF auto_test_flag=0 THEN what$="System out of auto test mode. " GOSUB save_log RETURN blank_stars: LOCATE 5,2 'clear light marks in front of test menu PRINT " " LOCATE 6,2 PRINT " " LOCATE 7,2 'clear x10 indicator and star for back room PRINT " " LOCATE 8,2 PRINT " " LOCATE 9,2 PRINT " " LOCATE 10,2 'clear alarm marks in front of test menu PRINT " " LOCATE 11,2 PRINT " " LOCATE 12,2 PRINT " " LOCATE 2,1 'clear fan note from screen PRINT SPC(7) 'setup plix for X-10 unit control hcode=4 'house code C ucode=1 'unit code 1 fcode=16 'all units off code GOSUB send_to_plix DELAY .2 'needs delay before turning on another X-10 unit. RETURN set_fake_io: 'Note the following dummy port may vary depending on the computer used. '&h3dc; Mike's safe port for testing I/O, control=0 sensor=11111111 '&h3ca; Larry's safe port for testing I/O, control=0 sensor=11111111 ' Use program Testport.exe to show what is available for bbase. SOUND 1000,1 IF simulate_io_flag=0 THEN 'do not log the light cycles bbase=&h3dc 'used as dummy port on Mike's PC simulate_io_flag=1 'log the light cycles ELSEIF simulate_io_flag=1 THEN bbase=&h380 'base port address for PDISO-8 I/O card simulate_io_flag=0 END IF fake_sensor=&hff 'reset sensor bits IF simulate_io_flag=1 THEN what$="System in simulate I/O test mode. " IF simulate_io_flag=0 THEN what$="System out of simulate I/O test mode. " count5=5 'to prevent bell with door open and unlocked GOSUB save_log 'Set up for write to 'ad_degs.log' and 'ciodas08.log' files for lm335 testing IF debug_flag=0 THEN '0 = no write, 1 = write debug_flag=1 COLOR 14 'yellow LOCATE 2,33 PRINT "A/D debug" COLOR 7 OPEN "ciodas08.log" FOR APPEND AS #6 'binary datafile OPEN "ad_degs.log" FOR APPEND AS #7 'a/d channel datafile PRINT #6, TIME$;" ";DATE$ PRINT #6, "" PRINT #6, "A/D chan","msb","lsb","volts","deg F" 'print to ciodas08.log ELSE 'note this flag is a compiled option debug_flag=0 LOCATE 2,33 PRINT SPC(9) CLOSE #6 'close ciodas08.log CLOSE #7 'close ad_degs.log END IF RETURN bit0_on: fake_sensor=fake_sensor XOR &b1 RETURN bit1_on: fake_sensor=fake_sensor XOR &b10 RETURN bit2_on: fake_sensor=fake_sensor XOR &b100 RETURN bit3_on: fake_sensor=fake_sensor XOR &b1000 RETURN bit4_on: fake_sensor=fake_sensor XOR &b10000 RETURN bit5_on: fake_sensor=fake_sensor XOR &b100000 RETURN bit6_on: fake_sensor=fake_sensor XOR &b1000000 RETURN bit7_on: fake_sensor=fake_sensor XOR &b10000000 RETURN check_season: date_now=VAL(MID$(DATE$,1,2)) IF date_now = 1 THEN temp$= "-Winter-" 'Jan. continues Winter (EST) IF date_now > 1 THEN temp$="-Spring-" 'Feb. starts Spring (EST) IF date_now > 4 THEN temp$="-Summer-" 'May starts Summer (EDT) IF date_now > 7 THEN temp$= "-Fall-" 'Aug. starts Fall (EDT) IF date_now > 10 THEN temp$= "-Winter-" 'Nov. starts Winter (EST) RETURN help: CLS SCREEN 0,0,2,2 'active page 2 and show visual page 2 COLOR 10 LOCATE 1,25 PRINT "Cursor Pad Keys: ^ < > v" COLOR 7 PRINT COLOR 10 PRINT "TO VIEW LOG - "; COLOR 7 PRINT "Displays the ascii HOUSE.LOG file that records various events and"_ "control cycles. The log file records data according the operating mode. It"_ "always records the alarm events. Alt-0 will delete and restart the file." PRINT COLOR 10 PRINT "AUTO TEST - "; COLOR 7 PRINT "Used to run an auto test routine that emulates the normal control"_ "cycles in about 120 seconds. The test will continue to repeat. The number"_ "of auto tests completed will be displayed next to the cursor keys."_ "The time ticks during the test are displayed next to the clock in the "_ "screen lower left corner. Also used with the Interface Board to simulate"_ "sensor input to the program to verify alarm responses. To record the"_ "control cycles in HOUSE.LOG, use the Log Lights toggle. The < key "_ "toggles into and out of the test." PRINT COLOR 10 PRINT "SIMULATE I/O TEST - "; COLOR 7 PRINT "If the interface board is not available, this toggle key"_ "will allow operating the sensors with the ALT keys. Can be used in "_ "conjunction with the Auto Test. Actual board I/O operation is defeated." PRINT COLOR 10 PRINT "LOG LIGHTS - "; COLOR 7 PRINT "Normally the log file only records sensor events, resets, etc."_ "When this toggle key is actuated, all the control cycles are logged,"_ "including the random variable added to the control setpoint [xxx]."_ "In Auto Test mode the time ticks are also added to the log (xxx)." PRINT COLOR 10 LOCATE 25,45 PRINT "Any key to return to status screen."; GOSUB waitabit RETURN help2: CLS SCREEN 0,0,3,3 COLOR 10 LOCATE 1,27 PRINT "More Help" PRINT PRINT "MENU.LOG - "; COLOR 7 PRINT "The console menu screen is saved to a displayable MENU?.LOG file"_ "after all control, and all alarmed (i.e. door locked) sensor events. Sequential"_ "MENU?.LOG files are saved for each sensor event while the house is alarmed."_ "This file can be used to quickly view the status of the system, either after the"_ "system is shutdown or concurrently while the alarm system is operating."_ "MENU?.LOG is a binary bitmap viewed with SEEMENU.EXE." PRINT COLOR 10 PRINT "TEMP.LOG - "; COLOR 7 PRINT "Temperature thermistors are measured thru the game port. Hourly "_ "average temperatures are displayed on right side of sceeen. Reading top to"_ "bottom; outside, 2nd floor, 1st floor, basement. The temperatures are saved"_ "hourly in the file TEMP.LOG . In auto test mode, the 4 intermediate"_ "temperature readings used for the average are displayed just under the "_ "'Test X done'. Calibration data is obtained from TEMP.INI which is"_ "generated from CALPORT.EXE. If TEMP.INI is not available, the program does"_ "not read or record temperatures. The accuracy of measuring 100K thermistors"_ "thru the analog game port depends on careful calibration of the thermistors."_ "The existing system has experienced variable long term temperature drift."_ "To correct this problem a CIO-DAS08/Jr A/D card is used to read voltages from"_ "LM335 temperature ic's. These must be initally calibrated to a reference "_ "voltage but are stable enough that the calibration is coded into the program"_ "Note that the reference voltage is the 5 vdc PC bus voltage, and changing "_ "computers requires new calibration for each LM335." PRINT COLOR 10 LOCATE 25,45 PRINT "Any key to return to status screen."; GOSUB waitabit RETURN help3: CLS SCREEN 0,0,4,4 COLOR 10 LOCATE 1,27 PRINT "Even More Help" PRINT COLOR 10 PRINT "CIODAS08.LOG - "; COLOR 7 PRINT "This file records the binary, voltage and calibrated "_ "temperatures as given by the CIO-DAS08/JR A/D conversion card reading LM335"_ "ic temperature sensors. Used for testing purposes and only written to with "_ "the 'Simulate I/O' mode on. Screen will have 'A/D debug' on 2nd screen line." PRINT COLOR 10 PRINT "AD_DEGS.LOG - "; COLOR 7 PRINT "This file records the A/D channel calibrated temperatures each"_ "time the LM335 voltages are read. Used for testing same as ciodas08.log" PRINT COLOR 10 PRINT "USING A PRINTER - "; COLOR 7 PRINT "Alt-P will cause Control and Sensor Events to be sent to a"_ "printer. A printer MUST be attached. Alt-P is a toggle key." PRINT COLOR 10 PRINT "X-10 - "; COLOR 7 PRINT "Alt-x will toggle the line monitoring of X-10 signals. Only house codes,"_ "not unit codes are available for monitoring. Results are saved in the log."_ "Off by default. When on, it lengthens the nominal 1 sec polling time by 40%." PRINT COLOR 10 PRINT "SCREEN TEMPERATURES - "; COLOR 7 PRINT "Alt-t will toggle displaying either temperatures from the"_ "thermistors read by the game port, or from the CIO-DAS08/JR card reading the"_ "LM335 ic's. The affected values are the 'Hr Avg' on the right side of the "_ "screen and the auto test 15 minute values. Both values are always logged"_ "in temp.log." PRINT COLOR 10 LOCATE 25,45 PRINT "Any key to return to status screen."; GOSUB waitabit RETURN waitabit: a$=INKEY$: IF a$="" THEN waitabit SCREEN 0,0,0,0 'restore the main program screen RETURN 'The following will save multiple console displays with all color attributes. ' Use SEEMENU.EXE to view menu?.log. ' This routine is very much faster then the following text version. read_screen: 'see Reference Guide pg 72 DEF SEG = &hb800 'address for color, eg. using VGA BSAVE "menu"+ LTRIM$(STR$(count1))+".log",0,4000 RETURN 'Alternative version to save a single console display menu as text only. ' Use LIST.EXE with screen wrap, or TYPE to view screen.log. 'read_screen: 'see Reference Guide pg 112 'IF auto_test_flag=1 THEN SOUND 3000,0.3 'OPEN "menu.log" FOR OUTPUT AS #3 'DEF SEG = &hb800 'address for color, mono is &hb000 'FOR i=0 TO 4000 STEP 2 'STEP 2 to skip attribute bytes ' y$=PEEK$(i,1) 'at i segment offset, read one byte ' PRINT #3, y$; 'NEXT i 'CLOSE #3 'IF auto_test_flag=1 THEN SOUND 3000,0.3 'RETURN 'Following routine derived from PowerBasic TIPS. 'Thermistor sequence on game port. 'port 1, pins 3-9, 1st floor dining rm 'port 2, pins 6-8, basement 'port 3, pins 11-1, 2nd floor spare rm 'port 4, pins 13-15, outside breezeway 'Note; SOUND functions affect port readings severely. read_temp: IF no_ini_flag=1 THEN RETURN 'if no temp.ini skip reading thermistor temperatures. REG %AX,&h8400 'load 84h in AH REG %DX,&h0001 'load 01h in DL CALL INTERRUPT &h15 AX%=REG(%AX) 'port 1 from 1st floor BX%=REG(%BX) 'port 2 from basement CX%=REG(%CX) 'port 3 from second floor DX%=REG(%DX) 'port 4 from breezeway INCR q 'the sample count 'Some game ports only support one joystick, so test all ports. IF AX%<>0 THEN degF1(q)= conv2temp!(AX%,1) 'read the temperature IF BX%<>0 THEN degF2(q)= conv2temp!(BX%,2) IF CX%<>0 THEN degF3(q)= conv2temp!(CX%,3) IF DX%<>0 THEN degF4(q)= conv2temp!(DX%,4) IF auto_test_flag=1 AND tog_lm335_flag=0 THEN GOSUB show_all_deg 'display house temperatures IF q=4 THEN 'after 4 readings, average the data degF1=(degF1(1)+degF1(2)+degF1(3)+degF1(4))/4 '1st floor degF2=(degF2(1)+degF2(2)+degF2(3)+degF2(4))/4 'basement degF3=(degF3(1)+degF3(2)+degF3(3)+degF3(4))/4 '2nd floor degF4=(degF4(1)+degF4(2)+degF4(3)+degF4(4))/4 'breezeway 'GOSUB save_temp 'now combined with lm335 save_temp q=0 END IF RETURN tog_lm335: 'toggle alt-z to toggle display thermisters or lm335 IF tog_lm335_flag=0 THEN tog_lm335_flag=1 ELSE tog_lm335_flag=0 '0 = thermistor, 1 = lm335 RETURN read_lm335: FOR n = 1 TO 4 'read 4 of 8 A/D channels with LM335 sensors attached OUT bbase_ad+2,n-1 'starting with channel 0, MUX write control byte DELAY 0.05 'small delay needed between writes to converter OUT bbase_ad+1,0 'any write to this address causes A/D conversion scount=0 label_3: statusreg=INP(bbase_ad+2) 'check to see if A/D conversion is done eoc=BIT(statusreg,7) 'check bit 7 for end of conversion INCR scount IF scount=10 GOTO label_5 'prevent hanging if no A/D card IF eoc=1 THEN GOTO label_3 'if eoc=1 A/D is busy, if 0 is done lsb=INP(bbase_ad) 'read lower byte value msb=INP(bbase_ad+1) 'read upper byte value bitpattern$=BIN$(lsb) 'give it an alpha pattern bitpattern2$=BIN$(msb) ad_channel=statusreg AND &b111 'read lower 3 bits to identify A/D channel msb=msb*16 'shift msb to left 0000 bits SHIFT RIGHT lsb, 4 'read left nibble of bbase+1 ad_counts=msb+lsb 'add bytes to get word SELECT CASE ad_channel 'calibrations using 5v regulated supply CASE=0 degf(r,n)=(ad_counts-3087.96)/2.2512 'hp-48 cal for #1 in breezeway CASE=1 degf(r,n)=(ad_counts-3085.326)/2.268 'hp-48 cal for #2 in 2nd floor CASE=2 degf(r,n)=(ad_counts-3090.873)/2.3036 'hp-48 cal for #3 in 1st floor CASE=3 degf(r,n)=(ad_counts-3093.087)/2.2666 'hp-48 cal for #4 in basement CASE ELSE degf(r,n)=(ad_counts-3088.713)/2.2979 'use spare #5 if more channels END SELECT IF debug_flag=1 THEN PRINT #6, ad_channel, bitpattern2$, bitpattern$, ad_counts, degf(r,n) WRITE #7, TIME$,r,degf(r,1),degf(r,2),degf(r,3),degf(r,4) 'write to ad_degs.log END IF NEXT n label_5: IF auto_test_flag=1 AND tog_lm335_flag=1 THEN GOSUB show_all_deg 'display house temperatures degoutside=degf(r,1) 'for aux rs232 display only INCR r 'the sample count IF debug_flag=1 THEN PRINT #6, "" WRITE #7, END IF IF r=4 THEN 'after 4 readings, average the data deg_F1=(degf(0,1)+degf(1,1)+degf(2,1)+degf(3,1))/4 deg_F2=(degf(0,2)+degf(1,2)+degf(2,2)+degf(3,2))/4 deg_F3=(degf(0,3)+degf(1,3)+degf(2,3)+degf(3,3))/4 deg_F4=(degf(0,4)+degf(1,4)+degf(2,4)+degf(3,4))/4 GOSUB save_temp 'record the average values r=0 END IF RETURN show_all_deg: COLOR 13 LOCATE 22,39 PRINT SPC(22) LOCATE 22,39 COLOR 12 IF tog_lm335_flag=0 THEN PRINT q; PRINT degF2(q);degF1(q);degF3(q);degF4(q);"F"; 'from game port thermistors ELSEIF tog_lm335_flag=1 THEN PRINT r+1; PRINT degf(r,4);degf(r,3);degf(r,2);degf(r,1);"F"; 'from lm335 A/D END IF COLOR 7 RETURN save_temp: ON ERROR RESUME NEXT 'prevent crash if temp.log currently accessed OPEN "temp.log" FOR APPEND AS #4 WRITE #4, TIME$,DATE$,"therm",degF2,degF1,degF3,degF4,"LM335",deg_F4,deg_F3,deg_F2,deg_F1 CLOSE #4 GOSUB rs232_aux_display2 RETURN get_temp_ini: ON ERROR RESUME NEXT OPEN "temp.ini" FOR INPUT AS #5 'read the regression coefficients CLS FOR i=1 TO 4 INPUT #5, b(i), m(i), rcoefa(i), rcoefb(i), rcoefc(i) PRINT b(i); m(i) PRINT rcoefa(i); rcoefb(i); rcoefc(i) NEXT i CLOSE #5 DELAY 2 'to allow quick view on screen to verify temp.ini IF b(1)=0 THEN no_ini_flag=1 'if no temp.ini do not read the temperatures RETURN read_x10: 'toggle alt-x to watch line for X10 events 'Note that this adds time to each scan loop, specifically '25 minutes to every hourly temperature average interval, 'ie. nominal 60 sec scan loop is now increased to 85 seconds. 'To correct for delay temp_interval is indecreased by .7 IF rd_x10_flag=0 THEN rd_x10_flag=1 temp_interval_old=temp_interval 'save original temp_interval=temp_interval*0.7 ELSE rd_x10_flag=0 temp_interval=temp_interval_old 'restore original END IF COLOR 12 LOCATE 15,1 IF rd_x10_flag=1 THEN PRINT "x10>" ELSE PRINT " " hc$="": fc$="" LOCATE 15,5 PRINT SPC(20) 'clear out old string RETURN send_to_plix: 'Note; X-10 adds 3 seconds to light control GOSUB find_plix 'in case PLIX is removed while program running IF plix_on_flag=0 THEN RETURN 'prevent lockup on printer port input OUT dport, &hFF 'allow PLIX to steal power cportv=3 'initialize control port value OUT cport, 9 'insure PLIX reset & CS are toggled OUT cport, cportv repeat=2 'repeat code 'sync with powerline xrange=0 GOSUB write_data GOSUB write_data GOSUB write_data xrange=31 GOSUB write_data 'send data for module control xrange=hcode GOSUB write_data xrange=ucode GOSUB write_data xrange=repeat GOSUB write_data xrange=hcode GOSUB write_data xrange=fcode 'on or off operation GOSUB write_data xrange=repeat GOSUB write_data RETURN find_plix: RESTORE DATA &h278,&h378,&h3BC 'check all three lpt ports FOR p=1 TO 3 READ dport 'data output port sport=dport+1 'status input port cport=dport+2 'control ouptut port plix_on_flag=0 'assume port status unknown OUT dport,&hFF 'write data=255 status=INP(sport) 'and read it back OUT dport,&h0 'write data=0 x10$="x10" IF(status<>INP(sport)) THEN plix_on_flag=1 'flag when plix port found RETURN 'leave routine if the port was flagged END IF NEXT p 'if no flag check the next port x10$="x? " 'if plix not found at any port RETURN read_data: 'Display last X-10 transmission received. 'Note that reading X10 only allows determining the house code and function. 'Therefore each TX should be set on Unit 1 and a different house code. direction=0 GOSUB set_direction 'SET direction xrange=0 'THIS ALLOWS THE PLIX CHIP TO DRIVE THE STATUS PORT GOSUB set_range 'SET DATA tx_flag=1 'assume that new data is online FOR z=0 TO 1 'GET 2 BYTES FROM PLIX enable=0 GOSUB set_enable 'set enable count=1 WHILE ready=0 GOSUB check_ready WEND nibble=2 GOSUB set_nibble 'SET nibble rangeLO=INP(sport) nibble=0 GOSUB set_nibble 'SET nibble rangeHI=INP(sport) xrange=0 IF (rangeLO AND &h10)=&h10 THEN xrange=xrange+&h1 IF (rangeLO AND &h20)=&h20 THEN xrange=xrange+&h2 IF (rangeLO AND &h80)=&h0 THEN xrange=xrange+&h4 IF (rangeHI AND &h10)=&h10 THEN xrange=xrange+&h8 IF (rangeHI AND &h20)=&h20 THEN xrange=xrange+&h10 IF z=0 THEN IF xrange>15 THEN xrange=xrange-16 ELSE tx_flag=0 'not new data IF z=0 THEN xhc=xrange ELSE xfc=xrange enable=1 GOSUB set_enable 'set enable count=1 WHILE ready=1 GOSUB check_ready WEND NEXT z 'GET ANOTHER BYTE FROM PLIX GOSUB what_house GOSUB what_function tx_time$=USING$("\ \",TIME$) IF tx_flag=1 THEN what$=tx_time$+" "+hc$+" "+fc$: GOSUB save_log RETURN write_data: DELAY .03 'required for timing on 33 mhz PC to allow turning off X-10 COLOR 10 GOSUB set_range 'set xrange direction=4 'for write GOSUB set_direction 'set direction enable=0 'chip enable bit GOSUB set_enable 'set plix enable WHILE ready=0 GOSUB check_ready LOCATE 1,1 PRINT "|"; LOCATE 1,1 PRINT "-"; WEND COLOR 12 LOCATE 1,1 PRINT "x" enable=1 'chip disable bit GOSUB set_enable 'set plix enable COLOR 10 WHILE ready=1 GOSUB check_ready LOCATE 1,1 PRINT "|"; LOCATE 1,1 PRINT "-"; WEND COLOR 12 LOCATE 1,1 PRINT "x" COLOR 7 RETURN set_range: 'SET DATA (xrange=DATA) OUT dport,(xrange OR &hE0) 'pad upper 3 bits RETURN set_direction: 'SET direction (dup=WRITE ddown=READ) cportv=((cportv AND &hFB) OR direction) RETURN set_nibble: 'SET nibble (ndown=LOWER 3 BITS nup=UPPER 2 BITS) cportv=((cportv AND &hFD) OR nibble) delay .1 OUT cport,cportv RETURN set_enable: 'set enable (sup=CHIP ENABLED sdown=CHIP DISABLED) cportv=((cportv AND &hFE) OR enable) OUT cport,cportv RETURN check_ready: 'CHECK READY, status pin 11 (busy pin) IF ((INP(sport) AND &h8)=&h8) THEN ready=1 ELSE ready=0 RETURN what_house: 'X10 house code lookup table SELECT CASE xhc 'have 20 spaces reserved for combined hc and fc strings CASE 6 :hc$="Xmas lights" '"A" CASE 7 :hc$="Garage light" '"B" CASE 4 :hc$="C" CASE 5 :hc$="D" CASE 8 :hc$="E" CASE 9 :hc$="F" CASE 10 :hc$="G" CASE 11 :hc$="H" CASE 14 :hc$="I" CASE 15 :hc$="J" CASE 12 :hc$="K" CASE 13 :hc$="L" CASE 0 :hc$="M" CASE 1 :hc$="N" CASE 2 :hc$="O" CASE 3 :hc$="P" END SELECT RETURN what_function: 'X10 function code lookup table SELECT CASE xfc CASE 16 :fc$="all on" CASE 24 :fc$="all off" CASE 20 :fc$="on" CASE 28 :fc$="off" END SELECT RETURN on_fan8: 'living room fan IF plix_on_flag=0 THEN RETURN 'if no X-10 skip IF tfan8_on=0 AND fan_test_flag=0 THEN RETURN 'allow testing off-season 'IF degF3<>0 AND degF30 AND deg_F20 AND degF30 AND deg_F20 THEN comportinput$=INPUT$(LOC(8), #8) 'deg1$=EXTRACT$(comportinput$,",") 'temp$=REMOVE$(comportinput$, deg1$+",") 'deg2$=EXTRACT$(temp$,",") 'temp$=REMOVE$(comportinput$, deg1$+","+deg2$+",") 'deg3$=EXTRACT$(temp$,",") 'deg4$=REMOVE$(comportinput$, deg1$+","+deg2$+","+deg3$+",") 'INCR q 'the sample count 'degF1(q)=VAL(deg1$) 'degF2(q)=VAL(deg2$) 'degF3(q)=VAL(deg3$) 'degF4(q)=VAL(deg4$) 'IF auto_test_flag=1 THEN GOSUB show_all_deg 'display house temperatures 'IF q=4 THEN 'after 4 readings, average the data ' degF1=(degF1(1)+degF1(2)+degF1(3)+degF1(4))/4 ' degF2=(degF2(1)+degF2(2)+degF2(3)+degF2(4))/4 ' degF3=(degF3(1)+degF3(2)+degF3(3)+degF3(4))/4 ' degF4=(degF4(1)+degF4(2)+degF4(3)+degF4(4))/4 ' GOSUB save_temp 'record the average values ' q=0 'END IF 'RETURN