periph / conn

Go·Hardware·Lean - Interfaces
https://periph.io
Apache License 2.0
67 stars 12 forks source link

gpioutil.Debounce not actually implemented #5

Open lutzky opened 3 years ago

lutzky commented 3 years ago

Apologies if I'm misreading. I have implemented manual debouncing and denoising for my own project, before realizing that gpioutil.Debounce exists. It would provide a cleaner API to do the same thing, so I looked into switching to using it. However, observing the current version of debounce.go, it appears that:

(I've tried to keep the checkbox entries in actual tasks, so they can be used with Task lists).

Am I missing something? I think, at least, that the documentation should clarify the state of this code.

Side-note: While I was aware of the importance of debouncing, denoising was newer to me, and I found out about it the annoying way (I have phantom GPIO "button presses" about every 8 hours; super annoying to debug). Once Debounce is implemented correctly, it's probably worth mentioning in the documentation of WaitForEdge.

maruel commented 3 years ago

There's historical reasons for this. 3 years ago I started looking at options to recreate the conn package as I don't feel the current interfaces are optimal. Then go modules were forced and I spent all my free time on splitting the repositories into real go packages.

You can find a bit more at:

Because of the uncertainty with how the GPIO functions would look like, I didn't spend time to fix the Debounce code when I carried it over from experimental at https://github.com/google/periph/tree/main/experimental/conn/gpio/gpioutil when I removed experimental when I created the new repositories. There's more at https://periph.io/news/2020/a_new_start/.

So that was a lot of words and links to say that help would be very appreciated.

lutzky commented 3 years ago

OK, at the very least I'll do the doc warning.

lutzky commented 3 years ago

Could you please hit the "Convert to issue" button on those tasks? (That should make it link up nicely and I can reference that in the pull request)

maruel commented 3 years ago

TIL

lutzky commented 3 years ago

After #10: So, to clarify, should the conn package be considered stable enough for it to be worth actually implementing this now (I mean, it's been 3 years)? Or is v4 right around the corner (...and then v4 needs an implementation of this)?

maruel commented 3 years ago

I started multiple changes for v4 but given my current work workload it's unlikely for me to have a v4 in the next year.

lutzky commented 3 years ago

Understood. So after the docfix is in, I'll see if I can take a whack at implementing the logic for v3.

lutzky commented 3 years ago

Looking at the current documentation, the Read method is also documented as being affected by debouncing: https://github.com/periph/conn/blob/9ee6d812a51e97b7bdbf8215670286b0f22d5f04/gpio/gpioutil/debounce.go#L59-L62

This is significantly more complicated to implement than the WaitForEdge variant, which would boil down to something like this:

func (d *debounced) WaitForEdge(timeout time.Duration) bool {
  prev := d.PinIO.Read()
  for {
    if !d.PinIO.WaitForEdge(timeout) {
      return false
    }
    time.Sleep(d.denoise)
    if d.PinIO.Read() != prev {
      return true
    }
  }
}

Looking around, there's a C library called pigpio which has a set_glitch_filter that seems to have similar functionality, and indeed only applies to their equivalent for WaitForEdge (although the implementation seems more complicated).

Getting this to work for Read as well is... tricky? I mean, I guess it could do this:

func (d *debounced) Read() gpio.Level {
  for {
    prev := d.PinIO.Read()
    time.Sleep(d.denoise)
    if d.PinIO.Read() == prev {
      return prev
    }
  }
}

Is that what you had in mind?

maruel commented 3 years ago

My thinking was to save one read if the last read occurred within d.denoise, but in hindsight I'm not sure it was a good idea.

lutzky commented 3 years ago

I'm not sure how that would work... and I don't think it can work in the case of "user calls Read just once". Am I missing something?

maruel commented 3 years ago

hence my "I'm not sure it was a good idea" :)

lutzky commented 3 years ago

Fair enough 😅 What do you think of my proposal?

maruel commented 3 years ago

lgtm

lutzky commented 3 years ago

Alright, started on this in #12, LMK what you think.