Sound Byte Libs 0.5.1-121-g3358a44
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
digital_gate.hpp
Go to the documentation of this file.
1// sbl/hw/components/input/digital_gate.hpp — Debounced digital gate input
2//
3// DigitalGateInput takes logical GPIO readings (true = gate high) and provides
4// debounced state with edge detection. Designed for Eurorack gate/trigger
5// signals read via GPIO pins (as opposed to GateInput which takes ADC values
6// with Schmitt trigger thresholds).
7//
8// Optional retrigger lockout prevents spurious double-triggers from noisy edges.
9//
10// Usage:
11// sbl::components::input::DigitalGateInput gate;
12// gate.update(gpio_reading); // Feed logical state each tick
13// if (gate.rising()) { ... } // One-shot rising edge (auto-resets)
14// if (gate.gate()) { ... } // Current debounced state
15
16#ifndef SBL_HW_COMPONENTS_INPUT_DIGITAL_GATE_HPP_
17#define SBL_HW_COMPONENTS_INPUT_DIGITAL_GATE_HPP_
18
19#include <cstdint>
20
21namespace sbl::components::input {
22
24 uint8_t debounce_count = 3; ///< Consecutive identical readings to accept
25 uint16_t retrigger_lockout = 0; ///< Minimum ticks between rising edges (0 = disabled)
26};
27
28/// Debounced digital gate input with edge detection and retrigger lockout.
29///
30/// @note All public methods are ISR-safe — pure state machine with no hardware I/O.
32public:
33 explicit DigitalGateInput(const DigitalGateConfig& config = {})
34 : threshold_(config.debounce_count),
35 lockout_time_(config.retrigger_lockout) {}
36
37 /// Feed a new logical GPIO reading.
38 /// Call once per update cycle (e.g. 200 Hz control rate).
39 void update(bool logical_state) {
40 // Tick down lockout
41 if (lockout_remaining_ > 0) {
42 --lockout_remaining_;
43 }
44
45 if (logical_state == stable_) {
46 // Input matches stable — reset debounce counter
47 counter_ = 0;
48 } else {
49 // Input differs — count toward transition
50 ++counter_;
51 if (counter_ >= threshold_) {
52 bool was = stable_;
53 stable_ = logical_state;
54 counter_ = 0;
55
56 if (stable_ && !was && lockout_remaining_ == 0) {
57 rising_ = true;
58 lockout_remaining_ = lockout_time_;
59 } else if (!stable_ && was) {
60 falling_ = true;
61 }
62 }
63 }
64 }
65
66 /// Current debounced gate state (true = high).
67 bool gate() const { return stable_; }
68
69 /// True if gate just went high (rising edge).
70 /// Consuming read — resets after first read. Call once per update cycle.
71 bool rising() {
72 bool e = rising_;
73 rising_ = false;
74 return e;
75 }
76
77 /// True if gate just went low (falling edge).
78 /// Consuming read — resets after first read. Call once per update cycle.
79 bool falling() {
80 bool e = falling_;
81 falling_ = false;
82 return e;
83 }
84
85 /// Reset all state.
86 void reset() {
87 counter_ = 0;
88 stable_ = false;
89 rising_ = false;
90 falling_ = false;
91 lockout_remaining_ = 0;
92 }
93
94private:
95 uint8_t threshold_;
96 uint16_t lockout_time_;
97
98 uint8_t counter_ = 0;
99 bool stable_ = false;
100 bool rising_ = false;
101 bool falling_ = false;
102 uint16_t lockout_remaining_ = 0;
103};
104
105} // namespace sbl::components::input
106
107#endif // SBL_HW_COMPONENTS_INPUT_DIGITAL_GATE_HPP_
bool gate() const
Current debounced gate state (true = high).
DigitalGateInput(const DigitalGateConfig &config={})
Pots, buttons, encoders.
Definition button.hpp:24
uint8_t debounce_count
Consecutive identical readings to accept.
uint16_t retrigger_lockout
Minimum ticks between rising edges (0 = disabled)