Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Low overhead debounce

Status
Not open for further replies.

Mosaic

Well-Known Member
hello:
If u guys are interested I did up a low overhead, scalable debouncer based around a 10ms ISR. About 50 asm instructions, using 2 bytes per switch, delivering debounce & standard press/hold/release switch states with a transition switch bit to allow for non repeating selections. No computed gotos, just some indirect addressing for scalable looping.

I call it low overhead cuz it only runs once per 10ms and uses 1 byte for debounce & press-hold delay & 1 switch state byte per switch. Only 1 local temp byte used.

So for 8 switches u only need 16bytes of GPR and under 7 words of code space per switch .The local temp byte is reusable in any other parts of your code as it keeps no data necessary for the next debounce iteration.

It can easily scale to as many switches as u like.
 
I normally manage debounce using a similar 10mS stratedgy but without any timers. Simply,
Code:
	movfw	PORTB		;read port
	movwf	temp		;save for later
	xorwf	previous,w	;find changed keys
	andwf	temp,w		;keep only new presses
	movwf	keys		;save
	movfw	temp		;get earlier vale
	movwf	previous		;store for next time
The above reads 8 normally low keys on portB.

To read normally high keys do,
Code:
	movfw	PORTB		;read port
	movwf	temp		;save for later
	xorwf	previous,w	;find changed keys
	andwf	[COLOR="red"]previous[/COLOR],w	;keep only new presses
	movwf	keys		;save
	movfw	temp		;get earlier vale
	movwf	previous		;store for next time

Edit, to see how this works view the video in this thread

Mike.
 
Last edited:
Hi Mosaic,

I use "parallel logic" similar to Pommie's along with 16 to 32 msec debounce intervals to detect "new press" or "new release" switch states. The method easily supports new press beeps, repeat key operation, short and long press detection, "toggle" switch emulation, and more.

Code:
;
;  swnew  ____---____-----_____   new switch sample
;  swold  _____---____-----____   switch state latch
;  delta  ____-__-___-____-____   changes, press or release
;  newhi  ____-______-_________   filter out release bits
;  flags  _____-------_________   toggle switch flag bits for 'main'
;
buttons
        comf    PORTA,W         ; sample active lo switches       |B0
;       movf    PORTA,W         ; sample active hi switches       |B0
        xorwf   swold,W         ; changes (press or release)      |B0
        xorwf   swold,F         ; update switch state latch       |B0
        andwf   swold,W         ; filter out "new release" bits   |B0
        xorwf   flags,F         ; toggle switch flag bits         |B0

I'm sure many people would like to see your method.

Cheerful regards, Mike
 
Last edited:
Here's my code, pls comment

Hi guys, thx for all the advice!

Here's the code I'm using now.

It handles parallel debounce for a whole port of keys (DbKeystate) as well as Key 'Hold" (HoldKeystate) plus a click transition ( KeyTrans) and a hold transition (Holdtrans). With these 4 control bytes I can do logic for both debounced clicks and Holds as well as debounced Release-from-click and Release-from-hold for the 8 keys. Its about 35 prg words in length and uses 2 counter bytes run off a 10msec ISR.
The keys are on PORTB. I used 4 bit logic as a guide rather than 8 as u see.

Code:
           movf PORTB,w ; get newstate							0101
	xorwf LastKeystate,w ; state changes						1100 =>	1001
	xorwf LastKeystate,f ; Last=New.							1100=>	0101
	andlw b'11111111'; test wreg if any bits changed
	btfss STATUS,Z; skip zero set, else (statechange)
	clrf Dbouncecount; reset counter (counts every 10msec in ISR)
	btfss Dbouncecount,1 ; skip if bit 1 set=> 20ms passed, else
	goto Testkeyhold;
	movf LastKeystate,w;								0101
	xorwf DbKeystate,w; get changes bet. current state and debounced state.		0110 =>	0011
	movwf KeyTrans; save in transition byte.						0011 (transition bits)
	xorwf DbKeystate,f; apply them to DB state	                                        0110 => 0101					
	
Testkeyhold
	movf  DbKeystate,w	;							0101
	andwf HoldKeystate,w ;zero Hold bits if matching key is released - wreg.	0011 =>	0001
	xorwf HoldKeystate,w ; get Transition from Hold to release				0011 =>	0010
	movwf Holdtrans; update Holdtransition byte.							0010
        xorwf KeyTrans,f ; toggle any matching release from clicks off, release from hold priority.
	xorwf HoldKeystate,f ; now immediately switch off Hold if a key is released - file.		0011 =>	0001
	xorwf DbKeystate,w ; get newly pressed keys to test for hold.(state change)				0101 =>	0100
	btfss STATUS,Z; skip if  no new key pressed, else
	clrf Holdcount ; clear counter (incr every 10ms in ISR) for ANY new DB keypress
		
Testholdcount ; test if timer expired
	btfss Dbouncecount,6 ; 640 ms
	goto Keydone
	movf DbKeystate,w;					0101
	xorwf HoldKeystate,w ; get statechanges			0001 =>	0100
	iorwf Holdtrans,f; update hold transition byte.			0010 =>	0110 (transition bits)
	;using what's still in wreg to apply changes		0100
	xorwf HoldKeystate,f;apply changes			0001 =>	0101
Keydone	return
 
Last edited:
That's the time delay before th key press becomes a key held down. Or long press.
How would you use that in a program? Are you trying to get two functions, "short" and "long" presses, from each switch?

Also, is there somewhere in the code in post #6 where you increment the "Dbouncecount" variable? If the code you posted is incomplete, perhaps you can add the missing code and improve the formatting so it's a bit easier to read? It might help if you comment on the switches being active low or active high.

I must say that code is quite a departure from your "dynamic time coupled cumulative decision" debounce method from just two months ago (lol)...
 
Last edited:
How would you use that in a program? Are you trying to get two functions, "short" and "long" presses, from each switch?

I did a CLICK function and a HOLD function. Plus A Release CLICK function and a Release HOLD function.
I need the HOLD function to force a different action from a simple click & release. Consider scrolling thru menu options by clicking a key and then needing to select 1 with the same key. That's how I use the HOLD or Long Press.

Also, is there somewhere in the code in post #6 where you increment the "Dbouncecount" variable?

No increment in code, it's done continuously in a 10ms ISR.
It might help if you comment on the switches being active low or active high.

Sorry,=> switches set the pin Hi when on.
I must say that code is quite a departure from your "dynamic time coupled cumulative decision" debounce method from just two months ago (lol)...

Due in great part to your help!
 
Last edited:
DBkeystate for current state 'short press' state of the switches, with KeyTrans tracking the latest short press transitions

Holdkeystate for the 'long press' state of the switches, with Holdtrans tracking the latest long press transitions
 
Status
Not open for further replies.

Latest threads

Back
Top