Lumitronix_Iflex_Pro_Workshop
Library to interact with the iFlexPro
Mbi6033GenericMethod.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2 LumitronixIFlex library helper functions for Mbi6033s using general Pins.
3 
4 Written by Michael C. Miller.
5 
6 I invest time and resources providing this open source code,
7 please support me by dontating (see https://github.com/Makuna)
8 
9 -------------------------------------------------------------------------
10 This file is part of the LUMITRONIX_iFlex_Workshop library.
11 
12 LumitronixIFlexBus is free software: you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as
14 published by the Free Software Foundation, either version 3 of
15 the License, or (at your option) any later version.
16 
17 LumitronixIFlexBus is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU Lesser General Public License for more details.
21 
22 You should have received a copy of the GNU Lesser General Public
23 License along with LumitronixIFlex. If not, see
24 <http://www.gnu.org/licenses/>.
25 -------------------------------------------------------------------------*/
26 
27 #pragma once
28 
29 // must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set
30 #if defined(ARDUINO_ARCH_AVR) && !defined(__arm__)
31 #include "TwoWireBitBangImpleAvr.h"
32 #else
33 #include "TwoWireBitBangImple.h"
34 #endif
35 
36 
37 template<typename T_TWOWIRE> class Mbi6033MethodBase
38 {
39 public:
40  typedef typename T_TWOWIRE::SettingsObject SettingsObject;
41 
42  Mbi6033MethodBase(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
43  _countChips(NeoUtil::RoundUp(pixelCount * elementSize, c_countBytesPerChip) / c_countBytesPerChip),
44  _sizeData(_countChips * c_countBytesPerChip + settingsSize),
45  _pinClock(pinClock),
46  _wire(pinClock, pinData)
47  {
48  _data = static_cast<uint8_t*>(malloc(_sizeData));
49  // data cleared later in Begin()
50  }
51 
52 #if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
53  Mbi6033MethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
54  Mbi6033MethodBase(SCK, MOSI, pixelCount, elementSize, settingsSize)
55  {
56  }
57 #endif
58 
60  {
61  free(_data);
62  }
63 
64  bool IsReadyToUpdate() const
65  {
66  return true; // clock driven chips don't have a required delay
67  }
68 
69 #if defined(ARDUINO_ARCH_ESP32)
70  void Initialize(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
71  {
72  _pinClock = sck;
73  _wire.begin(sck, miso, mosi, ss);
74  }
75 #endif
76 
77  void Initialize()
78  {
79  _wire.begin();
80  }
81 
82  void Update(bool)
83  {
84  // non current header format:
85  // 8 bits: command (0xf3) = non current header mode
86  // 14 bits: sync (0x0000)
87  // 14 bits: length (count chips - 1)
88  // 8 bits: configuration (0x02)
89  // bits (6-4) refresh rate divider bits (0 for fastest)
90  // bit (1) on or off
91  // 4 bits: header code name X1 (0x0)
92  const uint16_t chipLength = _countChips - 1;
93  const uint8_t headerFrame[6] = { 0xf3,
94  0x00,
95  static_cast<uint8_t>(chipLength >> 12),
96  static_cast<uint8_t>((chipLength >> 4) & 0xff),
97  static_cast<uint8_t>((chipLength << 4) & 0xff),
98  0x20 };
99 
100  // prefix protocol, >21us clock low, clock high, >21us clock low
101  // expecting at least 21us since last call to show
102  // but using hardware SPI won't allow messing with clock
103  // directly like this...
104  //delayMicroseconds(c_usResetTime);
105  //digitalWrite(_pinClock, HIGH);
106  //digitalWrite(_pinClock, LOW);
107  //delayMicroseconds(c_usResetTime);
108 
109  _wire.beginTransaction();
110 
111  // reset by toggle of clock
112  delayMicroseconds(c_usResetTime);
113  _wire.transmitBit(0); // Our Two Wire BitBang supports this
114  delayMicroseconds(c_usResetTime);
115 
116  // header frame
117  _wire.transmitBytes(headerFrame, sizeof(headerFrame));
118 
119  // data:
120  // 24 bytes per chip of data (12 16 bit values)
121  _wire.transmitBytes(_data, _sizeData);
122 
123  _wire.endTransaction();
124  }
125 
127  {
128  // this method requires update to be called only if changes to buffer
129  return false;
130  }
131 
132  uint8_t* getData() const
133  {
134  return _data;
135  };
136 
137  size_t getDataSize() const
138  {
139  return _sizeData;
140  };
141 
142  void applySettings([[maybe_unused]] const SettingsObject& settings)
143  {
144  _wire.applySettings(settings);
145  }
146 
147 private:
148  // while spec states 4 RGB * 16 bit values,
149  // its really 12 channels * 16 bit values, as they could
150  // be wired how ever the circuit is built, like 3 RGBW
151  static const uint16_t c_countBytesPerChip = 24; // twelve 16 bit values
152  static const uint16_t c_usResetTime = 21;
153 
154  const uint16_t _countChips; // not pixels, driver chips
155  const size_t _sizeData; // Size of '_data' buffer below
156 
157  uint8_t _pinClock;
158  T_TWOWIRE _wire;
159  uint8_t* _data; // Holds LED color values
160 };
161 
163 
164 /* Due to reset model by these chips needing to control clock, we can't use hardware SPI
165 * as neither the normal SPI exposes a single bit send nor does it allow direct clock pulses
166 * using digitalWrite. If a generalized solution could be found, then this could be enabled
167 *
168 #if !defined(__AVR_ATtiny85__) && !defined(ARDUINO_attiny)
169 #include "TwoWireSpiImple.h"
170 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> Mbi6033Spi40MhzMethod;
171 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Mbi6033Spi20MhzMethod;
172 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Mbi6033Spi10MhzMethod;
173 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> Mbi6033Spi5MhzMethod;
174 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Mbi6033Spi2MhzMethod;
175 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Mbi6033Spi1MhzMethod;
176 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Mbi6033Spi500KhzMethod;
177 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeedHz>> Mbi6033SpiHzMethod;
178 
179 typedef Mbi6033Spi10MhzMethod Mbi6033SpiMethod;
180 #endif
181 
182 #if defined(ARDUINO_ARCH_ESP32)
183 // Give option to use Vspi alias of Spi class if wanting to specify which SPI peripheral is used on the ESP32
184 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> Mbi6033Esp32Vspi40MhzMethod;
185 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Mbi6033Esp32Vspi20MhzMethod;
186 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Mbi6033Esp32Vspi10MhzMethod;
187 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> Mbi6033Esp32Vspi5MhzMethod;
188 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Mbi6033Esp32Vspi2MhzMethod;
189 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Mbi6033Esp32Vspi1MhzMethod;
190 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Mbi6033Esp32Vspi500KhzMethod;
191 typedef Mbi6033MethodBase<TwoWireSpiImple<SpiSpeedHz>> Mbi6033Esp32VspiHzMethod;
192 
193 typedef Mbi6033Spi10MhzMethod Mbi6033Esp32VspiMethod;
194 
195 #include "TwoWireHspiImple.h"
196 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed40Mhz>> Mbi6033Esp32Hspi40MhzMethod;
197 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed20Mhz>> Mbi6033Esp32Hspi20MhzMethod;
198 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed10Mhz>> Mbi6033Esp32Hspi10MhzMethod;
199 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed5Mhz>> Mbi6033Esp32Hspi5MhzMethod;
200 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed2Mhz>> Mbi6033Esp32Hspi2MhzMethod;
201 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed1Mhz>> Mbi6033Esp32Hspi1MhzMethod;
202 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeed500Khz>> Mbi6033Esp32Hspi500KhzMethod;
203 typedef Mbi6033MethodBase<TwoWireHspiImple<SpiSpeedHz>> Mbi6033Esp32HspiHzMethod;
204 
205 typedef Mbi6033Esp32Hspi10MhzMethod Mbi6033Esp32HspiMethod;
206 #endif
207 */
Mbi6033MethodBase< TwoWireBitBangImple > Mbi6033Method
Definition: Mbi6033GenericMethod.h:162
Definition: Mbi6033GenericMethod.h:38
T_TWOWIRE::SettingsObject SettingsObject
Definition: Mbi6033GenericMethod.h:40
void Update(bool)
Definition: Mbi6033GenericMethod.h:82
~Mbi6033MethodBase()
Definition: Mbi6033GenericMethod.h:59
bool IsReadyToUpdate() const
Definition: Mbi6033GenericMethod.h:64
void Initialize()
Definition: Mbi6033GenericMethod.h:77
uint8_t * getData() const
Definition: Mbi6033GenericMethod.h:132
void applySettings([[maybe_unused]] const SettingsObject &settings)
Definition: Mbi6033GenericMethod.h:142
bool AlwaysUpdate()
Definition: Mbi6033GenericMethod.h:126
Mbi6033MethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Mbi6033GenericMethod.h:53
Mbi6033MethodBase(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize, size_t settingsSize)
Definition: Mbi6033GenericMethod.h:42
size_t getDataSize() const
Definition: Mbi6033GenericMethod.h:137
Definition: NeoUtil.h:50