10#define IDLE_ADC_FULL_SCALE 65535U
11#define IDLE_MV_AT_FULL_SCALE 10624U
46 return p->read_battery !=
NULL &&
p->on_usb_power !=
NULL &&
47 p->send_heartbeat !=
NULL &&
p->poll_command !=
NULL;
62 idle->context = context;
66 idle->initialized =
true;
75 idle->next_heartbeat_ms = now_ms;
82 if (mv < c->battery_fail_mv) {
85 if (mv < c->battery_warn_mv) {
99 uint32_t warn_recover =
101 uint32_t fail_recover =
105 if (mv < c->battery_fail_mv) {
110 if (mv >= warn_recover) {
122 idle->context, now_ms,
idle->config.callback_budget_ms);
126 idle->last.supply_mv = 0U;
132 idle->last.supply_mv = mv;
136 if (
idle->port.on_usb_power(
idle->context)) {
142 idle->last.battery =
idle->battery_band;
146 idle->last.sequence += 1U;
147 idle->last.uptime_ms = now_ms;
150 idle->context, &
idle->last,
idle->config.callback_budget_ms);
156 idle->last.consecutive_send_failures = 0U;
157 }
else if (
idle->last.consecutive_send_failures < UINT8_MAX) {
158 idle->last.consecutive_send_failures += 1U;
164static int32_t
ms_until(uint32_t now_ms, uint32_t target_ms) {
165 return (int32_t)(target_ms - now_ms);
192 int32_t remaining =
ms_until(now_ms,
idle->next_heartbeat_ms);
193 if (remaining <= (int32_t)
idle->config.wake_tolerance_ms) {
197 result.heartbeat_sent =
true;
200 idle->next_heartbeat_ms = now_ms +
idle->config.heartbeat_interval_ms;
201 remaining = (int32_t)
idle->config.heartbeat_interval_ms;
205 uint32_t sleep_s = ((uint32_t)remaining + 999U) / 1000U;
207 result.sleep_s = sleep_s == 0U ? 1U : sleep_s;
static const emmc_port_t port
idle_result_t idle_on_wake(idle_t *idle, uint32_t now_ms)
const idle_heartbeat_t * idle_last_heartbeat(const idle_t *idle)
#define IDLE_ADC_FULL_SCALE
#define IDLE_MV_AT_FULL_SCALE
static idle_battery_state_t band_next(const idle_config_t *c, idle_battery_state_t previous, uint16_t mv)
static void send_heartbeat(idle_t *idle, uint32_t now_ms)
bool idle_enter(idle_t *idle, uint32_t now_ms)
uint16_t idle_counts_to_mv(uint32_t raw_counts)
bool idle_init(idle_t *idle, const idle_config_t *config, const idle_port_t *port, void *context)
static bool port_valid(const idle_port_t *p)
static int32_t ms_until(uint32_t now_ms, uint32_t target_ms)
static void read_battery(idle_t *idle, uint32_t now_ms)
static idle_battery_state_t band_fresh(const idle_config_t *c, uint16_t mv)
@ IDLE_EVENT_ARM_REQUESTED
#define IDLE_MAX_COMMANDS_PER_WAKE
static const idle_config_t config
static self_test_reply_t reply(self_test_result_t result, int32_t diagnostic)
uint32_t callback_budget_ms
uint32_t wake_tolerance_ms
uint16_t battery_hysteresis_mv
uint32_t heartbeat_interval_ms
self_test_result_t result