Lumitronix_Iflex_Pro_Workshop
Library to interact with the iFlexPro
NeoEsp32I2sMethod.h
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2 LumitronixIFlex library helper functions for Esp32.
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 // ESP32 C3 & S3 I2S is not supported yet due to significant changes to interface
30 #if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
31 
32 
33 extern "C"
34 {
35 #include "Esp32_i2s.h"
36 }
37 
38 const uint16_t c_dmaBytesPerPixelBytes = 4;
39 
40 class NeoEsp32I2sSpeedWs2812x
41 {
42 public:
43  const static uint32_t I2sSampleRate = 100000;
44  const static uint16_t ByteSendTimeUs = 10;
45  const static uint16_t ResetTimeUs = 300;
46 };
47 
48 class NeoEsp32I2sSpeedSk6812
49 {
50 public:
51  const static uint32_t I2sSampleRate = 100000;
52  const static uint16_t ByteSendTimeUs = 10;
53  const static uint16_t ResetTimeUs = 80;
54 };
55 
56 class NeoEsp32I2sSpeedTm1814
57 {
58 public:
59  const static uint32_t I2sSampleRate = 100000;
60  const static uint16_t ByteSendTimeUs = 10;
61  const static uint16_t ResetTimeUs = 200;
62 };
63 
64 class NeoEsp32I2sSpeedTm1914
65 {
66 public:
67  const static uint32_t I2sSampleRate = 100000;
68  const static uint16_t ByteSendTimeUs = 10;
69  const static uint16_t ResetTimeUs = 200;
70 };
71 
72 class NeoEsp32I2sSpeedTm1829
73 {
74 public:
75  const static uint32_t I2sSampleRate = 100000;
76  const static uint16_t ByteSendTimeUs = 10;
77  const static uint16_t ResetTimeUs = 200;
78 };
79 
80 class NeoEsp32I2sSpeed800Kbps
81 {
82 public:
83  const static uint32_t I2sSampleRate = 100000;
84  const static uint16_t ByteSendTimeUs = 10;
85  const static uint16_t ResetTimeUs = 50;
86 };
87 
88 class NeoEsp32I2sSpeed400Kbps
89 {
90 public:
91  const static uint32_t I2sSampleRate = 50000;
92  const static uint16_t ByteSendTimeUs = 20;
93  const static uint16_t ResetTimeUs = 50;
94 };
95 
96 class NeoEsp32I2sSpeedApa106
97 {
98 public:
99  const static uint32_t I2sSampleRate = 76000;
100  const static uint16_t ByteSendTimeUs = 14;
101  const static uint16_t ResetTimeUs = 50;
102 };
103 
104 class NeoEsp32I2sBusZero
105 {
106 public:
107  NeoEsp32I2sBusZero() {};
108 
109  const static uint8_t I2sBusNumber = 0;
110 };
111 
112 class NeoEsp32I2sBusOne
113 {
114 public:
115  NeoEsp32I2sBusOne() {};
116 
117  const static uint8_t I2sBusNumber = 1;
118 };
119 
120 // dynamic channel support
121 class NeoEsp32I2sBusN
122 {
123 public:
124  NeoEsp32I2sBusN(NeoBusChannel channel) :
125  I2sBusNumber(static_cast<uint8_t>(channel))
126  {
127  }
128  NeoEsp32I2sBusN() = delete; // no default constructor
129 
130  const uint8_t I2sBusNumber;
131 };
132 
133 class NeoEsp32I2sNotInverted
134 {
135 public:
136  const static bool Inverted = false;
137 };
138 
139 class NeoEsp32I2sInverted
140 {
141 public:
142  const static bool Inverted = true;
143 };
144 
145 template<typename T_SPEED, typename T_BUS, typename T_INVERT> class NeoEsp32I2sMethodBase
146 {
147 public:
148  typedef NeoNoSettings SettingsObject;
149 
150  NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
151  _sizeData(pixelCount * elementSize + settingsSize),
152  _pin(pin)
153  {
154  construct(pixelCount, elementSize, settingsSize);
155  }
156 
157  NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize, NeoBusChannel channel) :
158  _sizeData(pixelCount * elementSize + settingsSize),
159  _pin(pin),
160  _bus(channel)
161  {
162  construct(pixelCount, elementSize, settingsSize);
163  }
164 
165  ~NeoEsp32I2sMethodBase()
166  {
167  while (!IsReadyToUpdate())
168  {
169  yield();
170  }
171 
172  i2sDeinit(_bus.I2sBusNumber);
173 
174  gpio_matrix_out(_pin, 0x100, false, false);
175  pinMode(_pin, INPUT);
176 
177  free(_data);
178  heap_caps_free(_i2sBuffer);
179  }
180 
181  bool IsReadyToUpdate() const
182  {
183  return (i2sWriteDone(_bus.I2sBusNumber));
184  }
185 
186  void Initialize()
187  {
188  size_t dmaBlockCount = (_i2sBufferSize + I2S_DMA_MAX_DATA_LEN - 1) / I2S_DMA_MAX_DATA_LEN;
189 
190  i2sInit(_bus.I2sBusNumber,
191  false,
192  2, // bytes per sample
193  T_SPEED::I2sSampleRate,
194  I2S_CHAN_STEREO,
195  I2S_FIFO_16BIT_DUAL,
196  dmaBlockCount,
197  _i2sBuffer,
198  _i2sBufferSize);
199  i2sSetPins(_bus.I2sBusNumber, _pin, -1, -1, T_INVERT::Inverted);
200  }
201 
202  void Update(bool)
203  {
204  // wait for not actively sending data
205  while (!IsReadyToUpdate())
206  {
207  yield();
208  }
209 
210  FillBuffers();
211 
212  i2sWrite(_bus.I2sBusNumber);
213  }
214 
215  bool AlwaysUpdate()
216  {
217  // this method requires update to be called only if changes to buffer
218  return false;
219  }
220 
221  uint8_t* getData() const
222  {
223  return _data;
224  };
225 
226  size_t getDataSize() const
227  {
228  return _sizeData;
229  }
230 
231  void applySettings([[maybe_unused]] const SettingsObject& settings)
232  {
233  }
234 
235 private:
236  const size_t _sizeData; // Size of '_data' buffer
237  const uint8_t _pin; // output pin number
238  const T_BUS _bus; // holds instance for multi bus support
239 
240  uint8_t* _data; // Holds LED color values
241 
242  size_t _i2sBufferSize; // total size of _i2sBuffer
243  uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
244 
245  void construct(uint16_t pixelCount, size_t elementSize, size_t settingsSize)
246  {
247  // DMA is too fast to support a single pixel and maintain consistency
248  if (pixelCount < 2)
249  {
250  pixelCount = 2;
251  }
252 
253  uint16_t dmaSettingsSize = c_dmaBytesPerPixelBytes * settingsSize;
254  uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
255  uint16_t resetSize = c_dmaBytesPerPixelBytes * T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs;
256 
257  _i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize + resetSize;
258 
259  // must have a 4 byte aligned buffer for i2s
260  uint32_t alignment = _i2sBufferSize % 4;
261  if (alignment)
262  {
263  _i2sBufferSize += 4 - alignment;
264  }
265 
266  _data = static_cast<uint8_t*>(malloc(_sizeData));
267  // data cleared later in Begin()
268 
269  _i2sBuffer = static_cast<uint8_t*>(heap_caps_malloc(_i2sBufferSize, MALLOC_CAP_DMA));
270  // no need to initialize all of it, but since it contains
271  // "reset" bits that don't latter get overwritten we just clear it all
272  memset(_i2sBuffer, 0x00, _i2sBufferSize);
273  }
274 
275  void FillBuffers()
276  {
277  const uint16_t bitpatterns[16] =
278  {
279  0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
280  0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
281  0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
282  0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
283  };
284 
285  uint16_t* pDma = reinterpret_cast<uint16_t*>(_i2sBuffer);
286  uint8_t* pEnd = _data + _sizeData;
287  for (uint8_t* pPixel = _data; pPixel < pEnd; pPixel++)
288  {
289  *(pDma++) = bitpatterns[((*pPixel) & 0x0f)];
290  *(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f];
291  }
292  }
293 };
294 
295 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Ws2812xMethod;
296 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Sk6812Method;
297 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Tm1814Method;
298 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Tm1829Method;
299 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Tm1914Method;
300 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0800KbpsMethod;
301 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0400KbpsMethod;
302 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Apa106Method;
303 
304 
305 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Ws2812xInvertedMethod;
306 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Sk6812InvertedMethod;
307 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Tm1814InvertedMethod;
308 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Tm1914InvertedMethod;
309 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Tm1829InvertedMethod;
310 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0800KbpsInvertedMethod;
311 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0400KbpsInvertedMethod;
312 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Apa106InvertedMethod;
313 
314 #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
315 // (I2S_NUM_MAX == 2)
316 
317 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Ws2812xMethod;
318 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Sk6812Method;
319 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Tm1814Method;
320 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Tm1829Method;
321 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Tm1914Method;
322 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1800KbpsMethod;
323 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1400KbpsMethod;
324 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Apa106Method;
325 
326 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Ws2812xInvertedMethod;
327 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Sk6812InvertedMethod;
328 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Tm1814InvertedMethod;
329 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Tm1829InvertedMethod;
330 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Tm1914InvertedMethod;
331 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1800KbpsInvertedMethod;
332 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1400KbpsInvertedMethod;
333 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Apa106InvertedMethod;
334 
335 
336 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNWs2812xMethod;
337 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNSk6812Method;
338 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNTm1814Method;
339 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNTm1829Method;
340 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNTm1914Method;
341 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sN800KbpsMethod;
342 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sN400KbpsMethod;
343 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNApa106Method;
344 
345 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNWs2812xInvertedMethod;
346 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNSk6812InvertedMethod;
347 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1814, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNTm1814InvertedMethod;
348 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1829, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNTm1829InvertedMethod;
349 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedTm1914, NeoEsp32I2sBusN, NeoEsp32I2sNotInverted> NeoEsp32I2sNTm1914InvertedMethod;
350 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sN800KbpsInvertedMethod;
351 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sN400KbpsInvertedMethod;
352 typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusN, NeoEsp32I2sInverted> NeoEsp32I2sNApa106InvertedMethod;
353 
354 #endif
355 
356 #if !defined(LUMITRONIX_IFLEX_ESP32_RMT_DEFAULT) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
357 
358 // I2s Bus 1 method is the default method for Esp32
359 // Esp32 S2 & C3 & S3 will use RMT as the default allways
360 typedef NeoEsp32I2s1Ws2812xMethod NeoWs2813Method;
361 typedef NeoEsp32I2s1Ws2812xMethod NeoWs2812xMethod;
362 typedef NeoEsp32I2s1800KbpsMethod NeoWs2812Method;
363 typedef NeoEsp32I2s1Ws2812xMethod NeoWs2811Method;
364 typedef NeoEsp32I2s1Ws2812xMethod NeoWs2816Method;
365 typedef NeoEsp32I2s1Sk6812Method NeoSk6812Method;
366 typedef NeoEsp32I2s1Tm1814Method NeoTm1814Method;
367 typedef NeoEsp32I2s1Tm1829Method NeoTm1829Method;
368 typedef NeoEsp32I2s1Tm1914Method NeoTm1914Method;
369 typedef NeoEsp32I2s1Sk6812Method NeoLc8812Method;
370 typedef NeoEsp32I2s1Apa106Method NeoApa106Method;
371 
372 typedef NeoEsp32I2s1Ws2812xMethod Neo800KbpsMethod;
373 typedef NeoEsp32I2s1400KbpsMethod Neo400KbpsMethod;
374 
375 typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2813InvertedMethod;
376 typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2812xInvertedMethod;
377 typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2811InvertedMethod;
378 typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2816InvertedMethod;
379 typedef NeoEsp32I2s1800KbpsInvertedMethod NeoWs2812InvertedMethod;
380 typedef NeoEsp32I2s1Sk6812InvertedMethod NeoSk6812InvertedMethod;
381 typedef NeoEsp32I2s1Tm1814InvertedMethod NeoTm1814InvertedMethod;
382 typedef NeoEsp32I2s1Tm1829InvertedMethod NeoTm1829InvertedMethod;
383 typedef NeoEsp32I2s1Tm1914InvertedMethod NeoTm1914InvertedMethod;
384 typedef NeoEsp32I2s1Sk6812InvertedMethod NeoLc8812InvertedMethod;
385 typedef NeoEsp32I2s1Apa106InvertedMethod NeoApa106InvertedMethod;
386 
387 typedef NeoEsp32I2s1Ws2812xInvertedMethod Neo800KbpsInvertedMethod;
388 typedef NeoEsp32I2s1400KbpsInvertedMethod Neo400KbpsInvertedMethod;
389 
390 #endif // !defined(LUMITRONIX_IFLEX_ESP32_RMT_DEFAULT) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
391 
392 #endif
NeoBusChannel
Definition: NeoBusChannel.h:12
Definition: NeoSettings.h:29