From 8a13d6f0f411177cee296b6053b3382976a93211 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sun, 25 Aug 2024 19:59:32 -0700 Subject: [PATCH] Three four cadences (#827) i2s x1, x8, x16 now use a 3 step cadence (33% & 66% pulse width) by default saving 25% memory in DMA buffer. ESP32 & ESP32S2 --- src/internal/NeoMethods.h | 3 + src/internal/NeoUtil.h | 13 + src/internal/animations/NeoPixelAnimator.cpp | 1 - src/internal/methods/Esp32_i2s.c | 178 ++++--- src/internal/methods/Esp32_i2s.h | 5 +- src/internal/methods/FractionClk.c | 10 +- src/internal/methods/NeoBits.h | 103 ++++ src/internal/methods/NeoEsp32I2sMethod.h | 358 ++++++++------ src/internal/methods/NeoEsp32I2sXMethod.h | 487 ++++++++++++------- src/internal/methods/NeoEsp32LcdXMethod.h | 166 ++----- 10 files changed, 792 insertions(+), 532 deletions(-) create mode 100644 src/internal/methods/NeoBits.h diff --git a/src/internal/NeoMethods.h b/src/internal/NeoMethods.h index 1be92d0..569b716 100644 --- a/src/internal/NeoMethods.h +++ b/src/internal/NeoMethods.h @@ -26,6 +26,9 @@ License along with NeoPixel. If not, see -------------------------------------------------------------------------*/ #pragma once +// helper constants for method speeds and invert +#include "methods/NeoBits.h" + // Generic Two Wire (clk and data) methods // #include "methods/DotStarGenericMethod.h" diff --git a/src/internal/NeoUtil.h b/src/internal/NeoUtil.h index 8f69c42..4d8c858 100644 --- a/src/internal/NeoUtil.h +++ b/src/internal/NeoUtil.h @@ -112,4 +112,17 @@ public: return (b * 0x0202020202ULL & 0x010884422010ULL) % 1023; } */ + + template static void PrintBin(T_TYPE value) + { + const size_t CountBits = sizeof(value) * 8; + const T_TYPE BitMask = 1 << (CountBits - 1); + + for (uint8_t bit = 0; bit < CountBits; bit++) + { + Serial.print((value & BitMask) ? "1" : "0"); + value <<= 1; + } + } + }; \ No newline at end of file diff --git a/src/internal/animations/NeoPixelAnimator.cpp b/src/internal/animations/NeoPixelAnimator.cpp index b97565f..c23024d 100644 --- a/src/internal/animations/NeoPixelAnimator.cpp +++ b/src/internal/animations/NeoPixelAnimator.cpp @@ -25,7 +25,6 @@ License along with NeoPixel. If not, see -------------------------------------------------------------------------*/ #include -#include "NeoPixelBus.h" #include "NeoPixelAnimator.h" NeoPixelAnimator::NeoPixelAnimator(uint16_t countAnimations, uint16_t timeScale) : diff --git a/src/internal/methods/Esp32_i2s.c b/src/internal/methods/Esp32_i2s.c index ade1077..119cbc7 100644 --- a/src/internal/methods/Esp32_i2s.c +++ b/src/internal/methods/Esp32_i2s.c @@ -67,7 +67,11 @@ #include "esp32-hal.h" esp_err_t i2sSetClock(uint8_t bus_num, uint8_t div_num, uint8_t div_b, uint8_t div_a, uint8_t bck, uint8_t bits_per_sample); -esp_err_t i2sSetSampleRate(uint8_t bus_num, uint32_t sample_rate, bool parallel_mode, size_t bytes_per_sample); +esp_err_t i2sSetSampleRate(uint8_t bus_num, + uint16_t dmaBitPerDataBit, + uint16_t nsBitSendTime, + bool parallel_mode, + size_t bytesPerSample); #define MATRIX_DETACH_OUT_SIG 0x100 @@ -144,14 +148,22 @@ inline void dmaItemInit(lldesc_t* item, uint8_t* posData, size_t sizeData, lldes item->qe.stqe_next = itemNext; } -bool i2sInitDmaItems(uint8_t bus_num, uint8_t* data, size_t dataSize, bool parallel_mode, size_t bytes_per_sample) +bool i2sInitDmaItems(uint8_t bus_num, + uint8_t* data, + size_t dataSize, + bool parallel_mode, + size_t bytesPerSample) { if (bus_num >= NEO_I2S_COUNT) { return false; } - size_t silenceSize = parallel_mode ? I2S_DMA_SILENCE_SIZE * 8 * bytes_per_sample : I2S_DMA_SILENCE_SIZE; + // silenceSize is minimum data size to loop i2s for reset + // it is not the actual reset time, but parallel mode needs + // a bit more time since the data is x8/x16 + size_t silenceSize = parallel_mode ? + I2S_DMA_SILENCE_SIZE * 8 * bytesPerSample : I2S_DMA_SILENCE_SIZE; size_t dmaCount = I2S[bus_num].dma_count; if (I2S[bus_num].dma_items == NULL) @@ -240,13 +252,14 @@ esp_err_t i2sSetClock(uint8_t bus_num, return ESP_FAIL; } - //log_i("i2sSetClock bus %u, clkm_div_num %u, clk_div_a %u, clk_div_b %u, bck_div_num %u, bits_mod %u", - // bus_num, - // div_num, - // div_a, - // div_b, - // bck, - // bits); + log_i("i2sSetClock bus %u,\n clkm_div_num %u,\n clk_div_a %u,\n clk_div_b %u,\n bck_div_num %u,\n bits_mod %u,\n i2sClkBase %u", + bus_num, + div_num, + div_a, + div_b, + bck, + bits, + I2S_BASE_CLK); i2s_dev_t* i2s = I2S[bus_num].bus; @@ -270,9 +283,9 @@ esp_err_t i2sSetClock(uint8_t bus_num, typeof(i2s->sample_rate_conf) sample_rate_conf; sample_rate_conf.val = 0; sample_rate_conf.tx_bck_div_num = bck; - sample_rate_conf.rx_bck_div_num = bck; +// sample_rate_conf.rx_bck_div_num = 4; sample_rate_conf.tx_bits_mod = bits; - sample_rate_conf.rx_bits_mod = bits; +// sample_rate_conf.rx_bits_mod = bits; i2s->sample_rate_conf.val = sample_rate_conf.val; return ESP_OK; @@ -298,63 +311,39 @@ void i2sSetPins(uint8_t bus_num, #if defined(CONFIG_IDF_TARGET_ESP32S2) // S2 only has one bus - // + // single output I2S0O_DATA_OUT23_IDX // in parallel mode // 8bit mode : I2S0O_DATA_OUT16_IDX ~I2S0O_DATA_OUT23_IDX // 16bit mode : I2S0O_DATA_OUT8_IDX ~I2S0O_DATA_OUT23_IDX // 24bit mode : I2S0O_DATA_OUT0_IDX ~I2S0O_DATA_OUT23_IDX - if (parallel == -1) + i2sSignal = I2S0O_DATA_OUT23_IDX; + if (parallel != -1) { - i2sSignal = I2S0O_DATA_OUT23_IDX; - } - else if (busSampleSize == 1) - { - i2sSignal = I2S0O_DATA_OUT16_IDX + parallel; - } - else if (busSampleSize == 2) - { - i2sSignal = I2S0O_DATA_OUT8_IDX + parallel; - } - else - { - i2sSignal = I2S0O_DATA_OUT0_IDX + parallel; + i2sSignal -= ((busSampleSize * 8) - 1); + i2sSignal += parallel; } #else - if (bus_num == 0) + i2sSignal = I2S0O_DATA_OUT0_IDX; + + if (bus_num == 1) { - // in parallel mode - // 0-7 bits : I2S0O_DATA_OUT16_IDX ~I2S0O_DATA_OUT23_IDX - // 8-15 bits : I2S0O_DATA_OUT8_IDX ~I2S0O_DATA_OUT23_IDX - // 16-23 bits : I2S0O_DATA_OUT0_IDX ~I2S0O_DATA_OUT23_IDX - if (parallel == -1) - { - i2sSignal = I2S0O_DATA_OUT23_IDX; - } - else if (parallel < 8) - { - i2sSignal = I2S0O_DATA_OUT16_IDX + parallel; - } - else if (parallel < 16) - { - i2sSignal = I2S0O_DATA_OUT8_IDX + parallel - 8; - } - else - { - i2sSignal = I2S0O_DATA_OUT0_IDX + parallel - 16; - } + i2sSignal = I2S1O_DATA_OUT0_IDX; + } + + if (parallel == -1) + { + i2sSignal += 23; // yup, single channel is on 23 } else { - if (parallel == -1) + if (busSampleSize == 2) { - i2sSignal = I2S1O_DATA_OUT23_IDX; - } - else - { - i2sSignal = I2S1O_DATA_OUT0_IDX + parallel; + i2sSignal += 8; // yup, 16 bits starts at 8 } + i2sSignal += parallel; // add the parallel channel index } + #endif //log_i("i2sSetPins bus %u, i2sSignal %u, pin %u, mux %u", // bus_num, @@ -365,6 +354,7 @@ void i2sSetPins(uint8_t bus_num, } } +/* not used, but left around for reference void i2sSetClkWsPins(uint8_t bus_num, int8_t outClk, bool invertClk, @@ -400,6 +390,7 @@ void i2sSetClkWsPins(uint8_t bus_num, gpio_matrix_out(outWs, i2sSignalWs, invertWs, false); } } +*/ bool i2sWriteDone(uint8_t bus_num) { @@ -413,8 +404,9 @@ bool i2sWriteDone(uint8_t bus_num) void i2sInit(uint8_t bus_num, bool parallel_mode, - size_t bytes_per_sample, - uint32_t sample_rate, + size_t bytesPerSample, + uint16_t dmaBitPerDataBit, + uint16_t nsBitSendTime, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod, size_t dma_count, @@ -430,7 +422,7 @@ void i2sInit(uint8_t bus_num, I2S_DMA_SILENCE_BLOCK_COUNT_FRONT + I2S_DMA_SILENCE_BLOCK_COUNT_BACK; - if (!i2sInitDmaItems(bus_num, data, dataSize, parallel_mode, bytes_per_sample)) + if (!i2sInitDmaItems(bus_num, data, dataSize, parallel_mode, bytesPerSample)) { return; } @@ -479,7 +471,12 @@ void i2sInit(uint8_t bus_num, typeof(i2s->conf2) conf2; conf2.val = 0; conf2.lcd_en = parallel_mode; - conf2.lcd_tx_wrx2_en = 0; // parallel_mode; // ((parallel_mode) && (bytes_per_sample == 2)); + if ((parallel_mode) && (bytesPerSample == 1)) + { + conf2.lcd_tx_wrx2_en = 1; + conf2.lcd_tx_sdx2_en = 0; + } + i2s->conf2.val = conf2.val; } @@ -501,11 +498,11 @@ void i2sInit(uint8_t bus_num, typeof(i2s->fifo_conf) fifo_conf; fifo_conf.val = 0; - fifo_conf.rx_fifo_mod_force_en = 0; +// fifo_conf.rx_fifo_mod_force_en = 1; //? fifo_conf.tx_fifo_mod_force_en = 1; fifo_conf.tx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel - fifo_conf.rx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel - fifo_conf.rx_data_num = 32; //Thresholds. + // fifo_conf.rx_fifo_mod = fifo_mod; // 0-right&left channel;1-one channel + // fifo_conf.rx_data_num = 32; //Thresholds. fifo_conf.tx_data_num = 32; i2s->fifo_conf.val = fifo_conf.val; @@ -515,8 +512,8 @@ void i2sInit(uint8_t bus_num, typeof(i2s->conf1) conf1; conf1.val = 0; - conf1.tx_pcm_conf = 1; - conf1.rx_pcm_bypass = 1; +// conf1.tx_pcm_conf = 1; +// conf1.rx_pcm_bypass = 1; conf1.tx_stop_en = 0; conf1.tx_pcm_bypass = 1; @@ -527,7 +524,7 @@ void i2sInit(uint8_t bus_num, typeof(i2s->conf_chan) conf_chan; conf_chan.val = 0; conf_chan.tx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left - conf_chan.rx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left +// conf_chan.rx_chan_mod = chan_mod; // 0-two channel;1-right;2-left;3-righ;4-left i2s->conf_chan.val = conf_chan.val; } @@ -535,19 +532,28 @@ void i2sInit(uint8_t bus_num, typeof(i2s->conf) conf; conf.val = 0; conf.tx_msb_shift = !parallel_mode; // 0:DAC/PCM, 1:I2S - conf.tx_right_first = 0; // parallel_mode?; + conf.tx_right_first = 1; // parallel_mode? but no? + conf.tx_short_sync = 0; + // conf.tx_msb_right = 1; +#if defined(CONFIG_IDF_TARGET_ESP32S2) + conf.tx_dma_equal = parallel_mode; +#endif i2s->conf.val = conf.val; } i2s->timing.val = 0; #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) - i2s->pdm_conf.rx_pdm_en = 0; +// i2s->pdm_conf.rx_pdm_en = 0; i2s->pdm_conf.tx_pdm_en = 0; #endif - i2sSetSampleRate(bus_num, sample_rate, parallel_mode, bytes_per_sample); + i2sSetSampleRate(bus_num, + dmaBitPerDataBit, + nsBitSendTime, + parallel_mode, + bytesPerSample); /* */ //Reset FIFO/DMA -> needed? Doesn't dma_reset/fifo_reset do this? @@ -602,28 +608,34 @@ void i2sDeinit(uint8_t bus_num) } esp_err_t i2sSetSampleRate(uint8_t bus_num, - uint32_t rate, + uint16_t dmaBitPerDataBit, + uint16_t nsBitSendTime, bool parallel_mode, - size_t bytes_per_sample) + size_t bytesPerSample) { + const double I2sClkMhz = (double)I2S_BASE_CLK / 1000000; // 160000000 = 160.0 + const size_t bits_per_sample = bytesPerSample * 8; + if (bus_num >= NEO_I2S_COUNT) { return ESP_FAIL; } - uint8_t bck = 8; + uint8_t bck = 4; // must be 2+ due to ESP32S2 adjustment below + double clkSampleAdj = 1.0; // parallel mode needs a higher sample rate // - if (parallel_mode) + if (!parallel_mode) { - rate *= bytes_per_sample; -#if defined(CONFIG_IDF_TARGET_ESP32S2) - bck *= bytes_per_sample; -#endif + // non-parallel uses two values in the sample + // so the clock calcs need to adjust for this + // as it makes output faster + clkSampleAdj *= 2.0; } - double clkmdiv = (double)I2S_BASE_CLK / (rate * 256.0); + double clkmdiv = (double)nsBitSendTime / bytesPerSample / dmaBitPerDataBit / bck / 1000.0 * I2sClkMhz * clkSampleAdj; + if (clkmdiv > 256.0) { @@ -634,12 +646,20 @@ esp_err_t i2sSetSampleRate(uint8_t bus_num, { log_e("rate is too fast, clkmdiv = %f (%u, %u, %u)", clkmdiv, - rate, + nsBitSendTime, parallel_mode, - bytes_per_sample); + bytesPerSample); return ESP_FAIL; } +#if defined(CONFIG_IDF_TARGET_ESP32S2) + // ESP32S2 is just different + if (parallel_mode && bytesPerSample == 1) + { + bck /= 2; + } +#endif + // calc integer and franctional for more precise timing // uint8_t clkmInteger = clkmdiv; @@ -654,7 +674,7 @@ esp_err_t i2sSetSampleRate(uint8_t bus_num, divB, divA, bck, - bytes_per_sample * 8); + bits_per_sample); return ESP_OK; } diff --git a/src/internal/methods/Esp32_i2s.h b/src/internal/methods/Esp32_i2s.h index 23d1ac4..5741c5f 100644 --- a/src/internal/methods/Esp32_i2s.h +++ b/src/internal/methods/Esp32_i2s.h @@ -34,7 +34,8 @@ typedef enum { void i2sInit(uint8_t bus_num, bool parallel_mode, size_t bytes_per_sample, - uint32_t sample_rate, + uint16_t dmaBitPerDataBit, + uint16_t nsBitSendTime, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod, size_t dma_count, @@ -46,11 +47,13 @@ void i2sSetPins(uint8_t bus_num, int8_t parallel, int8_t busSampleSize, bool invert); +/* void i2sSetClkWsPins(uint8_t bus_num, int8_t outClk, bool invertClk, int8_t outWs, bool invertWs); + */ bool i2sWrite(uint8_t bus_num); bool i2sWriteDone(uint8_t bus_num); #ifdef NEOPIXELBUS_I2S_DEBUG diff --git a/src/internal/methods/FractionClk.c b/src/internal/methods/FractionClk.c index 622f660..151fd11 100644 --- a/src/internal/methods/FractionClk.c +++ b/src/internal/methods/FractionClk.c @@ -26,16 +26,18 @@ License along with NeoPixel. If not, see #include #include +#include #include "stdlib.h" + // UnitDecimalToFractionClks // Given unit decimal (floating point value less than 1.0), -// return a fraction numerator and denomenator that closesly matches that +// return a fraction numerator and denominator that closely matches that // // resultN - the address of the variable to place the numerator result -// resultD - the address of the variable to place the denomenator result -// unitDecimal - the decimal value that is less than 1.0 and greater than/eaual 0.0 -// accuracy - the accuracy needed to match for a fractionals (0.000001 is a good start) +// resultD - the address of the variable to place the denominator result +// unitDecimal - the decimal value that is less than 1.0 and greater than/equal 0.0 +// accuracy - the accuracy needed to match for a fractional (0.000001 is a good start) // void UnitDecimalToFractionClks(uint8_t* resultN, uint8_t* resultD, diff --git a/src/internal/methods/NeoBits.h b/src/internal/methods/NeoBits.h new file mode 100644 index 0000000..18bb7aa --- /dev/null +++ b/src/internal/methods/NeoBits.h @@ -0,0 +1,103 @@ +#pragma once +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Methods. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +// -------------------------------------------------------- +class NeoBitsSpeedWs2812x +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 300; +}; + +class NeoBitsSpeedWs2805 +{ +public: + const static uint16_t BitSendTimeNs = 1125; + const static uint16_t ResetTimeUs = 300; // spec is 280, intentionally longer for compatiblity use +}; + +class NeoBitsSpeedSk6812 +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 80; +}; + +class NeoBitsSpeedTm1814 +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 200; +}; + +class NeoBitsSpeedTm1914 +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 200; +}; + +class NeoBitsSpeedTm1829 +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 200; +}; + +class NeoBitsSpeed800Kbps +{ +public: + const static uint16_t BitSendTimeNs = 1250; + const static uint16_t ResetTimeUs = 50; +}; + +class NeoBitsSpeed400Kbps +{ +public: + const static uint16_t BitSendTimeNs = 2500; + const static uint16_t ResetTimeUs = 50; +}; + +class NeoBitsSpeedApa106 +{ +public: + const static uint16_t BitSendTimeNs = 1710; + const static uint16_t ResetTimeUs = 50; +}; + +//--------------------------------------------------------- +class NeoBitsNotInverted +{ +public: + const static bool Inverted = false; +}; + +class NeoBitsInverted +{ +public: + const static bool Inverted = true; +}; diff --git a/src/internal/methods/NeoEsp32I2sMethod.h b/src/internal/methods/NeoEsp32I2sMethod.h index 01c5141..fa9f18f 100644 --- a/src/internal/methods/NeoEsp32I2sMethod.h +++ b/src/internal/methods/NeoEsp32I2sMethod.h @@ -36,81 +36,6 @@ extern "C" #include "Esp32_i2s.h" } -const uint16_t c_dmaBytesPerPixelBytes = 4; - -// -------------------------------------------------------- -class NeoEsp32I2sSpeedWs2812x -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 300; -}; - -class NeoEsp32I2sSpeedWs2805 -{ -public: - const static uint32_t I2sSampleRate = 114678; // 917431 hz / 8 = 114678 - const static uint16_t ByteSendTimeUs = 9; - const static uint16_t ResetTimeUs = 300; // spec is 280, intentionally longer for compatiblity use -}; - -class NeoEsp32I2sSpeedSk6812 -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 80; -}; - -class NeoEsp32I2sSpeedTm1814 -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32I2sSpeedTm1914 -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32I2sSpeedTm1829 -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32I2sSpeed800Kbps -{ -public: - const static uint32_t I2sSampleRate = 100000; - const static uint16_t ByteSendTimeUs = 10; - const static uint16_t ResetTimeUs = 50; -}; - -class NeoEsp32I2sSpeed400Kbps -{ -public: - const static uint32_t I2sSampleRate = 50000; - const static uint16_t ByteSendTimeUs = 20; - const static uint16_t ResetTimeUs = 50; -}; - -class NeoEsp32I2sSpeedApa106 -{ -public: - const static uint32_t I2sSampleRate = 72960; // 588,235 hz / 8 = 73,529 sample rate - const static uint16_t ByteSendTimeUs = 14; - const static uint16_t ResetTimeUs = 50; -}; - // -------------------------------------------------------- class NeoEsp32I2sBusZero { @@ -142,20 +67,116 @@ public: }; // -------------------------------------------------------- -class NeoEsp32I2sNotInverted + + +// 4 step cadence, so pulses are 1/4 and 3/4 of pulse width +// +class NeoEsp32I2sCadence4Step { public: - const static bool Inverted = false; + const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches encoding + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + const uint16_t bitpatterns[16] = + { + 0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110, + 0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110, + 0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110, + 0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, + }; + + uint16_t* pDma = reinterpret_cast(dmaBuffer); + const uint8_t* pEnd = data + sizeData; + for (const uint8_t* pSrc = data; pSrc < pEnd; pSrc++) + { + *(pDma++) = bitpatterns[((*pSrc) >> 4) & 0x0f]; + *(pDma++) = bitpatterns[((*pSrc) & 0x0f)]; + } + } }; -class NeoEsp32I2sInverted +// fedc ba98 7654 3210 +// 0000 0000 0000 0000 +// 111 +// 3 step cadence, so pulses are 1/3 and 2/3 of pulse width +// +class NeoEsp32I2sCadence3Step { public: - const static bool Inverted = true; + const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + const uint16_t OneBit = 0b00000110; + const uint16_t ZeroBit = 0b00000100; + const uint8_t SrcBitMask = 0x80; + const size_t BitsInSample = sizeof(uint16_t) * 8; + + uint16_t* pDma = reinterpret_cast(dmaBuffer); + uint16_t dmaValue = 0; + uint8_t destBitsLeft = BitsInSample; + + const uint8_t* pSrc = data; + const uint8_t* pEnd = pSrc + sizeData; + + while (pSrc < pEnd) + { + uint8_t value = *(pSrc++); + + for (uint8_t bitSrc = 0; bitSrc < 8; bitSrc++) + { + const uint16_t Bit = ((value & SrcBitMask) ? OneBit : ZeroBit); + + if (destBitsLeft > 3) + { + destBitsLeft -= 3; + dmaValue |= Bit << destBitsLeft; + +#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) + NeoUtil::PrintBin(dmaValue); + Serial.print(" < "); + Serial.println(destBitsLeft); +#endif + } + else if (destBitsLeft <= 3) + { + uint8_t bitSplit = (3 - destBitsLeft); + dmaValue |= Bit >> bitSplit; + +#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) + NeoUtil::PrintBin(dmaValue); + Serial.print(" > "); + Serial.println(bitSplit); +#endif + // next dma value, store and reset + *(pDma++) = dmaValue; + dmaValue = 0; + + destBitsLeft = BitsInSample - bitSplit; + if (bitSplit) + { + dmaValue |= Bit << destBitsLeft; + } + +#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) + NeoUtil::PrintBin(dmaValue); + Serial.print(" v "); + Serial.println(bitSplit); +#endif + } + + // Next + value <<= 1; + } + } + // store the remaining bits + *pDma++ = dmaValue; + } }; // -------------------------------------------------------- -template class NeoEsp32I2sMethodBase +template class NeoEsp32I2sMethodBase { public: typedef NeoNoSettings SettingsObject; @@ -203,7 +224,8 @@ public: i2sInit(_bus.I2sBusNumber, false, 2, // bytes per sample - T_SPEED::I2sSampleRate, + T_CADENCE::DmaBitsPerPixelBit, + T_SPEED::BitSendTimeNs, I2S_CHAN_STEREO, I2S_FIFO_16BIT_DUAL, dmaBlockCount, @@ -220,7 +242,36 @@ public: yield(); } - FillBuffers(); + T_CADENCE::EncodeIntoDma(_i2sBuffer, _data, _sizeData); + +#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) + // dump the is2buffer + uint8_t* pDma = _i2sBuffer; + uint8_t* pEnd = pDma + _i2sBufferSize; + size_t index = 0; + + Serial.println(); + Serial.println("NeoEspI2sMethod - i2sBufferDump: "); + while (pDma < pEnd) + { + uint8_t value = *pDma; + + // a single bit pulse of data + if ((index % 4) == 0) + { + Serial.println(); + } + + NeoUtil::PrintBin(value); + + Serial.print(" "); + pDma++; + index++; + + } + Serial.println(); + +#endif // NEO_DEBUG_DUMP_I2S_BUFFER i2sWrite(_bus.I2sBusNumber); } @@ -263,9 +314,9 @@ private: // must have a 4 byte aligned buffer for i2s // since the reset/silence at the end is used for looping // it also needs to 4 byte aligned - size_t dmaSettingsSize = c_dmaBytesPerPixelBytes * settingsSize; - size_t dmaPixelSize = c_dmaBytesPerPixelBytes * pixelSize; - size_t resetSize = NeoUtil::RoundUp(c_dmaBytesPerPixelBytes * T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs, 4); + size_t dmaSettingsSize = T_CADENCE::DmaBitsPerPixelBit * settingsSize; + size_t dmaPixelSize = T_CADENCE::DmaBitsPerPixelBit * pixelSize; + size_t resetSize = NeoUtil::RoundUp(T_CADENCE::DmaBitsPerPixelBit * T_SPEED::ResetTimeUs / (T_SPEED::BitSendTimeNs * 8 / 1000), 4); _i2sBufferSize = NeoUtil::RoundUp(pixelCount * dmaPixelSize + dmaSettingsSize, 4) + resetSize; @@ -276,93 +327,86 @@ private: memset(_i2sBuffer, 0x00, _i2sBufferSize); } - void FillBuffers() - { - const uint16_t bitpatterns[16] = - { - 0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110, - 0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110, - 0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110, - 0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, - }; - uint16_t* pDma = reinterpret_cast(_i2sBuffer); - uint8_t* pEnd = _data + _sizeData; - for (uint8_t* pPixel = _data; pPixel < pEnd; pPixel++) - { - *(pDma++) = bitpatterns[((*pPixel) & 0x0f)]; - *(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f]; - } - } }; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2812xMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2805Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Sk6812Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1829Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1914Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0800KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0400KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Apa106Method; +#if defined(NPB_CONF_4STEP_CADENCE) + +typedef NeoEsp32I2sCadence4Step NeoEsp32I2sCadence; + +#else + +typedef NeoEsp32I2sCadence3Step NeoEsp32I2sCadence; + +#endif + +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2812xMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2805Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Sk6812Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1814Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1829Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1914Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0800KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0400KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Apa106Method; typedef NeoEsp32I2s0Ws2805Method NeoEsp32I2s0Ws2814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2812xInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0SWs2805InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Sk6812InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1814InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1914InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1829InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0800KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0400KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Apa106InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2812xInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0SWs2805InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Sk6812InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1814InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1914InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Tm1829InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0800KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0400KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Apa106InvertedMethod; typedef NeoEsp32I2s0SWs2805InvertedMethod NeoEsp32I2s0SWs2814InvertedMethod; #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) // (SOC_I2S_NUM == 2) -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2812xMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2805Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Sk6812Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1829Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1914Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1800KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1400KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Apa106Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2812xMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2805Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Sk6812Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1814Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1829Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1914Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1800KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1400KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Apa106Method; typedef NeoEsp32I2s1Ws2805Method NeoEsp32I2s1Ws2814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2812xInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2805InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Sk6812InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1814InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1829InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1914InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1800KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1400KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Apa106InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2812xInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Ws2805InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Sk6812InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1814InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1829InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Tm1914InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1800KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1400KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Apa106InvertedMethod; typedef NeoEsp32I2s1Ws2805InvertedMethod NeoEsp32I2s1Ws2814InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2812xMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2805Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNSk6812Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1829Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1914Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sN800KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sN400KbpsMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNApa106Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2812xMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2805Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNSk6812Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1814Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1829Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1914Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sN800KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sN400KbpsMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNApa106Method; typedef NeoEsp32I2sNWs2805Method NeoEsp32I2sNWs2814Method; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2812xInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2805InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNSk6812InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1814InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1829InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1914InvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sN800KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sN400KbpsInvertedMethod; -typedef NeoEsp32I2sMethodBase NeoEsp32I2sNApa106InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2812xInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNWs2805InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNSk6812InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1814InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1829InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNTm1914InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sN800KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sN400KbpsInvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2sNApa106InvertedMethod; typedef NeoEsp32I2sNWs2805InvertedMethod NeoEsp32I2sNWs2814InvertedMethod; #endif @@ -370,7 +414,7 @@ typedef NeoEsp32I2sNWs2805InvertedMethod NeoEsp32I2sNWs2814InvertedMethod; #if !defined(NEOPIXEL_ESP32_RMT_DEFAULT) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) // I2s Bus 1 method is the default method for Esp32 -// Esp32 S2 & C3 & S3 will use RMT as the default allways +// Esp32 S2 & C3 & S3 will use RMT as the default always typedef NeoEsp32I2s1Ws2812xMethod NeoWs2813Method; typedef NeoEsp32I2s1Ws2812xMethod NeoWs2812xMethod; typedef NeoEsp32I2s1800KbpsMethod NeoWs2812Method; diff --git a/src/internal/methods/NeoEsp32I2sXMethod.h b/src/internal/methods/NeoEsp32I2sXMethod.h index 458a3e1..cf56368 100644 --- a/src/internal/methods/NeoEsp32I2sXMethod.h +++ b/src/internal/methods/NeoEsp32I2sXMethod.h @@ -48,26 +48,153 @@ extern "C" // 0123456789abcdef // efcdab8967452301 + +// 3 step cadence, so pulses are 1/3 and 2/3 of pulse width // -// true size of mux channel, 8 bit -// -class NeoEspI2sMuxBusSize8Bit +class NeoEspI2sMuxBusSize8Bit3Step { public: - NeoEspI2sMuxBusSize8Bit() {}; + NeoEspI2sMuxBusSize8Bit3Step() {}; const static size_t MuxBusDataSize = 1; - const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches endcoding + const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + + // by using a 3 step cadence, the dma data can't be updated with a single OR operation as + // its value resides across a non-uint16_t aligned 3 element type, so it requires two separate OR + // operations to update a single pixel bit, the last element can be skipped as its always 0 + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData, uint8_t muxId) + { + uint8_t* pDma = dmaBuffer; + const uint8_t* pValue = data; + const uint8_t* pEnd = pValue + sizeData; + const uint8_t muxBit = 0x1 << muxId; +#if defined(CONFIG_IDF_TARGET_ESP32S2) + const uint8_t offsetMap[] = { 0, 1, 2, 3 }; // i2s sample is two 16bit values + +#else + const uint8_t offsetMap[] = { 2,3,0,1 }; // i2s sample is two 16bit values + +#endif + + uint8_t offset = 0; + + while (pValue < pEnd) + { + uint8_t value = *(pValue++); + + for (uint8_t bit = 0; bit < 8; bit++) + { + // first cadence step init to 1 + pDma[offsetMap[offset]] |= muxBit; + offset++; + if (offset > 3) + { + offset %= 4; + pDma += 4; + } + + // second cadence step set based on bit + if (value & 0x80) + { + pDma[offsetMap[offset]] |= muxBit; + } + // last cadence step already init to 0, skip it + offset += 2; + if (offset > 3) + { + offset %= 4; + pDma += 4; + } + + // Next + value <<= 1; + } + } + } +}; + + +// 3 step cadence, so pulses are 1/3 and 2/3 of pulse width +// +class NeoEspI2sMuxBusSize16Bit3Step +{ +public: + NeoEspI2sMuxBusSize16Bit3Step() {}; + + const static size_t MuxBusDataSize = 2; + const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + + // by using a 3 step cadence, the dma data can't be updated with a single OR operation as + // its value resides across a non-uint32_t aligned 3 element type, so it requires two seperate OR + // operations to update a single pixel bit, the last element can be skipped as its always 0 + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData, uint8_t muxId) + { + uint16_t* pDma = reinterpret_cast(dmaBuffer); + const uint8_t* pValue = data; + const uint8_t* pEnd = pValue + sizeData; + const uint16_t muxBit = 0x1 << muxId; +#if defined(CONFIG_IDF_TARGET_ESP32S2) + const uint8_t offsetMap[] = { 0, 1, 2, 3 }; // i2s sample is two 16bit values +#else + const uint8_t offsetMap[] = { 1, 0, 3, 2 }; // i2s sample is two 16bit values +#endif + uint8_t offset = 0; + + while (pValue < pEnd) + { + uint8_t value = *(pValue++); + + for (uint8_t bit = 0; bit < 8; bit++) + { + // first cadence step init to 1 + pDma[offsetMap[offset]] |= muxBit; + offset++; + if (offset > 3) + { + offset %= 4; + pDma += 4; + } + + // second cadence step set based on bit + if (value & 0x80) + { + pDma[offsetMap[offset]] |= muxBit; + } + offset++; + + // last cadence step already 0, skip it + offset++; + if (offset > 3) + { + offset %= 4; + pDma += 4; + } + + // Next + value <<= 1; + } + } + } +}; + + +// 4 step cadence, so pulses are 1/4 and 3/4 of pulse width +// +class NeoEspI2sMuxBusSize8Bit4Step +{ +public: + NeoEspI2sMuxBusSize8Bit4Step() {}; + + const static size_t MuxBusDataSize = 1; + const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches encoding static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData, uint8_t muxId) { #if defined(CONFIG_IDF_TARGET_ESP32S2) - // 1234 - order - // 3412 = actual due to endianness - // 00000001 - const uint32_t EncodedZeroBit = 0x00000100; - // 00010101 - const uint32_t EncodedOneBit = 0x01000101; + + const uint32_t EncodedZeroBit = 0x00000001; + const uint32_t EncodedOneBit = 0x00010101; + #else // 8 channel bits layout for DMA 32bit value // note, right to left @@ -106,78 +233,38 @@ public: } }; +// 4 step cadence, so pulses are 1/4 and 3/4 of pulse width // -// true size of mux channel, 16 bit -// -class NeoEspI2sMuxBusSize16Bit +class NeoEspI2sMuxBusSize16Bit4Step { public: - NeoEspI2sMuxBusSize16Bit() {}; + NeoEspI2sMuxBusSize16Bit4Step() {}; const static size_t MuxBusDataSize = 2; - const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches endcoding + const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches encoding static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData, uint8_t muxId) { #if defined(CONFIG_IDF_TARGET_ESP32S2) + const uint64_t EncodedZeroBit64 = 0x0000000000000001; + const uint64_t EncodedOneBit64 = 0x0000000100010001; + +#else // 1234 5678 - order // 3412 7856 = actual due to endianness // not swap 0000000000000001 const uint64_t EncodedZeroBit64 = 0x0000000000010000; // no swap 0000000100010001 const uint64_t EncodedOneBit64 = 0x0001000000010001; - // can be shifted by 8! + +#endif + Fillx16(dmaBuffer, data, sizeData, muxId, EncodedZeroBit64, EncodedOneBit64); -#else - - // 16 channel bits layout for DMA 64bit value - // note, right to left, destination is 32bit chunks - // due to indianness between peripheral and cpu, - // bytes within the words are swapped and words within dwords - // in the literal constants - // { } { } - // 0123 4567 89ab cdef - order of bytes in literal constant - // efcd ab89 6745 2301 - order of memory on ESP32 due to Endianness - // 6745 2301 efcd ab89 - 32bit dest means only map using 32bits so swap upper and lower - // - // Due to final bit locations, can't shift encoded one bit - // either left more than 7 or right more than 7 so we have to - // split the updates and use different encodings - if (muxId < 8) - { - // endian + dest swap 0000000000000001 - const uint64_t EncodedZeroBit64 = 0x0000000001000000; - // endian + dest swap 0000000100010001 - const uint64_t EncodedOneBit64 = 0x0100000001000100; - // cant be shifted by 8! - Fillx16(dmaBuffer, - data, - sizeData, - muxId, - EncodedZeroBit64, - EncodedOneBit64); - } - else - { - // endian + dest swap 0000000000000001 - // then pre shift by 8 0000000000000100 - const uint64_t EncodedZeroBit64 = 0x0000000000010000; - // endian + dest swap 0000000100010001 - // then pre shift by 8 0000010001000100 - const uint64_t EncodedOneBit64 = 0x0001000000010001; - Fillx16(dmaBuffer, - data, - sizeData, - muxId - 8, // preshifted - EncodedZeroBit64, - EncodedOneBit64); - } -#endif } protected: @@ -189,13 +276,14 @@ protected: const uint64_t EncodedOneBit64) { uint64_t* pDma64 = reinterpret_cast(dmaBuffer); - const uint8_t* pEnd = data + sizeData; + const uint8_t* pSrc = data; + const uint8_t* pEnd = pSrc + sizeData; const uint64_t OneBit = EncodedOneBit64 << muxShift; const uint64_t ZeroBit = EncodedZeroBit64 << muxShift; - - for (const uint8_t* pPixel = data; pPixel < pEnd; pPixel++) + + while (pSrc < pEnd) { - uint8_t value = *pPixel; + uint8_t value = *(pSrc++); for (uint8_t bit = 0; bit < 8; bit++) { @@ -206,6 +294,7 @@ protected: value <<= 1; } } + } }; @@ -213,7 +302,7 @@ protected: // tracks mux channels used and if updated // // T_FLAG - type used to store bit flags, UINT8_t for 8 channels, UINT16_t for 16 -// T_MUXSIZE - true size of mux channel = NeoEspI2sMuxBusSize8Bit or NeoEspI2sMuxBusSize16Bit +// T_MUXSIZE - true size of mux channel = NeoEspI2sMuxBusSize8Bit4Step or NeoEspI2sMuxBusSize16Bit4Step // template class NeoEspI2sMuxMap : public T_MUXSIZE @@ -334,7 +423,7 @@ public: { } - void Construct(const uint8_t busNumber, uint32_t i2sSampleRate) + void Construct(const uint8_t busNumber, uint16_t nsBitSendTime) { // construct only once on first time called if (I2sBuffer == nullptr) @@ -364,12 +453,13 @@ public: i2sInit(busNumber, true, T_MUXMAP::MuxBusDataSize, - i2sSampleRate, + T_MUXMAP::DmaBitsPerPixelBit, + nsBitSendTime, #if defined(CONFIG_IDF_TARGET_ESP32S2) // using these modes on ESP32S2 actually allows it to function // in both x8 and x16 - I2S_CHAN_STEREO, - I2S_FIFO_16BIT_DUAL, + I2S_CHAN_RIGHT_TO_LEFT, + I2S_FIFO_16BIT_SINGLE, // I2S_FIFO_32BIT_SINGLE #else // but they won't work on ESP32 in parallel mode, but these will I2S_CHAN_RIGHT_TO_LEFT, @@ -403,6 +493,38 @@ public: { if (MuxMap.IsAllMuxBusesUpdated()) { +#if defined(NEO_DEBUG_DUMP_I2S_BUFFER) + // dump the is2buffer + uint8_t* pDma = I2sBuffer; + uint8_t* pEnd = pDma + I2sBufferSize; + size_t index = 0; + + Serial.println(); + Serial.println("NeoEspI2sMonoBuffContext - i2sBufferDump: "); + while (pDma < pEnd) + { + uint8_t value = *pDma; + + // a single bit pulse of data + if ((index % (T_MUXMAP::DmaBitsPerPixelBit * T_MUXMAP::MuxBusDataSize)) == 0) + { + Serial.println(); + } + + for (uint8_t bit = 0; bit < 8; bit++) + { + Serial.print((value & 0x80) ? "1" : "0"); + value <<= 1; + } + Serial.print(" "); + pDma++; + index++; + + } + Serial.println(); + +#endif // NEO_DEBUG_DUMP_I2S_BUFFER + MuxMap.ResetMuxBusesUpdated(); i2sWrite(i2sBusNumber); } @@ -424,7 +546,7 @@ public: // so the buffer must be cleared first if (MuxMap.IsNoMuxBusesUpdate()) { - // clear all the data in preperation for each mux channel to add + // clear all the data in preparation for each mux channel to add memset(I2sBuffer, 0x00, I2sBufferSize); } @@ -462,21 +584,18 @@ public: // but without it presence they get zeroed far too late NeoEspI2sDblBuffContext() //: - //I2sBufferSize(0), - //I2sBuffer(nullptr), - //I2sEditBuffer(nullptr), - //MuxMap() { } - void Construct(const uint8_t busNumber, uint32_t i2sSampleRate) + void Construct(const uint8_t busNumber, uint16_t nsBitSendTime) { // construct only once on first time called if (I2sBuffer == nullptr) { // MuxMap.MaxBusDataSize = max size in bytes of a single channel // DmaBitsPerPixelBit = how many dma bits/byte are needed for each source (pixel) bit/byte - // T_MUXMAP::MuxBusDataSize = the true size of data for selected mux mode (not exposed size as i2s0 only supports 16bit mode) + // T_MUXMAP::MuxBusDataSize = the true size of data for selected mux mode (not exposed size as + // i2s0 only supports 16bit mode) I2sBufferSize = MuxMap.MaxBusDataSize * 8 * T_MUXMAP::DmaBitsPerPixelBit * T_MUXMAP::MuxBusDataSize; // must have a 4 byte aligned buffer for i2s @@ -507,12 +626,13 @@ public: i2sInit(busNumber, true, T_MUXMAP::MuxBusDataSize, - i2sSampleRate, + T_MUXMAP::DmaBitsPerPixelBit, + nsBitSendTime, #if defined(CONFIG_IDF_TARGET_ESP32S2) // using these modes on ESP32S2 actually allows it to function // in both x8 and x16 - I2S_CHAN_STEREO, - I2S_FIFO_16BIT_DUAL, + I2S_CHAN_RIGHT_TO_LEFT, + I2S_FIFO_16BIT_SINGLE, #else // but they won't work on ESP32 in parallel mode, but these will I2S_CHAN_RIGHT_TO_LEFT, @@ -610,9 +730,9 @@ public: _muxId = s_context.MuxMap.RegisterNewMuxBus(dataSize); } - void Initialize(uint8_t pin, uint32_t i2sSampleRate, bool invert) + void Initialize(uint8_t pin, uint16_t nsBitSendTime, bool invert) { - s_context.Construct(T_BUS::I2sBusNumber, i2sSampleRate); + s_context.Construct(T_BUS::I2sBusNumber, nsBitSendTime); i2sSetPins(T_BUS::I2sBusNumber, pin, _muxId, s_context.MuxMap.MuxBusDataSize, invert); } @@ -660,9 +780,9 @@ template T_BUSCONTEXT NeoEsp32I2sMuxBus class NeoEsp32I2sXMethodBase @@ -675,7 +795,7 @@ public: _pin(pin), _bus() { - _bus.RegisterNewMuxBus(_sizeData + T_SPEED::ResetTimeUs / T_SPEED::ByteSendTimeUs); + _bus.RegisterNewMuxBus(_sizeData + T_SPEED::ResetTimeUs / (T_SPEED::BitSendTimeNs * 8 / 1000)); } ~NeoEsp32I2sXMethodBase() @@ -697,7 +817,7 @@ public: void Initialize() { - _bus.Initialize(_pin, T_SPEED::I2sSampleRate, T_INVERT::Inverted); + _bus.Initialize(_pin, T_SPEED::BitSendTimeNs, T_INVERT::Inverted); _data = static_cast(malloc(_sizeData)); if (_data == nullptr) @@ -743,41 +863,70 @@ private: uint8_t* _data; // Holds LED color values }; +#if defined(NPB_CONF_4STEP_CADENCE) + +//------------------------------------ #if defined(CONFIG_IDF_TARGET_ESP32S2) -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0DblMux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0DblMux8Bus; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8DblWs2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8DblWs2812xMethod; #else -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux8Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux16Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux16Bus; -typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1DblMux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1DblMux8Bus; #endif +#else // NPB_CONF_3STEP_CADENCE + +//------------------------------------ +#if defined(CONFIG_IDF_TARGET_ESP32S2) + +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; + +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0DblMux8Bus; + +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8DblWs2812xMethod; + +#else + +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusZero> NeoEsp32I2s0Mux16Bus; + + +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux8Bus; +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1Mux16Bus; + +typedef NeoEsp32I2sMuxBus>, NeoEsp32I2sBusOne> NeoEsp32I2s1DblMux8Bus; + +#endif +#endif + // NORMAL // // I2s0x8 -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2812xMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2805Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Sk6812Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1814Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1829Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1914Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8800KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8400KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Apa106Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2805Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Sk6812Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1814Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1829Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1914Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8800KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8400KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Apa106Method; typedef NeoEsp32I2s0X8Ws2805Method NeoEsp32I2s0X8Ws2814Method; typedef NeoEsp32I2s0X8Ws2812xMethod NeoEsp32I2s0X8Ws2813Method; @@ -788,15 +937,15 @@ typedef NeoEsp32I2s0X8800KbpsMethod NeoEsp32I2s0X8Ws2812Method; typedef NeoEsp32I2s0X8Sk6812Method NeoEsp32I2s0X8Lc8812Method; // I2s0x16 -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2812xMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2805Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Sk6812Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1814Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1829Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1914Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16800KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16400KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Apa106Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2805Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Sk6812Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1814Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1829Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1914Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16800KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16400KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Apa106Method; typedef NeoEsp32I2s0X16Ws2805Method NeoEsp32I2s0X16Ws2814Method; typedef NeoEsp32I2s0X16Ws2812xMethod NeoEsp32I2s0X16Ws2813Method; @@ -809,17 +958,17 @@ typedef NeoEsp32I2s0X16Sk6812Method NeoEsp32I2s0X16Lc8812Method; #if !defined(CONFIG_IDF_TARGET_ESP32S2) // I2s1x8 -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8DblWs2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8DblWs2812xMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2812xMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2805Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Sk6812Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1814Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1829Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1914Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8800KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8400KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Apa106Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2805Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Sk6812Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1814Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1829Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1914Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8800KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8400KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Apa106Method; typedef NeoEsp32I2s1X8Ws2805Method NeoEsp32I2s1X8Ws2814Method; typedef NeoEsp32I2s1X8Ws2812xMethod NeoEsp32I2s1X8Ws2813Method; @@ -830,15 +979,15 @@ typedef NeoEsp32I2s1X8800KbpsMethod NeoEsp32I2s1X8Ws2812Method; typedef NeoEsp32I2s1X8Sk6812Method NeoEsp32I2s1X8Lc8812Method; // I2s1x16 -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2812xMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2805Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Sk6812Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1814Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1829Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1914Method; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16800KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16400KbpsMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Apa106Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2812xMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2805Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Sk6812Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1814Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1829Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1914Method; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16800KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16400KbpsMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Apa106Method; typedef NeoEsp32I2s1X16Ws2805Method NeoEsp32I2s1X16Ws2814Method; typedef NeoEsp32I2s1X16Ws2812xMethod NeoEsp32I2s1X16Ws2813Method; @@ -854,15 +1003,15 @@ typedef NeoEsp32I2s1X16Sk6812Method NeoEsp32I2s1X16Lc8812Method; // INVERTED // // I2s0x8 INVERTED -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2812xInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2805InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Sk6812InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1814InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1829InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1914InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8800KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8400KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Apa106InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2812xInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Ws2805InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Sk6812InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1814InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1829InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Tm1914InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8800KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8400KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X8Apa106InvertedMethod; typedef NeoEsp32I2s0X8Ws2805InvertedMethod NeoEsp32I2s0X8Ws2814InvertedMethod; typedef NeoEsp32I2s0X8Ws2812xInvertedMethod NeoEsp32I2s0X8Ws2813InvertedMethod; @@ -874,15 +1023,15 @@ typedef NeoEsp32I2s0X8Sk6812InvertedMethod NeoEsp32I2s0X8Lc8812InvertedMethod; // I2s0x16 INVERTED -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2812xInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2805InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Sk6812InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1814InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1829InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1914InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16800KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16400KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Apa106InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2812xInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Ws2805InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Sk6812InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1814InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1829InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Tm1914InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16800KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16400KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s0X16Apa106InvertedMethod; typedef NeoEsp32I2s0X16Ws2805InvertedMethod NeoEsp32I2s0X16Ws2814InvertedMethod; typedef NeoEsp32I2s0X16Ws2812xInvertedMethod NeoEsp32I2s0X16Ws2813InvertedMethod; @@ -895,15 +1044,15 @@ typedef NeoEsp32I2s0X16Sk6812InvertedMethod NeoEsp32I2s0X16Lc8812InvertedMethod #if !defined(CONFIG_IDF_TARGET_ESP32S2) // I2s1x8 INVERTED -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2812xInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2805InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Sk6812InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1814InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1829InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1914InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8800KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8400KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Apa106InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2812xInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Ws2805InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Sk6812InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1814InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1829InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Tm1914InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8800KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8400KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X8Apa106InvertedMethod; typedef NeoEsp32I2s1X8Ws2805InvertedMethod NeoEsp32I2s1X8Ws2814InvertedMethod; typedef NeoEsp32I2s1X8Ws2812xInvertedMethod NeoEsp32I2s1X8Ws2813InvertedMethod; @@ -914,15 +1063,15 @@ typedef NeoEsp32I2s1X8800KbpsInvertedMethod NeoEsp32I2s1X8Ws2812InvertedMethod; typedef NeoEsp32I2s1X8Sk6812InvertedMethod NeoEsp32I2s1X8Lc8812InvertedMethod; // I2s1x16 INVERTED -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2812xInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2805InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Sk6812InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1814InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1829InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1914InvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16800KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16400KbpsInvertedMethod; -typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Apa106InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2812xInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Ws2805InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Sk6812InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1814InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1829InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Tm1914InvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16800KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16400KbpsInvertedMethod; +typedef NeoEsp32I2sXMethodBase NeoEsp32I2s1X16Apa106InvertedMethod; typedef NeoEsp32I2s1X16Ws2805InvertedMethod NeoEsp32I2s1X16Ws2814InvertedMethod; typedef NeoEsp32I2s1X16Ws2812xInvertedMethod NeoEsp32I2s1X16Ws2813InvertedMethod; diff --git a/src/internal/methods/NeoEsp32LcdXMethod.h b/src/internal/methods/NeoEsp32LcdXMethod.h index 21e3815..025a9dc 100644 --- a/src/internal/methods/NeoEsp32LcdXMethod.h +++ b/src/internal/methods/NeoEsp32LcdXMethod.h @@ -43,6 +43,7 @@ extern "C" // // true size of mux channel, 8 bit +// 3 step cadence, so pulses are 1/3 and 2/3 of pulse width // class NeoEspLcdMuxBusSize8Bit { @@ -72,14 +73,14 @@ public: // first cadence step init to 1 *(pDma++) |= muxBit; - // second candence step set based on bit + // second cadence step set based on bit if (value & 0x80) { *(pDma) |= muxBit; } pDma++; - // last candence step already init to 0, skip it + // last cadence step already init to 0, skip it pDma++; // Next @@ -91,6 +92,7 @@ public: // // true size of mux channel, 16 bit +// 3 step cadence, so pulses are 1/3 and 2/3 of pulse width // class NeoEspLcdMuxBusSize16Bit { @@ -119,14 +121,14 @@ public: // first cadence step init to 1 *(pDma++) |= muxBit; - // second candence step set based on bit + // second cadence step set based on bit if (value & 0x80) { *(pDma) |= muxBit; } pDma++; - // last candence step already init to 0, skip it + // last cadence step already init to 0, skip it pDma++; // Next @@ -251,7 +253,6 @@ static IRAM_ATTR bool dma_callback(gdma_channel_handle_t dma_chan, // Manages the underlying I2S details including the buffer // This creates only a actively sending back buffer, // Note that the back buffer must be DMA memory, a limited resource -// Assumes a 3 step candence, so pulses are 1/3 and 2/3 of pulse width // // T_MUXMAP - NeoEspLcdMuxMap - tracking class for mux state // @@ -590,9 +591,9 @@ template T_BUSCONTEXT NeoEsp32LcdMuxBus::s_ // // wrapping layer of the lcd mux bus as a NeoMethod // -// T_SPEED - NeoEsp32LcdSpeed* (ex NeoEsp32LcdSpeedWs2812x) used to define output signal form +// T_SPEED - NeoBitsSpeed* (ex NeoBitsSpeedWs2812x) used to define output signal form // T_BUS - NeoEsp32LcdMuxBus, the bus to use -// T_INVERT - NeoEsp32LcdNotInverted or NeoEsp32LcdInverted, will invert output signal +// T_INVERT - NeoBitsNotInverted or NeoBitsInverted, will invert output signal // template class NeoEsp32LcdXMethodBase @@ -605,7 +606,7 @@ public: _pin(pin), _bus() { - size_t numResetBytes = T_SPEED::ResetTimeUs / (T_SPEED::BitSendTimeNs*8/1000); + size_t numResetBytes = T_SPEED::ResetTimeUs / (T_SPEED::BitSendTimeNs * 8 / 1000); _bus.RegisterNewMuxBus(_sizeData + numResetBytes); } @@ -680,95 +681,18 @@ private: typedef NeoEsp32LcdMuxBus>> NeoEsp32LcdMux8Bus; typedef NeoEsp32LcdMuxBus>> NeoEsp32LcdMux16Bus; -// -------------------------------------------------------- -class NeoEsp32LcdSpeedWs2812x -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 300; -}; - -class NeoEsp32LcdSpeeWs2805 -{ -public: - const static uint16_t BitSendTimeNs = 1125; - const static uint16_t ResetTimeUs = 300; // spec is 280, intentionally longer for compatiblity use -}; - -class NeoEsp32LcdSpeeSk6812 -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 80; -}; - -class NeoEsp32LcdSpeeTm1814 -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32LcdSpeeTm1914 -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32LcdSpeeTm1829 -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 200; -}; - -class NeoEsp32LcdSpee800Kbps -{ -public: - const static uint16_t BitSendTimeNs = 1250; - const static uint16_t ResetTimeUs = 50; -}; - -class NeoEsp32LcdSpee400Kbps -{ -public: - const static uint16_t BitSendTimeNs = 2500; - const static uint16_t ResetTimeUs = 50; -}; - -class NeoEsp32LcdSpeeApa106 -{ -public: - const static uint16_t BitSendTimeNs = 1710; - const static uint16_t ResetTimeUs = 50; -}; - -//--------------------------------------------------------- -class NeoEsp32LcdNotInverted -{ -public: - const static bool Inverted = false; -}; - -class NeoEsp32LcdInverted -{ -public: - const static bool Inverted = true; -}; - //-------------------------------------------------------- -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2812xMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2805Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Sk6812Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1814Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1829Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1914Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8800KbpsMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8400KbpsMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Apa106Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2812xMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2805Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Sk6812Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1814Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1829Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1914Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8800KbpsMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8400KbpsMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Apa106Method; typedef NeoEsp32LcdX8Ws2805Method NeoEsp32LcdX8Ws2814Method; typedef NeoEsp32LcdX8Ws2812xMethod NeoEsp32LcdX8Ws2813Method; @@ -778,15 +702,15 @@ typedef NeoEsp32LcdX8Ws2812xMethod NeoEsp32LcdX8Ws2816Method; typedef NeoEsp32LcdX8800KbpsMethod NeoEsp32LcdX8Ws2812Method; typedef NeoEsp32LcdX8Sk6812Method NeoEsp32LcdX8Lc8812Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2812xMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2805Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Sk6812Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1814Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1829Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1914Method; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16800KbpsMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16400KbpsMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Apa106Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2812xMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2805Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Sk6812Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1814Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1829Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1914Method; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16800KbpsMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16400KbpsMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Apa106Method; typedef NeoEsp32LcdX16Ws2805Method NeoEsp32LcdX16Ws2814Method; typedef NeoEsp32LcdX16Ws2812xMethod NeoEsp32LcdX16Ws2813Method; @@ -798,15 +722,15 @@ typedef NeoEsp32LcdX16Sk6812Method NeoEsp32LcdX16Lc8812Method; //-------------------------------------------------------- -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2812xInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2805InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Sk6812InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1814InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1829InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1914InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8800KbpsInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8400KbpsInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Apa106InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2812xInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Ws2805InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Sk6812InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1814InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1829InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Tm1914InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8800KbpsInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8400KbpsInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX8Apa106InvertedMethod; typedef NeoEsp32LcdX8Ws2805InvertedMethod NeoEsp32LcdX8Ws2814InvertedMethod; typedef NeoEsp32LcdX8Ws2812xInvertedMethod NeoEsp32LcdX8Ws2813InvertedMethod; @@ -816,15 +740,15 @@ typedef NeoEsp32LcdX8Ws2812xInvertedMethod NeoEsp32LcdX8Ws2816InvertedMethod; typedef NeoEsp32LcdX8800KbpsInvertedMethod NeoEsp32LcdX8Ws2812InvertedMethod; typedef NeoEsp32LcdX8Sk6812InvertedMethod NeoEsp32LcdX8Lc8812InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2812xInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2805InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Sk6812InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1814InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1829InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1914InvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16800KbpsInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16400KbpsInvertedMethod; -typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Apa106InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2812xInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Ws2805InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Sk6812InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1814InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1829InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Tm1914InvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16800KbpsInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16400KbpsInvertedMethod; +typedef NeoEsp32LcdXMethodBase NeoEsp32LcdX16Apa106InvertedMethod; typedef NeoEsp32LcdX16Ws2805InvertedMethod NeoEsp32LcdX16Ws2814InvertedMethod; typedef NeoEsp32LcdX16Ws2812xInvertedMethod NeoEsp32LcdX16Ws2813InvertedMethod;