Skip to content

Commit 9d6d547

Browse files
authored
Resolving issue #6 chaining TLC boards
Extended README with new example file. Extended library with support for multiple chained boards.
1 parent 327cdfe commit 9d6d547

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Usage Example
3030
=============
3131

3232
See examples/tlc5947_simpletest.py for a demo of the usage.
33+
See examples/tlc5947_chain.py for a demo of chained driver usage.
3334

3435
Contributing
3536
============

adafruit_tlc5947.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
CircuitPython module for the TLC5947 12-bit 24 channel LED PWM driver. See
2727
examples/simpletest.py for a demo of the usage.
2828
29-
* Author(s): Tony DiCola
29+
* Author(s): Tony DiCola, Walter Haschka
3030
3131
Implementation Notes
3232
--------------------
@@ -50,6 +50,8 @@
5050
# access is by design for the internal class.
5151
#pylint: disable=protected-access
5252

53+
_CHANNELS = 24
54+
_STOREBYTES = _CHANNELS + _CHANNELS//2
5355

5456
class TLC5947:
5557
"""TLC5947 12-bit 24 channel LED PWM driver. Create an instance of this by
@@ -66,6 +68,16 @@ class TLC5947:
6668
single one is updated. If you set to false to disable then
6769
you MUST call write after every channel update or when you
6870
deem necessary to update the chip state.
71+
72+
:param num_drivers: This is an integer that defaults to 1. It stands for the
73+
number of chained LED driver boards (DOUT of one board has
74+
to be connected to DIN of the next). For each board added,
75+
36 bytes of RAM memory will be taken. The channel numbers
76+
on the driver directly connected to the controller are 0 to
77+
23, and for each driver add 24 to the port number printed.
78+
The more drivers are chained, the more viable it is to set
79+
auto_write=false, and call write explicitly after updating
80+
all the channels.
6981
"""
7082

7183
class PWMOut:
@@ -115,14 +127,15 @@ def frequency(self, val):
115127
#pylint: enable=no-self-use,unused-argument
116128

117129

118-
def __init__(self, spi, latch, *, auto_write=True):
130+
def __init__(self, spi, latch, *, auto_write=True, num_drivers=1):
119131
self._spi = spi
120132
self._latch = latch
121133
self._latch.switch_to_output(value=False)
122-
# This device is just a big 36 byte long shift register. There's no
123-
# fancy protocol or other commands to send, just write out all 288
134+
# This device is just a big 36*n byte long shift register. There's no
135+
# fancy protocol or other commands to send, just write out all 288*n
124136
# bits every time the state is updated.
125-
self._shift_reg = bytearray(36)
137+
self._n = num_drivers
138+
self._shift_reg = bytearray(_STOREBYTES * self._n)
126139
# Save auto_write state (i.e. push out shift register values on
127140
# any channel value change).
128141
self.auto_write = auto_write
@@ -141,7 +154,7 @@ def write(self):
141154
# First ensure latch is low.
142155
self._latch.value = False
143156
# Write out the bits.
144-
self._spi.write(self._shift_reg, start=0, end=37)
157+
self._spi.write(self._shift_reg, start=0, end=_STOREBYTES*self._n +1)
145158
# Then toggle latch high and low to set the value.
146159
self._latch.value = True
147160
self._latch.value = False
@@ -152,10 +165,10 @@ def write(self):
152165
def _get_gs_value(self, channel):
153166
# pylint: disable=no-else-return
154167
# Disable should be removed when refactor can be tested
155-
assert 0 <= channel <= 23
168+
assert 0 <= channel < _CHANNELS * self._n
156169
# Invert channel position as the last channel needs to be written first.
157170
# I.e. is in the first position of the shift registr.
158-
channel = 23 - channel
171+
channel = _CHANNELS * self._n - 1 - channel
159172
# Calculate exact bit position within the shift register.
160173
bit_offset = channel * 12
161174
# Now calculate the byte that this position falls within and any offset
@@ -177,11 +190,11 @@ def _get_gs_value(self, channel):
177190
raise RuntimeError('Unsupported bit offset!')
178191

179192
def _set_gs_value(self, channel, val):
180-
assert 0 <= channel <= 23
193+
assert 0 <= channel < _CHANNELS * self._n
181194
assert 0 <= val <= 4095
182195
# Invert channel position as the last channel needs to be written first.
183196
# I.e. is in the first position of the shift registr.
184-
channel = 23 - channel
197+
channel = _CHANNELS * self._n - 1 - channel
185198
# Calculate exact bit position within the shift register.
186199
bit_offset = channel * 12
187200
# Now calculate the byte that this position falls within and any offset
@@ -226,20 +239,22 @@ def create_pwm_out(self, channel):
226239
# like when using the PWMOut mock class).
227240
def __len__(self):
228241
"""Retrieve the total number of PWM channels available."""
229-
return 24 # Always 24 channels on the chip.
242+
return _CHANNELS * self._n # number channels times number chips.
230243

231244
def __getitem__(self, key):
232-
"""Retrieve the 12-bit PWM value for the specified channel (0-23).
245+
"""Retrieve the 12-bit PWM value for the specified channel (0-max).
246+
max depends on the number of boards.
233247
"""
234-
assert 0 <= key <= 23
248+
assert 0 <= key < _CHANNELS * self._n
235249
return self._get_gs_value(key)
236250

237251
def __setitem__(self, key, val):
238-
"""Set the 12-bit PWM value (0-4095) for the specified channel (0-23).
252+
"""Set the 12-bit PWM value (0-4095) for the specified channel (0-max).
253+
max depends on the number of boards.
239254
If auto_write is enabled (the default) then the chip PWM state will
240255
immediately be updated too, otherwise you must call write to update
241256
the chip with the new PWM state.
242257
"""
243-
assert 0 <= key <= 23
258+
assert 0 <= key < _CHANNELS * self._n
244259
assert 0 <= val <= 4095
245260
self._set_gs_value(key, val)

0 commit comments

Comments
 (0)