;Curtain controller
; Version 05
;PIC16C84, set for 4.00MHz XTAL, WDT OFF, POR on
;Instruction time at 4MHZ is 1.0 us
;written in MASM
TIMEOUT_VAL EQU D'45' ;Timeout value in seconds to stop motors
INDF EQU 0x00 ;page 0 & 1
TMR0 EQU 0x01 ;0
OPTION_REG EQU 0x01 ;1
PCL EQU 0x02 ;0 & 1
STATUS EQU 0x03 ;0 & 1
FSR EQU 0x04 ;0 & 1
PORTA EQU 0x05 ;0
TRISA EQU 0x05 ;1
PORTB EQU 0x06 ;0
TRISB EQU 0x06 ;1
;0x07 not available
EEDATA EQU 0x08 ;0
EECON1 EQU 0x08 ;1
EEADR EQU 0x09 ;0
EECON2 EQU 0x09 ;1
PCLATH EQU 0x0A ;0 & 1
INTCON EQU 0x0B ;0 & 1
STATE_FLAGS EQU 0x0C
[\code]
delay1 EQU 0x0D ;Used in delay routine
delay2 EQU 0x0E ;Used in delay routine
delay3 EQU 0x0F ;Used in delay routine
timer0 EQU 0x10 ;Used in timout routine
timer1 EQU 0x11 ;Used in timout routine
EEPROM0 EQU 0x00 ;Saves copy of STATE_FLAGS when powered off
;----- STATUS Bits --------------------------------------------------------
IRP EQU H'0007'
RP1 EQU H'0006'
RP0 EQU H'0005'
NOT_TO EQU H'0004'
NOT_PD EQU H'0003'
Z EQU H'0002'
DC EQU H'0001'
C EQU H'0000'
;----- INTCON Bits --------------------------------------------------------
GIE EQU H'0007'
EEIE EQU H'0006'
T0IE EQU H'0005'
INTE EQU H'0004'
RBIE EQU H'0003'
T0IF EQU H'0002'
INTF EQU H'0001'
RBIF EQU H'0000'
;----- OPTION Bits --------------------------------------------------------
NOT_RBPU EQU H'0007'
INTEDG EQU H'0006'
T0CS EQU H'0005'
T0SE EQU H'0004'
PSA EQU H'0003'
PS2 EQU H'0002'
PS1 EQU H'0001'
PS0 EQU H'0000'
;----- EECON1 Bits --------------------------------------------------------
EEIF EQU H'0004'
WRERR EQU H'0003'
WREN EQU H'0002'
WR EQU H'0001'
RD EQU H'0000'
;==========================================================================
;
;I/O Pin useage
; RA0 Output Right close
; RA1 Output Right open
; RA2 Output Left close
; RA3 Output Left open
; RA4/TOCK1 Input
;
; RB0/INT Input
; RB1 Input
; RB2 Input
; RB3 Input
; RB4 Input Jumper to ground To control power on action. Off - move at power on. On no action at power on.
; RB5 Input Push button (Active low)
; RB6 Input Right current limit
; RB7 Input Left current limit
;
;STATE_FLAGS bit useage
;
; Bit0 Right closing
; Bit1 Right opening
; Bit2 Left closing
; Bit3 Left opening
; Bit4 Last direction - set for closing
; Bit5
; Bit6
; Bit7
; define reset and interrupt vector start addresses
org 0 ; start at address 0000h
goto INIT ; normal service routines from Reset vector
org 4 ; interrupt vector 0004h, start interrupt routine here
goto INIT ; interrupt (Should not get here as interrupts not used.)
; **********************************************************************************************
; Initialize
;
ORG 0x0005 ;Start of program memory
DE "V05 03/04/06"
;
INIT BCF INTCON,GIE ;turn off global interrupts
BTFSC INTCON,GIE ;Confirm global interrupts off
goto INIT
BSF STATUS,5 ;Select register bank 1
movlw B'11111111'
movwf TRISB ;Configure port B0-B7 as input
movlw B'00010000'
movwf TRISA ;Port A0-A3 as output , A4 as input
;
movlw B'00000100' ;timer ratio 1:32 (1/100sec). Pull-up Rs on (bit7=0)
movwf OPTION_REG
BCF STATUS,5 ;Select register bank 0
clrf PORTA ;Set initial state with motors stopped
movlw EEPROM0 ;EEPROM address
call EEREAD
movwf STATE_FLAGS
;
movlw D'100' ;Delay for 1 second
call Wait10ms
; ---------------------
; Test jumper for powerup action
;
movfw PORTB
andlw 0x10 ;Test for jumper present (Bit 4)
btfss STATUS, Z
goto MA04
;Main loop
MAIN
movfw PORTB
andlw 0x20 ;Test for push button to be released
btfsc STATUS, Z
goto MAIN ;Loop waiting for button to be released
;
MA01 movfw PORTB
andlw 0x20 ;Test for push button to be pressed
btfss STATUS, Z
goto MA01 ;Loop waiting for button to be pressed
call DELAY
MA02 movfw PORTB
andlw 0x20 ;Test for push button still pressed (de-bounce)
btfss STATUS, Z
goto MA01 ;False press go back to wait loop
;
MA03
movfw PORTB
andlw 0x20 ;Test for push button to be released
btfsc STATUS, Z
goto MA03 ;Loop waiting for button to be released
MA04
btfsc STATE_FLAGS,4 ;set if last direction was closing
goto MA05
call CLOSE
goto MAIN
MA05 call OPEN
goto MAIN
;
;
; ---------------------------------------------------------------------------------------
;
; SUBROUTINES FROM HERE
;
CLOSE
movlw TIMEOUT_VAL
movwf timer1
movlw D'100' ;Value for timer0 to reach zero in 1 second
movwf timer0
movlw 0x05 ;Bits 0 & 2
movwf PORTA ;Set both motors to close
movlw 0x15 ;Bits 0, 2, 4
movwf STATE_FLAGS
movlw EEPROM0 ;EEPROM address
movwf EEADR
movfw STATE_FLAGS
call EWRITE
CLOSE01
call TESTBUTTON ;"Z" set if button pressed
btfsc STATUS, Z
goto CLOSE05
btfss PORTB,6 ;Test for right current limit
goto CLOSE02
call DELAY
btfss PORTB,6 ;Test for right current limit again
goto CLOSE02
bcf PORTA,0 ;Stop right motor
bcf STATE_FLAGS,0 ;Clear right closing flag
CLOSE02
btfss PORTB,7 ;Test for left current limit
goto CLOSE03
call DELAY
btfss PORTB,7 ;Test for left current limit again
goto CLOSE03
bcf PORTA,2 ;Stop left motor
bcf STATE_FLAGS,2 ;Clear left closing flag
CLOSE03
movfw STATE_FLAGS
andlw 0x05 ;Test to see if neither motor closing flag is set
btfsc STATUS, Z ;If zero then finished closing
return
CLOSE04
call TIMEOUT
btfss STATUS, Z ;If set timeout has occured so stop motors
goto CLOSE01
CLOSE05
bcf PORTA,0 ;Stop right motor
bcf STATE_FLAGS,0 ;Clear right closing flag
bcf PORTA,2 ;Stop left motor
bcf STATE_FLAGS,2 ;Clear left closing flag
return
;
; ---------------------------------
;
OPEN
movlw TIMEOUT_VAL
movwf timer1
movlw D'100' ;Value for timer0 to reach zero in 1 second
movwf timer0
movlw 0x0A ;Bits 1 & 3
movwf PORTA ;Set both motors to open
movlw 0x0A ;Bits 1 & 3
movwf STATE_FLAGS
movlw EEPROM0 ;EEPROM address
movwf EEADR
movfw STATE_FLAGS
call EWRITE
OPEN01
call TESTBUTTON ;"Z" set if button pressed (7 Cycles if button not pressed)
btfsc STATUS, Z
goto OPEN05
btfss PORTB,6 ;Test for right current limit
goto OPEN02
call DELAY
btfss PORTB,6 ;Test for right current limit again
goto OPEN02
bcf PORTA,1 ;Stop right motor
bcf STATE_FLAGS,1 ;Clear right opening flag
OPEN02
btfss PORTB,7 ;Test for left current limit
goto OPEN03
call DELAY
btfss PORTB,7 ;Test for left current limit again
goto OPEN03
bcf PORTA,3 ;Stop left motor
bcf STATE_FLAGS,3 ;Clear left opening flag
OPEN03
movfw STATE_FLAGS
andlw 0x0A ;Test to see if neither motor closing flag is set
btfsc STATUS, Z ;If zero then finished opening
return
OPEN04
call TIMEOUT
btfss STATUS, Z ;If set timeout has occured so stop motors
goto OPEN01
OPEN05
bcf PORTA,1 ;Stop right motor
bcf STATE_FLAGS,1 ;Clear right opening flag
bcf PORTA,3 ;Stop left motor
bcf STATE_FLAGS,3 ;Clear left opening flag
return
;
; ---------------------------------
;*****************************************************************************
;
; Function : Test for button press and debounce ("0" for pressed)
; If button pressed "Z" flag will be set
;
; Input: None
;Time 6 cycles if button not pressed
;*****************************************************************************
TESTBUTTON
TB01 movfw PORTB
andlw 0x20 ;Test for push button to be pressed
btfss STATUS, Z
goto TB03 ;No button pressed - return
call DELAY
TB02 movfw PORTB
andlw 0x20 ;Test for push button still pressed (de-bounce)
TB03 return
;*****************************************************************************
DELAY ;Delay for 100 Ms
movlw D'10'
call Wait10ms
;*****************************************************************************
;
; Function : Wait100us
; delays for a multiple of 100us
;
; Input: multiple in W
;
;*****************************************************************************
Wait100us
movwf delay2
d1us002
movlw D'33' ;1 Cycle
movwf delay1 ;1 Cycle
d1us001
decfsz delay1, F ;1 cycle , 2 on skip
goto d1us001 ;2 cycles
decfsz delay2, F
goto d1us002
return
;*****************************************************************************
;
; Function : Wait10ms
; delays for a multiple of 10ms
;
; Input: multiple in W
;
;*****************************************************************************
Wait10ms
movwf delay3
d1ms001
movlw D'100'
call Wait100us
decfsz delay3, F
goto d1ms001
return
;*****************************************************************************
;*****************************************************************************
;
; Function : TIMEOUT
; Stops motors if limit not reached in preset time
; If timeout reached "Z" flag set
; Input: None
;
;*****************************************************************************
;
TIMEOUT
movlw 0x01
call Wait10ms
decfsz timer0
goto TO1
movlw D'100' ;Value for timer0 to reach zero in 1 second
movwf timer0
movfw timer0 ;This instruction makes sure the "Z" flag is clear
decfsz timer1
return
clrw ;Set the "Z" flag
return
TO1 movfw timer0 ;This instruction makes sure the "Z" flag is clear
return
;*****************************************************************************
;
; subroutine to read from EEPROM
;
; Function : EEREAD
;
; Input: EEPROM address to read from (In "W" register)
;
; Output: Date read from EEPROM (In "W" register)
;
;*****************************************************************************
; subroutine to read EEPROM memory
EEREAD movwf EEADR ; indirect special function register
bsf STATUS,RP0 ; select memory bank 1
bsf EECON1,RD ; read EEPROM
RD_RD nop
btfsc EECON1,RD ; skip if RD low (read complete)
goto RD_RD ; wait for low RD (read RD)
bcf STATUS,RP0 ; select bank 0
movf EEDATA,w ; EEPROM value in w
return
;*****************************************************************************
;
; subroutine to write to EEPROM
;
; Function : EWRITE
; Writes data in "W" register to internal EEPROM
; Address oe EEPROM to be written must first be put in EEADR register
;
; Input: Value to write to internal EEPROM
;
;*****************************************************************************
; subroutine to write to EEPROM
EWRITE movwf EEDATA ; data register
bcf INTCON,GIE ; disable interrupts
bsf STATUS,RP0 ; select bank 1
bsf EECON1,WREN ; enable write
movlw 0x55 ; place 55H in w for write sequence
movwf EECON2 ; write 55H to EECON2
movlw 0xAA ; AAH to w
movwf EECON2 ; write AA to EECON2
bsf EECON1,WR ; set WR bit and begin write sequence
bcf EECON1,WREN ; clear WREN bit
WRITE btfsc EECON1,WR ; skip if write complete WR=0 when write complete
goto WRITE ; not written yet
bcf EECON1,EEIF ; clear write interrupt flag
bcf STATUS,RP0 ; select bank 0
; bsf INTCON,GIE ; enable interrupts ;Not required as interrupts not used
return
;*****************************************************************************
END ;final line. This line must be retained.