PIC Microcontroler based Keyboard

Mike McLaren's 'debounce' and 'repeat' using vertical counters

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