;***************************************************************
;* Car Alarm System *
;* Main Unit *
;* Version 02 *
;* 1997 *
;* Low voltage immobilizer *
;* Full Interrupt version *
;***************************************************************
LIST P=PIC16C84, R=HEX
INCLUDE "f:\mpasm\include\p16C84.inc"
__CONFIG _XT_OSC & _WDT_OFF & _CP_OFF
;----- Port A bits -----
AlarmSW equ 4
DataOut equ 3
Lights equ 2
Beep equ 1
LED equ 0
;----- Port B bits -----
HiJackSW equ 7
IgnitionSW equ 6
MainSW equ 5
DelaySW equ 4
AlarmON equ 3
AlarmOFF equ 2
IRInp equ 0
;----- AlarmFlags bits -----
OFF_Flag equ 7
ON_Flag equ 6
NullFlag equ 5
IRFlag equ 4
AlarmFlag equ 3
IntrusionFlag equ 2
DelayFlag equ 1
BeepFlag equ 0
;----- Password -----
PASS1 equ 0x03
PASS2 equ 0xc2
PASS3 equ 0xa7
PASS4 equ 0x4f
PASS5 equ 0xe9
PASS6 equ 0x85
PASS7 equ 0x6b
PASS8 equ 0x1d
ALARM_TIME equ 0x0a
ALARM_COUNT equ 0x0a
BEEP_DELAY equ 0x08
LIGHTS_DELAY equ 0x06
LED_DELAY equ 0x02
;----- Local DATA -----
DelayCountLow equ 0x0c
DelayCountHi equ 0x0d
AlarmCount equ 0x0e
IRCount equ 0x0f
AlarmFlags equ 0x10
TempW equ 0x11
TempSTATUS equ 0x12
IRCorrection equ 0x13
Dig1 equ 0x14
Dig2 equ 0x15
Dig3 equ 0x16
Dig4 equ 0x17
Dig5 equ 0x18
Dig6 equ 0x19
Dig7 equ 0x1a
Dig8 equ 0x1b
TransmitCount equ 0x1c
TransmitTimes equ 0x1d
BeepDelay equ 0x1e
LightsDelay equ 0x1f
LedDelay equ 0x20
AlarmTime equ 0x21
;----- CODE -----
org 0
goto Start
; ------------ I N T E R R U P T R O U T I N E -------------
org 0x04 ;min3-max4 mks
movwf TempW ;save W and STATUS
movf STATUS,W
movwf TempSTATUS
btfss INTCON,INTF
goto WatchTimer
clrf Dig1
clrf Dig2
clrf Dig3
clrf Dig4
clrf Dig5
clrf Dig6
clrf Dig7
clrf Dig8
movlw 0xc2
call IRDelay ;delay 194*3-1+5=586 mks
call IRDelay ;delay 194*3-1+5=586 mks
nop
nop
clrf IRCorrection ;reset correction
btfsc PORTB,IRInp ;set correction -3 mks
goto RestoreIntFlag
incf IRCorrection,F
btfsc PORTB,IRInp ;set correction -2 mks
goto SetCorrection
incf IRCorrection,F
btfsc PORTB,IRInp ;set correction -1 mks
goto SetCorrection
incf IRCorrection,F
btfsc PORTB,IRInp ;set correction 0 mks delay 3 mks
goto SetCorrection
incf IRCorrection,F
btfsc PORTB,IRInp ;set correction +1 mks
goto SetCorrection
incf IRCorrection,F
btfsc PORTB,IRInp ;set correction +2 mks
goto SetCorrection
goto RestoreIntFlag
SetCorrection:
movlw 0x7e ;~4 mks after start
call IRDelay ;delay 126*3-1+5=382 mks
nop
nop
bsf STATUS,C ;this STOP bit will end the loop
NextDigit:
rrf Dig8,F
rrf Dig7,F
rrf Dig6,F
rrf Dig5,F
rrf Dig4,F
rrf Dig3,F
rrf Dig2,F
rrf Dig1,F
btfsc STATUS,C ;check for STOP bit
goto Compare
bsf AlarmFlags,NullFlag ;Set the null flag
RetryDigit:
bcf AlarmFlags,IRFlag ;1 mks Reset bit read flag
nop
nop
nop
btfsc PORTB,IRInp ;5th mks look for a bit
bsf AlarmFlags,IRFlag ;Set if bit read
movlw 0x05
movwf IRCount
StartCorrection: ;Delay 35+IRCorrection mks
movf IRCount,W ;for T=400 mks delay 38 mks
subwf IRCorrection,W
btfsc STATUS,C
goto AddCorrection
AddCorrection:
decfsz IRCount,F
goto StartCorrection
nop
movlw 0x6e
call IRDelay ;Delay 110*3-1+5=334 mks
btfss AlarmFlags,IRFlag
goto ResetFlag
btfsc AlarmFlags,NullFlag ;If flag is clear it was "1"
goto Set0
nop
bsf STATUS,C ;Set an overflow flag to read "1"
goto NextDigit
Set0:
bcf STATUS,C ;Reset an overflow flag to read "0"
goto NextDigit
ResetFlag:
movlw 0x02
call IRDelay ;Delay 2*3-1+5=10 mks
btfss AlarmFlags,NullFlag ;Error if an overflow flag already reset
goto RestoreIntFlag
bcf AlarmFlags,NullFlag
goto RetryDigit
Compare:
nop ;401th mks
nop
nop
nop
btfsc PORTB,IRInp ;405th mks watch for clear bit
goto RestoreIntFlag
movlw 0x05
movwf IRCount
StartCorrection1: ;Delay 35+IRCorrection mks
movf IRCount,W ;for T=400 mks delay 38 mks
subwf IRCorrection,W
btfsc STATUS,C
goto AddCorrection1
AddCorrection1:
decfsz IRCount,F
goto StartCorrection1
nop
movlw PASS8
xorwf Dig8,W
btfss STATUS,Z
goto BadCode
movlw PASS7
xorwf Dig7,W
btfss STATUS,Z
goto BadCode
movlw PASS6
xorwf Dig6,W
btfss STATUS,Z
goto BadCode
movlw PASS5
xorwf Dig5,W
btfss STATUS,Z
goto BadCode
movlw PASS4
xorwf Dig4,W
btfss STATUS,Z
goto BadCode
movlw PASS3
xorwf Dig3,W
btfss STATUS,Z
goto BadCode
movlw PASS2
xorwf Dig2,W
btfss STATUS,Z
goto BadCode
movf Dig1,W
andlw b'00001111'
xorlw PASS1
btfss STATUS,Z
goto BadCode
movlw 0x6a ;480 mks
call IRDelay ;delay 106*3-1+5=322 mks
nop
nop
btfsc PORTB,IRInp ;805 mks
goto RestoreIntFlag
movlw 0x05
movwf IRCount
StartCorrection2: ;Delay 35+IRCorrection mks
movf IRCount,W ;for T=400 mks delay 38 mks
subwf IRCorrection,W
btfsc STATUS,C
goto AddCorrection2
AddCorrection2:
decfsz IRCount,F
goto StartCorrection2
nop
movlw 0x75
call IRDelay ;delay 117*3-1+5=355 mks
nop
nop
btfss PORTB,IRInp ;5th mks look for a STOP bit
goto RestoreIntFlag
clrf PORTA
movlw b'11000000'
andwf Dig1,W
btfsc STATUS,Z
goto RestoreIntFlag
iorwf AlarmFlags,F ;Save a valid function (ON/OFF)
btfss AlarmFlags,ON_Flag
goto TestOFF
btfss PORTA,AlarmSW
goto SetBeep ;Toggle beep flag
bcf AlarmFlags,OFF_Flag ;ON flag has the highest priority
goto SetAlarm
TestOFF:
btfss AlarmFlags,OFF_Flag
goto RestoreIntFlag
btfsc PORTA,AlarmSW
goto SetBeep ;Toggle beep flag
movlw 0x32 ;Set 50 ms delay
call SystemAlarm ;Beep and Lights for 100 ms
movlw 0xff
call Delay ;wait for 512 ms
call Delay
btfss AlarmFlags,AlarmFlag ;Another alarm if intrusion flag was set
goto SetAlarm
movlw 0x32 ;Set 50 ms delay
call SystemAlarm
movlw 0xff
call Delay ;wait for 512 ms
call Delay
SetAlarm:
movlw 0x32 ;Set 50 ms delay
call SystemAlarm
movlw 0x03
movwf IRCount ;Set 3 attempts to switch a distance relay
RetrySetAlarm:
btfsc AlarmFlags,ON_Flag
bsf PORTB,AlarmON
btfsc AlarmFlags,OFF_Flag
bsf PORTB,AlarmOFF
movlw 0x05 ;make 5 transmitions (Delay 178 to 306 ms)
movwf TransmitTimes
NextTransmit:
call Transmit
decfsz TransmitTimes,F
goto NextTransmit
bcf PORTB,AlarmON
bcf PORTB,AlarmOFF
btfss AlarmFlags,ON_Flag
goto WatchOFF
btfss PORTA,AlarmSW
goto RestoreIntFlag
goto WatchDone
WatchOFF:
btfsc PORTA,AlarmSW
goto RestoreIntFlag
WatchDone:
movlw 0xff
call Delay ;wait for 256 ms
decfsz IRCount,F
goto RetrySetAlarm
goto RestoreIntFlag
SetBeep:
movlw b'00000001' ;toggle beep flag
xorwf AlarmFlags,F
movlw 0x64 ;set delay for 100 ms
call SystemAlarm
movlw b'00111111'
andwf AlarmFlags,F ;reset ON and OFF flags
goto RestoreIntFlag
BadCode:
bsf AlarmFlags,IntrusionFlag ;Set an intrusion flag for bad code
clrf AlarmTime
RestoreIntFlag:
bcf INTCON,INTF
WatchTimer:
btfss INTCON,T0IF
goto WatchSwitch
bcf INTCON,T0IF ;clear flag
btfsc PORTA,AlarmSW ;if Alarm is OFF skip the rest
goto WatchSwitch
btfsc AlarmFlags,IntrusionFlag ;Alarm if intrusion
goto Intrusion
decf LedDelay,F ;Decrement LED Delay
btfss STATUS,Z ;if Zero then
bcf PORTA,LED ;clear LED and
decfsz AlarmTime,F ;If time not reached then out
goto WatchSwitch
movlw LED_DELAY
movwf LedDelay ;set LED Delay
movlw ALARM_TIME
movwf AlarmTime ;set Alarm Time
bsf PORTA,LED ;Turn LED ON
goto WatchSwitch
Intrusion:
bsf AlarmFlags,AlarmFlag ;save intrusion
bsf PORTA,LED ;Turn ON LED
decf BeepDelay,F ;Decrement BeepDelay
btfss STATUS,Z ;if Zero then
bcf PORTA,Beep ;clear Beep
decf LightsDelay,F ;Decrement LightsDelay
btfss STATUS,Z ;if Zero then
bcf PORTA,Lights ;clear Beep
decfsz AlarmTime,F ;If time not reached then out
goto WatchSwitch
movlw BEEP_DELAY
movwf BeepDelay ;set Alarm Delay
movlw LIGHTS_DELAY
movwf LightsDelay ;set Lights Delay
movlw ALARM_TIME
movwf AlarmTime ;set Alarm Time
btfss AlarmFlags,BeepFlag ;Watch BeepFlag
bsf PORTA,Beep
bsf PORTA,Lights
decfsz AlarmCount,F ;If count not reached then out
goto WatchSwitch
movlw ALARM_COUNT
movwf AlarmCount ;set Alarm Count
bcf AlarmFlags,IntrusionFlag ;clear intrusion flag
bsf INTCON,RBIF ;watch switches
WatchSwitch:
btfss INTCON,RBIF
goto RestoreStatus
comf PORTB,W ;read switches
andlw b'11110000'
btfsc STATUS,Z ;all switches open
goto RestoreStatus
movlw 0x1e
call Delay
comf PORTB,W ;read switches again
andlw b'11110000'
btfsc STATUS,Z ;a less than 30 ms pulse was detected
goto RestoreStatus
bsf AlarmFlags,IntrusionFlag ;Set an intrusion if some switches closed
clrf AlarmTime
RestoreStatus:
bcf INTCON,RBIF
movf TempSTATUS,W ;Restore W and STATUS
movwf STATUS
movf TempW,W
retfie
; ------------ S U B R O U T I N E S -------------
Delay ;W mks delay with 4MHz oscilator
movwf DelayCountHi
; clrf DelayCountLow
DelayLoop:
; nop
; incfsz DelayCountLow,F
; goto DelayLoop
decfsz DelayCountHi,F
goto DelayLoop
return
IRDelay
movwf IRCount ;delay W*3-1+5 mks
DelayStart:
decfsz IRCount,F
goto DelayStart
return
Transmit
movlw 0x0a
call Delay ;wait for 10 ms
movlw 0x40
movwf TransmitCount ;64 bits transmition
bsf PORTA,DataOut
nop
nop
movlw 0x02
call IRDelay ;delay 2*3-1+5=10 mks
bcf PORTA,DataOut
movlw 0xc4
call IRDelay ;delay 196*3-1+5=592 mks
call IRDelay ;delay 196*3-1+5=592 mks
NextDig:
bsf PORTA,DataOut
bcf STATUS,C
rrf Dig8,F
rrf Dig7,F
rrf Dig6,F
rrf Dig5,F
rrf Dig4,F
rrf Dig3,F
rrf Dig2,F
rrf Dig1,F
nop
nop
nop
nop
bcf PORTA,DataOut
movlw 0x0a
call IRDelay ;delay 10*3-1+5=34
btfss STATUS,C
goto Send0
movlw 0x84
call IRDelay ;delay 132*3-1+5=400 mks
Send0:
movlw 0x71
call IRDelay ;delay 113*3-1+5=343 mks
decfsz TransmitCount,F
goto NextDig
nop
bsf PORTA,DataOut
nop
nop
movlw 0x02
call IRDelay ;delay 2*3-1+5=10 mks
bcf PORTA,DataOut
movlw 0xc4
call IRDelay ;delay 196*3-1+5=592 mks
call IRDelay ;delay 196*3-1+5=592 mks
bsf PORTA,DataOut
nop
nop
movlw 0x02
call IRDelay ;delay 2*3-1+5=10 mks
bcf PORTA,DataOut
return
SystemAlarm
btfss AlarmFlags,BeepFlag
bsf PORTA,Beep
bsf PORTA,Lights
call Delay
call Delay
bcf PORTA,Beep
bcf PORTA,Lights
return
; ------------ M A I N -------------
Start:
clrf PORTA
clrf PORTB
clrf EEDATA
clrf EEADR
clrf AlarmFlags
movlw ALARM_COUNT
movwf AlarmCount ;set Alarm Count
clrf BeepDelay
clrf LightsDelay
clrf LedDelay
clrf AlarmTime
bsf STATUS,RP0 ;set bank 1
movlw b'00010000' ;Port A
movwf TRISA
movlw b'11110011' ;Port B
movwf TRISB
movlw b'11010001' ;disable pull-up and enable timer0
movwf OPTION_REG
bcf STATUS,RP0 ;set bank 0
movlw b'10111000' ;enable interrupts
movwf INTCON
Main:
goto Main
org 0x3ff
goto Start ;Restart if got here
end