PIC Microcontroler based Keyboard

Mike McLaren's 'debounce', 'beep', and 'toggle' using vertical counters

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