Skip to content

Commit 17f16db

Browse files
authored
Merge pull request #29 from tekktrik/doc/typing-and-documentation
Add type annotations, update documentation
2 parents 32ae578 + fde1577 commit 17f16db

File tree

2 files changed

+84
-53
lines changed

2 files changed

+84
-53
lines changed

adafruit_drv2605.py

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515

1616
from 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

@@ -72,14 +78,18 @@
7278

7379

7480
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+
"""
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

218240
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+
"""
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

249274
class 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

280308
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+
"""
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))

examples/drv2605_simpletest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
while True:
2323
print("Playing effect #{0}".format(effect_id))
2424
drv.sequence[0] = adafruit_drv2605.Effect(effect_id) # Set the effect on slot 0.
25-
# You can assign effects to up to 7 different slots to combine
25+
# You can assign effects to up to 8 different slots to combine
2626
# them in interesting ways. Index the sequence property with a
27-
# slot number 0 to 6.
27+
# slot number 0 to 7.
2828
# Optionally, you can assign a pause to a slot. E.g.
2929
# drv.sequence[1] = adafruit_drv2605.Pause(0.5) # Pause for half a second
3030
drv.play() # play the effect

0 commit comments

Comments
 (0)