31
31
from micropython import const
32
32
from adafruit_ticks import ticks_ms , ticks_diff
33
33
34
- _DEBOUNCED_STATE = const (0x01 )
35
- _UNSTABLE_STATE = const (0x02 )
36
- _CHANGED_STATE = const (0x04 )
34
+ try :
35
+ from typing import Callable , Optional , Union
36
+ from circuitpython_typing .io import ROValueIO
37
+ except ImportError :
38
+ pass
37
39
38
- _TICKS_PER_SEC = const (1000 )
40
+ _DEBOUNCED_STATE : int = const (0x01 )
41
+ _UNSTABLE_STATE : int = const (0x02 )
42
+ _CHANGED_STATE : int = const (0x04 )
43
+
44
+ _TICKS_PER_SEC : int = const (1000 )
39
45
40
46
41
47
class Debouncer :
42
48
"""Debounce an input pin or an arbitrary predicate"""
43
49
44
- def __init__ (self , io_or_predicate , interval = 0.010 ):
50
+ def __init__ (
51
+ self ,
52
+ io_or_predicate : Union [ROValueIO , Callable [[], bool ]],
53
+ interval : float = 0.010 ,
54
+ ) -> None :
45
55
"""Make an instance.
46
- :param DigitalInOut/function io_or_predicate: the DigitalIO or function to debounce
47
- :param int interval: bounce threshold in seconds (default is 0.010, i.e. 10 milliseconds)
56
+ :param DigitalInOut/function io_or_predicate: the DigitalIO or
57
+ function that returns a boolean to debounce
58
+ :param float interval: bounce threshold in seconds (default is 0.010, i.e. 10 milliseconds)
48
59
"""
49
60
self .state = 0x00
50
61
if hasattr (io_or_predicate , "value" ):
@@ -59,21 +70,21 @@ def __init__(self, io_or_predicate, interval=0.010):
59
70
60
71
# Could use the .interval setter, but pylint prefers that we explicitly
61
72
# set the real underlying attribute:
62
- self ._interval_ticks = interval * _TICKS_PER_SEC
73
+ self ._interval_ticks = int ( interval * _TICKS_PER_SEC )
63
74
64
- def _set_state (self , bits ) :
75
+ def _set_state (self , bits : int ) -> None :
65
76
self .state |= bits
66
77
67
- def _unset_state (self , bits ) :
78
+ def _unset_state (self , bits : int ) -> None :
68
79
self .state &= ~ bits
69
80
70
- def _toggle_state (self , bits ) :
81
+ def _toggle_state (self , bits : int ) -> None :
71
82
self .state ^= bits
72
83
73
- def _get_state (self , bits ) :
84
+ def _get_state (self , bits : int ) -> bool :
74
85
return (self .state & bits ) != 0
75
86
76
- def update (self , new_state = None ):
87
+ def update (self , new_state : Optional [ int ] = None ) -> None :
77
88
"""Update the debouncer state. MUST be called frequently"""
78
89
now_ticks = ticks_ms ()
79
90
self ._unset_state (_CHANGED_STATE )
@@ -96,38 +107,38 @@ def update(self, new_state=None):
96
107
self ._state_changed_ticks = now_ticks
97
108
98
109
@property
99
- def interval (self ):
110
+ def interval (self ) -> float :
100
111
"""The debounce delay, in seconds"""
101
112
return self ._interval_ticks / _TICKS_PER_SEC
102
113
103
114
@interval .setter
104
- def interval (self , new_interval_s ) :
115
+ def interval (self , new_interval_s : float ) -> None :
105
116
self ._interval_ticks = new_interval_s * _TICKS_PER_SEC
106
117
107
118
@property
108
- def value (self ):
119
+ def value (self ) -> bool :
109
120
"""Return the current debounced value."""
110
121
return self ._get_state (_DEBOUNCED_STATE )
111
122
112
123
@property
113
- def rose (self ):
124
+ def rose (self ) -> bool :
114
125
"""Return whether the debounced value went from low to high at the most recent update."""
115
126
return self ._get_state (_DEBOUNCED_STATE ) and self ._get_state (_CHANGED_STATE )
116
127
117
128
@property
118
- def fell (self ):
129
+ def fell (self ) -> bool :
119
130
"""Return whether the debounced value went from high to low at the most recent update."""
120
131
return (not self ._get_state (_DEBOUNCED_STATE )) and self ._get_state (
121
132
_CHANGED_STATE
122
133
)
123
134
124
135
@property
125
- def last_duration (self ):
136
+ def last_duration (self ) -> float :
126
137
"""Return the number of seconds the state was stable prior to the most recent transition."""
127
138
return self ._last_duration_ticks / _TICKS_PER_SEC
128
139
129
140
@property
130
- def current_duration (self ):
141
+ def current_duration (self ) -> float :
131
142
"""Return the number of seconds since the most recent transition."""
132
143
return ticks_diff (ticks_ms (), self ._state_changed_ticks ) / _TICKS_PER_SEC
133
144
@@ -148,12 +159,12 @@ class Button(Debouncer):
148
159
149
160
def __init__ (
150
161
self ,
151
- pin ,
152
- short_duration_ms = 200 ,
153
- long_duration_ms = 500 ,
154
- value_when_pressed = False ,
162
+ pin : Union [ ROValueIO , Callable [[], bool ]] ,
163
+ short_duration_ms : int = 200 ,
164
+ long_duration_ms : int = 500 ,
165
+ value_when_pressed : bool = False ,
155
166
** kwargs
156
- ):
167
+ ) -> None :
157
168
self .short_duration_ms = short_duration_ms
158
169
self .long_duration_ms = long_duration_ms
159
170
self .value_when_pressed = value_when_pressed
@@ -165,20 +176,20 @@ def __init__(
165
176
super ().__init__ (pin , ** kwargs )
166
177
167
178
@property
168
- def pressed (self ):
179
+ def pressed (self ) -> bool :
169
180
"""Return whether the button was pressed or not at the last update."""
170
181
return (self .value_when_pressed and self .rose ) or (
171
182
not self .value_when_pressed and self .fell
172
183
)
173
184
174
185
@property
175
- def released (self ):
186
+ def released (self ) -> bool :
176
187
"""Return whether the button was release or not at the last update."""
177
188
return (self .value_when_pressed and self .fell ) or (
178
189
not self .value_when_pressed and self .rose
179
190
)
180
191
181
- def update (self , new_state = None ):
192
+ def update (self , new_state : Optional [ int ] = None ) -> None :
182
193
super ().update (new_state )
183
194
if self .pressed :
184
195
self .last_change_ms = ticks_ms ()
@@ -210,12 +221,12 @@ def update(self, new_state=None):
210
221
self .short_to_show = 0
211
222
212
223
@property
213
- def short_count (self ):
224
+ def short_count (self ) -> int :
214
225
"""Return the number of short press if a series of short presses has
215
226
ended at the last update."""
216
227
return self .short_to_show
217
228
218
229
@property
219
- def long_press (self ):
230
+ def long_press (self ) -> bool :
220
231
"""Return whether a long press has occured at the last update."""
221
232
return self .long_to_show
0 commit comments