1515
1616from adafruit_bus_device .i2c_device import I2CDevice
1717
18+ try :
19+ from typing import Union
20+ from busio import I2C
21+ except ImportError :
22+ pass
23+
1824__version__ = "0.0.0-auto.0"
1925__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DRV2605.git"
2026
7278
7379
7480class 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+ """
7686
7787 # Class-level buffer for reading and writing data with the sensor.
7888 # This reduces memory allocations but means the code is not re-entrant or
7989 # thread safe!
8090 _BUFFER = bytearray (2 )
8191
82- def __init__ (self , i2c , address = _DRV2605_ADDR ):
92+ def __init__ (self , i2c : I2C , address : int = _DRV2605_ADDR ) -> None :
8393 self ._device = I2CDevice (i2c , address )
8494 # Check chip ID is 3 or 7 (DRV2605 or DRV2605L).
8595 status = self ._read_u8 (_DRV2605_REG_STATUS )
@@ -106,95 +116,107 @@ def __init__(self, i2c, address=_DRV2605_ADDR):
106116 self .library = LIBRARY_TS2200A
107117 self ._sequence = _DRV2605_Sequence (self )
108118
109- def _read_u8 (self , address ) :
119+ def _read_u8 (self , address : int ) -> int :
110120 # Read an 8-bit unsigned value from the specified 8-bit address.
111121 with self ._device as i2c :
112122 self ._BUFFER [0 ] = address & 0xFF
113123 i2c .write_then_readinto (self ._BUFFER , self ._BUFFER , out_end = 1 , in_end = 1 )
114124 return self ._BUFFER [0 ]
115125
116- def _write_u8 (self , address , val ) :
126+ def _write_u8 (self , address : int , val : int ) -> None :
117127 # Write an 8-bit unsigned value to the specified 8-bit address.
118128 with self ._device as i2c :
119129 self ._BUFFER [0 ] = address & 0xFF
120130 self ._BUFFER [1 ] = val & 0xFF
121131 i2c .write (self ._BUFFER , end = 2 )
122132
123- def play (self ):
133+ def play (self ) -> None :
124134 """Play back the select effect(s) on the motor."""
125135 self ._write_u8 (_DRV2605_REG_GO , 1 )
126136
127- def stop (self ):
137+ def stop (self ) -> None :
128138 """Stop vibrating the motor."""
129139 self ._write_u8 (_DRV2605_REG_GO , 0 )
130140
131141 @property
132- def mode (self ):
142+ def mode (self ) -> int :
133143 """
134144 The mode of the chip. Should be a value of:
135145
136- - MODE_INTTRIG: Internal triggering, vibrates as soon as you call
146+ * `` MODE_INTTRIG`` : Internal triggering, vibrates as soon as you call
137147 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.
145155
146156 See the datasheet for the meaning of modes beyond MODE_INTTRIG.
147157 """
148158 return self ._read_u8 (_DRV2605_REG_MODE )
149159
150160 @mode .setter
151- def mode (self , val ) :
161+ def mode (self , val : int ) -> None :
152162 if not 0 <= val <= 7 :
153163 raise ValueError ("Mode must be a value within 0-7!" )
154164 self ._write_u8 (_DRV2605_REG_MODE , val )
155165
156166 @property
157- def library (self ):
167+ def library (self ) -> int :
158168 """
159169 The library selected for waveform playback. Should be
160170 a value of:
161171
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
169179
170180 See the datasheet for the meaning and description of effects in each
171181 library.
172182 """
173183 return self ._read_u8 (_DRV2605_REG_LIBRARY ) & 0x07
174184
175185 @library .setter
176- def library (self , val ) :
186+ def library (self , val : int ) -> None :
177187 if not 0 <= val <= 6 :
178188 raise ValueError ("Library must be a value within 0-6!" )
179189 self ._write_u8 (_DRV2605_REG_LIBRARY , val )
180190
181191 @property
182- def sequence (self ):
192+ def sequence (self ) -> "_DRV2605_Sequence" :
183193 """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
187197 values and the associated waveform / effect.
188198
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)
190209 """
191210 return self ._sequence
192211
193- def set_waveform (self , effect_id , slot = 0 ) :
212+ def set_waveform (self , effect_id : int , slot : int = 0 ) -> None :
194213 """Select an effect waveform for the specified slot (default is slot 0,
195214 but up to 8 effects can be combined with slot values 0 to 7). See the
196215 datasheet for a complete table of effect ID values and the associated
197216 waveform / effect.
217+
218+ :param int effect_id: The effect ID of the waveform
219+ :param int slot: The sequence slot to use
198220 """
199221 if not 0 <= effect_id <= 123 :
200222 raise ValueError ("Effect ID must be a value within 0-123!" )
@@ -203,87 +225,96 @@ def set_waveform(self, effect_id, slot=0):
203225 self ._write_u8 (_DRV2605_REG_WAVESEQ1 + slot , effect_id )
204226
205227 # pylint: disable=invalid-name
206- def use_ERM (self ):
228+ def use_ERM (self ) -> None :
207229 """Use an eccentric rotating mass motor (the default)."""
208230 feedback = self ._read_u8 (_DRV2605_REG_FEEDBACK )
209231 self ._write_u8 (_DRV2605_REG_FEEDBACK , feedback & 0x7F )
210232
211233 # pylint: disable=invalid-name
212- def use_LRM (self ):
234+ def use_LRM (self ) -> None :
213235 """Use a linear resonance actuator motor."""
214236 feedback = self ._read_u8 (_DRV2605_REG_FEEDBACK )
215237 self ._write_u8 (_DRV2605_REG_FEEDBACK , feedback | 0x80 )
216238
217239
218240class Effect :
219- """DRV2605 waveform sequence effect."""
241+ """DRV2605 waveform sequence effect.
242+
243+ :param int effect_id: The ID number of the effect
244+ """
220245
221- def __init__ (self , effect_id ) :
246+ def __init__ (self , effect_id : int ) -> None :
222247 self ._effect_id = 0
223248 # pylint: disable=invalid-name
224249 self .id = effect_id
225250
226251 @property
227- def raw_value (self ):
252+ def raw_value (self ) -> int :
228253 """Raw effect ID."""
229254 return self ._effect_id
230255
231256 @property
232257 # pylint: disable=invalid-name
233- def id (self ):
258+ def id (self ) -> int :
234259 """Effect ID."""
235260 return self ._effect_id
236261
237262 @id .setter
238263 # pylint: disable=invalid-name
239- def id (self , effect_id ) :
264+ def id (self , effect_id : int ) -> None :
240265 """Set the effect ID."""
241266 if not 0 <= effect_id <= 123 :
242267 raise ValueError ("Effect ID must be a value within 0-123!" )
243268 self ._effect_id = effect_id
244269
245- def __repr__ (self ):
270+ def __repr__ (self ) -> str :
246271 return "{}({})" .format (type (self ).__qualname__ , self .id )
247272
248273
249274class Pause :
250- """DRV2605 waveform sequence timed delay."""
275+ """DRV2605 waveform sequence timed delay.
251276
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 :
253281 # Bit 7 must be set for a slot to be interpreted as a delay
254282 self ._duration = 0x80
255283 self .duration = duration
256284
257285 @property
258- def raw_value (self ):
286+ def raw_value (self ) -> int :
259287 """Raw pause duration."""
260288 return self ._duration
261289
262290 @property
263- def duration (self ):
291+ def duration (self ) -> float :
264292 """Pause duration in seconds."""
265293 # Remove wait time flag bit and convert duration to seconds
266294 return (self ._duration & 0x7F ) / 100.0
267295
268296 @duration .setter
269- def duration (self , duration ) :
297+ def duration (self , duration : float ) -> None :
270298 """Sets the pause duration in seconds."""
271299 if not 0.0 <= duration <= 1.27 :
272300 raise ValueError ("Pause duration must be a value within 0.0-1.27!" )
273301 # Add wait time flag bit and convert duration to centiseconds
274302 self ._duration = 0x80 | round (duration * 100.0 )
275303
276- def __repr__ (self ):
304+ def __repr__ (self ) -> str :
277305 return "{}({})" .format (type (self ).__qualname__ , self .duration )
278306
279307
280308class _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+ """
282313
283- def __init__ (self , DRV2605_instance ) :
314+ def __init__ (self , DRV2605_instance : DRV2605 ) -> None :
284315 self ._drv2605 = DRV2605_instance
285316
286- def __setitem__ (self , slot , effect ) :
317+ def __setitem__ (self , slot : int , effect : Union [ Effect , Pause ]) -> None :
287318 """Write an Effect or Pause to a slot."""
288319 if not 0 <= slot <= 7 :
289320 raise IndexError ("Slot must be a value within 0-6!" )
@@ -292,7 +323,7 @@ def __setitem__(self, slot, effect):
292323 # pylint: disable=protected-access
293324 self ._drv2605 ._write_u8 (_DRV2605_REG_WAVESEQ1 + slot , effect .raw_value )
294325
295- def __getitem__ (self , slot ) :
326+ def __getitem__ (self , slot : int ) -> Union [ Effect , Pause ] :
296327 """Read an effect ID from a slot. Returns either a Pause or Effect class."""
297328 if not 0 <= slot <= 7 :
298329 raise IndexError ("Slot must be a value within 0-6!" )
@@ -302,11 +333,11 @@ def __getitem__(self, slot):
302333 return Pause ((slot_contents & 0x7F ) / 100.0 )
303334 return Effect (slot_contents )
304335
305- def __iter__ (self ):
336+ def __iter__ (self ) -> Union [ Effect , Pause ] :
306337 """Returns an iterator over the waveform sequence slots."""
307338 for slot in range (0 , 8 ):
308339 yield self [slot ]
309340
310- def __repr__ (self ):
341+ def __repr__ (self ) -> str :
311342 """Return a string representation of all slot's effects."""
312343 return repr (list (self ))
0 commit comments