You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/07/13 00:26:02 UTC

[GitHub] ccollins476ad closed pull request #1268: util/debounce: Debouncing / hysteresis utility pkg

ccollins476ad closed pull request #1268: util/debounce: Debouncing / hysteresis utility pkg
URL: https://github.com/apache/mynewt-core/pull/1268
 
 
   

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/util/debounce/include/debounce/debounce.h b/util/debounce/include/debounce/debounce.h
new file mode 100644
index 0000000000..952c6b4c63
--- /dev/null
+++ b/util/debounce/include/debounce/debounce.h
@@ -0,0 +1,115 @@
+/*
+ * 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 H_DEBOUNCE_
+#define H_DEBOUNCE_
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include "os/mynewt.h"
+
+/**
+ * @brief Debouncer - toggles between two states with jitter control.
+ *
+ * A debouncer is always in one of two states: low or high.  The state is
+ * derived from changes to the debouncer's counter.  When the counter increases
+ * up to the debouncer's high threshold (>=), the debouncer enters the high state.
+ * The debouner remains in the high state until its counter drops down to its
+ * low threshold (<=).  The counter saturates at a configured maximum value
+ * (i.e., the counter will never exceed the max).
+ *
+ * Restrictions:
+ *     o thresh_low < thresh_high
+ *     o thresh_high <= max
+ * 
+ * All struct fields should be considered private.
+ */
+struct debouncer {
+    uint16_t thresh_low;
+    uint16_t thresh_high;
+    uint16_t max;
+    uint16_t cur;
+    uint8_t state;
+};
+
+/**
+ * @brief Sets the provided debouncer's counter to the specified value.
+ *
+ * @param debouncer             The debouncer to set.
+ * @param val                   The value to set the debouncer's counter to.
+ */
+void debouncer_set(struct debouncer *debouncer, uint16_t val);
+
+/**
+ * @brief Adjusts the provided debouncer's counter by the specified amonut.
+ *
+ * @param debouncer             The debouncer to adjust.
+ * @param delta                 The amount to change the debouncer's counter by
+ *                                  (positive for increase; negative for
+ *                                  decrease).
+ *
+ * @return                      0 on success;
+ *                              SYS_EINVAL if the specified delta is out of
+ *                                  range (less than -UINT16_MAX or greater
+ *                                  than UINT16_MAX)
+ */
+int debouncer_adjust(struct debouncer *debouncer, int32_t delta);
+
+/**
+ * @brief Initializes a debouncer with the specified configuration.
+ *
+ * @param debouncer             The debouncer to initialize.
+ * @param thresh_low            The low threshold.
+ * @param thresh_high           The high threshold.
+ * @param max                   The maximum value the debouncer's counter can
+ *                                  attain.
+ *
+ * @return                      0 on success; SYS_EINVAL on error
+ */
+int debouncer_init(struct debouncer *debouncer, uint16_t thresh_low,
+                   uint16_t thresh_high, uint16_t max);
+
+/**
+ * @brief Indicates which of the two states the provided debouncer is in.
+ *
+ * @param debouncer             The debouncer to query.
+ *
+ * @return                      1 if the debouncer is in the high state;
+ *                              0 if the debouncer is in the low state.
+ */
+static inline int
+debouncer_state(const struct debouncer *debouncer)
+{
+    return debouncer->state;
+}
+
+/**
+ * @brief Retrieves the provided debouncer's current counter value.
+ *
+ * @param debouncer             The debouncer to query.
+ *
+ * @return                      The debouncer's counter value.
+ */
+static inline uint16_t
+debouncer_val(const struct debouncer *debouncer)
+{
+    return debouncer->cur;
+}
+
+#endif
diff --git a/util/debounce/pkg.yml b/util/debounce/pkg.yml
new file mode 100644
index 0000000000..3648f8f4a1
--- /dev/null
+++ b/util/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: "util/debounce"
+pkg.description: "Debouncing / hysteresis utility package."
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - debounce
+    - hysteresis
diff --git a/util/debounce/src/debounce.c b/util/debounce/src/debounce.c
new file mode 100644
index 0000000000..cf4775744d
--- /dev/null
+++ b/util/debounce/src/debounce.c
@@ -0,0 +1,88 @@
+/*
+ * 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 "os/mynewt.h"
+#include "debounce/debounce.h"
+
+void
+debouncer_set(struct debouncer *debouncer, uint16_t val)
+{
+    debouncer->cur = val;
+
+    if (debouncer->state) {
+        if (debouncer->cur <= debouncer->thresh_low) {
+            debouncer->state = 0;
+        }
+    } else {
+        if (debouncer->cur >= debouncer->thresh_high) {
+            debouncer->state = 1;
+        }
+    }
+}
+
+int
+debouncer_adjust(struct debouncer *debouncer, int32_t delta)
+{
+    int32_t new_val;
+
+    if (delta > UINT16_MAX || delta < -UINT16_MAX) {
+        return SYS_EINVAL;
+    }
+
+    new_val = debouncer->cur + delta;
+    if (new_val > debouncer->max) {
+        new_val = debouncer->max;
+    } else if (new_val < 0) {
+        new_val = 0;
+    }
+
+    debouncer_set(debouncer, new_val);
+
+    return 0;
+}
+
+void
+debouncer_reset(struct debouncer *debouncer)
+{
+    debouncer->cur = 0;
+    debouncer->state = 0;
+}
+
+int
+debouncer_init(struct debouncer *debouncer, uint16_t thresh_low,
+               uint16_t thresh_high, uint16_t max)
+{
+    if (thresh_low >= thresh_high) {
+        return SYS_EINVAL;
+    }
+
+    if (thresh_high > max) {
+        return SYS_EINVAL;
+    }
+
+    *debouncer = (struct debouncer) {
+        .thresh_low = thresh_low,
+        .thresh_high = thresh_high,
+        .max = max,
+        .cur = 0,
+        .state = 0,
+    };
+
+    return 0;
+}
diff --git a/util/debounce/test/pkg.yml b/util/debounce/test/pkg.yml
new file mode 100644
index 0000000000..698e100de5
--- /dev/null
+++ b/util/debounce/test/pkg.yml
@@ -0,0 +1,31 @@
+# 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: util/debounce/test
+pkg.type: unittest
+pkg.description: "Unit tests for the debouncer utility."
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - '@apache-mynewt-core/test/testutil'
+    - '@apache-mynewt-core/util/debounce'
+
+pkg.deps.SELFTEST:
+    - '@apache-mynewt-core/sys/console/stub'
diff --git a/util/debounce/test/src/debounce_test.c b/util/debounce/test/src/debounce_test.c
new file mode 100644
index 0000000000..0a7f5cea78
--- /dev/null
+++ b/util/debounce/test/src/debounce_test.c
@@ -0,0 +1,39 @@
+/*
+ * 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 "os/mynewt.h"
+#include "debounce_test.h"
+
+TEST_SUITE(debounce_test_suite_misc)
+{
+    debounce_test_case_init();
+    debounce_test_case_basic();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    debounce_test_suite_misc();
+
+    return tu_any_failed;
+}
+
+#endif
diff --git a/util/debounce/test/src/debounce_test.h b/util/debounce/test/src/debounce_test.h
new file mode 100644
index 0000000000..f5cd0eb11c
--- /dev/null
+++ b/util/debounce/test/src/debounce_test.h
@@ -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.
+ */
+
+#ifndef H_DEBOUNCE_TEST_
+#define H_DEBOUNCE_TEST_
+
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+
+TEST_SUITE_DECL(debounce_test_suite_misc);
+TEST_CASE_DECL(debounce_test_case_init);
+TEST_CASE_DECL(debounce_test_case_basic);
+
+#endif
diff --git a/util/debounce/test/src/testcases/debounce_test_case_basic.c b/util/debounce/test/src/testcases/debounce_test_case_basic.c
new file mode 100644
index 0000000000..ab48ec31a4
--- /dev/null
+++ b/util/debounce/test/src/testcases/debounce_test_case_basic.c
@@ -0,0 +1,76 @@
+/*
+ * 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 "os/mynewt.h"
+#include "debounce/debounce.h"
+#include "debounce_test.h"
+
+TEST_CASE(debounce_test_case_basic)
+{
+    struct debouncer d;
+    int rc;
+    int i;
+
+    rc = debouncer_init(&d, 10, 20, 100);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    // Ensure debouncer not triggered for first 19 increments.
+    for (i = 0; i < 19; i++) {
+        rc = debouncer_adjust(&d, 1);
+        TEST_ASSERT_FATAL(rc == 0);
+        TEST_ASSERT(!debouncer_state(&d));
+        TEST_ASSERT(debouncer_val(&d) == i + 1);
+    }
+
+    // Ensure 20th increment triggers debouncer.
+    rc = debouncer_adjust(&d, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 20);
+
+    // Ensure debouncer remains triggered during decrease to 11.
+    for (i = 0; i < 9; i++) {
+        rc = debouncer_adjust(&d, -1);
+        TEST_ASSERT_FATAL(rc == 0);
+        TEST_ASSERT(debouncer_state(&d));
+        TEST_ASSERT(debouncer_val(&d) == 20 - i - 1);
+    }
+
+    // Ensure decrement to 10 removes trigger.
+    rc = debouncer_adjust(&d, -1);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(!debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 10);
+
+    // Increment back to 11 does not trigger debouncer.
+    rc = debouncer_adjust(&d, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(!debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 11);
+
+    // Ensure debouncer won't increase beyond max.
+    debouncer_set(&d, 100);
+    TEST_ASSERT(debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 100);
+
+    rc = debouncer_adjust(&d, 1);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT(debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 100);
+}
diff --git a/util/debounce/test/src/testcases/debounce_test_case_init.c b/util/debounce/test/src/testcases/debounce_test_case_init.c
new file mode 100644
index 0000000000..390c6ad11e
--- /dev/null
+++ b/util/debounce/test/src/testcases/debounce_test_case_init.c
@@ -0,0 +1,44 @@
+/*
+ * 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 "os/mynewt.h"
+#include "debounce/debounce.h"
+#include "debounce_test.h"
+
+TEST_CASE(debounce_test_case_init)
+{
+    struct debouncer d;
+    int rc;
+
+    // Invalid configuration - thresh_low > thresh_high.
+    rc = debouncer_init(&d, 20, 10, 100);
+    TEST_ASSERT_FATAL(rc == SYS_EINVAL);
+
+    // Invalid configuration - thresh_high > max.
+    rc = debouncer_init(&d, 10, 20, 15);
+    TEST_ASSERT_FATAL(rc == SYS_EINVAL);
+
+    // Successful init.
+    rc = debouncer_init(&d, 10, 20, 100);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    // Verify initial state.
+    TEST_ASSERT(!debouncer_state(&d));
+    TEST_ASSERT(debouncer_val(&d) == 0);
+}


 

----------------------------------------------------------------
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