How to port this code ?

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I want to use the code below from embedded.com for my switch debouncing.

The problems is that my version of the code works only after releasing the button. It's supposed to detect only the last change. Full explanation here: My favourite software debouncers (Listing 2)

// Service routine called by a timer interrupt
bool_t DebounceSwitch2()
{
    static uint16_t State = 0; // Current debounce status
    State=(State<<1) | !RawKeyPressed() | 0xe000;
    if(State==0xf000)return TRUE;
    return FALSE;
}

My version for CodevisionAVR:

char DebounceNollaa()
{
    static int State = 0; // Current debounce status
    State=(State<<1) | !nollaa | 0xe000;
    if(State==0xf000)return 1;
    return 0;
}

And it gets called by timer0 isr like this:

if (DebounceNollaa())
	{
	nollaus();
	paivita = 1;
	}

My coding skills aren't that good, so I'm (again) in need of help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,
If you want to get the keycode as fast as possible, use debouncing algorithm listed below. It requires a timer that runs in background and stops after debounce time expired.

if (debounce timer busy)
    return 0;

If (keypress detected)
    {
    Start debounce timer (e.g., for 100ms);
    return keycode;
    }
else
    return 0;

Cats never lie. At least, they do this rarely.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
State=(State<<1) | !nollaa | 0xe000; 

How are you deriving the value of "nollaa"?

Mr. Ganssle's code assumes non-0 means the button is pressed, while on
the STK200 e.g. the PIN value for a pressed button is 0.

Also, are you masking uninteresting bits in the raw PINx value?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The nollaa is just PINC.2 and is active low. How should I read it ? I don't have a clue on how to read it any other way than that. :oops:

#define nollaa PINC.2
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you will need to invert your reading of the pin. Or adjust the rest of the code to reflect the inverse state (which is the better solution here).

char DebounceNollaa()
{
    static int State = 0; // Current debounce status
    State=(State<<1) | nollaa | 0xe000;
    if(State==0xf000)return 1;
    return 0;
} 

note how !nollaa is now just nollaa, this should reflect the inverse state properly now.

A couple of points here. This code is actually quite inefficient on an AVR, since it is using 16 bit variables. Also note that the example code probably expects true to be 0xFF, and false to be 0x00 (hence the need for 16 bit vars). In your code your true & false are 1 & 0, meaning it will take much longer for the true state to become active. I suggest rewriting the algorithm with the smaller size in mind, to make it more efficient both speed & memory wise for the AVR.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Fri. Aug 20, 2004 - 04:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

note how !nollaa is now just nollaa, this should reflect the inverse state properly now.

I tried this, and it doesn't work as the pin is pulled high. So I guess I need to invert it before calling the routine ? Doesn't that do the same thing ? Too little sleep gets me studip, or I'm just stupid :D

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

extin wrote:
Quote:

note how !nollaa is now just nollaa, this should reflect the inverse state properly now.

I tried this, and it doesn't work as the pin is pulled high. So I guess I need to invert it before calling the routine ? Doesn't that do the same thing ? Too little sleep gets me studip, or I'm just stupid :D

The fact that it's pulled high is not the problem here. I was editing my post above, when you replied. Please read the last little bit, wehre I talk about the True & False values, and efficiency.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I anyway needed to detect short or long push, so I'll write a better one.

Thanks for the help!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pulled-high should be fine. All this method is doing is (compactly) checking
for one "not-pressed" event (0x1000) followed by 11 "pressed" events.

I've never used CodeVision, so maybe I should ask (rather than
assuming): If PINC2 is high, is the value of PINC.2 0x01 or is it 0x04?
The reason I ask is that there is a (slightly) subtle trick in the original:
the use of the "!" operator guarantees that the result of the expression
is either 0 or 1, even if the RawKeyPressed() macro/function returns a
raw PIN value such as 0x04, and the method depends on this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are correct that the ! operator is guaranteeing 0x00 or 0x01 (I was expecting to see 0xFF for true, in error) In either case (though the compiler should be shifting it down to the lsb position to comply with the C bitfield spec, eventhough they break the naming spec) It does not matter what bit it sets, really, the only effect it would have is shortening the time from the press to the result.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Fri. Aug 20, 2004 - 05:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mckenney wrote:

I've never used CodeVision, so maybe I should ask (rather than
assuming): If PINC2 is high, is the value of PINC.2 0x01 or is it 0x04?

I think it's 0x01. Using PINx.x read the pin bits.
Quote:

From Codevision Help:
The bit level access to the I/O registers is accomplished using bit selectors appended after the name of the I/O register.
Because bit level access to I/O registers is done using the CBI, SBI, SBIC and SBIS instructions, the register address must be in the 0 to 1Fh range for sfrb and in the 0 to 1Eh range for sfrw.

Also I don't have RawKeyPressed() funtion in my code, the PIN state is read directly.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The debounce code should be fine (with the modification I showed) At what rate is your timer calling the debounce routine?

Try toggeling an LED each time the routine is called. If the poll-rate is relatively slow, then you may need to hold the buffon for a longer period of time before the event actually shows up.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Fri. Aug 20, 2004 - 05:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

extin wrote:

Also I don't have RawKeyPressed() funtion in my code, the PIN state is read directly.

That was intended as a place holder, to read the button state. It is meant to be supplied by you the programmer. In this case reading PINx.n should be fine, as long as you compensate for the fact that 0=pressed and 1=released.

unsigned char RawKEyPressed() {
    return ! nollaa;
}

If you use the function above, it should work with the original unmodified version of the algorithm.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.