Skip to content

Commit

Permalink
Merge pull request #11 from process1183/sequence_property
Browse files Browse the repository at this point in the history
Indexable waveform sequence property
  • Loading branch information
tannewt authored Nov 4, 2018
2 parents 0429b55 + f978a65 commit 331776c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 10 deletions.
110 changes: 110 additions & 0 deletions adafruit_drv2605.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def __init__(self, i2c, address=_DRV2605_ADDR):
# Default to internal trigger mode and TS2200 A library.
self.mode = MODE_INTTRIG
self.library = LIBRARY_TS2200A
self._sequence = _DRV2605_Sequence(self)

def _read_u8(self, address):
# Read an 8-bit unsigned value from the specified 8-bit address.
Expand Down Expand Up @@ -196,6 +197,18 @@ def library(self, val):
raise ValueError('Library must be a value within 0-6!')
self._write_u8(_DRV2605_REG_LIBRARY, val)

@property
def sequence(self):
"""List-like sequence of waveform effects.
Get or set an effect waveform for slot 0-6 by indexing the sequence
property with the slot number. A slot must be set to either an Effect()
or Pause() class. See the datasheet for a complete table of effect ID
values and the associated waveform / effect.
E.g. 'slot_0_effect = drv.sequence[0]', 'drv.sequence[0] = Effect(88)'
"""
return self._sequence

def set_waveform(self, effect_id, slot=0):
"""Select an effect waveform for the specified slot (default is slot 0,
but up to 7 effects can be combined with slot values 0 to 6). See the
Expand All @@ -219,3 +232,100 @@ def use_LRM(self):
"""Use a linear resonance actuator motor."""
feedback = self._read_u8(_DRV2605_REG_FEEDBACK)
self._write_u8(_DRV2605_REG_FEEDBACK, feedback | 0x80)



class Effect:
"""DRV2605 waveform sequence effect."""
def __init__(self, effect_id):
self._effect_id = 0
# pylint: disable=invalid-name
self.id = effect_id

@property
def raw_value(self):
"""Raw effect ID."""
return self._effect_id

@property
# pylint: disable=invalid-name
def id(self):
"""Effect ID."""
return self._effect_id

@id.setter
# pylint: disable=invalid-name
def id(self, effect_id):
"""Set the effect ID."""
if not 0 <= effect_id <= 123:
raise ValueError('Effect ID must be a value within 0-123!')
self._effect_id = effect_id

def __repr__(self):
return "{}({})".format(type(self).__qualname__, self.id)



class Pause:
"""DRV2605 waveform sequence timed delay."""
def __init__(self, duration):
# Bit 7 must be set for a slot to be interpreted as a delay
self._duration = 0x80
self.duration = duration

@property
def raw_value(self):
"""Raw pause duration."""
return self._duration

@property
def duration(self):
"""Pause duration in seconds."""
# Remove wait time flag bit and convert duration to seconds
return (self._duration & 0x7f) / 100.0

@duration.setter
def duration(self, duration):
"""Set the pause duration in seconds."""
if not 0.0 <= duration <= 1.27:
raise ValueError('Pause duration must be a value within 0.0-1.27!')
# Add wait time flag bit and convert duration to centiseconds
self._duration = 0x80 | round(duration * 100.0)

def __repr__(self):
return "{}({})".format(type(self).__qualname__, self.duration)



class _DRV2605_Sequence:
"""Class to enable List-like indexing of the waveform sequence slots."""
def __init__(self, DRV2605_instance):
self._drv2605 = DRV2605_instance

def __setitem__(self, slot, effect):
"""Write an Effect or Pause to a slot."""
if not 0 <= slot <= 6:
raise IndexError('Slot must be a value within 0-6!')
if not isinstance(effect, (Effect, Pause)):
raise TypeError('Effect must be either an Effect() or Pause()!')
# pylint: disable=protected-access
self._drv2605._write_u8(_DRV2605_REG_WAVESEQ1 + slot, effect.raw_value)

def __getitem__(self, slot):
"""Read an effect ID from a slot. Returns either a Pause or Effect class."""
if not 0 <= slot <= 6:
raise IndexError('Slot must be a value within 0-6!')
# pylint: disable=protected-access
slot_contents = self._drv2605._read_u8(_DRV2605_REG_WAVESEQ1 + slot)
if slot_contents & 0x80:
return Pause((slot_contents & 0x7f) / 100.0)
return Effect(slot_contents)

def __iter__(self):
"""Return an iterator over the waveform sequence slots."""
for slot in range(0, 7):
yield self[slot]

def __repr__(self):
"""Return a string representation of all slot's effects."""
return repr([effect for effect in self])
21 changes: 11 additions & 10 deletions examples/drv2605_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@
# Main loop runs forever trying each effect (1-117).
# See table 11.2 in the datasheet for a list of all the effect names and IDs.
# http://www.ti.com/lit/ds/symlink/drv2605.pdf
effect = 1
effect_id = 1
while True:
print('Playing effect #{0}'.format(effect))
drv.set_waveform(effect) # Select the effect on slot 0.
# Optionally you can assign effects to up to 7 different slots to combine
# them in interesting ways. Use the slot keyword and specify a slot 0 to 6
# (0 is the default).
#drv.set_waveform(effect, slot=1)
print('Playing effect #{0}'.format(effect_id))
drv.sequence[0] = adafruit_drv2605.Effect(effect_id) # Set the effect on slot 0.
# You can assign effects to up to 7 different slots to combine
# them in interesting ways. Index the sequence property with a
# slot number 0 to 6.
# Optionally, you can assign a pause to a slot. E.g.
# drv.sequence[1] = adafruit_drv2605.Pause(0.5) # Pause for half a second
drv.play() # Play the effect.
time.sleep(0.5)
# Increment effect ID and wrap back around to 1.
effect += 1
if effect > 117:
effect = 1
effect_id += 1
if effect_id > 117:
effect_id = 1

0 comments on commit 331776c

Please sign in to comment.