Files
JBao_Magic_Box_FW/apps/usr_app/app_shake_wake.c
T
2026-09-01 17:31:15 +08:00

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();
}
}