list p=12F635, b=8, c= 102, n=71, t=on, st=off, f=inhx32
;******************************************************************
;* *
;* Filename: Ignition 12F635 v2.asm *
;* Author: Mike McLaren, K8LH *
;* Date: 16-Feb-10 (last revision 16-Feb-10) *
;* *
;* 12F635 Single Button Ignition/Starter experiment (short *
;* and long switch press detection) *
;* *
;* *
;* MPLab: 8.14 (tabs=8) *
;* MPAsm: 5.15 *
;* *
;******************************************************************
#include <p12f635.inc>
errorlevel -302
radix dec
__config _FCMEN_OFF&_IESO_OFF&_MCLRE_OFF&_WDT_OFF&_INTRC_OSC_NOCLKOUT
;--< hardware >----------------------------------------------------
#define ignition GPIO,0 ; GP0 = active hi ignition relay
#define starter GPIO,1 ; GP1 = active hi starter relay
;--< variables >---------------------------------------------------
swnew equ 0x40 ; fresh switch sample (b3 bit)
swold equ 0x41 ; switch state latch (b3 bit)
mstmr equ 0x42 ; msec timer
swtmr equ 0x43 ; 1 sec switch timer
;--< constants >---------------------------------------------------
#define running swold,0 ; running flag
;--< macros >------------------------------------------------------
;
; uDelay(Tcy) in-line delay macro, range 1..1023 cycles,
; produces 1 to 6 instructions.
;
clock equ 4 ; 4-MHz clock
usecs equ clock/4 ; cycles/usec multiplier
uDelay macro pTime
local dloop
if pTime > 3
movlw (pTime)/4-1 ;
dloop addlw -1 ;
bc dloop ;
endif
if pTime%4 & 1
nop ; 1 cycle
endif
if pTime%4 & 2
goto $+1 ; 2 cycles
endif
endm
;******************************************************************
;* Reset Vector *
;******************************************************************
org 0x0000
v_Reset
clrf STATUS ; |B0
movlw b'00000111' ; |B0
movwf CMCON0 ; comparator off |B0
clrf GPIO ; clear GPIO output latches |B0
bsf STATUS,RP0 ; bank 1 |B1
movlw b'00001000' ; GP3 input, all others outputs |B1
movwf TRISIO ; |B1
;
; setup INTOSC for 4 MHz
;
movlw b'01100000' ; |B1
movwf OSCCON ; 4-mhz INTOSC system clock |B1
Stable btfss OSCCON,HTS ; oscillator stable? |B1
goto Stable ; no, branch, else |B1
bcf STATUS,RP0 ; bank 0 |B0
clrf swold ; clear switch state latch |B0
clrf swtmr ; clear 1 second timer |B0
clrc ; clear Carry |B0
;
; unsigned char swnew = 0; // fresh switch sample
; unsigned char swold = 0; // switch state latch
; unsigned char mstmr = 0; // 32-msec debounce/beep timer
; unsigned char swtmr = 0; // 1-second switch timer
;
; #define ignition gpio.0 // GP0, active hi relay output
; #define starter gpio.1 // GP1, active hi relay output
; #define running swold.0 // flag
;
; #define newpress swnew.3 == 1 && swold.3 == 0
; #define newrelease swnew.3 == 0 && swold.3 == 1
; #define allowstart ignition == 1 && running == 0
;
; while(1)
; { delay_ms(32); // 32-msec debounce intervals
; swnew = ~gpio; // sample active lo switch GP3
; if(newpress) // if "new press"
; { swold.3 = 1; // update switch state latch
; swtmr = 1000/32; // start 1 second timer
; beep1(); // send a single beep
; }
; if(newrelease) // if "new release"
; { swold.3 = 0; // update switch state latch
; starter = 0; // turn GP1 "starter" off
; if(swtmr) // if "short" press
; { ignition ^= 1; // toggle GP0 "ignition"
; swtmr = 0; // turn 1 second timer off
; running = 0; // clear "running" flag
; } //
; }
; if(swtmr) // if 1 second timer running
; { swtmr--; // decrement it
; if(swtmr == 0) // if timed out
; { beep2(); // send a double beep
; if(allowstart) // if start allowed
; { running = 1; // set "running" flag
; starter = 1; // turn GP1 "starter" on
; } //
; } //
; }
; }
;
newsample
call dbdelay ; 32-msec debounce delay |B0
comf GPIO,W ; sample active lo GP3 switch |B0
movwf swnew ; save fresh sample |B0
newpress
btfsc swnew,3 ; swnew.3 == 1 and |B0
btfsc swold,3 ; swold.3 == 0 (new press)? |B0
goto newrelease ; no, branch, else |B0
bsf swold,3 ; update swold.3 state latch |B0
call beep1 ; do a single 32-msec beep and |B0
movlw 1000/32 ; start 1 second timer |B0
movwf swtmr ; |B0
newrelease
btfss swnew,3 ; swnew.3 == 0 and |B0
btfss swold,3 ; swold.3 == 1 (new release)? |B0
goto timeout ; no, branch, else |B0
bcf swold,3 ; update swold.3 state latch |B0
bcf starter ; turn GP1 'starter' off |B0
movf swtmr,W ; timed out "long" press? |B0
bz newsample ; yes, branch (done), else |B0
clrf swtmr ; turn off 1 second timer |B0
movlw b'00000001' ; use GP0 pin mask to |B0
xorwf GPIO,F ; toggle GP0 'ignition' output |B0
bcf running ; clear "running" flag |B0
timeout
movf swtmr,F ; switch timer running? |B0
bz newsample ; no, branch, else |B0
decfsz swtmr,F ; is it timed out? |B0
goto newsample ; no, branch, else |B0
call beep2 ; do a double beep |B0
btfsc ignition ; ignition == 1 and |B0
btfsc running ; running == 0 (allow start)? |B0
goto newsample ; no, branch, else |B0
bsf running ; set "running" flag |B0
bsf starter ; turn GP1 'starter' on |B0
goto newsample ; |B0
;******************************************************************
; subroutines *
;******************************************************************
beep2
call beep1 ; 32-msec delay with beep |B0
call dbdelay ; 32-msec delay |B0
beep1
setc ; 32-msec delay with beep |B0
dbdelay
movlw 32 ; C = 0, delay, C = 1, beep |B0
movwf mstmr ; mstmr = 32 msecs |B0
dbloop
movlw b'00000100' ; mask for GP2 'spkr' pin |B0
skpnc ; beep task? no, skip, else |B0
xorwf GPIO,F ; toggle the speaker pin |B0
uDelay (1000*usecs-6) ; 1-msec minus 6 cycles |B0
decfsz mstmr,F ; done? yes, skip, else |B0
goto dbloop ; loop |B0
clrc ; |B0
return ; |B0
;******************************************************************
end