mynewt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] mkiiskila closed pull request #751: Driver for debouncing an input pin.
Date Thu, 01 Jan 1970 00:00:00 GMT
mkiiskila closed pull request #751: Driver for debouncing an input pin.
URL: https://github.com/apache/mynewt-core/pull/751
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/hw/drivers/debounce/include/debounce/debounce.h b/hw/drivers/debounce/include/debounce/debounce.h
new file mode 100644
index 000000000..f82bae397
--- /dev/null
+++ b/hw/drivers/debounce/include/debounce/debounce.h
@@ -0,0 +1,235 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef _DEBOUNCE_DEBOUNCE_H_
+#define _DEBOUNCE_DEBOUNCE_H_
+
+/*
+ * debounce
+ *
+ * Driver to debounce a pin and optionally call a callback
+ * when the state changes.
+ *
+ * The implementation registers an IRQ callback for the pin, once triggered
+ * a periodic timer is used to check the state of the pin until it becomes
+ * stable for a certain number of times.
+ *
+ * This way debouncing doesn't consume any processing resources unless its
+ * pin actually changes and it is not susceptible to the thundering herd
+ * problem of IRQs that can be triggered by noisy inputs. See
+ * \c debounce_set_params for a detailed description of how the parameters
+ * influence the minimum time a signal is required to remain stable for it
+ * to be detected.
+ *
+ * The API relies on a structure of type \c debounce_t to remain valid for the
+ * lifetime of debouncing a pin. The structure can be dynamically allocated or
+ * statically defined.
+ *
+ * // ---------------------- Example begin --------------------------
+ *
+ * void buttonPressed(debounce_t *d) {
+ *     if (debounce_state(d)) {
+ *         ... code to process button press event
+ *     } else {
+ *         ... code to process button depress event
+ *     }
+ * }
+ *
+ * debounce_t button;
+ *
+ * int main(int argc, char *argv[]) {
+ *     ...
+ *     debounce_init(&button, BUTTON_PIN, HAL_GPIO_PULL_UP, 0);
+ *     debounce_start(&button, DEBOUNCE_CALLBACK_EVENT_ANY, buttonPressed, NULL);
+ *     ...
+ * }
+ *
+ * // ---------------------- Example end --------------------------
+ *
+ * The driver relies on
+ *   hal_timer ... at least one HW timer needs to be configured
+ *                 and running
+ *   hal_gpio  ... specifically the irq interface is used in order
+ *                 to detect the initial trigger for debouncing
+ */
+
+#include "hal/hal_gpio.h"
+#include "hal/hal_timer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Internal structure for debouncing a pin. Application code should only
+ * use the API to access it's data members and not directly manipulate or
+ * retrieve any of them.
+ */
+typedef struct debounce_pin {
+    uint32_t pin     : 24;
+    uint32_t state   :  1;
+    uint32_t on_rise :  1;
+    uint32_t on_fall :  1;
+    uint32_t         :  0;
+    uint32_t ticks   : 16;
+    uint32_t count   :  8;
+    uint32_t accu    :  8;
+    void (*on_change)(struct debounce_pin*);
+    void *arg;
+    struct hal_timer timer;
+} debounce_pin_t;
+
+/*
+ * A callback can be invoked when the debounced pin's state changes. It
+ * can either be invoked when the pin rises, falls or on any state change.
+ * If either \c DEBOUNCE_CALLBACK_NEVER is specified or the callbak itself
+ * is set to \c NULL no callback is invoked.
+ */
+typedef enum debounce_callback_event {
+    DEBOUNCE_CALLBACK_NEVER      = 0, /* no callback invocation */
+    DEBOUNCE_CALLBACK_EVENT_RISE = 1, /* callbak when signal rises */
+    DEBOUNCE_CALLBACK_EVENT_FALL = 2, /* callbak when signal falls */
+    DEBOUNCE_CALLBACK_EVENT_ANY  = 3  /* callbak when signal changes */
+} debounce_callback_event_t;
+
+/*
+ * Prototype for the callback function. The callback has access to the pin,
+ * current state and the initially provided argument through the API.
+ * See also
+ *  - debounce_arg
+ *  - debounce_pin
+ *  - debounce_state
+ */
+typedef void (*debounce_callback_t)(debounce_pin_t *);
+
+/**
+ * debounce init
+ *
+ * Initializes the specified pin to be debounced. Has to be called before
+ * any other debouncing function on the given \c debounce structure.
+ *
+ * @param d         Structure to manage debouncing
+ * @param pin       Pin number to set as input
+ * @param pull      Pull type, see hal_gpio.h
+ * @param timer     The HW timer number to be used by the debouncer.
+ *                  The timer has to be configured and setup properly by the
+ *                  application before this call.
+ *
+ * @return int  0: no error; -1 otherwise.
+ */
+int debounce_init(debounce_pin_t *d, int pin, hal_gpio_pull_t pull, int timer);
+
+/**
+ * debounce set params
+ *
+ * Can optionally be used to tune the debouncing parameters.
+ * Once there is a pin change detected debouncing the checks the pin's state
+ * periodically and requires it to be identical for a certain number of times.
+ *
+ * The critical time introduced by debouncing can be calculated by
+ *   critical_time = timer_tick_period * ticks * count
+ * This value describes the minim latency introduce by debouncing a pin. It
+ * also represents the minimum time a pin has to be asserted or not for the
+ * change to be propagated.
+ *
+ * The default values are defined by package values
+ *   DEBOUNCE_PARAM_TICKS 1
+ *   DEBOUNCE_PARAM_COUNT 10
+ *
+ *
+ * @param d         Structure to manage debouncing
+ * @param ticks     The # ticks used as the time interval for debouncing
+ * @param count     The # times the pin state has to be stable for
+ *                  debouncing to complete
+ *
+ * @return int  0: no error; -1 otherwise.
+ */
+int debounce_set_params(debounce_pin_t *d, uint16_t ticks, uint8_t count);
+
+/**
+ * debounce start
+ *
+ * Starts the debouncing algorithm an a previously initialized structure.
+ *
+ * @param d         Structure to manage debouncing
+ * @param event     On which event(s) the callback should be invoked
+ * @param cb        The callback
+ * @param arg       Transparent argument available to the callback
+ *
+ * @return int  0: no error; -1 otherwise.
+ */
+int debounce_start(debounce_pin_t *d,
+                   debounce_callback_event_t event,
+                   debounce_callback_t cb,
+                   void *arg);
+
+/**
+ * debounce stop
+ *
+ * Stops debouncing of a pin
+ *
+ * @param d         Structure to manage debouncing
+ *
+ * @return int  0: no error; -1 otherwise.
+ */
+int debounce_stop(debounce_pin_t*);
+
+/**
+ * debounce pin
+ *
+ * @param d         Structure to manage debouncing
+ *
+ * @return int  pin
+ */
+static inline int
+debounce_pin(debounce_pin_t *d)
+{
+    return d->pin;
+}
+
+/**
+ * debounce state
+ *
+ * @param d         Structure to manage debouncing
+ *
+ * @return int  state
+ */
+static inline int
+debounce_state(debounce_pin_t *d)
+{
+    return d->state;
+}
+
+/**
+ * debounce arg
+ *
+ * @param d         Structure to manage debouncing
+ *
+ * @return void*  arg
+ */
+static inline void*
+debounce_arg(debounce_pin_t *d)
+{
+    return d->arg;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEBOUNCE_DEBOUNCE_H_ */
diff --git a/hw/drivers/debounce/pkg.yml b/hw/drivers/debounce/pkg.yml
new file mode 100644
index 000000000..bc76875d7
--- /dev/null
+++ b/hw/drivers/debounce/pkg.yml
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: hw/drivers/debounce
+pkg.description: Basic pin debounce driver.
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.deps:
+    - "hw/hal"
diff --git a/hw/drivers/debounce/src/debounce.c b/hw/drivers/debounce/src/debounce.c
new file mode 100644
index 000000000..b02bf55bf
--- /dev/null
+++ b/hw/drivers/debounce/src/debounce.c
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "debounce/debounce.h"
+#include "syscfg/syscfg.h"
+#include <string.h>
+
+static void
+debounce_check(void *arg)
+{
+    debounce_pin_t *d = (debounce_pin_t*)arg;
+
+    int32_t btn = hal_gpio_read(d->pin) ? +1 : -1;
+    int32_t integrate = (int32_t)d->accu + btn;
+
+    if (integrate >= d->count) {
+        if (0 == d->state) {
+            d->state = 1;
+            if (d->on_rise && d->on_change) {
+                d->on_change(d);
+            }
+        }
+        integrate = d->count;
+    } else if ( integrate <= 0) {
+        if (1 == d->state) {
+            d->state = 0;
+            if (d->on_fall && d->on_change) {
+                d->on_change(d);
+            }
+        }
+        integrate = 0;
+    }
+    d->accu = integrate;
+
+    if (0 == integrate || d->count == integrate) {
+        /* debouncing complete, no point in periodically updating */
+        hal_gpio_irq_enable(d->pin);
+    } else {
+        /* no decision yet, continue debouncing */
+        hal_timer_start(&d->timer, d->ticks);
+    }
+}
+
+static void
+debounce_trigger(void *arg)
+{
+    debounce_pin_t *d = (debounce_pin_t*)arg;
+
+    /* once triggered, switch to periodic checks */
+    hal_gpio_irq_disable(d->pin);
+    hal_timer_start(&d->timer, d->ticks);
+}
+
+
+int
+debounce_init(debounce_pin_t *d, int pin, hal_gpio_pull_t pull, int timer)
+{
+    memset(d, 0, sizeof(debounce_pin_t));
+    d->pin = pin;
+    d->ticks = MYNEWT_VAL(DEBOUNCE_PARAM_TICKS);
+    d->count = MYNEWT_VAL(DEBOUNCE_PARAM_COUNT);
+
+    if (hal_timer_set_cb(timer, &d->timer, debounce_check, d)) {
+        return -1;
+    }
+
+    if (hal_gpio_irq_init(pin, debounce_trigger, d, HAL_GPIO_TRIG_BOTH, pull)) {
+        return -1;
+    }
+
+    if (hal_gpio_read(pin)) {
+        d->state = 1;
+        d->accu = d->count;
+    }
+
+    return 0;
+}
+
+int
+debounce_set_params(debounce_pin_t *d, uint16_t ticks, uint8_t count)
+{
+    d->ticks = ticks;
+    d->count = count;
+    if (d->state) {
+        d->accu = count;
+    }
+
+    return 0;
+}
+
+int
+debounce_start(debounce_pin_t *d,
+               debounce_callback_event_t event,
+               debounce_callback_t cb,
+               void *arg)
+{
+    d->on_rise = (event & DEBOUNCE_CALLBACK_EVENT_RISE) ? 1 : 0;
+    d->on_fall = (event & DEBOUNCE_CALLBACK_EVENT_FALL) ? 1 : 0;
+    d->on_change = cb;
+    d->arg = arg;
+
+    hal_gpio_irq_enable(d->pin);
+    return 0;
+}
+
+int
+debounce_stop(debounce_pin_t *d)
+{
+    hal_gpio_irq_disable(d->pin);
+    hal_timer_stop(&d->timer);
+    return 0;
+}
diff --git a/hw/drivers/debounce/syscfg.yml b/hw/drivers/debounce/syscfg.yml
new file mode 100644
index 000000000..3d218ce81
--- /dev/null
+++ b/hw/drivers/debounce/syscfg.yml
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+    DEBOUNCE_PARAM_TICKS:
+        description: >
+            The timeout used to periodically check the pin to be debounced
+            for its value to become stable.
+        value: 1
+    DEBOUNCE_PARAM_COUNT:
+        description: >
+            The number of times a pin has to read the same value in order
+            for debouncing to complete successfully.
+        value: 10


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message