;Program for control the internal car light.
;Version V1.40
;Used microcontroller - PIC12F629

			LIST P=12F629
			INCLUDE <P12F629.inc>
			__config H'04C'

LIGHT_CONTROL						equ		0					;lamp control pin
DOOR_SWITCH							equ		1					;Driver Door switch input
CENTRAL_LOCK_ON						equ		2					;Alarm input - inverted
CENTRAL_LOCK_OFF					equ		4					;Alarm input
POWER_SWITCH						equ		5					;Power switch input
LIGHT_STATE							equ		0					;Flag for store light state
LONG_CONT_LIGHT						equ		1
DRIVER_DOOR_WAS_OPENED				equ		2
DOOR_OPEN							equ		0
DRIVER_DOOR							equ		1
PASSENGER_DOOR						equ		2
COUNTER1_200ms_IDLE					equ		0xFF
COUNTER2_200ms_IDLE					equ		0xA0
COUNTER1_50ms_IDLE					equ		0xFF
COUNTER2_50ms_IDLE					equ		0x2A
COUNTER1_15s_WAIT_10_S				equ		0xFF
COUNTER2_15s_WAIT_10_S				equ		0xFF
COUNTER3_15s_WAIT_10_S				equ		d'2'
COUNTER4_200ms_WAIT_10_S			equ		0xFF
COUNTER5_200ms_WAIT_10_S			equ		0x07
COUNTER4_50ms_WAIT_10_S				equ		0xFF
COUNTER5_50ms_WAIT_10_S				equ		0x02
LIGHT_ON_COUNTER_WAIT_10_S			equ		d'90'
LIGHT_OFF_COUNTER_WAIT_10_S			equ		d'20'
COUNTER1_1s_SLOWLY_OFF_LIGHT		equ		0xFF
COUNTER2_1s_SLOWLY_OFF_LIGHT		equ		0x40	;	0x25 - for 1 sec.
LIGHT_ON_COUNTER_SLOWLY_OFF			equ		d'90'
LIGHT_OFF_COUNTER_SLOWLY_OFF		equ		d'20'
COUNTER1_1s_SLOWLY_ON_LIGHT			equ		0xFF
COUNTER2_1s_SLOWLY_ON_LIGHT			equ		0x25
LIGHT_ON_COUNTER_SLOWLY_ON			equ		d'20'
LIGHT_OFF_COUNTER_SLOWLY_ON			equ		d'100'

	cblock 0x20
			Counter1
			Counter2
			Counter3
			Counter4
			Counter5
			TempCounter
			TempCounter1
			LightOnTimer
			LightOffTimer
			FlagReg
			ResultReg
			LightOnTimerBase
			LightOffTimerBase
	endc
	


			org		0x0
			goto	START

			org		0x20
;************************************************************************
;START -> Init internal hardware, some ram if needed too.				*
;************************************************************************
START:
			clrwdt
			clrf	STATUS
			movlw	OPTION_REG
			movwf	FSR
			movlw	b'11111111'											
			movwf	INDF											;Wake-up on change enable, WDT on max.
			clrf	INTCON
			movlw	PIE1
			movwf	FSR
			clrf	INDF
			clrf	PIR1
			movlw	PCON
			movwf	FSR
			movlw	b'00000011'
			movwf	INDF
			movlw	b'00000111'
			movwf	CMCON
			clrf	GPIO
			movlw	TRISIO
			movwf	FSR
			movlw	b'00111110'
			movwf	INDF
			movlw	IOCB
			movwf	FSR
			movlw	b'00010010'
			movwf	INDF
			
			movlw	0x20
			movwf	FSR
CLEAR_RAM
			clrf	INDF
			incf	FSR,f
			btfss	FSR,7
			goto	CLEAR_RAM
			call	DELAY_50ms
;************************************************************************
;* IDLE STATE -> Light is off, sleep and wait openning the door.		*
;************************************************************************
IDLE_STATE:	
		;	bsf		GPIO,LIGHT_CONTROL	
		;	call	DELAY_50ms
			bcf		GPIO,LIGHT_CONTROL	
			btfss	GPIO,CENTRAL_LOCK_OFF 
			goto	IDLE_TEST_LOCK_OFF
			btfss	GPIO,DOOR_SWITCH
			goto 	IDLE_DOOR_IS_OPEN

IDLE_SLEEP:
			movlw	b'00001000'											;Enable wake up from pin change 
			movwf	INTCON				
			movf	GPIO,w												;Read inputs before sleep
			bcf		INTCON,GPIF
			sleep
			nop
			goto	IDLE_STATE											;If door is closed - sleep

IDLE_DOOR_IS_OPEN:
			movlw	COUNTER1_200ms_IDLE									;Set COUNTER1 & COUNTER2 for looping 200ms
			movwf	Counter1
			movlw	COUNTER2_200ms_IDLE
			movwf	Counter2

IDLE_TEST_200_MS:														;Check 200ms to clear door switch noise
			btfsc	GPIO,DOOR_SWITCH
			goto	IDLE_STATE
			decfsz	Counter1,f
			goto	IDLE_TEST_200_MS
			decfsz 	Counter2,f	
			goto 	IDLE_TEST_200_MS
			goto	CONT_LIGHT_STATE									;Turn on the lights

IDLE_TEST_LOCK_OFF:
			movlw	COUNTER1_50ms_IDLE									;Set COUNTER1 & COUNTER2 for looping 100ms
			movwf	Counter1
			movlw	COUNTER2_50ms_IDLE
			movwf	Counter2

IDLE_TEST_LOCK_OFF_100_MS:												;Check 100ms to clear alarm pulse noise 
			btfsc	GPIO,CENTRAL_LOCK_OFF
			goto	IDLE_STATE
			decfsz	Counter1,f
			goto	IDLE_TEST_LOCK_OFF_100_MS
			decfsz 	Counter2,f	
			goto 	IDLE_TEST_LOCK_OFF_100_MS
			call	SLOWLY_ON_LIGHT_STATE
			goto	WAIT_10_S_STATE

;************************************************************************
;* CONT. LIGHT STATE -> Light is on, stay and wait closing the door.	*
;************************************************************************				
CONT_LIGHT_STATE:														;Lamp is turned ON outside
			bcf		GPIO,LIGHT_CONTROL									;Do not turn it On from the pic
			clrwdt														;Calm the dog
			btfsc	GPIO,DOOR_SWITCH
			goto	CONT_LIGHT_DOOR_IS_CLOSED
			goto	CONT_LIGHT_STATE

CONT_LIGHT_DOOR_IS_CLOSED:
			bsf		GPIO,LIGHT_CONTROL									;turn on light
																		
;************************************************************************
;* WAIT 10 s -> The door is closed, light is on for 10s.				*
;************************************************************************
WAIT_10_S_STATE:															;Door is closed, wait 10 seconds
									
			movlw	COUNTER1_15s_WAIT_10_S								;Set COUNTER1,2 & 3 for looping 10s
			movwf	Counter1
			movlw	COUNTER2_15s_WAIT_10_S
			movwf	Counter2
			movlw	COUNTER3_15s_WAIT_10_S
			movwf	Counter3				
			movlw	LIGHT_ON_COUNTER_WAIT_10_S
			movwf	LightOnTimer
			bsf		FlagReg,LIGHT_STATE

WAIT_10_S_DOOR_IS_CLOSED:
WAIT_10_S_CENTRAL_LOCK_INACTIVE:
WAIT_10_S_POWER_SWITCH_INACTIVE:
			
			clrwdt														;Calm the dog		
			btfss	FlagReg,LIGHT_STATE									;Process the light_1
			goto	WAIT_10_S_LIGHT_IS_OFF
WAIT_10_S_LIGHT_IS_ON:
			bsf		GPIO,LIGHT_CONTROL									;Turn on light
			decfsz	LightOnTimer,f
			goto	WAIT_10_S_CHECK_SWITCH
			bcf		FlagReg,LIGHT_STATE
			movlw	LIGHT_OFF_COUNTER_WAIT_10_S
			movwf	LightOffTimer
			goto	WAIT_10_S_CHECK_SWITCH
WAIT_10_S_LIGHT_IS_OFF:
			bcf		GPIO,LIGHT_CONTROL										;Turn off light
			decfsz	LightOffTimer,f
			goto	WAIT_10_S_CHECK_SWITCH
			bsf		FlagReg,LIGHT_STATE
			movlw	LIGHT_ON_COUNTER_WAIT_10_S
			movwf	LightOnTimer

WAIT_10_S_CHECK_SWITCH:
			movlw	0x20
			movwf	TempCounter
WAIT_10_S_TEMP_DELAY
			decfsz	TempCounter,f
			goto	WAIT_10_S_TEMP_DELAY
			btfsc	FlagReg,LIGHT_STATE
			goto	WAIT_10_S_SKIP_DOOR_TEST_1
			btfss	GPIO,DOOR_SWITCH											;Wait 10s with closed door
			goto	WAIT_10_S_DOOR_IS_OPENED
WAIT_10_S_SKIP_DOOR_TEST_1:
			btfss	GPIO,POWER_SWITCH											;Test power switch
			goto	WAIT_10_S_POWER_SWITCH_ACTIVE				
			btfss	GPIO,CENTRAL_LOCK_ON										;Test central lock on
			goto	WAIT_10_S_LOCK_ON			
			decfsz	Counter1,f
			goto	WAIT_10_S_DOOR_IS_CLOSED
			decfsz	Counter2,f
			goto	WAIT_10_S_DOOR_IS_CLOSED
			decfsz	Counter3,f
			goto	WAIT_10_S_DOOR_IS_CLOSED
			call	SLOWLY_OFF_LIGHT_STATE
			goto	IDLE_STATE									;Go to Slowly turn off the lights

WAIT_10_S_DOOR_IS_OPENED:

			movlw	COUNTER4_200ms_WAIT_10_S								;Set COUNTER4 & COUNTER5 for looping 200ms
			movwf	Counter4
			movlw	COUNTER5_200ms_WAIT_10_S
			movwf	Counter5	

WAIT_10_S_CHECK_OPENNING:
			btfss	FlagReg,LIGHT_STATE											;Process the light_2
			goto	WAIT_10_S_LIGHT_IS_OFF_2
WAIT_10_S_LIGHT_IS_ON_2:
			bsf		GPIO,LIGHT_CONTROL
			decfsz	LightOnTimer,f
			goto	WAIT_10_S_CHECK_SWITCH_2
			bcf		FlagReg,LIGHT_STATE
			movlw	LIGHT_OFF_COUNTER_WAIT_10_S
			movwf	LightOffTimer
			goto	WAIT_10_S_CHECK_SWITCH_2
WAIT_10_S_LIGHT_IS_OFF_2:
			bcf		GPIO,LIGHT_CONTROL
			decfsz	LightOffTimer,f
			goto	WAIT_10_S_CHECK_SWITCH_2
			bsf		FlagReg,LIGHT_STATE
			movlw	LIGHT_ON_COUNTER_WAIT_10_S
			movwf	LightOnTimer

WAIT_10_S_CHECK_SWITCH_2:
			movlw	0x20
			movwf	TempCounter
WAIT_10_S_TEMP_DELAY_2
			decfsz	TempCounter,f
			goto	WAIT_10_S_TEMP_DELAY_2
			btfsc	FlagReg,LIGHT_STATE
			goto	WAIT_10_S_SKIP_DOOR_TEST_2
			btfsc	GPIO,DOOR_SWITCH											;Check 200ms to clear door switch noise
			goto	WAIT_10_S_DOOR_IS_CLOSED
WAIT_10_S_SKIP_DOOR_TEST_2:
			decfsz	Counter4,f
			goto	WAIT_10_S_CHECK_OPENNING
			decfsz 	Counter5,f	
			goto	WAIT_10_S_CHECK_OPENNING
			goto	CONT_LIGHT_STATE											;Door is stable open, go to LIGHT STATE


WAIT_10_S_POWER_SWITCH_ACTIVE:
			movlw	COUNTER4_200ms_WAIT_10_S										;Set COUNTER4 & COUNTER5 for looping 200ms
			movwf	Counter4
			movlw	COUNTER5_200ms_WAIT_10_S
			movwf	Counter5	

WAIT_10_S_CHECK_SWITCHING:
			btfss	FlagReg,LIGHT_STATE												;Process the light_3
			goto	WAIT_10_S_LIGHT_IS_OFF_3
WAIT_10_S_LIGHT_IS_ON_3:
			bsf		GPIO,LIGHT_CONTROL
			decfsz	LightOnTimer,f
			goto	WAIT_10_S_CHECK_POWER_SWITCH
			bcf		FlagReg,LIGHT_STATE
			movlw	LIGHT_OFF_COUNTER_WAIT_10_S
			movwf	LightOffTimer
			goto	WAIT_10_S_CHECK_POWER_SWITCH
WAIT_10_S_LIGHT_IS_OFF_3:
			bcf		GPIO,LIGHT_CONTROL
			decfsz	LightOffTimer,f
			goto	WAIT_10_S_CHECK_POWER_SWITCH
			bsf		FlagReg,LIGHT_STATE
			movlw	LIGHT_ON_COUNTER_WAIT_10_S
			movwf	LightOnTimer

WAIT_10_S_CHECK_POWER_SWITCH:
			movlw	0x20
			movwf	TempCounter
WAIT_10_S_TEMP_DELAY_3
			decfsz	TempCounter,f
			goto	WAIT_10_S_TEMP_DELAY_3
			btfsc	GPIO,POWER_SWITCH												;Check 200ms to clear powers switch noise
			goto	WAIT_10_S_POWER_SWITCH_INACTIVE
			decfsz	Counter4,f
			goto	WAIT_10_S_CHECK_SWITCHING
			decfsz 	Counter5,f	
			goto	WAIT_10_S_CHECK_SWITCHING
			call	SLOWLY_OFF_LIGHT_STATE
			goto	IDLE_STATE														;Power switch activated, go to Slowly off

WAIT_10_S_LOCK_ON:
			movlw	COUNTER4_50ms_WAIT_10_S										;Set COUNTER4 & COUNTER5 for looping 50ms
			movwf	Counter4
			movlw	COUNTER5_50ms_WAIT_10_S
			movwf	Counter5	

WAIT_10_S_CHECK_LOCKING:
			btfss	FlagReg,LIGHT_STATE												;Process the light_3
			goto	WAIT_10_S_LIGHT_IS_OFF_4
WAIT_10_S_LIGHT_IS_ON_4:
			bsf		GPIO,LIGHT_CONTROL
			decfsz	LightOnTimer,f
			goto	WAIT_10_S_CHECK_LOCK_ON
			bcf		FlagReg,LIGHT_STATE
			movlw	LIGHT_OFF_COUNTER_WAIT_10_S
			movwf	LightOffTimer
			goto	WAIT_10_S_CHECK_LOCK_ON
WAIT_10_S_LIGHT_IS_OFF_4:
			bcf		GPIO,LIGHT_CONTROL
			decfsz	LightOffTimer,f
			goto	WAIT_10_S_CHECK_LOCK_ON
			bsf		FlagReg,LIGHT_STATE
			movlw	LIGHT_ON_COUNTER_WAIT_10_S
			movwf	LightOnTimer

WAIT_10_S_CHECK_LOCK_ON:
			movlw	0x20
			movwf	TempCounter
WAIT_10_S_TEMP_DELAY_4
			decfsz	TempCounter,f
			goto	WAIT_10_S_TEMP_DELAY_4
			btfsc	GPIO,CENTRAL_LOCK_ON												;Check 50ms to clear alarm noise
			goto	WAIT_10_S_CENTRAL_LOCK_INACTIVE
			decfsz	Counter4,f
			goto	WAIT_10_S_CHECK_LOCKING
			decfsz 	Counter5,f	
			goto	WAIT_10_S_CHECK_LOCKING
			call	SLOWLY_OFF_LIGHT_STATE
			goto	IDLE_STATE														;Power switch activated, go to Slowly off	
;************************************************************************
;* SLOWLY OFF LIGHT -> Slowly shut off the lights aprox. 1 sec			*
;************************************************************************			
SLOWLY_OFF_LIGHT_STATE:
			movlw	COUNTER1_1s_SLOWLY_OFF_LIGHT						;Set COUNTER1,2 & 3 for looping 1s
			movwf	Counter1
			movlw	COUNTER2_1s_SLOWLY_OFF_LIGHT
			movwf	Counter2				
			movlw	LIGHT_ON_COUNTER_SLOWLY_OFF
			movwf	LightOnTimerBase
			movwf	LightOnTimer
			movlw	LIGHT_OFF_COUNTER_SLOWLY_OFF
			movwf	LightOffTimerBase
			bsf		FlagReg,LIGHT_STATE

SLOWLY_OFF_LIGHT_LOOP:
			
			clrwdt														;Calm the dog		
			btfss	FlagReg,LIGHT_STATE									;Process the light_1
			goto	SLOWLY_OFF_LIGHT_LIGHT_IS_OFF
SLOWLY_OFF_LIGHT_LIGHT_IS_ON:
			bsf		GPIO,LIGHT_CONTROL
			decfsz	LightOnTimer,f
			goto	SLOWLY_OFF_LIGHT_MENAGE_PWM
			bcf		FlagReg,LIGHT_STATE
			movf	LightOffTimerBase,w
			movwf	LightOffTimer
			goto	SLOWLY_OFF_LIGHT_MENAGE_PWM
SLOWLY_OFF_LIGHT_LIGHT_IS_OFF:
			bcf		GPIO,LIGHT_CONTROL
			decfsz	LightOffTimer,f
			goto	SLOWLY_OFF_LIGHT_MENAGE_PWM
			bsf		FlagReg,LIGHT_STATE
			movf	LightOnTimerBase,w
			movwf	LightOnTimer

SLOWLY_OFF_LIGHT_MENAGE_PWM:
		
			movlw	0x20
			movwf	TempCounter
SLOWLY_OFF_LIGHT_TEMP_DELAY
			decfsz	TempCounter,f
			goto	SLOWLY_OFF_LIGHT_TEMP_DELAY
			decfsz	Counter1,f
			goto	SLOWLY_OFF_LIGHT_LOOP
			decf	LightOnTimerBase,f							;Manipulate PWM
		;	decf	LightOnTimerBase,f							;for 1 sec
			incf	LightOffTimerBase,f							;for 1 sec
			incf	LightOffTimerBase,f
			decfsz	Counter2,f
			goto	SLOWLY_OFF_LIGHT_LOOP
			return									;Go to idle state

;************************************************************************
;* SLOWLY ON LIGHT -> Slowly shut off the lights aprox. 1 sec			*
;************************************************************************			
SLOWLY_ON_LIGHT_STATE:
			movlw	COUNTER1_1s_SLOWLY_ON_LIGHT						;Set COUNTER1,2 & 3 for looping 1s
			movwf	Counter1
			movlw	COUNTER2_1s_SLOWLY_ON_LIGHT
			movwf	Counter2				
			movlw	LIGHT_ON_COUNTER_SLOWLY_ON
			movwf	LightOnTimerBase
			movwf	LightOnTimer
			movlw	LIGHT_OFF_COUNTER_SLOWLY_ON
			movwf	LightOffTimerBase
			bsf		FlagReg,LIGHT_STATE

SLOWLY_ON_LIGHT_LOOP:
			
			clrwdt														;Calm the dog		
			btfss	FlagReg,LIGHT_STATE									;Process the light_1
			goto	SLOWLY_ON_LIGHT_LIGHT_IS_OFF
SLOWLY_ON_LIGHT_LIGHT_IS_ON:
			bsf		GPIO,LIGHT_CONTROL
			decfsz	LightOnTimer,f
			goto	SLOWLY_ON_LIGHT_MENAGE_PWM
			bcf		FlagReg,LIGHT_STATE
			movf	LightOffTimerBase,w
			movwf	LightOffTimer
			goto	SLOWLY_ON_LIGHT_MENAGE_PWM
SLOWLY_ON_LIGHT_LIGHT_IS_OFF:
			bcf		GPIO,LIGHT_CONTROL
			decfsz	LightOffTimer,f
			goto	SLOWLY_ON_LIGHT_MENAGE_PWM
			bsf		FlagReg,LIGHT_STATE
			movf	LightOnTimerBase,w
			movwf	LightOnTimer

SLOWLY_ON_LIGHT_MENAGE_PWM:
		
			movlw	0x20
			movwf	TempCounter
SLOWLY_ON_LIGHT_TEMP_DELAY
			decfsz	TempCounter,f
			goto	SLOWLY_ON_LIGHT_TEMP_DELAY

			decfsz	Counter1,f
			goto	SLOWLY_ON_LIGHT_LOOP
			decf	LightOffTimerBase,f	
			decf	LightOffTimerBase,f		
		;	decf	LightOffTimerBase,f	
		;	decf	LightOffTimerBase,f									;Manipulate PWM
		;	incf	LightOnTimerBase,f
		;	incf	LightOnTimerBase,f
			incf	LightOnTimerBase,f
			incf	LightOnTimerBase,f
			decfsz	Counter2,f
			goto	SLOWLY_ON_LIGHT_LOOP
			return													;Go to idle state


;************************************************************************
;* DELAY_50ms															*
;************************************************************************
DELAY_50ms:
			
			movlw	0xFF
			movwf	TempCounter
			movlw	0x42
			movwf	TempCounter1

DELAY_50ms_LOOP:
			
			decfsz	TempCounter,f
			goto	DELAY_50ms_LOOP
			decfsz	TempCounter1,f
			goto	DELAY_50ms_LOOP
			return
			END
