;*************************************************************** ;* 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