15
15
16
16
from adafruit_bus_device .i2c_device import I2CDevice
17
17
18
+ try :
19
+ from typing import Union
20
+ from busio import I2C
21
+ except ImportError :
22
+ pass
23
+
18
24
__version__ = "0.0.0-auto.0"
19
25
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DRV2605.git"
20
26
72
78
73
79
74
80
class DRV2605 :
75
- """TI DRV2605 haptic feedback motor driver module."""
81
+ """TI DRV2605 haptic feedback motor driver module.
82
+
83
+ :param I2C i2c: The board I2C object
84
+ :param int address: The I2C address
85
+ """
76
86
77
87
# Class-level buffer for reading and writing data with the sensor.
78
88
# This reduces memory allocations but means the code is not re-entrant or
79
89
# thread safe!
80
90
_BUFFER = bytearray (2 )
81
91
82
- def __init__ (self , i2c , address = _DRV2605_ADDR ):
92
+ def __init__ (self , i2c : I2C , address : int = _DRV2605_ADDR ) -> None :
83
93
self ._device = I2CDevice (i2c , address )
84
94
# Check chip ID is 3 or 7 (DRV2605 or DRV2605L).
85
95
status = self ._read_u8 (_DRV2605_REG_STATUS )
@@ -106,95 +116,107 @@ def __init__(self, i2c, address=_DRV2605_ADDR):
106
116
self .library = LIBRARY_TS2200A
107
117
self ._sequence = _DRV2605_Sequence (self )
108
118
109
- def _read_u8 (self , address ) :
119
+ def _read_u8 (self , address : int ) -> int :
110
120
# Read an 8-bit unsigned value from the specified 8-bit address.
111
121
with self ._device as i2c :
112
122
self ._BUFFER [0 ] = address & 0xFF
113
123
i2c .write_then_readinto (self ._BUFFER , self ._BUFFER , out_end = 1 , in_end = 1 )
114
124
return self ._BUFFER [0 ]
115
125
116
- def _write_u8 (self , address , val ) :
126
+ def _write_u8 (self , address : int , val : int ) -> None :
117
127
# Write an 8-bit unsigned value to the specified 8-bit address.
118
128
with self ._device as i2c :
119
129
self ._BUFFER [0 ] = address & 0xFF
120
130
self ._BUFFER [1 ] = val & 0xFF
121
131
i2c .write (self ._BUFFER , end = 2 )
122
132
123
- def play (self ):
133
+ def play (self ) -> None :
124
134
"""Play back the select effect(s) on the motor."""
125
135
self ._write_u8 (_DRV2605_REG_GO , 1 )
126
136
127
- def stop (self ):
137
+ def stop (self ) -> None :
128
138
"""Stop vibrating the motor."""
129
139
self ._write_u8 (_DRV2605_REG_GO , 0 )
130
140
131
141
@property
132
- def mode (self ):
142
+ def mode (self ) -> int :
133
143
"""
134
144
The mode of the chip. Should be a value of:
135
145
136
- - MODE_INTTRIG: Internal triggering, vibrates as soon as you call
146
+ * `` MODE_INTTRIG`` : Internal triggering, vibrates as soon as you call
137
147
play(). Default mode.
138
- - MODE_EXTTRIGEDGE: External triggering, edge mode.
139
- - MODE_EXTTRIGLVL: External triggering, level mode.
140
- - MODE_PWMANALOG: PWM/analog input mode.
141
- - MODE_AUDIOVIBE: Audio-to-vibration mode.
142
- - MODE_REALTIME: Real-time playback mode.
143
- - MODE_DIAGNOS: Diagnostics mode.
144
- - MODE_AUTOCAL: Auto-calibration mode.
148
+ * `` MODE_EXTTRIGEDGE`` : External triggering, edge mode.
149
+ * `` MODE_EXTTRIGLVL`` : External triggering, level mode.
150
+ * `` MODE_PWMANALOG`` : PWM/analog input mode.
151
+ * `` MODE_AUDIOVIBE`` : Audio-to-vibration mode.
152
+ * `` MODE_REALTIME`` : Real-time playback mode.
153
+ * `` MODE_DIAGNOS`` : Diagnostics mode.
154
+ * `` MODE_AUTOCAL`` : Auto-calibration mode.
145
155
146
156
See the datasheet for the meaning of modes beyond MODE_INTTRIG.
147
157
"""
148
158
return self ._read_u8 (_DRV2605_REG_MODE )
149
159
150
160
@mode .setter
151
- def mode (self , val ) :
161
+ def mode (self , val : int ) -> None :
152
162
if not 0 <= val <= 7 :
153
163
raise ValueError ("Mode must be a value within 0-7!" )
154
164
self ._write_u8 (_DRV2605_REG_MODE , val )
155
165
156
166
@property
157
- def library (self ):
167
+ def library (self ) -> int :
158
168
"""
159
169
The library selected for waveform playback. Should be
160
170
a value of:
161
171
162
- - LIBRARY_EMPTY: Empty
163
- - LIBRARY_TS2200A: TS2200 library A (the default)
164
- - LIBRARY_TS2200B: TS2200 library B
165
- - LIBRARY_TS2200C: TS2200 library C
166
- - LIBRARY_TS2200D: TS2200 library D
167
- - LIBRARY_TS2200E: TS2200 library E
168
- - LIBRARY_LRA: LRA library
172
+ * `` LIBRARY_EMPTY`` : Empty
173
+ * `` LIBRARY_TS2200A`` : TS2200 library A (the default)
174
+ * `` LIBRARY_TS2200B`` : TS2200 library B
175
+ * `` LIBRARY_TS2200C`` : TS2200 library C
176
+ * `` LIBRARY_TS2200D`` : TS2200 library D
177
+ * `` LIBRARY_TS2200E`` : TS2200 library E
178
+ * `` LIBRARY_LRA`` : LRA library
169
179
170
180
See the datasheet for the meaning and description of effects in each
171
181
library.
172
182
"""
173
183
return self ._read_u8 (_DRV2605_REG_LIBRARY ) & 0x07
174
184
175
185
@library .setter
176
- def library (self , val ) :
186
+ def library (self , val : int ) -> None :
177
187
if not 0 <= val <= 6 :
178
188
raise ValueError ("Library must be a value within 0-6!" )
179
189
self ._write_u8 (_DRV2605_REG_LIBRARY , val )
180
190
181
191
@property
182
- def sequence (self ):
192
+ def sequence (self ) -> "_DRV2605_Sequence" :
183
193
"""List-like sequence of waveform effects.
184
- Get or set an effect waveform for slot 0-7 by indexing the sequence
185
- property with the slot number. A slot must be set to either an Effect()
186
- or Pause() class. See the datasheet for a complete table of effect ID
194
+ Get or set an effect waveform for slot 0-6 by indexing the sequence
195
+ property with the slot number. A slot must be set to either an :class:`~ Effect`
196
+ or :class:`~ Pause` class. See the datasheet for a complete table of effect ID
187
197
values and the associated waveform / effect.
188
198
189
- E.g. 'slot_0_effect = drv.sequence[0]', 'drv.sequence[0] = Effect(88)'
199
+ E.g.:
200
+ .. code-block:: python
201
+
202
+ # Getting the effect stored in a slot
203
+ slot_0_effect = drv.sequence[0]
204
+
205
+ .. code-block:: python
206
+
207
+ # Setting an Effect in the first sequence slot
208
+ drv.sequence[0] = Effect(88)
190
209
"""
191
210
return self ._sequence
192
211
193
- def set_waveform (self , effect_id , slot = 0 ) :
212
+ def set_waveform (self , effect_id : int , slot : int = 0 ) -> None :
194
213
"""Select an effect waveform for the specified slot (default is slot 0,
195
214
but up to 8 effects can be combined with slot values 0 to 7). See the
196
215
datasheet for a complete table of effect ID values and the associated
197
216
waveform / effect.
217
+
218
+ :param int effect_id: The effect ID of the waveform
219
+ :param int slot: The sequence slot to use
198
220
"""
199
221
if not 0 <= effect_id <= 123 :
200
222
raise ValueError ("Effect ID must be a value within 0-123!" )
@@ -203,87 +225,96 @@ def set_waveform(self, effect_id, slot=0):
203
225
self ._write_u8 (_DRV2605_REG_WAVESEQ1 + slot , effect_id )
204
226
205
227
# pylint: disable=invalid-name
206
- def use_ERM (self ):
228
+ def use_ERM (self ) -> None :
207
229
"""Use an eccentric rotating mass motor (the default)."""
208
230
feedback = self ._read_u8 (_DRV2605_REG_FEEDBACK )
209
231
self ._write_u8 (_DRV2605_REG_FEEDBACK , feedback & 0x7F )
210
232
211
233
# pylint: disable=invalid-name
212
- def use_LRM (self ):
234
+ def use_LRM (self ) -> None :
213
235
"""Use a linear resonance actuator motor."""
214
236
feedback = self ._read_u8 (_DRV2605_REG_FEEDBACK )
215
237
self ._write_u8 (_DRV2605_REG_FEEDBACK , feedback | 0x80 )
216
238
217
239
218
240
class Effect :
219
- """DRV2605 waveform sequence effect."""
241
+ """DRV2605 waveform sequence effect.
242
+
243
+ :param int effect_id: The ID number of the effect
244
+ """
220
245
221
- def __init__ (self , effect_id ) :
246
+ def __init__ (self , effect_id : int ) -> None :
222
247
self ._effect_id = 0
223
248
# pylint: disable=invalid-name
224
249
self .id = effect_id
225
250
226
251
@property
227
- def raw_value (self ):
252
+ def raw_value (self ) -> int :
228
253
"""Raw effect ID."""
229
254
return self ._effect_id
230
255
231
256
@property
232
257
# pylint: disable=invalid-name
233
- def id (self ):
258
+ def id (self ) -> int :
234
259
"""Effect ID."""
235
260
return self ._effect_id
236
261
237
262
@id .setter
238
263
# pylint: disable=invalid-name
239
- def id (self , effect_id ) :
264
+ def id (self , effect_id : int ) -> None :
240
265
"""Set the effect ID."""
241
266
if not 0 <= effect_id <= 123 :
242
267
raise ValueError ("Effect ID must be a value within 0-123!" )
243
268
self ._effect_id = effect_id
244
269
245
- def __repr__ (self ):
270
+ def __repr__ (self ) -> str :
246
271
return "{}({})" .format (type (self ).__qualname__ , self .id )
247
272
248
273
249
274
class Pause :
250
- """DRV2605 waveform sequence timed delay."""
275
+ """DRV2605 waveform sequence timed delay.
251
276
252
- def __init__ (self , duration ):
277
+ :param float duration: The duration of the pause in seconds
278
+ """
279
+
280
+ def __init__ (self , duration : float ) -> None :
253
281
# Bit 7 must be set for a slot to be interpreted as a delay
254
282
self ._duration = 0x80
255
283
self .duration = duration
256
284
257
285
@property
258
- def raw_value (self ):
286
+ def raw_value (self ) -> int :
259
287
"""Raw pause duration."""
260
288
return self ._duration
261
289
262
290
@property
263
- def duration (self ):
291
+ def duration (self ) -> float :
264
292
"""Pause duration in seconds."""
265
293
# Remove wait time flag bit and convert duration to seconds
266
294
return (self ._duration & 0x7F ) / 100.0
267
295
268
296
@duration .setter
269
- def duration (self , duration ) :
297
+ def duration (self , duration : float ) -> None :
270
298
"""Sets the pause duration in seconds."""
271
299
if not 0.0 <= duration <= 1.27 :
272
300
raise ValueError ("Pause duration must be a value within 0.0-1.27!" )
273
301
# Add wait time flag bit and convert duration to centiseconds
274
302
self ._duration = 0x80 | round (duration * 100.0 )
275
303
276
- def __repr__ (self ):
304
+ def __repr__ (self ) -> str :
277
305
return "{}({})" .format (type (self ).__qualname__ , self .duration )
278
306
279
307
280
308
class _DRV2605_Sequence :
281
- """Class to enable List-like indexing of the waveform sequence slots."""
309
+ """Class to enable List-like indexing of the waveform sequence slots.
310
+
311
+ :param DRV2605 DRV2605_instance: The DRV2605 instance
312
+ """
282
313
283
- def __init__ (self , DRV2605_instance ) :
314
+ def __init__ (self , DRV2605_instance : DRV2605 ) -> None :
284
315
self ._drv2605 = DRV2605_instance
285
316
286
- def __setitem__ (self , slot , effect ) :
317
+ def __setitem__ (self , slot : int , effect : Union [ Effect , Pause ]) -> None :
287
318
"""Write an Effect or Pause to a slot."""
288
319
if not 0 <= slot <= 7 :
289
320
raise IndexError ("Slot must be a value within 0-6!" )
@@ -292,7 +323,7 @@ def __setitem__(self, slot, effect):
292
323
# pylint: disable=protected-access
293
324
self ._drv2605 ._write_u8 (_DRV2605_REG_WAVESEQ1 + slot , effect .raw_value )
294
325
295
- def __getitem__ (self , slot ) :
326
+ def __getitem__ (self , slot : int ) -> Union [ Effect , Pause ] :
296
327
"""Read an effect ID from a slot. Returns either a Pause or Effect class."""
297
328
if not 0 <= slot <= 7 :
298
329
raise IndexError ("Slot must be a value within 0-6!" )
@@ -302,11 +333,11 @@ def __getitem__(self, slot):
302
333
return Pause ((slot_contents & 0x7F ) / 100.0 )
303
334
return Effect (slot_contents )
304
335
305
- def __iter__ (self ):
336
+ def __iter__ (self ) -> Union [ Effect , Pause ] :
306
337
"""Returns an iterator over the waveform sequence slots."""
307
338
for slot in range (0 , 8 ):
308
339
yield self [slot ]
309
340
310
- def __repr__ (self ):
341
+ def __repr__ (self ) -> str :
311
342
"""Return a string representation of all slot's effects."""
312
343
return repr (list (self ))
0 commit comments