Shop OBEX P1 Docs P2 Docs Learn Events
Button Debouncing for the Masses! — Parallax Forums

Button Debouncing for the Masses!

KyeKye Posts: 2,200
edited 2010-03-12 19:55 in Propeller 1
I couldn't seem to find any button debouncer drivers up in the Obex.

So...

http://obex.parallax.com/objects/585/

I wrote a pretty nice one that has every feature you would ever need.

It gives the user the ability to:

Get the debounced button state.
Get how long the debounced button has been in that state in milliseconds.
Get if the debounced button was pressed. (Returns true once per press)
Get if the debounced button was released. (Returns true once per release)

The driver runs on a seperate cog and handles eight buttons at a time.

The deounce period is over 10 milliseconds so you shouldn't have any odd button behaviour.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
«1

Comments

  • TonyWaiteTonyWaite Posts: 219
    edited 2010-03-09 16:19
    Thank you!

    T o n y
  • Martin HodgeMartin Hodge Posts: 1,246
    edited 2010-03-09 17:09
    Kye, you da man! Thanks!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -MH
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-09 17:43
    It is hard to find things in ObEx -- I gave up looking for a PASM RC-5 decoder yesterday and wrote my own (okay, I would have, anyway, but it's always nice to see what others do).

    Here's my debouncing object:
    -- obex.parallax.com/objects/489/

    Like yours, it runs in its own cog, but with mine you specify a debounce period (10 to 100ms, defaults to 25). The button(s) state(s) must remain constant for the entire period to be considered valid. It will work with any number of inputs (up to 32) and you can specify active-high or active-low.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA

    Post Edited (JonnyMac) : 3/9/2010 5:51:37 PM GMT
  • Rob7Rob7 Posts: 275
    edited 2010-03-09 18:02
    Kye,

    Wow that's great !

    Thanks!!!
  • KyeKye Posts: 2,200
    edited 2010-03-09 18:37
    @JonnyMac

    When you search for "button" yours does not come up. =)

    I was going to write mine in asm to support all 32 I/Os at once... but doing it in ASM would have been very painful due to all the array acesses I am using in the spin code.

    Thanks,

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-09 19:53
    Kye,

    If you get a chance to look at my code you'll find it's very simple because I am looking at all inputs at once for a given period (though I actually sample 8x per millisecond to ensure the input is clean). What I probably need to add is a mechanism to read a specific group of [noparse][[/noparse]debounced] pins, similar to result := ina[noparse][[/noparse]msb..lsb].

    While a tad off topic... I know you know how to do this, but you may find these subroutines convenient; I have a couple projects that need to use arrays in pasm and I'm putting these to work.

    ' basepntr = address of array/table
    ' idx = index of element to write
    ' value = value that is read
    
    read                    mov     tmp1, basepntr
                            add     tmp1, idx
                            movs    rdval, tmp1
                            nop
    rdval                   mov     value, 0-0
    read_ret                ret
    
    
    ' basepntr = address of array/table
    ' idx = index of element to write
    ' value = value to write
    
    write                   mov     tmp1, basepntr
                            add     tmp1, idx
                            movd    wrval, tmp1
                            nop
    wrval                   mov     0-0, value
    write_ret               ret
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • KyeKye Posts: 2,200
    edited 2010-03-09 22:04
    Ah JonnyMac! All my drivers are made to be optimized. "Nops" are not for me.

    Since I'm supporting more features than just button states it means the ASM will have to be pretty complex to handle everything the spin code was doing.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-10 00:08
    Ahh... the term "optimized." Sounds a bit like hyperbole to me. IMHO, clean, efficient code doesn't need a big marketing splash -- its performance and ease-of-use will speak for itself.

    As for the nop, the instruction pipeline of the Propeller requires an instruction between the movd or movs and the actual mov -- not my rules, it's how the chip works. If you want to do arrays in assembly, which I need at the moment for a lighting controller, this is how it's done. I simply created subroutines that make my life in this particular program a little easier.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • KyeKye Posts: 2,200
    edited 2010-03-10 04:48
    Haha, That's what I'm saying. For this particular piece of code it would make sense, but for most it does not.

    I'll let you in on a little piece of interesting info about all my drivers. Look at the compiled byte image for my drivers. You'll notice an interesting pattern. =)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • mparkmpark Posts: 1,305
    edited 2010-03-10 06:00
    What's the pattern?
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-10 07:18
    The one thing I would suggest, Kye, is that you not hard-wire pin numbers and such in your objects. Let's say I have a project that wants to use your debounce object and the hardware needs pin group 0. Then I create another program that needs pin group 3. Well... if I go back and recompile the first project it now doesn't work because of the hard-wired group definition has been changed to 3. I suggest you move these kinds of things to the initialization method (passed as parameters) so that the end user never has to modified your object code.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • KyeKye Posts: 2,200
    edited 2010-03-10 16:20
    @JonnyMac

    I thought about implementing that type of feature. I know everyone else does it. But I've been designing all my drivers for use on a standard platform where the pinout cannot change and I will only be using one of each.

    I have starting including a warning in my drivers about this. I have also included warning about not acessing the driver library with multiple cores at once.

    Most, if not all the code on the OBEX i've seen has no default support for multiprocessor acess.

    @mpark - I spend alot of time optimizing my drivers. One way to get myself to make the code as clean and as optimized as possible is to set a random hard to reach goal that forces you to look for better ways of doing things to make your code faster.

    What I've been doing is forcing all my drivers to have a flat executable byte image that uses every byte allocated for the driver in longs. This execrise has greatly improved my coding skills as well as shrinking my code and making it much faster.

    Did you know that 0, and 1, require only one byte to be represented in spin while 2 - 255 require 2 bytes. Numbers greater than that require 3 or four bytes while (-1) requires only one byte again?

    There's alot of interesting things you learn about spin by looking at the compiled byte image.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-03-10 17:45
    Kye said...
    But I've been designing all my drivers for use on a standard platform ...
    Hmm, I didn't know there was one standard platform. I'm with Jon, Kye. It's better to make an object flexible, if you can, rather than chaining it to a single platform. As an example, I've written a few objects for the Propeller Backpack. If it's possible for these objects to run on other platforms, I include two start routines: a simple start that assumes the Backpack will be used, and startexplicit, which makes no such assumption and typically includes parameters related to pin assignments. In such a case, start simply calls startexplicit with the Backpack's settings.

    -Phil
  • KyeKye Posts: 2,200
    edited 2010-03-10 22:50
    I'll get arround to doing this for my objects sooner or later.

    For now, there is at least a disclaimer.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,

    Post Edited (Kye) : 3/11/2010 6:52:24 AM GMT
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-11 00:15
    When I worked for Toro there were signs all over the office that said, "If you don't have time to do it right, when will you find time to do it again?" Good advice. Since you're very prolific with code you'll want to make sure your next object has the flexibility suggested by Phil.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • BradCBradC Posts: 2,601
    edited 2010-03-11 00:24
    Kye said...

    Did you know that 0, and 1, require only one byte to be represented in spin while 2 - 255 require 2 bytes. Numbers greater than that require 3 or four bytes while (-1) requires only one byte again?

    There's alot of interesting things you learn about spin by looking at the compiled byte image.

    This is why some people compilers that provide a "de-compiled" listing of the spin code. Not only do you see what it is doing, but you see why it is doing it.

    There's a lot of interesting things you can learn about spin by looking at the interpreter source and program list files.

    Did you know that the compiler has several ways of encoding constants and will iterate through them looking for the smallest way to do it?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    You only ever need two tools in life. If it moves and it shouldn't use Duct Tape. If it does not move and it should use WD40.
  • KyeKye Posts: 2,200
    edited 2010-03-11 06:54
    @BradC - I know. Its pretty interesting Brad.

    @JonnyMac - But who's right? =) I didn't make the pins in my drivers constants for no reason. I'll add more features later on.

    ...

    Almost done with the full featured FAT Engine. Just gotta test the code out the code for a few days and I'll post up the newest version. Hopefully there won't be any problems. Its much more improved than before.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Paul Sr.Paul Sr. Posts: 435
    edited 2010-03-11 13:47
    Kye said...

    @JonnyMac - But who's right?

    Likely EVERYONE ELSE who is trying to explain that developing your drivers/apps with flexibility would make them significantly more usable/desirable, particularly for those who are trying to learn from the fruits of your efforts. You are producing some nice stuff, but you should heed the advise of the much more experienced people who are so willing to help you improve your offerings. Use your talents wisely!
  • KyeKye Posts: 2,200
    edited 2010-03-11 15:43
    I'm just leading explaining why I haven't does so yet. I plan on adding pin selection features. I also plan on adding multi cog acesss features. =)

    ...

    Okay, this post has gone way off topic.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-11 19:11
    Kye said...

    @JonnyMac - But who's right? =) I didn't make the pins in my drivers constants for no reason. I'll add more features later on.

    Everyone, of course -- depends on context. That said, I think most professionals would agree that when you create an object for public use (i.e., release to ObEx -- and in your case, amply promoted as available and "easy to use") it can be re-used without having to edit the file. Otherwise, it's not much more convenient than doing a copy-paste-edit of code one needs.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-11 20:09
    I think it would be cool to have ratings in the object exchange which tells if the object is good for beginners or not.

    I don't tend to squeeze out every single byte possible out of driver code I write, but some people forget that we program a microcontroller. It's not a PC where you have enough RAM and disc-space so that you don't have to take care of single bytes - even if those single bytes sum up to megabytes for a program in the end.

    Beginners should learn that they have to read the drivers comments! And it definitely is not a mistake to teach efficient coding straight from the beginning and not code every driver for the beginners comfort. For example the text LCD driver I added to the object exchange recently does not have a single SPIN-wrapper function which would make things easier. You have to understand how that LCD controller works and you have to do some bit-shifts to pass all the needed parameters in one long.

    Last but not least we should keep in mind that coding style is also a matter of taste. One likes it this way, one likes it another way ... One style is better for readability, one style is better for performance, one is better for code size. No matter what code ends up in the object exchange, you can learn from it the one way or the other. In the worst case you learn which way you don't like and you end up re-writing the driver.

    That said ... how would it be to have code groups in the object exchange. I think there are now 3 drivers out for HD44780-style text LCDs. Would be nice to have all on one page which describes the differences and gives their ratings.

    Post Edited (MagIO2) : 3/11/2010 8:14:59 PM GMT
  • KyeKye Posts: 2,200
    edited 2010-03-11 20:29
    That is a good idea MagIO2. Before we do that however we first need to find out a way to get people to rate object on the OBEX. I've noticed that most of the stuff there is unrated.

    Okay, JonnyMac, I attached my q-encoder driver with updated support for variable pin assingments.

    What do you think?


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • jazzedjazzed Posts: 11,803
    edited 2010-03-11 20:44
    Maybe Objects should be rated like movies:
      G general audience PG13 not for newbies R guidance required X some code may not be appropriate XX uses many raw/bare Propeller tricks XXX hard core programmers only ... NR not rated of course [noparse]:)[/noparse]
    MagIO is fully correct on style. Although if someone is paying for your source code, it's best to follow their rules.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Short answers? Not available at this time since I think you deserve more information than you requested.
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-03-11 20:45
    Well ... for the "suggested experience level" you don't need the audience. The author can start with a suggestion. Audience will only increase accuracy of the rating.
  • jazzedjazzed Posts: 11,803
    edited 2010-03-11 20:53
    MagIO2 said...
    Well ... for the "suggested experience level" you don't need the audience. The author can start with a suggestion. Audience will only increase accuracy of the rating.
    Yes. At least that could be the start of the rating and feedback may follow.
    Today's system depends on some other person feeling excited or qualified to judge.
    The number of downloads today seems to be a fair indication of interest at least.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Short answers? Not available at this time since I think you deserve more information than you requested.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-03-11 20:56
    There's a fuzzy boundary between programming style and programming substance. How wide that fuzzy area is and where it's located will vary from person to person. For pin assignments, I would consider the choice betwen literals, declared constants, or variables to be a matter of substance, since it could affect how a person uses the program. Whether to name your declared CONstants in ALL CAPS? That's a question of style, since it does not affect usage. At least that's where I draw the line.

    -Phil
  • JonnyMacJonnyMac Posts: 9,208
    edited 2010-03-11 21:20
    Kye said...

    Okay, JonnyMac, I attached my q-encoder driver with updated support for variable pin assingments.

    What do you think?

    Nicely done. You have, in fact, done yourself and anyone that uses your object a favor. Let me give you a real-world example. I've designed a couple of Propeller-based products for EFX-TEK but when I turned the initial schematic over to my business partner (another former Parallaxian, John Barrowman), I didn't assign specific pins except for the programming and I2C port. This let John route the boards in the cleanest possible manner. Once the board was routed I simply plugged the final pin #s into my initialization code and away we went.

    In your career you will have the opportunity to work with a lot of programmers, many will not be at your level. Even those that are, however, will appreciate that you haven't created work for them to use your drivers in the manner they'd like to.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon McPhalen
    Hollywood, CA
  • KyeKye Posts: 2,200
    edited 2010-03-11 22:21
    Okay, well while we are all here.

    I need to add locks to my file system driver. That said, I plan on just using the lock number of whatever processor gets taken by a cognew I need to call to run the ASM block driver.

    I'm thinking this method won't have two many problems. But would it be a bad idea to do this?

    Thanks,

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-03-11 23:03
    Use locknew to get the lock number. Don't tie it to the cog number. Doing so may conflict with other locks in other objects.

    -Phil
  • KyeKye Posts: 2,200
    edited 2010-03-11 23:16
    Okay, Then what should I return from my start function?

    The cog number or lock number? Or should I make another function for this? I'm trying to make the fact that I'm using locks transparent.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
Sign In or Register to comment.