Lumitronix_Iflex_Pro_Workshop
Library to interact with the iFlexPro
Tlc5947GenericMethod.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2 LumitronixIFlex library helper functions for Tlc5947 24 channel PWM controller using general Pins.
3 
4 Written by Michael C. Miller.
5 Written by Dennis Kasprzyk.
6 
7 I invest time and resources providing this open source code,
8 please support me by dontating (see https://github.com/Makuna)
9 
10 -------------------------------------------------------------------------
11 This file is part of the LUMITRONIX_iFlex_Workshop library.
12 
13 LumitronixIFlexBus is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as
15 published by the Free Software Foundation, either version 3 of
16 the License, or (at your option) any later version.
17 
18 LumitronixIFlexBus is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22 
23 You should have received a copy of the GNU Lesser General Public
24 License along with LumitronixIFlex. If not, see
25 <http://www.gnu.org/licenses/>.
26 -------------------------------------------------------------------------*/
27 
28 #pragma once
29 
30 // must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set
31 #if defined(ARDUINO_ARCH_AVR) && !defined(__arm__)
32 #include "TwoWireBitBangImpleAvr.h"
33 #else
34 #include "TwoWireBitBangImple.h"
35 #endif
36 
37 #define TLC5947_MODULE_PWM_CHANNEL_COUNT 24
38 
40 {
41 public:
42  static const size_t sizeChannel = 1;
43  static void ConvertFrame(uint8_t* sendBufferPtr, uint8_t* channelPtr)
44  {
45  // Write 2 channels into 3 bytes scaling 8-bit to 12-bit per channel
46  for (int indexChannel = 0; indexChannel < TLC5947_MODULE_PWM_CHANNEL_COUNT; indexChannel += 2)
47  {
48  uint8_t ch1 = *channelPtr--;
49  uint8_t ch2 = *channelPtr--;
50 
51  *sendBufferPtr++ = ch1;
52  *sendBufferPtr++ = (ch1 & 0xf0) | (ch2 >> 4);
53  *sendBufferPtr++ = ((ch2 << 4) & 0xf0) | (ch2 >> 4);
54  }
55  }
56 };
57 
59 {
60 public:
61  static const size_t sizeChannel = 2;
62  static void ConvertFrame(uint8_t* sendBufferPtr, uint8_t* sourceBufferPtr)
63  {
64  uint16_t* channelPtr = (uint16_t*)sourceBufferPtr;
65 
66  // Write 2 channels into 3 bytes using upper 12-bit of each channel
67  for (int indexChannel = 0; indexChannel < TLC5947_MODULE_PWM_CHANNEL_COUNT; indexChannel += 2)
68  {
69  uint8_t ch1 = *channelPtr--;
70  uint8_t ch2 = *channelPtr--;
71 
72  *sendBufferPtr++ = ch1 >> 8;
73  *sendBufferPtr++ = (ch1 & 0xf0) | (ch2 >> 12);
74  *sendBufferPtr++ = ch2 >> 4;
75  }
76  }
77 };
78 
79 
80 template<typename T_BITCONVERT, typename T_TWOWIRE> class Tlc5947MethodBase
81 {
82 public:
83  typedef typename T_TWOWIRE::SettingsObject SettingsObject;
84 
85  // 24 channel * 12 bit
86  static const size_t sizeSendBuffer = 36;
87 
88  Tlc5947MethodBase(uint8_t pinClock, uint8_t pinData, uint8_t pinLatch, uint8_t pinOutputEnable, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
89  _countModule((pixelCount * elementSize + TLC5947_MODULE_PWM_CHANNEL_COUNT - 1) / TLC5947_MODULE_PWM_CHANNEL_COUNT),
90  _sizeData(_countModule * TLC5947_MODULE_PWM_CHANNEL_COUNT + settingsSize),
91  _wire(pinClock, pinData),
92  _pinLatch(pinLatch),
93  _pinOutputEnable(pinOutputEnable)
94  {
95  _data = static_cast<uint8_t*>(malloc(_sizeData));
96  pinMode(pinLatch, OUTPUT);
97  pinMode(pinOutputEnable, OUTPUT);
98  digitalWrite(pinOutputEnable, HIGH);
99  }
100 
101  Tlc5947MethodBase(uint8_t pinClock, uint8_t pinData, uint8_t pinLatch, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
102  Tlc5947MethodBase(pinClock, pinData, pinLatch, -1, pixelCount, elementSize, settingsSize)
103  {
104  }
105 
106 #if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
107  Tlc5947MethodBase(uint8_t pinLatch, uint8_t pinOutputEnable, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
108  Tlc5947MethodBase(SCK, MOSI, pinLatch, pinOutputEnable, pixelCount, elementSize, settingsSize)
109  {
110  }
111 
112  Tlc5947MethodBase(uint8_t pinLatch, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
113  Tlc5947MethodBase(SCK, MOSI, pinLatch, -1, pixelCount, elementSize, settingsSize)
114  {
115  }
116 #endif
117 
119  {
120  free(_data);
121  pinMode(_pinLatch, INPUT);
122  pinMode(_pinOutputEnable, INPUT);
123  }
124 
125  bool IsReadyToUpdate() const
126  {
127  return true; // dot stars don't have a required delay
128  }
129 
130 #if defined(ARDUINO_ARCH_ESP32)
131  void Initialize(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
132  {
133  _wire.begin(sck, miso, mosi, ss);
134  }
135 #endif
136 
137  void Initialize()
138  {
139  _wire.begin();
140  memset(_data, 0, _sizeData);
141  }
142 
143  void Update(bool)
144  {
145 
146  digitalWrite(_pinOutputEnable, HIGH);
147 
148  digitalWrite(_pinLatch, LOW);
149  _wire.beginTransaction();
150 
151  // We need to write the channels in reverse order. Get a Pointer to the last channel.
152  uint8_t* lastChannelPtr = _data + ((_countModule * TLC5947_MODULE_PWM_CHANNEL_COUNT - 1) * T_BITCONVERT::sizeChannel);
153  for (uint16_t countSend = 0; countSend < _countModule; countSend++)
154  {
155  // We pass a pointer to the last channel and ConvertFrame reads the channels backwards
156  T_BITCONVERT::ConvertFrame(_sendBuffer, lastChannelPtr);
157  _wire.transmitBytes(_sendBuffer, sizeSendBuffer);
158  lastChannelPtr -= TLC5947_MODULE_PWM_CHANNEL_COUNT * T_BITCONVERT::sizeChannel;
159  }
160 
161  _wire.endTransaction();
162  digitalWrite(_pinLatch, HIGH);
163  digitalWrite(_pinLatch, LOW);
164  digitalWrite(_pinOutputEnable, LOW);
165  }
166 
168  {
169  // this method requires update to be called only if changes to buffer
170  return false;
171  }
172 
173  uint8_t* getData() const
174  {
175  return _data;
176  };
177 
178  size_t getDataSize() const
179  {
180  return _sizeData;
181  };
182 
183  void applySettings([[maybe_unused]] const SettingsObject& settings)
184  {
185  _wire.applySettings(settings);
186  }
187 
188 private:
189  const uint16_t _countModule; // Number of tlc5947 modules
190  const size_t _sizeData; // Size of '_data' buffer below
191 
192  T_TWOWIRE _wire;
193  uint8_t* _data; // Holds LED color values
194  uint8_t _sendBuffer[sizeSendBuffer]; // Holds channel values for one module
195  uint8_t _pinLatch;
196  uint8_t _pinOutputEnable;
197 };
198 
201 
202 #if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
203 #include "TwoWireSpiImple.h"
204 
205 // for standalone
208 
209 // for cascaded devices
212 
215 
216 
217 #endif
218 
219 
220 
#define TLC5947_MODULE_PWM_CHANNEL_COUNT
Definition: Tlc5947GenericMethod.h:37
Tlc5947MethodBase< Tlc5947Converter8Bit, TwoWireSpiImple< SpiSpeed30Mhz > > Tlc5947Spi30MhzMethod
Definition: Tlc5947GenericMethod.h:206
Tlc5947MethodBase< Tlc5947Converter8Bit, TwoWireSpiImple< SpiSpeed15Mhz > > Tlc5947SpiMethod
Definition: Tlc5947GenericMethod.h:213
Tlc5947MethodBase< Tlc5947Converter16Bit, TwoWireSpiImple< SpiSpeed15Mhz > > Tlc5947Spi15MhzMethod16Bit
Definition: Tlc5947GenericMethod.h:211
Tlc5947MethodBase< Tlc5947Converter8Bit, TwoWireSpiImple< SpiSpeed15Mhz > > Tlc5947Spi15MhzMethod
Definition: Tlc5947GenericMethod.h:210
Tlc5947MethodBase< Tlc5947Converter16Bit, TwoWireSpiImple< SpiSpeed30Mhz > > Tlc5947Spi30MhzMethod16Bit
Definition: Tlc5947GenericMethod.h:207
Tlc5947MethodBase< Tlc5947Converter8Bit, TwoWireBitBangImple > Tlc5947Method
Definition: Tlc5947GenericMethod.h:199
Tlc5947MethodBase< Tlc5947Converter16Bit, TwoWireBitBangImple > Tlc5947Method16Bit
Definition: Tlc5947GenericMethod.h:200
Tlc5947MethodBase< Tlc5947Converter16Bit, TwoWireSpiImple< SpiSpeed15Mhz > > Tlc5947SpiMethod16Bit
Definition: Tlc5947GenericMethod.h:214
Definition: Tlc5947GenericMethod.h:59
static const size_t sizeChannel
Definition: Tlc5947GenericMethod.h:61
static void ConvertFrame(uint8_t *sendBufferPtr, uint8_t *sourceBufferPtr)
Definition: Tlc5947GenericMethod.h:62
Definition: Tlc5947GenericMethod.h:40
static const size_t sizeChannel
Definition: Tlc5947GenericMethod.h:42
static void ConvertFrame(uint8_t *sendBufferPtr, uint8_t *channelPtr)
Definition: Tlc5947GenericMethod.h:43
Definition: Tlc5947GenericMethod.h:81
bool IsReadyToUpdate() const
Definition: Tlc5947GenericMethod.h:125
Tlc5947MethodBase(uint8_t pinLatch, uint8_t pinOutputEnable, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Tlc5947GenericMethod.h:107
size_t getDataSize() const
Definition: Tlc5947GenericMethod.h:178
void Initialize()
Definition: Tlc5947GenericMethod.h:137
bool AlwaysUpdate()
Definition: Tlc5947GenericMethod.h:167
void applySettings([[maybe_unused]] const SettingsObject &settings)
Definition: Tlc5947GenericMethod.h:183
void Update(bool)
Definition: Tlc5947GenericMethod.h:143
Tlc5947MethodBase(uint8_t pinClock, uint8_t pinData, uint8_t pinLatch, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Tlc5947GenericMethod.h:101
Tlc5947MethodBase(uint8_t pinClock, uint8_t pinData, uint8_t pinLatch, uint8_t pinOutputEnable, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Tlc5947GenericMethod.h:88
T_TWOWIRE::SettingsObject SettingsObject
Definition: Tlc5947GenericMethod.h:83
static const size_t sizeSendBuffer
Definition: Tlc5947GenericMethod.h:86
uint8_t * getData() const
Definition: Tlc5947GenericMethod.h:173
~Tlc5947MethodBase()
Definition: Tlc5947GenericMethod.h:118
Tlc5947MethodBase(uint8_t pinLatch, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Tlc5947GenericMethod.h:112