ISF15ACP4 Driver 1.0.0
API reference
Loading...
Searching...
No Matches
isf15acp4_button_ui.ipp
Go to the documentation of this file.
1#ifndef ISF15ACP4_BUTTON_UI_HEADER_INCLUDED
2#error "isf15acp4_button_ui.ipp must be included from isf15acp4_button_ui.hpp"
3#endif
4
5#include <cmath>
6
7namespace isf15acp4 {
8
9inline ButtonUI::ButtonUI(uint32_t debounce_ms, uint32_t long_press_ms) noexcept
10 : debounce_ms_(debounce_ms), long_press_ms_(long_press_ms) {}
11
12inline ButtonEvent ButtonUI::Update(bool pressed, uint32_t elapsed_ms) noexcept {
13 stable_ms_ += elapsed_ms;
14 if (stable_ms_ < debounce_ms_) {
15 return ButtonEvent::None;
16 }
17 stable_ms_ = 0;
18
19 if (pressed && !is_down_) {
20 is_down_ = true;
21 hold_ms_ = 0;
22 long_fired_ = false;
23 ++press_count_;
25 }
26
27 if (!pressed && is_down_) {
28 is_down_ = false;
29 const auto ev = long_fired_ ? ButtonEvent::None : ButtonEvent::Click;
30 hold_ms_ = 0;
31 return ev == ButtonEvent::None ? ButtonEvent::Released : ev;
32 }
33
34 if (pressed && is_down_) {
35 hold_ms_ += elapsed_ms;
36 if (!long_fired_ && hold_ms_ >= long_press_ms_) {
37 long_fired_ = true;
39 }
40 }
41
42 return ButtonEvent::None;
43}
44
45inline void ButtonUI::DrawStatus(GraphicsContext& gfx, const char* label, bool active) const noexcept {
46 gfx.Clear(active ? MakeColor565(0, 40, 0) : colors::Black);
47 gfx.FillRect({0, 0, gfx.Width(), 11}, colors::Blue);
48 gfx.DrawString(4, 2, label != nullptr ? label : "BTN", colors::White);
49 gfx.DrawString(4, 20, active ? "PRESSED" : "READY", active ? colors::Green : colors::Gray);
50 gfx.DrawRect({2, 14, static_cast<uint8_t>(gfx.Width() - 3), static_cast<uint8_t>(gfx.Height() - 3)},
51 active ? colors::Green : colors::White);
52}
53
54inline void ButtonUI::DrawGauge(GraphicsContext& gfx, uint8_t cx, uint8_t cy, uint8_t radius,
55 float value_0_to_1, Color565 fg, Color565 bg) noexcept {
56 if (value_0_to_1 < 0.0f) {
57 value_0_to_1 = 0.0f;
58 }
59 if (value_0_to_1 > 1.0f) {
60 value_0_to_1 = 1.0f;
61 }
62
63 for (uint8_t r = 0; r <= radius; ++r) {
64 for (int angle = 180; angle >= 0; --angle) {
65 const float rad = static_cast<float>(angle) * 3.14159265f / 180.0f;
66 const int x = static_cast<int>(cx + std::cos(rad) * static_cast<float>(r));
67 const int y = static_cast<int>(cy + std::sin(rad) * static_cast<float>(r));
68 const float t = static_cast<float>(angle) / 180.0f;
69 const Color565 c = (t <= value_0_to_1) ? fg : bg;
70 if (x >= 0 && y >= 0 && x < gfx.Width() && y < gfx.Height()) {
71 gfx.SetPixel(static_cast<uint8_t>(x), static_cast<uint8_t>(y), c);
72 }
73 }
74 }
75}
76
77} // namespace isf15acp4
ButtonUI(uint32_t debounce_ms=25, uint32_t long_press_ms=800) noexcept
Definition isf15acp4_button_ui.ipp:9
void DrawStatus(GraphicsContext &gfx, const char *label, bool active) const noexcept
Draw idle/active visual using graphics context.
Definition isf15acp4_button_ui.ipp:45
static void DrawGauge(GraphicsContext &gfx, uint8_t cx, uint8_t cy, uint8_t radius, float value_0_to_1, Color565 fg, Color565 bg) noexcept
Draw a compact gauge arc and numeric value.
Definition isf15acp4_button_ui.ipp:54
ButtonEvent Update(bool pressed, uint32_t elapsed_ms) noexcept
Poll raw pressed state and return edge/event classification.
Definition isf15acp4_button_ui.ipp:12
Owns the active graphics backend selected at construction time.
Definition isf15acp4_graphics_context.hpp:42
constexpr Color565 Black
Definition isf15acp4_types.hpp:116
constexpr Color565 White
Definition isf15acp4_types.hpp:117
constexpr Color565 Gray
Definition isf15acp4_types.hpp:125
constexpr Color565 Green
Definition isf15acp4_types.hpp:119
constexpr Color565 Blue
Definition isf15acp4_types.hpp:120
Definition isf15acp4.hpp:19
ButtonEvent
Edge-qualified button events from debounced polling.
Definition isf15acp4_button_ui.hpp:27
uint16_t Color565
16-bit RGB565 color value (R5G6B5).
Definition isf15acp4_types.hpp:50
constexpr Color565 MakeColor565(uint8_t r, uint8_t g, uint8_t b) noexcept
Build an RGB565 color from 8-bit RGB channels.
Definition isf15acp4_types.hpp:110