#ifndef SAFETY_H #define SAFETY_H #include #include /* * SaltyLab Safety Systems * * Covers: * - IWDG hardware watchdog (MCU reset if main loop hangs) * - RC signal timeout monitoring * - Tilt fault alert via buzzer * - Arm hold interlock (must hold arm for ARMING_HOLD_MS) * - Remote e-stop over 4G MQTT (CDC 'E'/'F'/'Z' commands) */ typedef enum { ESTOP_CLEAR = 0, ESTOP_TILT = 1, ESTOP_RC_KILL = 2, ESTOP_REMOTE = 3, ESTOP_CELLULAR_TIMEOUT = 4, } EstopSource; /* * safety_init() — call once in main() after HAL_Init(). * Starts IWDG with WATCHDOG_TIMEOUT_MS timeout from config.h. * Starts ARMING_HOLD_MS countdown from config.h. */ void safety_init(void); /* * safety_refresh() — call every main loop iteration. * Resets IWDG counter. If not called within WATCHDOG_TIMEOUT_MS, * the MCU will reset (independent of software — cannot be disabled). */ void safety_refresh(void); /* * safety_rc_alive() — returns true if RC receiver has sent a frame * within RC_TIMEOUT_MS. Call from the balance loop. */ bool safety_rc_alive(uint32_t now); /* * safety_alert_tilt_fault() — one-shot buzzer beep for tilt fault. * Safe to call repeatedly; only fires once per fault. */ void safety_alert_tilt_fault(bool faulted); /* * safety_arm_interlock() — returns true once arm button has been * held for ARMING_HOLD_MS from the moment safety_arm_start() was called. */ void safety_arm_start(uint32_t now); /* Call when arm requested */ bool safety_arm_ready(uint32_t now); /* Poll until true, then arm */ void safety_arm_cancel(void); /* Cancel pending arm */ void safety_remote_estop(EstopSource src); void safety_remote_estop_clear(void); EstopSource safety_get_estop(void); bool safety_remote_estop_active(void); #endif /* SAFETY_H */