'portc pin0 is mode switch 'portc pin1 is function switch 'portc pin2 is set data input 'portc pin3 LED indicator 'portc pin4 future use 'portc pin5 when high stores alarm data into memory via interrupt routine 'portc pin6 is the relay & buzzer control output 'portc pin7 alarm on/auto/off switch 'portb pin7 goes to D7 on LCD 'portb pin6 goes to D6 on LCD 'portb pin5 goes to D5 on LCD 'portb pin4 goes to D4 on LCD 'portb pin3 goes to EN on LCD 'portb pin2 goes to RS on LCD 'portb pin1 goes to RESET (pin 11) on 4040 'portb pin0 goes to minute output (pin 10) on 4001 'b11 records mode switch 3 = days; 2 = hrs; 1 = min; 0 = run 'b12 records function switch 2 = set time; 1 = set alarm on time; 0 = set alarm off time 'b13 contains hours during set hours process 'b14 contains mins during set minutes process start0: 'preload data data 0,("SUN",24,0,0,0) data 7,("MON",24,0,0,0) data 14,("TUE",24,0,0,0) data 21,("WED",24,0,0,0) data 28,("THU",24,0,0,0) data 35,("FRI",24,0,0,0) data 42,("SAT",24,0,0,0) symbol s = b15 symbol m = b9 symbol h = b10 symbol new = b3 symbol day = b4 symbol onmin = b5 symbol onhr = b6 symbol offmin = b7 symbol offhr = b8 symbol mode = b11 symbol function = b12 symbol sethours = b13 symbol setminutes = b14 symbol databyte = b16 symbol position = b17 symbol character = b18 symbol rs = b.2 symbol en = b.3 symbol onday = b19 symbol setdays = b23 symbol resettime = b.1 symbol timerout = pinb.0 symbol tempposition = b24 symbol swap1 = b25 symbol swap2 = b26 setint %00100000,%00100000 dirsB = %11111110 outpinsB = 0:low c.6:low c.3 'set all outputs to 0. Ensures relay & mains switched off gosub initialise 'initialise LCD position = $82:character = ":":gosub sendchar 'send fixed characters to LCD position = $c6:gosub sendchar position = $cc:gosub sendchar position = $87:character = "M":gosub sendchar poke 28,"n","o"," ","a","l","a","r","m"," "," "," " swap1 = "#" swap2 = " " bptr = 7*day + 3 read bptr,onhr,onmin,offhr,offmin main:'main routine is normal clock operation loop3: if pinc.7 = 0 then 'check if alarm is set character = "*" 'if so set DP on unit hours else character = " " 'if not turn off indicator low c.6:low c.3 'and turn off relay endif position = $cf:gosub sendchar bptr = 7*day:position = $89 'display day of week read bptr,character:gosub sendchar:inc bptr read bptr,character:gosub sendnext:inc bptr read bptr,character:gosub sendnext if h > 12 then 'set up for 12 hour clock b21 = h - 12 else b21 = h endif if h > 11 then character = "P" else character = "A" endif position = $86:gosub sendchar bintoascii b21,b0,b1,b2 'output routine to display hrs position = $80 character = b1:gosub sendchar character = b2:gosub sendnext bintoascii m,b0,b1,b2'output routine to display mins position = $83 character = b1:gosub sendchar character = b2:gosub sendnext onday = day'update alarm display to show current alarm info gosub writealarm if onhr = h and onmin = m and pinc.7 = 0 then 'check if relay should turn on high c.6:high c.3 'turn on relay & LED elseif offhr = h and offmin = m then 'check if relay should turn off low c.6:low c.3 'turn off relay & LED endif readadc 0,b0 'check whether task has changed if b0 > 64 then low c.3:low c.6 'turn off LED/mains goto settime endif swap swap1,swap2 position = $8f:character = swap1:gosub sendchar goto loop3 settime:'routine to set time or alarm time information gosub check 'check what settings to change mode = b0 'permanently keep values so that changes can be detected function = b1 if mode = 0 then 'this is exit settime condition goto main endif on mode gosub nil,minutes,hr,days goto settime check:'subroutine check determines switch positions readadc 0,b0 'check if hr or min to set or to resume clock if b0 > 213 then 'set days condition b0 = 3 elseif b0 > 128 then 'this is set hrs condition b0 = 2 elseif b0 > 42 then 'this is the set mins condition b0 = 1 else b0 = 0 'this is the run condition endif readadc 1,b1 ' now check which to set - time;alarm on time; alarm off time if b1 < 64 then b1 = 0 'setting alarm off time elseif b1 > 190 then b1 = 2 'setting time else b1 = 1 'setting alarm on time endif return days:'subroutine to increment days if function = 2 then 'determine whether TIME day or ALARM day is being altered setdays = day position = $89 else setdays = onday position = $c0 endif tset: 'this loop increments the DAY bptr = 7*setdays 'display current day on correct line read bptr,character:gosub sendchar:inc bptr read bptr,character:gosub sendnext:inc bptr read bptr,character:gosub sendnext 'if setting alarm you may have already set HRS & MIN therefore you do not want these values 'changed. So only display current alarm details if alarm not being set. Displaying alarm details when 'alarm is not set facilitates checking daily alarm details tempposition = position 'store position as it will be changed in subroutine if pinc.7 = 1 and function < 2 then 'alarm not set so display current alarm setting for this day gosub writealarm 'write alarm data character = " " 'prepare to update display with alarm not set symbol else character = "*" endif position = $cf:gosub sendchar 'send alarm on/off symbol position = tempposition 'restore position for b3 = 0 to 80 'loop to slow incrementing process to a suitable time gosub check 'check if selection has changed if b1 <> function or b0 <> mode then pause 500 'needed to debounce switch gosub check 'check again now switch has had time to settle return endif next b3 if pinc.2 = 0 then tset 'no button is pressed so go back setdays = setdays + 1 'otherwise set button is pressed so update days if setdays = 7 then setdays = 0 endif if function = 2 then 'update day to appropriate variable day = setdays return else onday = setdays endif goto tset hr: 'subroutine hr increments hours in setting mode on function gosub aloff1, alon1, time1 'get correct hour to update in sethours loop1: if onhr = 24 and function < 2 then 'this is the condition for no alarm that day gosub noalarm else bintoascii sethours,b0,b1,b2 'get hours digits in b1 & b2 character = b1:gosub sendchar 'display on LCD in correct position character = b2:gosub sendnext endif gosub alarmcheck 'check alarm on/off status & write symbol on LCD for b3 = 0 to 35 gosub check 'check if selection has changed if b1 <> function or b0 <> mode then on function gosub aloff2, alon2,time2 'restore the updated hour or minute pause 500 'necessary for debouncing switch gosub check 'check again now switch has had time to settle return endif next b3 if pinc.2 = 0 then loop1'no button is pressed so go back if onhr = 24 and function < 2 then 'in alarm set mode & showing "no alarm" gosub resetdisplay 'need to remove "no alarm" text & display 0's goto loop1 endif sethours = sethours + 1 'the button is pressed so increment hrs if sethours = 24 then if function <> 1 then 'not setting onhr so 24 not allowed sethours = 0 else onhr = sethours 'setting onhr & 24 is allowed. need to update endif endif goto loop1 resetdisplay: 'subroutine to remove "no alarm" from display & start setting alarm process tempposition = position 'save current position sethours = 0:setminutes = 0:onhr = 0 'reset all alarm digits to 0 bptr = 7*onday + 3 write bptr,0,0,0,0 'store into memory gosub writealarm 'update display position = tempposition 'restore position return minutes: 'subroutine minutes increments minutes in setting mode on function gosub aloff1, alon1, time1 'get correct minute to update in setminutes position = position + 3 'get correct position on LCD loop2: if onhr = 24 and function < 2 then gosub noalarm else bintoascii setminutes,b0,b1,b2'b1 & b2 contain minute digits character = b1:gosub sendchar:character = b2:gosub sendnext 'display minutes endif gosub alarmcheck 'check alarm on/off status & write symbol on LCD for b3 = 0 to 30 gosub check 'check if selection has changed if b1 <> function or b0 <> mode then on function gosub aloff2, alon2,time2 'restore the updated hour or minute pause 500 'necessary for debouncing switch gosub check 'check again now switch has had time to settle return endif next b3 if pinc.2 = 0 then loop2 'no button is pressed so go back if onhr = 24 and function < 2 then 'in alarm set mode & showing "no alarm" gosub resetdisplay 'need to remove "no alarm" text & display 0's goto loop2 endif setminutes = setminutes + 1 'the button is pressed so increment hrs if setminutes > 59 then setminutes = 0 endif goto loop2 alarmcheck:'Checks status of alarm switch in setting mode & displays symbol on LCD tempposition = position 'save current position if pinc.7 = 0 then character = "*" else character = " " endif position = $cf:gosub sendchar: position = tempposition return time1: sethours = h setminutes = m position = $80 return time2: pulsout resettime,200 h = sethours m = setminutes return alon1: sethours = onhr setminutes = onmin position = $c4 return alon2: onhr = sethours onmin = setminutes return aloff1: sethours = offhr setminutes = offmin position = $ca return aloff2: offhr = sethours offmin = setminutes return writealarm: 'writes alarm info for current day bptr = 7*onday:position = $c0'send day read bptr,character:gosub sendchar:inc bptr read bptr,character:gosub sendnext:inc bptr read bptr,character:gosub sendnext character = " ":gosub sendnext bptr = 7*onday + 3'now get rest of alarm info read bptr,onhr,onmin,offhr,offmin if onhr < 24 then bintoascii onhr,b0,b1,b2 'send onhr character = b1:gosub sendnext character = b2:gosub sendnext character = ":":gosub sendnext bintoascii onmin,b0,b1,b2 'send onmin character = b1:gosub sendnext character = b2:gosub sendnext character = " ":gosub sendnext bintoascii offhr,b0,b1,b2 'send offhr character = b1:gosub sendnext character = b2:gosub sendnext character = ":":gosub sendnext bintoascii offmin,b0,b1,b2 'send offmin character = b1:gosub sendnext character = b2:gosub sendnext else gosub noalarm endif return noalarm:'displays message "no alarm" when onhr is 24 tempposition = position bptr = 7*onday:position = $c0'send day read bptr,character:gosub sendchar:inc bptr read bptr,character:gosub sendnext:inc bptr read bptr,character:gosub sendnext character = " ":gosub sendnext bptr = 28:position = $c4 'send "no alarm" message character = @bptrinc:gosub sendchar for b0 = 1 to 10 character = @bptrinc:gosub sendnext next b0 position = tempposition return sendchar: 'displays "character" at "position" databyte = position:low rs:gosub fullbyte 'position cursor sendnext: 'displays "character" at next position databyte = character:high rs:gosub fullbyte 'send character return initialise: 'INITIALISATION SUBROUTINE'''''''''''''''''''''''''''''''''''''' databyte = 3:GOSUB lowernibble:PAUSE 5 'reset databyte = 3:GOSUB lowernibble:PAUSE 5 'reset databyte = 3:GOSUB lowernibble:PAUSE 5 'reset databyte = 2:GOSUB lowernibble 'set 4 bit mode databyte = %00101000:GOSUB fullbyte '4 bit,2lines,5x7 display databyte = %00001100:GOSUB fullbyte 'set display on,no cursor databyte = %00000110:GOSUB fullbyte 'set increment on write databyte = %00000001:GOSUB fullbyte 'clear display return fullbyte: 'SEND A BYTE TO LCD IN 2 NIBBLES. UPPER NIBBLE 1ST'''''''''''''''''''''''''''''''''''''' b20 = databyte and 16 if b20 = 16 then high b.4 else low b.4 endif b20 = databyte and 32 if b20 = 32 then high b.5 else low b.5 endif b20 = databyte and 64 if b20 = 64 then high b.6 else low b.6 endif b20 = databyte and 128 if b20 = 128 then high b.7 else low b.7 endif high en:low en 'TELL LCD TO ACCEPT DATA. lowernibble: 'ENTRY POINT TO SEND JUST 4 BITS TO LCD. ALSO SENDS LOWER NIBBLE'''''''''''''''''''''''''''''''''''''' b20 = databyte and 1 if b20 = 1 then high b.4 else low b.4 endif b20 = databyte and 2 if b20 = 2 then high b.5 else low b.5 endif b20 = databyte and 4 if b20 = 4 then high b.6 else low b.6 endif b20 = databyte and 8 if b20 = 8 then high b.7 else low b.7 endif high en:low en 'TELL LCD TO ACCEPT DATA. RETURN nil:'a dummy address return start1: 'parallel processing mode invoked timecheck: 'checks for timing pulses and counts them if timerout = 1 then timecheck timeloop2: if timerout = 0 then timeloop2 gosub increment goto timecheck increment: 'increments minutes and hours and days when necessary m = m+1 if m=60 then m=0 h = h + 1 endif if h = 24 then h = 0 day = day + 1 if day = 7 then day = 0 endif bptr = 7*day +3 read bptr,onhr,onmin,offhr,offmin 'new day so update alarm info endif return interrupt: 'interrupt routine to store alarm data high c.3 'turn on Led on function gosub aloff2,alon2,time2 'update bptr = 7*onday + 3 write bptr, onhr,onmin,offhr,offmin 'store alarm information loop4: if pinc.5 = 1 then loop4 'stay here until store switch is released low c.3 'turn off Led setint %00100000,%00100000 'reset interrupt return