113 lines
2.7 KiB
C
113 lines
2.7 KiB
C
/******************************************************************************
|
|
* @file app_shake_wake.c
|
|
* @brief PA3 vibration-switch wake detector.
|
|
*
|
|
* The fitted switch is normally closed to ground. A vibration opens the
|
|
* contact, so PA3 goes high, then returns low when the contact closes again.
|
|
* A wake is accepted only after the high level has been stable for the
|
|
* re-arm interval and is generated on the following high-to-low transition.
|
|
******************************************************************************/
|
|
|
|
#include "app_shake_wake.h"
|
|
#include "board_pin.h"
|
|
#include "asm/gpio.h"
|
|
|
|
typedef struct {
|
|
AppShakeWakeAllowedFn allowed;
|
|
AppShakeWakeTriggerFn trigger;
|
|
uint8_t enable;
|
|
uint8_t armed;
|
|
uint8_t trigger_pending;
|
|
uint8_t high_ticks;
|
|
} AppShakeWakeCtx_t;
|
|
|
|
static AppShakeWakeCtx_t s_shake;
|
|
|
|
static void shake_reset_detection(void)
|
|
{
|
|
s_shake.armed = 0;
|
|
s_shake.trigger_pending = 0;
|
|
s_shake.high_ticks = 0;
|
|
}
|
|
|
|
static void shake_pin_init(void)
|
|
{
|
|
#if BOARD_SHAKE_ENABLE
|
|
gpio_set_die(BOARD_SHAKE_PIN, 1);
|
|
gpio_direction_input(BOARD_SHAKE_PIN);
|
|
gpio_set_pull_up(BOARD_SHAKE_PIN, 1);
|
|
gpio_set_pull_down(BOARD_SHAKE_PIN, 0);
|
|
#endif
|
|
}
|
|
|
|
void app_shake_wake_init(AppShakeWakeAllowedFn allowed,
|
|
AppShakeWakeTriggerFn trigger)
|
|
{
|
|
s_shake.allowed = allowed;
|
|
s_shake.trigger = trigger;
|
|
s_shake.enable = 0;
|
|
shake_reset_detection();
|
|
shake_pin_init();
|
|
}
|
|
|
|
void app_shake_wake_set_enable(uint8_t enable)
|
|
{
|
|
s_shake.enable = !!enable;
|
|
shake_reset_detection();
|
|
}
|
|
|
|
void app_shake_wake_reset(void)
|
|
{
|
|
shake_reset_detection();
|
|
}
|
|
|
|
void app_shake_wake_poll(void)
|
|
{
|
|
uint8_t pin_high;
|
|
uint8_t rearm_ticks;
|
|
|
|
if (!s_shake.enable) {
|
|
shake_reset_detection();
|
|
return;
|
|
}
|
|
|
|
#if BOARD_SHAKE_ENABLE
|
|
pin_high = (uint8_t)(gpio_read(BOARD_SHAKE_PIN) == BOARD_SHAKE_ACTIVE_LEVEL);
|
|
#else
|
|
pin_high = 0;
|
|
#endif
|
|
rearm_ticks = (uint8_t)(BOARD_SHAKE_REARM_MS / BOARD_SHAKE_POLL_MS);
|
|
if (!rearm_ticks) {
|
|
rearm_ticks = 1;
|
|
}
|
|
|
|
if (pin_high) {
|
|
if (s_shake.high_ticks < rearm_ticks) {
|
|
s_shake.high_ticks++;
|
|
}
|
|
if (s_shake.high_ticks >= rearm_ticks) {
|
|
s_shake.armed = 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* The contact has closed again: this is the verified wake edge. */
|
|
s_shake.high_ticks = 0;
|
|
if (s_shake.armed) {
|
|
s_shake.armed = 0;
|
|
s_shake.trigger_pending = 1;
|
|
}
|
|
|
|
if (!s_shake.trigger_pending) {
|
|
return;
|
|
}
|
|
s_shake.trigger_pending = 0;
|
|
if (!s_shake.allowed || !s_shake.allowed()) {
|
|
shake_reset_detection();
|
|
return;
|
|
}
|
|
if (s_shake.trigger) {
|
|
s_shake.trigger();
|
|
}
|
|
}
|