; Program ALARMSRC.ASM
;
; PIC program for vibration 446 bike alarm
;
; (c)2003 Tim Dunne

; Version 1.3
;  * shorten rangecheck pulse to avoid popping on pager radio
;               (added DELAY_MS to wait for no. of mS in W)
;
; Version 1.2
;  * press call twice on alarm due to short call tone
;    		on 'C' radio module
;  * timings adjusted for luggage loop alarm also
;  * insert delay going into alarm to remove key rollover bug
;
; Version 1.1
;  * add luggage loop detection 
;  * decrease rangecheck to 5 seconds


; aseembler directives

          LIST p=16f84
	  #include <p16f84.inc>
          __CONFIG 3FF1H

     CONSTANT BASE_VAR=0CH

; variable declarations

LOOP1          EQU BASE_VAR+0
LOOP2          EQU BASE_VAR+1
W_SAVE         EQU BASE_VAR+2
STATUS_SAVE    EQU BASE_VAR+3
QSECS          EQU BASE_VAR+4
COUNTER_SV     EQU BASE_VAR+5
LOOP1_SV       EQU BASE_VAR+6
LOOP2_SV       EQU BASE_VAR+7
QSECS_SV       EQU BASE_VAR+8
LOOP1_MS       EQU BASE_VAR+9
LOOP2_MS       EQU BASE_VAR+10
LOOP1_MS_SV    EQU BASE_VAR+11
LOOP2_MS_SV    EQU BASE_VAR+12				

; program setup

     ORG 000H

     GOTO MAIN 			; main program vector

     ORG 004H

     GOTO INT_SERV		; interrupt vector

MAIN:
     BSF STATUS, RP0    	; select register bank 1
     MOVLW B'00000000'
     MOVWF TRISA		; set all port a bits to outputs
     MOVLW B'00010001'
     MOVWF TRISB		; set port b bits RB0 and RB4 to inputs, 
				; all others outputs
     BCF STATUS, RP0    	; select register bank 0


     MOVLW B'00011100'	
     MOVWF PORTA		; set radio control lines high 
				; and led lines low
     MOVLW B'11101110'	
     MOVWF PORTB		; set unused outputs on port b high
     
     		
     BSF PORTA,0
     BSF PORTA,1		; turn on both leds for orange
     MOVLW D'8'
     CALL QUARTER		; wait 2 seconds for radio to settle
     BCF PORTA,2		; press power button
     MOVLW D'12'
     CALL QUARTER       	; wait 3 seconds for radio to turn on
     BCF PORTA,0
     BCF PORTA,1		; turn off both leds
     BSF PORTA,2  		; release POWER button							
     	
     BSF STATUS, RP0    	; select register bank 1
     BSF OPTION_REG, INTEDG   	; interupt on positive
     BCF STATUS, RP0    	; select register bank 0
     BCF INTCON, INTF   	; clear interrupt flag
     BCF INTCON, RBIF
     BSF INTCON, INTE   	; enable RB0 interrupts
     BSF INTCON, RBIE		; enable RB4-RB7 change interrupt
     BSF INTCON, GIE    	; enable interrupts
     MOVLW D'4'
     CALL QUARTER		; 1 second delay before rangecheck

RANGECHECK:
     BSF PORTA,1		; turn on red led
     BCF PORTA,3		; press PTT button
     MOVLW D'150'
     CALL DELAY_MS		; broadcast for 150mS
     BCF PORTA,1		; turn off red led
     BSF PORTA,3		; release PTT button	

     MOVLW D'20'
     CALL QUARTER		; wait 5 seconds	

     GOTO RANGECHECK		; go back and do it again

; End of Main

DELAY_250:               	; 250 msec delay

     MOVLW D'250'
     MOVWF LOOP2
DELAY_1:
     MOVLW D'110'
     MOVWF LOOP1
INNER:    
     NOP
     NOP
     NOP
     NOP
     NOP
     NOP
     NOP
     DECFSZ LOOP1, F
     GOTO INNER
     DECFSZ LOOP2, F
     GOTO DELAY_1
     RETURN    

DELAY_MS:               	; miliseconds delay

     MOVWF LOOP2_MS
DELAY1_MS:
     MOVLW D'110'
     MOVWF LOOP1_MS
INNER_MS:    
     NOP
     NOP
     NOP
     NOP
     NOP
     NOP
     NOP
     DECFSZ LOOP1_MS, F
     GOTO INNER_MS
     DECFSZ LOOP2_MS, F
     GOTO DELAY1_MS
     RETURN    

QUARTER:			; pause for period in W in 
				; .25 second resolution
     MOVWF QSECS
QLOOP:
     CALL DELAY_250		; wait for 250 miliseconds
     DECFSZ QSECS,F		; decrement counter
     GOTO QLOOP			; loop again if result not zero
     RETURN

INT_SERV:			; interrupt service routine 
     MOVWF W_SAVE       	; save W
     SWAPF STATUS, W    	; save STATUS 
     MOVWF STATUS_SAVE

     BCF STATUS, RP0    	; be sure we are in bank 0

     MOVFW LOOP1
     MOVWF LOOP1_SV
     MOVFW LOOP2
     MOVWF LOOP2_SV
     MOVFW QSECS
     MOVWF QSECS_SV		
     MOVFW LOOP1_MS
     MOVWF LOOP1_MS_SV
     MOVFW LOOP2_MS
     MOVWF LOOP2_MS_SV		; save current state of variables

     BTFSS INTCON, RBIF		; is this the luggage loop interrupt?
     GOTO VIBEALARM		; no? must be vibration	

     BTFSC PORTB, 4		; has the loop been broken?
     GOTO CLEAR_RBINTF		; if not, clear interrupt and return

     BCF PORTA,1		; turn off red led
     BSF PORTA,0		; turn on green led
     BSF PORTA,3		; ensure PTT is not pressed
     MOVLW D'4'
     CALL QUARTER               ; defeat key rollover	

LUGGAGEALARM:
     BCF PORTA,4		; press call button
     MOVLW D'6'
     CALL QUARTER		; wait 1.5 seconds

     BSF PORTA,4		; release call button

     MOVLW D'16'
     CALL QUARTER		; wait for 4 seconds
     
     BTFSC PORTB,4		; has loop been restored?
     GOTO LUGGAGEALARM		; no? repeat alarm

     BCF PORTA,0		; turn off green led

CLEAR_RBINTF
     MOVF PORTB, 1		; clear portb mismatch
     BCF INTCON, RBIF		; clear RB4-RB7 interrupt
     GOTO ENDINT		; restore variables and return

VIBEALARM:
     BCF PORTA,1		; turn off red led
     BSF PORTA,0		; turn on green led
     BSF PORTA,3		; ensure PTT is not pressed
     MOVLW D'4'
     CALL QUARTER               ; defeat key rollover

     BCF PORTA,4		; press call button
     MOVLW D'6'
     CALL QUARTER		; wait 1.5 seconds
     BSF PORTA,4		; release call button
     MOVLW D'16'
     CALL QUARTER		; wait for 4 seconds
     BCF PORTA,4		; press call button
     MOVLW D'6'
     CALL QUARTER		; wait 1.5 seconds
     BSF PORTA,4		; release call button
     MOVLW D'18'
     CALL QUARTER		; wait for 4.5 seconds
     
     BCF PORTA,0		; turn off green led
    
     BCF INTCON, INTF		; indicate that interrupt has been 
				; serviced

ENDINT:
     MOVFW LOOP1_SV
     MOVWF LOOP1
     MOVFW LOOP2_SV
     MOVWF LOOP2
     MOVFW QSECS_SV
     MOVWF QSECS	
     MOVFW LOOP1_MS_SV
     MOVWF LOOP1_MS
     MOVFW LOOP2_MS_SV
     MOVWF LOOP2_MS		; restore variables	
     
     SWAPF STATUS_SAVE, W
     MOVWF STATUS		; restore W and STATUS
     SWAPF W_SAVE, F
     SWAPF W_SAVE, W     

     RETFIE

     END