You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2022/02/22 18:24:05 UTC

[mynewt-core] 02/02: hw/sensors: BMA400 sleep/wake notification

This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit c0f7072bd7c27613c867a5a155fa8e41748f9bfd
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Fri Feb 18 14:10:48 2022 +0100

    hw/sensors: BMA400 sleep/wake notification
    
    Sleep and wake notification was not working.
    For this to work interrupt pin that is dedicated to wake state
    has to be re-armed for different edge since there is no
    sleep-change notification and some MCUs supported in mynewt
    don't have trigger for both edges so far.
---
 hw/drivers/sensors/bma400/include/bma400/bma400.h |  3 +
 hw/drivers/sensors/bma400/src/bma400.c            | 69 +++++++++++++++++++++--
 2 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/hw/drivers/sensors/bma400/include/bma400/bma400.h b/hw/drivers/sensors/bma400/include/bma400/bma400.h
index b160b79..98d445b 100755
--- a/hw/drivers/sensors/bma400/include/bma400/bma400.h
+++ b/hw/drivers/sensors/bma400/include/bma400/bma400.h
@@ -25,6 +25,7 @@
 #include <sensor/sensor.h>
 #include <sensor/accel.h>
 #include <sensor/temperature.h>
+#include <hal/hal_gpio.h>
 #include "../../src/bma400_priv.h"
 
 #ifdef __cplusplus
@@ -475,6 +476,7 @@ struct bma400_int {
     bool asleep;
     /* Configured interrupts */
     struct sensor_int ints[2];
+    hal_gpio_irq_trig_t armed_trigger[2];
 };
 
 /* Device private data */
@@ -490,6 +492,7 @@ struct bma400_private_driver_data {
     /* Shadow copy of registers */
     struct bma400_reg_cache cache;
     uint8_t transact;
+    uint8_t woke;
 
     /* Active interrupt state */
     struct bma400_int intr;
diff --git a/hw/drivers/sensors/bma400/src/bma400.c b/hw/drivers/sensors/bma400/src/bma400.c
index 1c2ba1e..c13ed50 100755
--- a/hw/drivers/sensors/bma400/src/bma400.c
+++ b/hw/drivers/sensors/bma400/src/bma400.c
@@ -728,6 +728,31 @@ bma400_set_acc_cfg(struct bma400 *bma400, struct bma400_acc_cfg *cfg)
     return bma400_commit(bma400);
 }
 
+static void
+bma400_arm_interrupt(struct bma400 *bma400, bma400_int_num_t int_num, hal_gpio_irq_trig_t trig)
+{
+    struct bma400_private_driver_data *pdd;
+    pdd = &bma400->pdd;
+    int host_pin;
+    int int_ix = (int)int_num - 1;
+
+    if (int_ix >= 0 && pdd->intr.armed_trigger[int_ix] != trig) {
+        host_pin = pdd->intr.ints[int_ix].host_pin;
+        if (pdd->intr.armed_trigger[int_ix] != HAL_GPIO_TRIG_NONE) {
+            hal_gpio_irq_release(host_pin);
+        }
+
+        pdd->intr.armed_trigger[int_ix] = trig;
+        if (trig != HAL_GPIO_TRIG_NONE) {
+            hal_gpio_irq_init(host_pin,
+                              bma400_interrupt_handler, bma400,
+                              trig,
+                              HAL_GPIO_PULL_NONE);
+            hal_gpio_irq_enable(host_pin);
+        }
+    }
+}
+
 int
 bma400_set_int12_cfg(struct bma400 *bma400, struct bma400_int_pin_cfg *cfg)
 {
@@ -741,9 +766,7 @@ bma400_set_int12_cfg(struct bma400 *bma400, struct bma400_int_pin_cfg *cfg)
             trig = cfg->int1_level ? HAL_GPIO_TRIG_RISING : HAL_GPIO_TRIG_FALLING;
             bma400->pdd.intr.ints[0].host_pin = cfg->int1_host_pin;
             bma400->pdd.intr.ints[0].active = cfg->int1_level;
-            hal_gpio_irq_init(cfg->int1_host_pin,
-                              bma400_interrupt_handler,
-                              bma400, trig, HAL_GPIO_PULL_NONE);
+            bma400_arm_interrupt(bma400, BMA400_INT1_PIN, trig);
         }
     }
     if (cfg->int2_host_pin != bma400->pdd.intr.ints[1].host_pin) {
@@ -754,9 +777,7 @@ bma400_set_int12_cfg(struct bma400 *bma400, struct bma400_int_pin_cfg *cfg)
             trig = cfg->int1_level ? HAL_GPIO_TRIG_RISING : HAL_GPIO_TRIG_FALLING;
             bma400->pdd.intr.ints[1].host_pin = cfg->int2_host_pin;
             bma400->pdd.intr.ints[1].active = cfg->int2_level;
-            hal_gpio_irq_init(cfg->int2_host_pin,
-                              bma400_interrupt_handler,
-                              bma400, trig, HAL_GPIO_PULL_NONE);
+            bma400_arm_interrupt(bma400, BMA400_INT2_PIN, trig);
         }
     }
 
@@ -882,6 +903,10 @@ bma400_set_wakeup(struct bma400 *bma400, struct bma400_wakeup_cfg *cfg)
     bma400_set_register_field(bma400, BMA400_REG_INT1_MAP, BMA400_INT1_MAP_WKUP_INT1, cfg->int_num == BMA400_INT1_PIN);
     bma400_set_register_field(bma400, BMA400_REG_INT2_MAP, BMA400_INT2_MAP_WKUP_INT2, cfg->int_num == BMA400_INT2_PIN);
 
+    if (cfg->int_num != BMA400_NO_INT_PIN) {
+        bma400->pdd.allowed_events |= SENSOR_EVENT_TYPE_SLEEP | SENSOR_EVENT_TYPE_WAKEUP;
+    }
+
     return bma400_commit(bma400);
 }
 
@@ -1658,8 +1683,13 @@ bma400_sensor_handle_interrupt(struct sensor *sensor)
     struct bma400_private_driver_data *pdd;
     struct bma400_int_status int_status;
     int rc;
+    uint8_t woke;
+    int8_t wakeup_pin;
+    int wakeup_pin_state;
+    int16_t host_wakeup_pin;
 
     bma400 = (struct bma400 *)SENSOR_GET_DEVICE(sensor);
+    wakeup_pin = (int8_t)bma400->cfg.wakeup_cfg.int_num - 1;
     pdd = &bma400->pdd;
 
     rc = bma400_get_int_status(bma400, &int_status);
@@ -1668,6 +1698,33 @@ bma400_sensor_handle_interrupt(struct sensor *sensor)
         return rc;
     }
 
+    if (wakeup_pin >= 0 &&
+        (pdd->notify_ctx.snec_evtype & (SENSOR_EVENT_TYPE_WAKEUP | SENSOR_EVENT_TYPE_SLEEP)) != 0) {
+        host_wakeup_pin = pdd->intr.ints[wakeup_pin].host_pin;
+        wakeup_pin_state = hal_gpio_read(host_wakeup_pin);
+        woke = wakeup_pin_state == pdd->intr.ints[wakeup_pin].active;
+
+        bma400_arm_interrupt(bma400, bma400->cfg.wakeup_cfg.int_num,
+                             wakeup_pin_state ? HAL_GPIO_TRIG_FALLING : HAL_GPIO_TRIG_RISING);
+
+        if (woke != pdd->woke) {
+            pdd->woke = woke;
+            /*
+             * Wakeup interrupt pin stays active whole time till device goes to sleep,
+             * notify client only once.
+             */
+            if (woke) {
+                if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_WAKEUP) {
+                    sensor_mgr_put_notify_evt(&pdd->notify_ctx, SENSOR_EVENT_TYPE_WAKEUP);
+                }
+            } else {
+                if (pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_SLEEP) {
+                    sensor_mgr_put_notify_evt(&pdd->notify_ctx, SENSOR_EVENT_TYPE_SLEEP);
+                }
+            }
+        }
+    }
+
     if ((pdd->notify_ctx.snec_evtype & SENSOR_EVENT_TYPE_SINGLE_TAP) &&
         (int_status.int_stat1 & BMA400_INT_STAT1_S_TAP_INT_STAT)) {
         sensor_mgr_put_notify_evt(&pdd->notify_ctx, SENSOR_EVENT_TYPE_SINGLE_TAP);