This example ISR code features a switch press 'beep' function and supports standard "momentary" and "toggle" emulation switch types using standard normally-open push button switches. I often use "toggle" switch emulation for lighted switches (push to toggle from off-to-on and push to toggle from on-to-off).
;******************************************************************
;
; Mike McLaren's "debounce" vertical counter example ISR code
; based on concepts/examples from Jonny Doin and Scott Dattalo
;
; <> process up to eight switches in parallel
; <> eight independent 24.0-msec "debounce" vertical counters
; <> debounced switch press audible feedback (beep or click)
; <> momentary switch operation (test then clear a SWITCH bit)
; <> toggle switch emulation (push to toggle a SWITCH bit from
; off-to-on or from on-to-off) perfect for lighted switches
;
; 27 words/27 cycles (14-bit core), or
; 18 words/18 cycles without switch press beep code
;
; setup the SWKEYS variable with "live" switch press data from
; your switch input pins or your scanned switch matrix before
; falling into this routine. A '1' bit represents a 'pressed'
; switch and a '0' bit represents a 'released' switch.
;
; execute this code each 1.0-msec interrupt cycle
;
;
; clear vertical counters for bouncing and steady-state switches
;
ISR_Sw
movf SWKEYS,W ; live switch press data |B0
xorwf SLATCH,W ; debounced pressed switch latch |B0
andwf VCBIT0,f ; |B0
andwf VCBIT1,f ; |B0
;
; cyclic vertical counter algorithm. vcmask is seeded with the
; active switch mask and bn' is the previous state of bn before
; the bit increment operation.
;
; a switch is debounced or filtered after sampling it at the
; same level through four vertical counts spanning 24.0-msecs
;
; b0 ^= (vcmask)
; b1 ^= (vcmask & b0')
; b2 ^= (vcmask & b0' & b1')
;
; Mike McLaren's "cumulative AND" vertical counter method
;
; b0 ^= vcmask : vcmask &= bo'
; b1 ^= vcmask : vcmask &= b1'
; b2 ^= vcmask
;
andwf COLPOS,W ; 8-msec 'column' prescaler |B0
movwf VCMASK ; seed "cumulative AND" mask |B0
xorwf VCBIT0,f ; b0 ^= vcmask |B0
xorwf VCBIT0,W ; restore b0' in W |B0
andwf VCMASK,W ; vcmask &= b0' |B0
movwf VCMASK ; |B0
xorwf VCBIT1,f ; b1 ^= vcmask |B0
xorwf VCBIT1,W ; restore b1' in W |B0
andwf VCMASK,W ; vcmask &= b1' |B0
;
; each '1' bit in the SLATCH variable represents a "debounced"
; 24.0-msec switch press (bit cleared when switch is released)
;
xorwf SLATCH,f ; update debounced state latch |B0
;
; send a 32-msec short beep for new debounced switch presses
;
andwf SWKEYS,W ; new debounced switch press? |B0
btfss STATUS,Z ; no, skip, else |B0
bsf BEEPER,5 ; send 32-msec short beep |B0
;
; toggle SWITCH flag bits for processing by the MAIN program
;
; test SWITCH bits for emulated "toggle" switches. test then
; clear SWITCH bits for "momentary" switches.
;
xorwf SWITCH,f ; toggle SWITCH bits for MAIN |B0
;
; advance ring counter prescaler (initialized value = 00000001)
; for the next interrupt cycle
;
rlf COLPOS,W ; advance column ring counter |B0
rlf COLPOS,f ; |B0
;
; beep (500-Hz tone with 1.0-msec interrupts)
;
movf BEEPER,W ; beep timer set? |B0
bz ISR_Next ; no, branch, else |B0
movf GPIO,W ; read port |B0
xorlw 1<<Speaker ; |B0
movwf GPIO ; toggle piezo speaker pin |B0
decf BEEPER,f ; decrement timer |B0
;
ISR_Next