rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
ui_value_gate.h
1/*
2 * Whether a screen's output value follows its controls.
3 *
4 * MOTOR & ESC's throttle and SERVO's position are commanded only while the
5 * bench drives them. One definition of that, shared by both screens, from
6 * what a screen knows: the bench's last report of its armed state, and what
7 * the screen itself has asked of the bench and not yet been answered on.
8 *
9 * OFF the bench reports disarmed and nothing is asked
10 * ARMING an ARM is posted; the bench has not reported armed
11 * LIVE the bench reports armed and nothing asks it to stop
12 * LEAVING a DISARM is posted or a STOP latched; the bench still reports
13 * armed, for the frames its answer takes
14 *
15 * Only LIVE takes input. Everything a screen decides about the value reads
16 * ui_value_state(): the input gate, the dimming, the owners of the value
17 * (a drag, the knob, a sweep, a run), which end on the edge out of LIVE,
18 * and the callbacks that arrive late.
19 *
20 * A link that goes quiet under an armed bench is not an input here: the
21 * panel latches a stop for it, which is one.
22 *
23 * SPDX-License-Identifier: MIT
24 */
25#pragma once
26
27#include <stdbool.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33typedef enum {
34 UI_VALUE_OFF = 0,
35 UI_VALUE_ARMING,
36 UI_VALUE_LIVE,
37 UI_VALUE_LEAVING,
38} ui_value_state_t;
39
40typedef struct {
41 bool armed;
43 bool arm_asked;
47
49typedef enum {
50 UI_VALUE_EDGE_NONE = 0,
51 UI_VALUE_EDGE_LIVE,
52 UI_VALUE_EDGE_LEFT,
53} ui_value_edge_t;
54
55static inline ui_value_state_t ui_value_state(const ui_value_gate_t *g)
56{
57 if (g->armed) {
58 return g->leave_asked ? UI_VALUE_LEAVING : UI_VALUE_LIVE;
59 }
60 return g->arm_asked ? UI_VALUE_ARMING : UI_VALUE_OFF;
61}
62
63static inline bool ui_value_live(const ui_value_gate_t *g)
64{
65 return ui_value_state(g) == UI_VALUE_LIVE;
66}
67
68static inline ui_value_edge_t ui_value_edge(ui_value_state_t before,
69 ui_value_state_t after)
70{
71 if (before != UI_VALUE_LIVE && after == UI_VALUE_LIVE) {
72 return UI_VALUE_EDGE_LIVE;
73 }
74 if (before == UI_VALUE_LIVE && after != UI_VALUE_LIVE) {
75 return UI_VALUE_EDGE_LEFT;
76 }
77 return UI_VALUE_EDGE_NONE;
78}
79
81static inline void ui_value_ask_arm(ui_value_gate_t *g)
82{
83 g->arm_asked = true;
84}
85
87static inline void ui_value_drop_arm(ui_value_gate_t *g)
88{
89 g->arm_asked = false;
90}
91
99static inline ui_value_edge_t ui_value_ask_leave(ui_value_gate_t *g)
100{
101 const ui_value_state_t before = ui_value_state(g);
102 if (g->armed) {
103 g->leave_asked = true;
104 }
105 g->arm_asked = false;
106 return ui_value_edge(before, ui_value_state(g));
107}
108
111static inline ui_value_edge_t ui_value_hide(ui_value_gate_t *g)
112{
113 const ui_value_state_t before = ui_value_state(g);
114 g->armed = false;
115 g->arm_asked = false;
116 return ui_value_edge(before, ui_value_state(g));
117}
118
121static inline ui_value_edge_t ui_value_report(ui_value_gate_t *g, bool armed)
122{
123 const ui_value_state_t before = ui_value_state(g);
124 g->armed = armed;
125 if (armed) {
126 g->arm_asked = false;
127 } else {
128 g->leave_asked = false;
129 }
130 return ui_value_edge(before, ui_value_state(g));
131}
132
133#ifdef __cplusplus
134}
135#endif
Definition ui_value_gate.h:40
bool arm_asked
Definition ui_value_gate.h:43
bool armed
Definition ui_value_gate.h:41
bool leave_asked
Definition ui_value_gate.h:44