Code:
@ DEVICE PIC16f877a, HS_OSC, PWRT_ON, BOD_ON
include "modedefs.bas"
DEFINE OSC 20
' define the I/O pins
I2CDATA VAR PORTC.4
I2CCLK VAR PORTC.3
SerialTX VAR PORTC.6 'pic centric
SerialRX VAR PORTC.7 'pic centric
P_SP_reset VAR PORTE.0 ' site player reset 1 == reset
' P_ indicates pin or port
P_zone1 VAR PORTB.3
P_zone2 VAR PORTB.2
P_zone3 VAR PORTB.1
P_zone4 VAR PORTB.0
P_zone5 VAR PORTD.7
P_zone6 VAR PORTD.6
P_zone7 VAR PORTD.5
P_zone8 VAR PORTD.4
P_zone9 VAR PORTC.5
P_zone10 VAR PORTD.3
P_zone11 VAR PORTD.2
P_zone12 VAR PORTD.1
P_zone13 VAR PORTD.0
P_zone14 VAR PORTC.2
P_zone15 VAR PORTC.1
P_zone16 VAR PORTC.0
P_zone17 VAR PORTA.2
P_zone18 VAR PORTA.3
SP_STATUS con $10
SP_NOP CON $00
SP_READ1byte CON $C0
SP_READ2bytes CON $C1
SP_READ3bytes CON $C2
SP_READ5bytes CON $C4
SP_WRITE1byte CON $80
SP_WRITE2bytes CON $81
SP_WRITE5bytes CON $84
' this is the SP start address for the RTC data
SP_RTCADDR con $7f ' siteplayer address for RTC variables
' these are the binary values from from the web page
SP_DAY var byte ' binary data from the SP
SP_HOURS var byte
SP_MINUTES var byte
SP_SECONDS var byte
SP_AMPM var byte
'these are the BCD and tweaked data to be written to the RTC
RTC_DAY var byte
RTC_HOURS var byte
RTC_MINUTES var byte
RTC_SECONDS var byte
RTC_AMPM var byte 'bit 5 of hour (am/pm) 1==PM
SP_STARTHOUR con $96
SP_STARTMINUTE con $97
SP_STARTAMPM CON $98
SP_WINTER con $A0
' this is the zone 1 start address - 1 'cause
' at read current_zone = 0, so to start the process we increment current_zone
SP_ManualAddr con $83 ' siteplayer address for manual times
' These come from the site players status read
SP_bstatus var byte
manual_run var bit
timed_run var bit
PREVIOUS_MINUTE var byte 'used to decrement the valve times
RTC_STATUS VAR WORD
RTC_STATUS = $003F
RTC_TIMEADDR var word
RTC_TIMEADDR = $0030 ' start of a continuous read ($30 +)
winter VAR bit
T_zone VAR byte
valve_number var byte ' dummy used in for loop during write to EEPROM
valvetime var byte
current_zone var byte
start_hour var byte
start_minute var byte
start_ampm var byte
i2c_ack VAR BIT ' acknowledgement bit
i2c_in var byte ' don't care data from the RTC
BIN2BCD_TEMP var byte
BIN2BCD_VAL var byte
BCD2BIN_TEMP var byte
BCD2BIN_VAL var byte
TEMP1 var byte
TEMP2 var byte
i var byte
t_zone = 0
Current_zone = 0
PREVIOUS_MINUTE = $FF
winter = 0
main:
SEROUT2 SerialTX, 84, [$10]
SERIN2 SerialRX, 84, [SP_bstatus]
if SP_bstatus.7 and SP_bstatus.0 then
Serout2 SerialTX, 84, [SP_READ5bytes, SP_RTCADDR]
SERIN2 SerialRX, 84, [SP_SECONDS, SP_MINUTES, SP_HOuRS, SP_DAY, SP_AMPM]
gosub UPDATE_CURRENT_TIME
endif
if SP_bstatus.7 and SP_bstatus.1 then
SEROUT2 SerialTX, 84, [SP_READ3bytes, SP_STARTHOUR]
SERIN2 SerialRX, 84, [start_hour, start_minute, start_ampm]
write SP_STARTHOUR, start_hour
write SP_STARTMINUTE, start_minute
write SP_STARTAMPM, start_ampm
endif
if SP_bstatus.7 and SP_bstatus.2 then
for valve_number = 1 to 126 ' 1 - 126 memory locations
SEROUT2 SerialTX, 84, [SP_READ1byte, valve_number]
SERIN2 SerialRX, 84, [valvetime]
write valve_number, valvetime
next valve_number
endif
if SP_bstatus.7 and SP_bstatus.3 then
Current_zone = 1
manual_run = 1
gosub MANUALRUN
endif
gosub READ_TIME
SEROUT2 SerialTX, 84, [SP_WRITE5bytes, SP_RTCADDR, SP_SECONDS, SP_MINUTES, SP_HOURS, SP_DAY, SP_AMPM]
if current_zone = 0 then
PREVIOUS_MINUTE = SP_MINUTES
endif
if SP_MINUTES != PREVIOUS_MINUTE and current_zone > 0 THEN
PREVIOUS_MINUTE = SP_MINUTES
T_zone = T_zone - 1
endif
' if we decrement beyond 0 then floor the value
if T_zone = 255 then
T_zone = 0
endif
if SP_HOURS = start_hour and SP_MINUTES = start_minute and current_zone = 0 and winter = 0 and manual_run = 0 then
current_zone = 1
timed_run = 1
gosub GET_CURRENT_VALVE_RUN_TIME
endif
if current_zone > 0 and current_zone < 19 and T_zone = 0 and manual_run = 0 then
current_zone = current_zone + 1 'move to the next zone
gosub GET_CURRENT_VALVE_RUN_TIME
endif
if current_zone > 0 and current_zone < 19 and T_zone = 0 and manual_run = 1 then
current_zone = current_zone + 1 'move to the next zone
gosub MANUALRUN
endif
if current_zone > 18 and T_zone = 0 then
current_zone = 0
manual_run = 0
timed_run = 0
endif
if T_zone > 0 and current_zone = 1 then
high P_Zone1
else
low P_Zone1
endif
if T_zone > 0 and current_zone = 2 then
high P_Zone2
else
Low P_Zone2
endif
if T_zone > 0 and current_zone = 3 then
high P_zone3
else
low P_zone3
endif
if T_zone > 0 and current_zone = 4 then
high P_zone4
else
low P_zone4
endif
if T_zone > 0 and current_zone = 5 then
high P_zone5
else
low P_zone5
endif
if T_zone > 0 and current_zone = 6 then
high P_zone6
else
low P_zone6
endif
if T_zone > 0 and current_zone = 7 then
high P_zone7
else
low P_zone7
endif
if T_zone > 0 and current_zone = 8 then
high P_zone8
else
low P_zone8
endif
if T_zone > 0 and current_zone = 9 then
high P_zone9
else
low P_zone9
endif
if T_zone > 0 and current_zone = 10 then
high P_zone10
else
low P_zone10
endif
if T_zone > 0 and current_zone = 11 then
high P_zone11
else
low P_zone11
endif
if T_zone > 0 and current_zone = 12 then
high P_zone12
else
low P_zone12
endif
if T_zone > 0 and current_zone = 13 then
high P_zone13
else
low P_zone13
endif
if T_zone > 0 and current_zone = 14 then
high P_zone14
else
low P_zone14
endif
if T_zone > 0 and current_zone = 15 then
high P_zone15
else
low P_zone15
endif
if T_zone > 0 and current_zone = 16 then
high P_zone16
else
low P_zone16
endif
if T_zone > 0 and current_zone = 17 then
high P_zone17
else
low P_zone17
endif
if T_zone > 0 and current_zone = 18 then
HIGH P_zone18
else
low P_zone18
endif
pause 1000
goto main
UPDATE_CURRENT_TIME:
BIN2BCD_VAL = SP_SECONDS
gosub BIN_TO_BCD
RTC_SECONDS = BIN2BCD_VAL
BIN2BCD_VAL = SP_MINUTES
gosub BIN_TO_BCD
RTC_MINUTES = BIN2BCD_VAL
BIN2BCD_VAL = SP_HOURS
gosub BIN_TO_BCD
RTC_HOURS = BIN2BCD_VAL
RTC_HOURS.7 = 0 'clear mil bit
RTC_HOURS.5 = SP_AMPM.0 'fixup the AM/PM bit
I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$02] 'set REL
I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$06] 'set WREL & REL
I2CWRITE I2CDATA, I2CCLK, $DE, RTC_TIMEADDR, [RTC_SECONDS, RTC_MINUTES, RTC_HOURS, $00, $00, $00, SP_DAY, $00]
pause 10
I2CWRITE I2CDATA, I2CCLK, $DE, RTC_STATUS, [$00] 'clear WREL & REL
RETURN
MANUALRUN:
SEROUT2 SerialTX, 84, [SP_READ1byte, SP_ManualAddr+current_zone]
SERIN2 SerialRX, 84, [T_zone]
RETURN
GET_CURRENT_VALVE_RUN_TIME:
read (SP_DAY*18)+current_zone, T_zone
RETURN
READ_TIME:
' start
HIGH I2CDATA
HIGH I2CCLK
LOW I2CDATA
LOW I2CCLK
SHIFTOUT I2CDATA,I2CCLK,1,[$DE]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1] 'Receive ACK bit
SHIFTOUT I2CDATA,I2CCLK,1,[$00]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1] 'Receive ACK bit
SHIFTOUT I2CDATA,I2CCLK,1,[$30]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1] 'Receive ACK bit
HIGH I2CDATA
HIGH I2CCLK
LOW I2CDATA
LOW I2CCLK
SHIFTOUT I2CDATA,I2CCLK,1,[$DF]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_ack\1]
SHIFTIN I2CDATA,I2CCLK,0,[Sp_SECONDS]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[SP_MINUTES]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[SP_HOURS]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[i2c_in]
SHIFTOUT I2CDATA,I2CCLK,1,[%0\1]
SHIFTIN I2CDATA,I2CCLK,0,[SP_DAY]
SHIFTOUT I2CDATA,I2CCLK,1,[%1\1]
LOW I2CDATA
HIGH I2CCLK
HIGH I2CDATA
PAUSE 1
BCD2BIN_VAL = SP_SECONDS
gosub BCD_TO_BIN
SP_SECONDS = BCD2BIN_VAL
BCD2BIN_VAL = SP_MINUTES
gosub BCD_TO_BIN
SP_MINUTES = BCD2BIN_VAL
SP_AMPM = SP_HOURS.5
SP_HOURS.5 = 0 ' clear AM/PM bit before we unBCD
BCD2BIN_VAL = SP_HOURS
gosub BCD_TO_BIN
SP_HOURS = BCD2BIN_VAL
return
BIN_TO_BCD:
BIN2BCD_TEMP = ((BIN2BCD_VAL/10)<<4)+(BIN2BCD_VAL//10)
BIN2BCD_VAL = BIN2BCD_TEMP
return
BCD_TO_BIN:
TEMP1 = BCD2BIN_VAL & $F ' Convert the values from BCD to BIN
TEMP2 = BCD2BIN_VAL & $F0 ' Mask off high nibble
TEMP2 = TEMP2 >> 4 ' divide by 16
TEMP2 = TEMP2 * 10 ' X by 10
BCD2BIN_VAL = TEMP1 + TEMP2
return
End
Bookmarks