From be59dc3db7b0e483e1322783570421cb530e6be0 Mon Sep 17 00:00:00 2001 From: Kawin Pechetratanapanit <39807451+kawinie@users.noreply.github.com> Date: Sat, 16 May 2026 04:04:05 -0700 Subject: [PATCH] feat(v2): blink V/A readout while output disabled Half-period 500ms (1Hz cycle). --- include/v2/stages/normal/normal_view.h | 17 +++++++++++------ include/v2/stages/normal_stage.h | 14 ++++++++++---- test/test_v2_normal/test.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/include/v2/stages/normal/normal_view.h b/include/v2/stages/normal/normal_view.h index 52590a8..3446809 100644 --- a/include/v2/stages/normal/normal_view.h +++ b/include/v2/stages/normal/normal_view.h @@ -4,12 +4,12 @@ */ #pragma once -#include - #include #include #include +#include + #include "v2/events.h" #include "v2/images.h" #include "v2/pocketpd.h" @@ -25,6 +25,7 @@ namespace pocketpd { bool has_profile = false; bool is_pps = false; bool output_enabled = false; + bool readout_visible = true; bool locked = false; uint8_t arrow_frame = 0; SensorSnapshot snapshot{}; @@ -57,7 +58,7 @@ namespace pocketpd { static constexpr uint8_t ARROW_W = 20; static constexpr uint8_t ARROW_H = 20; static constexpr std::array CURSOR_X = {33, 39, 45}; - static constexpr uint8_t CURSOR_W = 7; + static constexpr uint8_t CURSOR_W = 6; public: static constexpr uint8_t PADLOCK_X = 116; @@ -78,8 +79,8 @@ namespace pocketpd { std::array buf{}; d.set_font(tempo::Font::XL); - draw_measured(d, "V", V_MEASURED_Y, vm.snapshot.vbus_mv, buf); - draw_measured(d, "A", A_MEASURED_Y, vm.snapshot.current_ma, buf); + draw_measured(d, "V", V_MEASURED_Y, vm.snapshot.vbus_mv, buf, vm.readout_visible); + draw_measured(d, "A", A_MEASURED_Y, vm.snapshot.current_ma, buf, vm.readout_visible); d.set_font(tempo::Font::BASE); std::snprintf(buf.data(), buf.size(), "[%u]", vm.active_pdo_index); @@ -115,9 +116,13 @@ namespace pocketpd { const char* label, uint8_t y, uint32_t value, - std::array& buf + std::array& buf, + bool show_value ) { d.draw_text(1, y, label); + if (!show_value) { + return; + } const unsigned long whole = value / 1000; const unsigned long fraction = (value % 1000) / 10; std::snprintf(buf.data(), buf.size(), "%lu.%02lu", whole, fraction); diff --git a/include/v2/stages/normal_stage.h b/include/v2/stages/normal_stage.h index 2cfea50..9f9d269 100644 --- a/include/v2/stages/normal_stage.h +++ b/include/v2/stages/normal_stage.h @@ -4,20 +4,20 @@ */ #pragma once +#include + #include #include #include -#include - #include "v2/app.h" #include "v2/events.h" #include "v2/hal/output_gate.h" #include "v2/hal/pd_sink_controller.h" +#include "v2/pocketpd.h" #include "v2/stages/normal/fixed_mode.h" #include "v2/stages/normal/normal_view.h" #include "v2/stages/normal/pps_mode.h" -#include "v2/pocketpd.h" namespace pocketpd { @@ -43,8 +43,10 @@ namespace pocketpd { IntervalTimer m_render_interval{40}; uint8_t m_arrow_frame = 0; uint32_t m_last_draw_ms = 0; + bool m_blink_visible = true; static constexpr uint32_t SENSOR_EMA_DEN = 4; + static constexpr uint32_t READOUT_BLINK_HALF_PERIOD_MS = 500; public: static constexpr const char* LOG_TAG = "Normal"; @@ -126,6 +128,8 @@ namespace pocketpd { log.debug("draw period={}ms (~{}Hz)", period, hz); } m_last_draw_ms = now_ms; + m_blink_visible = m_output_gate.is_enabled() || + ((now_ms / READOUT_BLINK_HALF_PERIOD_MS) % 2 == 0); draw(); } } @@ -133,7 +137,8 @@ namespace pocketpd { void on_event(Conductor& conductor, const Event& event, uint32_t) override { auto handler = tempo::overloaded{ [&](const ButtonEvent& evt) { - // L+R combo always reachable; must precede lock guard so a locked screen can unlock. + // L+R combo always reachable; must precede lock guard so a locked screen can + // unlock. if (evt.lr_long()) { m_locked = !m_locked; return; @@ -244,6 +249,7 @@ namespace pocketpd { .active_pdo_index = m_active_pdo_index, .has_profile = m_active_pdo_index >= 0, .output_enabled = m_output_gate.is_enabled(), + .readout_visible = m_blink_visible, .locked = m_locked, .arrow_frame = m_arrow_frame, .snapshot = m_snapshot, diff --git a/test/test_v2_normal/test.cpp b/test/test_v2_normal/test.cpp index 0b51718..36d1a4a 100644 --- a/test/test_v2_normal/test.cpp +++ b/test/test_v2_normal/test.cpp @@ -401,6 +401,30 @@ TEST(NormalView, UnlockedDoesNotDrawPadlock) { NormalView::render(display, vm); } +TEST(NormalView, ReadoutHiddenKeepsLabelsHidesValues) { + using ::testing::_; + using ::testing::AtLeast; + using ::testing::HasSubstr; + using ::testing::StrEq; + NiceMock display; + + EXPECT_CALL(display, draw_text(_, _, _)).Times(::testing::AnyNumber()); + EXPECT_CALL(display, draw_text(1, 14, StrEq("V"))).Times(AtLeast(1)); + EXPECT_CALL(display, draw_text(1, 48, StrEq("A"))).Times(AtLeast(1)); + EXPECT_CALL(display, draw_text(_, 14, HasSubstr("5."))).Times(0); + EXPECT_CALL(display, draw_text(_, 48, HasSubstr("1."))).Times(0); + + NormalViewModel vm{}; + vm.has_profile = true; + vm.is_pps = false; + vm.output_enabled = false; + vm.readout_visible = false; + vm.active_pdo_index = 0; + vm.snapshot = SensorSnapshot{0, 5000, 1234}; + + NormalView::render(display, vm); +} + TEST(NormalStage, ComboLongTogglesLock) { NiceMock display; NiceMock sink;