;
        Title "DIY K181"


;
; PURPOSE IS TO READ A 4 BIT VALUE OF DECYPHER IT INTO 10
; RELAY OUTPUTS
; OUTPUTS CAN TOGGLE ON EACH KEY PRESS
; OR BE ON-OFF WITH EACH KEY PRESS
;
; VERSION 1.1  TONY NIXON DECEMBER 3, 2002



;
        list P = 16F627
;
        include "P16f627.inc"
;


        errorlevel         -(305), -(302), -(306)
;
; ------------------
; CONFIGURATION FUSE
; ------------------
;
        __CONFIG _CP_OFF & _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _BODEN_OFF & _LVP_OFF & _MCLRE_ON



;
; --------------------
; USER RAM DEFINITIONS
; --------------------
;
        CBLOCK 0x20


DelayH
DelayL
Count
DataCount
DataTemp
DataNew
RelayBCD
Temp


        ENDC
;
; -----------------
; PORTA DEFINITIONS
; -----------------
;
Data1   equ 0h
Data2   equ 1h
Data3   equ 2h
Relay10 equ 3h
ModeLED equ 4h


Relay1  equ 6h
Data0   equ 7h


NoKeys  equ b'10000111'


;
; -----------------
; PORTB DEFINITIONS
; -----------------
;
Relay9  equ 0h
Relay8  equ 1h
Relay7  equ 2h
Relay6  equ 3h
Relay5  equ 4h
Relay4  equ 5h
Relay3  equ 6h
Relay2  equ 7h
;
; --------------------------
; Flag1 REGISTER DEFINITIONS
; --------------------------
;
;


;
; -------
; DEFINES
; -------
;
#Define Relay1_ON               bsf PORTA,Relay1
#Define Relay1_OFF      bcf PORTA,Relay1
#Define Relay2_ON               bsf PORTB,Relay2
#Define Relay2_OFF      bcf PORTB,Relay2
#Define Relay3_ON               bsf PORTB,Relay3
#Define Relay3_OFF      bcf PORTB,Relay3
#Define Relay4_ON               bsf PORTB,Relay4
#Define Relay4_OFF      bcf PORTB,Relay4
#Define Relay5_ON               bsf PORTB,Relay5
#Define Relay5_OFF      bcf PORTB,Relay5
#Define Relay6_ON               bsf PORTB,Relay6
#Define Relay6_OFF      bcf PORTB,Relay6
#Define Relay7_ON               bsf PORTB,Relay7
#Define Relay7_OFF      bcf PORTB,Relay7
#Define Relay8_ON               bsf PORTB,Relay8
#Define Relay8_OFF      bcf PORTB,Relay8
#Define Relay9_ON               bsf PORTB,Relay9
#Define Relay9_OFF      bcf PORTB,Relay9
#Define Relay10_ON      bsf PORTA,Relay10
#Define Relay10_OFF     bcf PORTA,Relay10
#Define ModeLED_ON      bcf PORTA,ModeLED
#Define ModeLED_OFF     bsf PORTA,ModeLED
#Define SkipIfData0_Low btfsc DataNew,Data0
#Define SkipIfData1_Low btfsc DataNew,Data1
#Define SkipIfData2_Low btfsc DataNew,Data2
#Define SkipIfData3_Low btfsc DataNew,Data3
#Define ReadDataPort_W  movf PORTA,W


ToggleRelay_1   MACRO
                movlw b'01000000'
                xorwf PORTA
                ENDM
ToggleRelay_2   MACRO
                movlw b'10000000'
                xorwf PORTB
                ENDM
ToggleRelay_3   MACRO
                movlw b'01000000'
                xorwf PORTB
                ENDM
ToggleRelay_4   MACRO
                movlw b'00100000'
                xorwf PORTB
                ENDM
ToggleRelay_5   MACRO
                movlw b'00010000'
                xorwf PORTB
                ENDM
ToggleRelay_6   MACRO
                movlw b'00001000'
                xorwf PORTB
                ENDM
ToggleRelay_7   MACRO
                movlw b'00000100'
                xorwf PORTB
                ENDM
ToggleRelay_8   MACRO
                movlw b'00000010'
                xorwf PORTB
                ENDM
ToggleRelay_9   MACRO
                movlw b'00000001'
                xorwf PORTB
                ENDM
ToggleRelay_10  MACRO
                movlw b'00001000'
                xorwf PORTA
                ENDM
;
; --------------------
; INTERNAL EEPROM DATA
; --------------------
;
EEFlag1 equ 0h          ; Data Relays 1 - 8
EEFlag2 equ 1h          ; Data Relays 9 - 10


;
; ----------------
; CODE BEGINS HERE
; ----------------
;
        org 0x0000
        goto Start
;
; -------------------------------
; ONE OR MORE BUTTONS ARE PRESSED
; -------------------------------
; if non toggle mode - relay output goes ON
; if toggle mode - relay toggles
;
RelayON movf RelayBCD,W
        addwf PCL
        return                  ; 0000 = none
        goto Relay_4            ; 0001 = 4
        goto Relay_3            ; 0010 = 3
        goto Relay_10           ; 0011 = 10
        goto Relay_2            ; 0100 = 2
        goto Relay_9            ; 0101 = 9
        goto Relay_8            ; 0110 = 8
        return                  ; 0111 = ?
        goto Relay_1            ; 1000 = 1
        goto Relay_7            ; 1001 = 7
        goto Relay_6            ; 1010 = 6
        return                  ; 1011 = ?
        goto Relay_5            ; 1100 = 5
        return                  ; 1101 = ?
        return                  ; 1110 = ?
        return                  ; 1111 = ?
;
; -------------------------
; ALL BUTTONS CHANGED TO UP
; -------------------------
; if non toggle mode - relay output goes OFF
; if toggle mode - no change to relay state
;
RelayOFF        movf RelayBCD,W         ; relay number that was turned on
        addwf PCL
        return                  ; 0000 = none
        goto Rel4_Off           ; 0001 = 4
        goto Rel3_Off           ; 0010 = 3
        goto Rel10_Off          ; 0011 = 10
        goto Rel2_Off           ; 0100 = 2
        goto Rel9_Off           ; 0101 = 9
        goto Rel8_Off           ; 0110 = 8
        return                  ; 0111 = ?
        goto Rel1_Off           ; 1000 = 1
        goto Rel7_Off           ; 1001 = 7
        goto Rel6_Off           ; 1010 = 6
        return                  ; 1011 = ?
        goto Rel5_Off           ; 1100 = 5
        return                  ; 1101 = ?
        return                  ; 1110 = ?
        return                  ; 1111 = ?
;
; ---------------------------------------------------------
; SAME KEY(S) PRESSED AFTER TIMEOUT - do toggle mode change
; ---------------------------------------------------------
;
ExpTable        movf RelayBCD,W         ; relay number that was turned on
        addwf PCL
        return                  ; 0000 = none
        goto TogR_4             ; 0001 = 4
        goto TogR_3             ; 0010 = 3
        goto TogR_10            ; 0011 = 10
        goto TogR_2             ; 0100 = 2
        goto TogR_9             ; 0101 = 9
        goto TogR_8             ; 0110 = 8
        return                  ; 0111 = ?
        goto TogR_1             ; 1000 = 1
        goto TogR_7             ; 1001 = 7
        goto TogR_6             ; 1010 = 6
        return                  ; 1011 = ?
        goto TogR_5             ; 1100 = 5
        return                  ; 1101 = ?
        return                  ; 1110 = ?
        return                  ; 1111 = ?
;
; ----------
; CODE START
; ----------
;
Start   clrf PORTA
        clrf PORTB
        bsf STATUS,RP0
        movlw b'10000111'               ; all out except data inputs
        movwf TRISA
        clrf TRISB
        bcf STATUS,RP0
;
; -----------------------
; DISABLE THE COMPARATORS
; -----------------------
;
        movlw b'00000111'               ; disable comparators
        movwf CMCON


        movlw d'100'            ; flash mode LED briefly at power up
        movwf Count
        ModeLED_ON
ONwait  call DelayWt
        decfsz Count
        goto ONwait
        ModeLED_OFF


        clrf DataCount


        bsf STATUS,RP0
        movlw b'10000101'
        movwf OPTION_REG
        bcf STATUS,RP0


        clrf TMR0
        bcf INTCON,T0IF
;
; --------------------
; MAIN CODE LOOP START
; --------------------
; 16mS @ 4MHz
;
MainLoop        btfss INTCON,T0IF
        goto MainLoop


        bcf INTCON,T0IF


        ReadDataPort_W
        movwf DataNew
        andlw NoKeys    
        btfsc STATUS,Z
        goto MainLoop           ; no key pressed


        clrf DataCount
        call RelayBit           ; decodes keypress to 0 - 15 -> W
        movwf RelayBCD
        call RelayON            ; turn on relay or toggle it
        clrf TMR0
        bcf INTCON,T0IF
;
; WAIT HERE UNTIL KEY(S) ARE RELEASED
; IF DATACOUNT = MAX THEN TOGGLE KEY MODE
;
WaitLoop        btfss INTCON,T0IF
        goto WaitLoop


        bcf INTCON,T0IF


        incf DataCount
        movlw d'125'            ; 2 seconds @ 16mS Loop @ 4MHz
        xorwf DataCount,W
        btfsc STATUS,Z
        goto ChgTogMod


        ReadDataPort_W
        andlw NoKeys
        btfss STATUS,Z
        goto WaitLoop


        call RelayOFF
        goto MainLoop
;
; CHANGE KEY MODE
;
ChgTogMod       call ExpTable
        movlw d'40'             ; flash mode LED briefly
        movwf Count
        ModeLED_ON
ONwait2 call DelayWt
        decfsz Count
        goto ONwait2
        ModeLED_OFF
;
; WAIT HERE UNTIL KEY(S) ARE RELEASED
;
WaitLp  btfss INTCON,T0IF
        goto WaitLp


        bcf INTCON,T0IF
        ReadDataPort_W
        andlw NoKeys
        btfss STATUS,Z
        goto WaitLp


        call RelayOFF
        goto MainLoop
;
; ------------------------------------
; OPERATE RELAYS FROM INITIAL KEYPRESS
; ------------------------------------
;
Relay_1 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000001'
        btfsc STATUS,Z
        goto TogMode1
;
; RELAY 1 NON TOGGLE - TURN IT ON
;
        Relay1_ON
        return
;
; RELAY 1 TOGGLE - ALTERNATE STATE
;
TogMode1        ToggleRelay_1
        return


;
; if non toggle mode - relay 2 output goes ON
; if toggle mode - change relay 2 state
;
Relay_2 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000010'
        btfsc STATUS,Z
        goto TogMode2
;
; RELAY 2 NON TOGGLE - TURN IT ON
;
        Relay2_ON
        return
;
; RELAY 2 TOGGLE - ALTERNATE STATE
;
TogMode2        ToggleRelay_2
        return


;
; if non toggle mode - relay 3 output goes ON
; if toggle mode - change relay 3 state
;
Relay_3 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000100'
        btfsc STATUS,Z
        goto TogMode3
;
; RELAY 3 NON TOGGLE - TURN IT ON
;
        Relay3_ON
        return
;
; RELAY 3 TOGGLE - ALTERNATE STATE
;
TogMode3        ToggleRelay_3
        return


;
; if non toggle mode - relay 4 output goes ON
; if toggle mode - change relay  state
;
Relay_4 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00001000'
        btfsc STATUS,Z
        goto TogMode4
;
; RELAY 4 NON TOGGLE - TURN IT ON
;
        Relay4_ON
        return
;
; RELAY 4 TOGGLE - ALTERNATE STATE
;
TogMode4        ToggleRelay_4
        return


;
; if non toggle mode - relay 5 output goes ON
; if toggle mode - change relay 5 state
;
Relay_5 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00010000'
        btfsc STATUS,Z
        goto TogMode5
;
; RELAY 5 NON TOGGLE - TURN IT ON
;
        Relay5_ON
        return
;
; RELAY 5 TOGGLE - ALTERNATE STATE
;
TogMode5        ToggleRelay_5
        return


;
; if non toggle mode - relay 6 output goes ON
; if toggle mode - change relay 6 state
;
Relay_6 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00100000'
        btfsc STATUS,Z
        goto TogMode6
;
; RELAY 6 NON TOGGLE - TURN IT ON
;
        Relay6_ON
        return
;
; RELAY 6 TOGGLE - ALTERNATE STATE
;
TogMode6        ToggleRelay_6
        return


;
; if non toggle mode - relay 7 output goes ON
; if toggle mode - change relay 7 state
;
Relay_7 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'01000000'
        btfsc STATUS,Z
        goto TogMode7
;
; RELAY 7 NON TOGGLE - TURN IT ON
;
        Relay7_ON
        return
;
; RELAY 7 TOGGLE - ALTERNATE STATE
;
TogMode7        ToggleRelay_7
        return


;
; if non toggle mode - relay 8 output goes ON
; if toggle mode - change relay 8 state
;
Relay_8 clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'10000000'
        btfsc STATUS,Z
        goto TogMode8
;
; RELAY 8 NON TOGGLE - TURN IT ON
;
        Relay8_ON
        return
;
; RELAY 8 TOGGLE - ALTERNATE STATE
;
TogMode8        ToggleRelay_8
        return


;
; if non toggle mode - relay 9 output goes ON
; if toggle mode - change relay 9 state
;
Relay_9 movlw 1h                        ; relays 9 - 10 toggle flags in EEP 0x01
        call RdEep
        andlw b'00000001'
        btfsc STATUS,Z
        goto TogMode9
;
; RELAY 9 NON TOGGLE - TURN IT ON
;
        Relay9_ON
        return
;
; RELAY 9 TOGGLE - ALTERNATE STATE
;
TogMode9        ToggleRelay_9
        return


;
; if non toggle mode - relay 10 output goes ON
; if toggle mode - change relay 10 state
;
Relay_10        movlw 1h                        ; relays 9 - 10 toggle flags in EEP 0x01
        call RdEep
        andlw b'00000010'
        btfsc STATUS,Z
        goto TogMode10
;
; RELAY 10 NON TOGGLE - TURN IT ON
;
        Relay10_ON
        return
;
; RELAY 10 TOGGLE - ALTERNATE STATE
;
TogMode10       ToggleRelay_10
        return
;
; ---------------
; TURN RELAYS OFF
; ---------------
;
Rel1_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000001'
        btfsc STATUS,Z
        return
;
; RELAY 1 NON TOGGLE - TURN IT OFF
;
        Relay1_OFF
        return
;
; If relay 2 not in toggle mode, turn it off
;
Rel2_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000010'
        btfsc STATUS,Z
        return
;
; RELAY 2 NON TOGGLE - TURN IT OFF
;
        Relay2_OFF
        return
;
; If relay 3 not in toggle mode, turn it off
;
Rel3_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00000100'
        btfsc STATUS,Z
        return
;
; RELAY 3 NON TOGGLE - TURN IT OFF
;
        Relay3_OFF
        return
;
; If relay 4 not in toggle mode, turn it off
;
Rel4_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00001000'
        btfsc STATUS,Z
        return
;
; RELAY 4 NON TOGGLE - TURN IT OFF
;
        Relay4_OFF
        return
;
; If relay 5 not in toggle mode, turn it off
;
Rel5_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00010000'
        btfsc STATUS,Z
        return
;
; RELAY 5 NON TOGGLE - TURN IT OFF
;
        Relay5_OFF
        return
;
; If relay 6 not in toggle mode, turn it off
;
Rel6_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'00100000'
        btfsc STATUS,Z
        return
;
; RELAY 6 NON TOGGLE - TURN IT OFF
;
        Relay6_OFF
        return
;
; If relay 7 not in toggle mode, turn it off
;
Rel7_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'01000000'
        btfsc STATUS,Z
        return
;
; RELAY 7 NON TOGGLE - TURN IT OFF
;
        Relay7_OFF
        return
;
; If relay 8 not in toggle mode, turn it off
;
Rel8_Off        clrw                    ; relays 1 - 8 toggle flags in EEP 0x00
        call RdEep
        andlw b'10000000'
        btfsc STATUS,Z
        return
;
; RELAY 8 NON TOGGLE - TURN IT OFF
;
        Relay8_OFF
        return
;
; If relay 9 not in toggle mode, turn it off
;
Rel9_Off        movlw 1h                        ; relays 9 - 10 toggle flags in EEP 0x01
        call RdEep
        andlw b'00000001'
        btfsc STATUS,Z
        return
;
; RELAY 9 NON TOGGLE - TURN IT OFF
;
        Relay9_OFF
        return
;
; If relay 10 not in toggle mode, turn it off
;
Rel10_Off       movlw 1h                        ; relays 9 - 10 toggle flags in EEP 0x01
        call RdEep
        andlw b'00000010'
        btfsc STATUS,Z
        return
;
; RELAY 10 NON TOGGLE - TURN IT OFF
;
        Relay10_OFF
        return
;
; ----------------------------
; TOGGLE ON/OFF - TOGGLE MODES
; ----------------------------
;
TogR_1  clrw
        call RdEep
        xorlw b'00000001'
        call WrtEep
        return
;
; alternate toggle mode = key 2
;
TogR_2  clrw
        call RdEep
        xorlw b'00000010'
        call WrtEep
        return
;
; alternate toggle mode = key 3
;
TogR_3  clrw
        call RdEep
        xorlw b'00000100'
        call WrtEep
        return
;
; alternate toggle mode = key 4
;
TogR_4  clrw
        call RdEep
        xorlw b'00001000'
        call WrtEep
        return
;
; alternate toggle mode = key 5
;
TogR_5  clrw
        call RdEep
        xorlw b'00010000'
        call WrtEep
        return
;
; alternate toggle mode = key 6
;
TogR_6  clrw
        call RdEep
        xorlw b'00100000'
        call WrtEep
        return
;
; alternate toggle mode = key 7
;
TogR_7  clrw
        call RdEep
        xorlw b'01000000'
        call WrtEep
        return
;
; alternate toggle mode = key 8
;
TogR_8  clrw
        call RdEep
        xorlw b'10000000'
        call WrtEep
        return
;
; alternate toggle mode = key 9
;
TogR_9  movlw 1h
        call RdEep
        xorlw b'00000001'
        call WrtEep
        return
;
; alternate toggle mode = key 10
;
TogR_10 movlw 1h
        call RdEep
        xorlw b'00000010'
        call WrtEep
        return
;
; --------------------------------------
; DETERMINE RELAY OUTPUT FROM INPUT DATA
; --------------------------------------
;
RelayBit        clrf DataTemp
        SkipIfData0_Low
        bsf DataTemp,0
        SkipIfData1_Low
        bsf DataTemp,1
        SkipIfData2_Low
        bsf DataTemp,2
        SkipIfData3_Low
        bsf DataTemp,3
        movf DataTemp,W
        return
;
; -------------------
; ~ 12mS DELAY @ 4MHZ
; -------------------
;
DelayWt clrf DelayL
        movlw 10h
        movwf DelayH
ctlp3   decfsz DelayL,F
        goto ctlp3
        decfsz DelayH,F
        goto ctlp3
        return
;
; -----------------------------
; WRITE AN INTERNAL EEPROM BYTE
; -----------------------------
;
WrtEep  bsf STATUS,RP0          ; RAM Page 1
        movwf EEDATA
        bsf EECON1,WREN
        movlw 55h
        movwf EECON2
        movlw 0xAA
        movwf EECON2
        bsf EECON1,WR
WrtLoop nop
        btfsc EECON1,WR
        goto WrtLoop


        bcf EECON1,WREN
        bcf STATUS,RP0          ; RAM Page 0
        return
;
; ----------------------------
; READ AN INTERNAL EEPROM BYTE
; ----------------------------
; Result is in W
;
RdEep   bsf STATUS,RP0          ; RAM Page 1
        movwf EEADR
        bsf EECON1,RD           ; read back ROM location
        nop                     ; in case internal ROM reading
        nop
        movf EEDATA,W
        bcf STATUS,RP0          ; RAM Page 0
        return
;
;
        end
