power: convert board voltage handling to millivolts

This commit is contained in:
CinderSocket
2026-03-27 22:28:45 -07:00
parent a5a9453d23
commit 156a7b0697
4 changed files with 41 additions and 25 deletions

View File

@@ -1,5 +1,7 @@
#include "board_power_lifecycle.h"
#define SEADER_BOARD_POWER_AVAILABLE_MV 4500U
SeaderBoardPowerAcquirePlan seader_board_power_plan_acquire(bool otg_already_enabled) {
SeaderBoardPowerAcquirePlan plan = {
.should_enable_otg = !otg_already_enabled,
@@ -9,23 +11,23 @@ SeaderBoardPowerAcquirePlan seader_board_power_plan_acquire(bool otg_already_ena
return plan;
}
bool seader_board_power_is_available(bool otg_enabled, float vbus_voltage) {
return otg_enabled || vbus_voltage >= 4.5f;
bool seader_board_power_is_available(bool otg_enabled, uint16_t vbus_mv) {
return otg_enabled || vbus_mv >= SEADER_BOARD_POWER_AVAILABLE_MV;
}
SeaderBoardRuntimePowerState seader_board_runtime_power_state(
bool otg_requested,
bool otg_enabled,
float vbus_voltage,
uint16_t vbus_mv,
bool otg_fault,
bool grace_active,
uint32_t grace_elapsed_ms,
uint32_t grace_window_ms) {
if(seader_board_power_is_available(otg_enabled, vbus_voltage)) {
if(seader_board_power_is_available(otg_enabled, vbus_mv)) {
return SeaderBoardRuntimePowerStateHealthy;
}
if(otg_fault && vbus_voltage < 4.5f) {
if(otg_fault && vbus_mv < SEADER_BOARD_POWER_AVAILABLE_MV) {
return SeaderBoardRuntimePowerStateLost;
}

View File

@@ -33,11 +33,11 @@ typedef struct {
} SeaderBoardPowerAcquirePlan;
SeaderBoardPowerAcquirePlan seader_board_power_plan_acquire(bool otg_already_enabled);
bool seader_board_power_is_available(bool otg_enabled, float vbus_voltage);
bool seader_board_power_is_available(bool otg_enabled, uint16_t vbus_mv);
SeaderBoardRuntimePowerState seader_board_runtime_power_state(
bool otg_requested,
bool otg_enabled,
float vbus_voltage,
uint16_t vbus_mv,
bool otg_fault,
bool grace_active,
uint32_t grace_elapsed_ms,

View File

@@ -44,9 +44,9 @@ static MunitResult test_power_available_when_usb_vbus_is_already_present(
(void)params;
(void)fixture;
munit_assert_true(seader_board_power_is_available(false, 5.0f));
munit_assert_true(seader_board_power_is_available(true, 0.0f));
munit_assert_false(seader_board_power_is_available(false, 4.4f));
munit_assert_true(seader_board_power_is_available(false, 5000U));
munit_assert_true(seader_board_power_is_available(true, 0U));
munit_assert_false(seader_board_power_is_available(false, 4400U));
return MUNIT_OK;
}
@@ -56,7 +56,7 @@ static MunitResult test_power_unavailable_when_neither_otg_nor_vbus_is_present(
(void)params;
(void)fixture;
munit_assert_false(seader_board_power_is_available(false, 0.0f));
munit_assert_false(seader_board_power_is_available(false, 0U));
return MUNIT_OK;
}
@@ -67,23 +67,23 @@ static MunitResult test_runtime_power_state_uses_handoff_grace(
(void)fixture;
munit_assert_int(
seader_board_runtime_power_state(false, false, 5.0f, false, false, 0U, 2000U),
seader_board_runtime_power_state(false, false, 5000U, false, false, 0U, 2000U),
==,
SeaderBoardRuntimePowerStateHealthy);
munit_assert_int(
seader_board_runtime_power_state(true, false, 0.0f, false, false, 0U, 2000U),
seader_board_runtime_power_state(true, false, 0U, false, false, 0U, 2000U),
==,
SeaderBoardRuntimePowerStateGracePending);
munit_assert_int(
seader_board_runtime_power_state(true, false, 0.0f, false, true, 1500U, 2000U),
seader_board_runtime_power_state(true, false, 0U, false, true, 1500U, 2000U),
==,
SeaderBoardRuntimePowerStateGracePending);
munit_assert_int(
seader_board_runtime_power_state(true, false, 0.0f, false, true, 2000U, 2000U),
seader_board_runtime_power_state(true, false, 0U, false, true, 2000U, 2000U),
==,
SeaderBoardRuntimePowerStateLost);
munit_assert_int(
seader_board_runtime_power_state(true, true, 0.0f, false, true, 2000U, 2000U),
seader_board_runtime_power_state(true, true, 0U, false, true, 2000U, 2000U),
==,
SeaderBoardRuntimePowerStateHealthy);
return MUNIT_OK;
@@ -96,7 +96,7 @@ static MunitResult test_runtime_power_state_fault_is_immediate(
(void)fixture;
munit_assert_int(
seader_board_runtime_power_state(true, false, 0.0f, true, false, 0U, 2000U),
seader_board_runtime_power_state(true, false, 0U, true, false, 0U, 2000U),
==,
SeaderBoardRuntimePowerStateLost);
return MUNIT_OK;

View File

@@ -260,6 +260,19 @@ static void seader_hf_read_fail(Seader* seader, SeaderHfReadFailureReason reason
sizeof(seader->read_error));
}
static uint16_t seader_board_vbus_mv_from_volts(float vbus_voltage) {
if(vbus_voltage <= 0.0f) {
return 0U;
}
const float scaled_mv = (vbus_voltage * 1000.0f) + 0.5f;
if(scaled_mv >= 65535.0f) {
return UINT16_MAX;
}
return (uint16_t)scaled_mv;
}
static void seader_board_runtime_monitor_tick(Seader* seader) {
if(!seader || !seader->power || !seader->board_power_enabled ||
seader->board_status == SeaderBoardStatusPowerLost) {
@@ -274,17 +287,18 @@ static void seader_board_runtime_monitor_tick(Seader* seader) {
PowerInfo info;
power_get_info(seader->power, &info);
const uint16_t vbus_mv = seader_board_vbus_mv_from_volts(info.voltage_vbus);
const bool otg_requested = power_is_otg_enabled(seader->power);
const uint32_t now = furi_get_tick();
const uint32_t elapsed =
seader->board_power_loss_pending ? (now - seader->board_power_loss_started_at) : 0U;
const bool otg_fault = furi_hal_power_check_otg_fault() && info.voltage_vbus < 4.5f;
const bool otg_fault = furi_hal_power_check_otg_fault() && vbus_mv < 4500U;
const SeaderBoardRuntimePowerState runtime_state = seader_board_runtime_power_state(
otg_requested,
info.is_otg_enabled,
info.voltage_vbus,
vbus_mv,
otg_fault,
seader->board_power_loss_pending,
elapsed,
@@ -399,21 +413,21 @@ static bool seader_board_power_on(Seader* seader) {
furi_delay_ms(SEADER_BOARD_POWER_SETTLE_MS);
const bool otg_enabled = furi_hal_power_is_otg_enabled();
const float vbus_voltage = furi_hal_power_get_usb_voltage();
const uint16_t vbus_mv = seader_board_vbus_mv_from_volts(furi_hal_power_get_usb_voltage());
seader->board_power_owned = plan.owns_otg && otg_enabled;
if(!seader_board_power_is_available(otg_enabled, vbus_voltage)) {
if(!seader_board_power_is_available(otg_enabled, vbus_mv)) {
FURI_LOG_W(
TAG,
"Board power unavailable after OTG request: otg=%d vbus=%.1fV",
"Board power unavailable after OTG request: otg=%d vbus=%umV",
otg_enabled,
(double)vbus_voltage);
vbus_mv);
seader_board_power_fail(seader, SeaderBoardStatusFaultPreEnable);
return false;
}
if(!otg_enabled && vbus_voltage >= 4.5f) {
FURI_LOG_I(TAG, "Using external VBUS power at %.1fV", (double)vbus_voltage);
if(!otg_enabled && vbus_mv >= 4500U) {
FURI_LOG_I(TAG, "Using external VBUS power at %umV", vbus_mv);
}
if(furi_hal_power_check_otg_fault()) {