This code provides the same features as the 'debounce', 'beep', and 'toggle' example with additional vertical counters and code to provide a 512.0-msec 'repeat' capability for designated switches.
;****************************************************************** ; ; Mike McLaren's vertical counter "debounce" & "repeat" sample ; ISR code based on concepts from Jonny Doin and Scott Dattalo ; ; <> process up to eight switches using 'parallel' code ; <> eight independent 24.0-msec "debounce" vertical counters ; <> debounced switch press audible feedback (beep or click) ; <> 512.0-msec repeat rate for designated repeat switches ; <> designate repeat switches on-the-fly ; <> 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 ; ; 48 words/48 cycles (16-bit core) ; ; ; ; 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 any released or bouncing switches ; ISR_Sw movf SWKEYS,W ; live switch press data andwf VCBIT0,f ; VC bit 0 byte andwf VCBIT1,f ; VC bit 1 byte andwf VCBIT2,f ; VC bit 2 byte andwf VCBIT3,f ; VC bit 3 byte andwf VCBIT4,f ; VC bit 4 byte andwf VCBIT5,f ; VC bit 5 byte andwf SWDATA,f ; debounce byte (24-msec latch) ; ; cyclic vertical counter algorithm. vcmask is seeded with an ; 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') ; b3 ^= (vcmask & b0' & b1' & b2') ; b4 ^= (vcmask & b0' & b1' & b2' & b3') ; b5 ^= (vcmask & b0' & b1' & b2' & b3' & b4') ; ; Mike McLaren's "cumulative AND" vertical counter method ; ; b0 ^= vcmask : vcmask &= b0' ; b1 ^= vcmask : vcmask &= b1' ; b2 ^= vcmask : vcmask &= b2' ; b3 ^= vcmask : vcmask &= b3' ; b4 ^= vcmask : vcmask &= b4' ; b5 ^= vcmask : vcmask &= b5' ; andwf COLPOS,W ; 8-msec 'column' prescaler movwf VCMASK ; seed "cumulative AND" mask xorwf VCBIT0,f ; b0 ^= vcmask xorwf VCBIT0,W ; restore original b0' in W andwf VCMASK,W ; vcmask &= b0' movwf VCMASK ; xorwf VCBIT1,f ; b1 ^= vcmask xorwf VCBIT1,W ; restore original b1' in W andwf VCMASK,W ; vcmask &= b1' ; ; each '1' bit in the SWDATA variable represents a "debounced" ; 24.0-msec switch press (bit cleared when switch is released) ; iorwf SWDATA,f ; set debounced switch bits ; ; repeat counters (512.0-msecs) ; movwf VCMASK ; xorwf VCBIT2,f ; b2 ^= vcmask xorwf VCBIT2,W ; restore original b2' in W andwf VCMASK,W ; vcmask &= b2' movwf VCMASK ; xorwf VCBIT3,f ; b3 ^= vcmask xorwf VCBIT3,W ; restore original b3' in W andwf VCMASK,W ; vcmask &= b3' movwf VCMASK ; xorwf VCBIT4,f ; b4 ^= vcmask xorwf VCBIT4,W ; restore original b4' in W andwf VCMASK,W ; vcmask &= b4' movwf VCMASK ; xorwf VCBIT5,f ; b5 ^= vcmask xorwf VCBIT5,W ; restore original b5' in W andwf VCMASK,W ; vcmask &= b5' ; ; alternate version of code above uses 10 words/31 cycles ; compared to 16 words/16 cycles ; ; lfsr 0,VCBIT2 ; can't mess up WREG ; lfsr 1,0x0004 ; ;vcinc movwf VCMASK ; save vcmask ; xorwf INDF0,f ; bn ^= (VCMASK) ; xorwf POSTINC0,W ; restore bn' in W ; andwf VCMASK,W ; vcmask &= bn' ; decfsz FSR1L,f ; ; bra vcinc ; ; ; apply repeat switch mask and and make any new repeating ; switch look like a "new" switch press by toggling its ; SWPEND switch pressed latch bit off. ; andwf REPEAT,W ; mask non-repeat switches xorwf SWPEND,f ; turn a "repeat" into a "new" ; ; update SWPEND debounced switch pressed latch ; movf SWDATA,W ; debounced switch pressed bits xorwf SWPEND,W ; xor switch pressed latch xorwf SWPEND,f ; update switch pressed latch ; ; send a 32-msec short beep for new debounced switch presses ; andwf SWDATA,W ; new debounced switch press? btfss STATUS,Z ; no, skip, else bsf BEEPER,5 ; send 32-msec short beep ; ; toggle SWITCH flag bits for processing by the MAIN program ; ; test SWITCH bits for emulated "toggle" switches. test then ; clear SWITCH bits for "momentary" and "repeat" switches. ; xorwf SWITCH,f ; toggle SWITCH bits for MAIN ; ; advance ring counter prescaler (initialized value = 00000001) ; for the next interrupt cycle ; rlncf COLPOS,f ; advance column ring counter ; ; beep (500-Hz tone with 1.0-msec interrupts) ; movf BEEPER,W ; beep on? bz ISR_Next ; no, branch, else btg Speaker ; toggle piezo speaker pin decf BEEPER,f ; decrement beep msec counter ; ISR_Next