From 156a7b06976a02c30f4c4f370bc8da56da68bbdc Mon Sep 17 00:00:00 2001 From: CinderSocket Date: Fri, 27 Mar 2026 22:28:45 -0700 Subject: [PATCH] power: convert board voltage handling to millivolts --- board_power_lifecycle.c | 12 +++++---- board_power_lifecycle.h | 4 +-- lib/host_tests/test_board_power_lifecycle.c | 20 +++++++------- seader.c | 30 +++++++++++++++------ 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/board_power_lifecycle.c b/board_power_lifecycle.c index e53e2fd..f9de2e2 100644 --- a/board_power_lifecycle.c +++ b/board_power_lifecycle.c @@ -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; } diff --git a/board_power_lifecycle.h b/board_power_lifecycle.h index 4773079..48cd335 100644 --- a/board_power_lifecycle.h +++ b/board_power_lifecycle.h @@ -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, diff --git a/lib/host_tests/test_board_power_lifecycle.c b/lib/host_tests/test_board_power_lifecycle.c index 737bd5c..cd0eafc 100644 --- a/lib/host_tests/test_board_power_lifecycle.c +++ b/lib/host_tests/test_board_power_lifecycle.c @@ -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; diff --git a/seader.c b/seader.c index 03e24c7..02d7c03 100644 --- a/seader.c +++ b/seader.c @@ -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()) {