forked from Makuna/NeoPixelBus
Delay between pixels (#668)
* Delay inter pixel support * s2 s3 c3 Bitbang * deprecate NeoPixelBrightnessBus
This commit is contained in:
@@ -69,6 +69,7 @@ NeoTm1829Method KEYWORD1
|
|||||||
NeoTx1812Method KEYWORD1
|
NeoTx1812Method KEYWORD1
|
||||||
NeoLc8812Method KEYWORD1
|
NeoLc8812Method KEYWORD1
|
||||||
NeoApa106Method KEYWORD1
|
NeoApa106Method KEYWORD1
|
||||||
|
NeoIntertekMethod KEYWORD1
|
||||||
Neo800KbpsInvertedMethod KEYWORD1
|
Neo800KbpsInvertedMethod KEYWORD1
|
||||||
Neo400KbpsInvertedMethod KEYWORD1
|
Neo400KbpsInvertedMethod KEYWORD1
|
||||||
NeoWs2813InvertedMethod KEYWORD1
|
NeoWs2813InvertedMethod KEYWORD1
|
||||||
@@ -83,6 +84,7 @@ NeoTm1829InvertedMethod KEYWORD1
|
|||||||
NeoTx1812InvertedMethod KEYWORD1
|
NeoTx1812InvertedMethod KEYWORD1
|
||||||
NeoLc8812InvertedMethod KEYWORD1
|
NeoLc8812InvertedMethod KEYWORD1
|
||||||
NeoApa106InvertedMethod KEYWORD1
|
NeoApa106InvertedMethod KEYWORD1
|
||||||
|
NeoInvertedIntertekMethod KEYWORD1
|
||||||
NeoEsp8266DmaWs2812xMethod KEYWORD1
|
NeoEsp8266DmaWs2812xMethod KEYWORD1
|
||||||
NeoEsp8266DmaWs2816Method KEYWORD1
|
NeoEsp8266DmaWs2816Method KEYWORD1
|
||||||
NeoEsp8266DmaSk6812Method KEYWORD1
|
NeoEsp8266DmaSk6812Method KEYWORD1
|
||||||
|
@@ -28,7 +28,8 @@ License along with NeoPixel. If not, see
|
|||||||
|
|
||||||
#include "NeoPixelBus.h"
|
#include "NeoPixelBus.h"
|
||||||
|
|
||||||
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelBrightnessBus :
|
|
||||||
|
template<typename T_COLOR_FEATURE, typename T_METHOD> class [[deprecated("Use NeoPixelBusLg instead.")]] NeoPixelBrightnessBus :
|
||||||
public NeoPixelBus<T_COLOR_FEATURE, T_METHOD>
|
public NeoPixelBus<T_COLOR_FEATURE, T_METHOD>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@@ -125,7 +125,15 @@ public:
|
|||||||
const static uint32_t ResetTimeUs = 50;
|
const static uint32_t ResetTimeUs = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NeoEsp8266DmaSpeedIntertek : public NeoEsp8266DmaSpeedBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t I2sClockDivisor = 5; // 0-63
|
||||||
|
const static uint32_t I2sBaseClockDivisor = 10; // 0-63
|
||||||
|
const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element
|
||||||
|
const static uint32_t ResetTimeUs = 12470;
|
||||||
|
const static uint32_t InterPixelTimeUs = 20;
|
||||||
|
};
|
||||||
|
|
||||||
class NeoEsp8266DmaInvertedSpeed800KbpsBase : public NeoEsp8266DmaInvertedSpeedBase
|
class NeoEsp8266DmaInvertedSpeed800KbpsBase : public NeoEsp8266DmaInvertedSpeedBase
|
||||||
{
|
{
|
||||||
@@ -183,32 +191,103 @@ public:
|
|||||||
const static uint32_t ResetTimeUs = 50;
|
const static uint32_t ResetTimeUs = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NeoEsp8266DmaInvertedSpeedIntertek : public NeoEsp8266DmaInvertedSpeedBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t I2sClockDivisor = 5; // 0-63
|
||||||
|
const static uint32_t I2sBaseClockDivisor = 10; // 0-63
|
||||||
|
const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
|
||||||
|
const static uint32_t ResetTimeUs = 12470;
|
||||||
|
const static uint32_t InterPixelTimeUs = 20;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T_SPEED> class NeoEsp8266DmaEncode : public T_SPEED
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static size_t SpacingPixelSize(size_t sizePixel)
|
||||||
|
{
|
||||||
|
return sizePixel;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T_SPEED> class NeoEsp8266DmaMethodBase : NeoEsp8266I2sMethodCore
|
static void FillBuffers(uint8_t* i2sBuffer,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t sizeData,
|
||||||
|
[[maybe_unused]] size_t sizePixel)
|
||||||
|
{
|
||||||
|
uint16_t* pDma = (uint16_t*)i2sBuffer;
|
||||||
|
const uint8_t* pEnd = data + sizeData;
|
||||||
|
for (const uint8_t* pData = data; pData < pEnd; pData++)
|
||||||
|
{
|
||||||
|
*(pDma++) = T_SPEED::Convert(((*pData) & 0x0f));
|
||||||
|
*(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T_SPEED> class NeoEsp8266DmaPixelSpacingEncode : public T_SPEED
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static size_t SpacingPixelSize(size_t sizePixel)
|
||||||
|
{
|
||||||
|
return sizePixel + T_SPEED::InterPixelTimeUs / T_SPEED::ByteSendTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillBuffers(uint8_t* i2sBuffer,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t sizeData,
|
||||||
|
size_t sizePixel)
|
||||||
|
{
|
||||||
|
uint16_t* pDma = (uint16_t*)i2sBuffer;
|
||||||
|
const uint8_t* pEnd = data + sizeData;
|
||||||
|
uint8_t element = 0;
|
||||||
|
for (const uint8_t* pData = data; pData < pEnd; pData++)
|
||||||
|
{
|
||||||
|
*(pDma++) = T_SPEED::Convert(((*pData) & 0x0f));
|
||||||
|
*(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f);
|
||||||
|
|
||||||
|
element++;
|
||||||
|
if (element == sizePixel)
|
||||||
|
{
|
||||||
|
element = 0;
|
||||||
|
|
||||||
|
for (uint8_t padding = 0;
|
||||||
|
padding < (T_SPEED::InterPixelTimeUs / T_SPEED::ByteSendTimeUs);
|
||||||
|
padding++)
|
||||||
|
{
|
||||||
|
*(pDma++) = T_SPEED::IdleLevel * 0xffff;
|
||||||
|
*(pDma++) = T_SPEED::IdleLevel * 0xffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T_ENCODER> class NeoEsp8266DmaMethodBase : NeoEsp8266I2sMethodCore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef NeoNoSettings SettingsObject;
|
typedef NeoNoSettings SettingsObject;
|
||||||
|
|
||||||
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
||||||
|
_sizePixel(elementSize),
|
||||||
_sizeData(pixelCount * elementSize + settingsSize)
|
_sizeData(pixelCount * elementSize + settingsSize)
|
||||||
{
|
{
|
||||||
size_t dmaPixelSize = DmaBytesPerPixelBytes * elementSize;
|
size_t dmaPixelSize = DmaBytesPerPixelBytes * T_ENCODER::SpacingPixelSize(_sizePixel);
|
||||||
size_t dmaSettingsSize = DmaBytesPerPixelBytes * settingsSize;
|
size_t dmaSettingsSize = DmaBytesPerPixelBytes * settingsSize;
|
||||||
|
|
||||||
size_t i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize;
|
size_t i2sBufferSize = pixelCount * dmaPixelSize + dmaSettingsSize;
|
||||||
|
// size is rounded up to nearest c_I2sByteBoundarySize
|
||||||
|
i2sBufferSize = NeoUtil::RoundUp(i2sBufferSize, c_I2sByteBoundarySize);
|
||||||
|
|
||||||
// normally 24 bytes creates the minimum 50us latch per spec, but
|
// calculate a buffer size that takes reset amount of time
|
||||||
// with the new logic, this latch is used to space between mulitple states
|
size_t i2sResetSize = T_ENCODER::ResetTimeUs * DmaBytesPerPixelBytes / T_ENCODER::ByteSendTimeUs;
|
||||||
// buffer size = (24 * (reset time / 50)) / 6
|
// size is rounded up to nearest c_I2sByteBoundarySize
|
||||||
size_t i2sZeroesSize = (24L * (T_SPEED::ResetTimeUs / 50L)) / 6L;
|
i2sResetSize = NeoUtil::RoundUp(i2sResetSize, c_I2sByteBoundarySize);
|
||||||
|
|
||||||
size_t is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize;
|
size_t is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize;
|
||||||
|
|
||||||
_data = static_cast<uint8_t*>(malloc(_sizeData));
|
_data = static_cast<uint8_t*>(malloc(_sizeData));
|
||||||
// data cleared later in Begin()
|
// data cleared later in Begin()
|
||||||
|
|
||||||
AllocateI2s(i2sBufferSize, i2sZeroesSize, is2BufMaxBlockSize, T_SPEED::IdleLevel);
|
AllocateI2s(i2sBufferSize, i2sResetSize, is2BufMaxBlockSize, T_ENCODER::IdleLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
NeoEsp8266DmaMethodBase([[maybe_unused]] uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
NeoEsp8266DmaMethodBase([[maybe_unused]] uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
||||||
@@ -228,7 +307,7 @@ public:
|
|||||||
// wait for any pending sends to complete
|
// wait for any pending sends to complete
|
||||||
// due to internal i2s caching/send delays, this can more that once the data size
|
// due to internal i2s caching/send delays, this can more that once the data size
|
||||||
uint32_t time = micros();
|
uint32_t time = micros();
|
||||||
while ((micros() - time) < ((getPixelTime() + T_SPEED::ResetTimeUs) * waits))
|
while ((micros() - time) < ((getPixelTime() + T_ENCODER::ResetTimeUs) * waits))
|
||||||
{
|
{
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
@@ -245,7 +324,7 @@ public:
|
|||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
InitializeI2s(T_SPEED::I2sClockDivisor, T_SPEED::I2sBaseClockDivisor);
|
InitializeI2s(T_ENCODER::I2sClockDivisor, T_ENCODER::I2sBaseClockDivisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR Update(bool)
|
void IRAM_ATTR Update(bool)
|
||||||
@@ -255,10 +334,9 @@ public:
|
|||||||
{
|
{
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
FillBuffers();
|
T_ENCODER::FillBuffers(_i2sBuffer, _data, _sizeData, _sizePixel);
|
||||||
|
|
||||||
// toggle state so the ISR reacts
|
WriteI2s();
|
||||||
_dmaState = NeoDmaState_Pending;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AlwaysUpdate()
|
bool AlwaysUpdate()
|
||||||
@@ -285,23 +363,13 @@ private:
|
|||||||
// due to encoding required for i2s, we need 4 bytes to encode the pulses
|
// due to encoding required for i2s, we need 4 bytes to encode the pulses
|
||||||
static const uint16_t DmaBytesPerPixelBytes = 4;
|
static const uint16_t DmaBytesPerPixelBytes = 4;
|
||||||
|
|
||||||
|
const size_t _sizePixel; // size of a pixel in _data
|
||||||
const size_t _sizeData; // Size of '_data' buffer
|
const size_t _sizeData; // Size of '_data' buffer
|
||||||
uint8_t* _data; // Holds LED color values
|
uint8_t* _data; // Holds LED color values
|
||||||
|
|
||||||
void FillBuffers()
|
|
||||||
{
|
|
||||||
uint16_t* pDma = (uint16_t*)_i2sBuffer;
|
|
||||||
uint8_t* pEnd = _data + _sizeData;
|
|
||||||
for (uint8_t* pData = _data; pData < pEnd; pData++)
|
|
||||||
{
|
|
||||||
*(pDma++) = T_SPEED::Convert(((*pData) & 0x0f));
|
|
||||||
*(pDma++) = T_SPEED::Convert(((*pData) >> 4) & 0x0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getPixelTime() const
|
uint32_t getPixelTime() const
|
||||||
{
|
{
|
||||||
return (T_SPEED::ByteSendTimeUs * this->_sizeData);
|
return (T_ENCODER::ByteSendTimeUs * GetSendSize() / DmaBytesPerPixelBytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -309,25 +377,27 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
// normal
|
// normal
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedWs2812x> NeoEsp8266DmaWs2812xMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeedWs2812x>> NeoEsp8266DmaWs2812xMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedSk6812> NeoEsp8266DmaSk6812Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeedSk6812>> NeoEsp8266DmaSk6812Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedTm1814> NeoEsp8266DmaTm1814Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeedTm1814>> NeoEsp8266DmaTm1814Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedTm1829> NeoEsp8266DmaTm1829Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeedTm1829>> NeoEsp8266DmaTm1829Method;
|
||||||
typedef NeoEsp8266DmaTm1814Method NeoEsp8266DmaTm1914Method;
|
typedef NeoEsp8266DmaTm1814Method NeoEsp8266DmaTm1914Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed800Kbps> NeoEsp8266Dma800KbpsMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeed800Kbps>> NeoEsp8266Dma800KbpsMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed400Kbps> NeoEsp8266Dma400KbpsMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeed400Kbps>> NeoEsp8266Dma400KbpsMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedApa106> NeoEsp8266DmaApa106Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaSpeedApa106>> NeoEsp8266DmaApa106Method;
|
||||||
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaPixelSpacingEncode<NeoEsp8266DmaSpeedIntertek>> NeoEsp8266DmaIntertekMethod;
|
||||||
|
|
||||||
|
|
||||||
// inverted
|
// inverted
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedWs2812x> NeoEsp8266DmaInvertedWs2812xMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeedWs2812x>> NeoEsp8266DmaInvertedWs2812xMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedSk6812> NeoEsp8266DmaInvertedSk6812Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeedSk6812>> NeoEsp8266DmaInvertedSk6812Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedTm1814> NeoEsp8266DmaInvertedTm1814Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeedTm1814>> NeoEsp8266DmaInvertedTm1814Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedTm1829> NeoEsp8266DmaInvertedTm1829Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeedTm1829>> NeoEsp8266DmaInvertedTm1829Method;
|
||||||
typedef NeoEsp8266DmaInvertedTm1814Method NeoEsp8266DmaInvertedTm1914Method;
|
typedef NeoEsp8266DmaInvertedTm1814Method NeoEsp8266DmaInvertedTm1914Method;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed800Kbps> NeoEsp8266DmaInverted800KbpsMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeed800Kbps>> NeoEsp8266DmaInverted800KbpsMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed400Kbps> NeoEsp8266DmaInverted400KbpsMethod;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeed400Kbps>> NeoEsp8266DmaInverted400KbpsMethod;
|
||||||
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedApa106> NeoEsp8266DmaInvertedApa106Method;
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaEncode<NeoEsp8266DmaInvertedSpeedApa106>> NeoEsp8266DmaInvertedApa106Method;
|
||||||
|
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaPixelSpacingEncode<NeoEsp8266DmaInvertedSpeedIntertek>> NeoEsp8266DmaInvertedIntertekMethod;
|
||||||
|
|
||||||
// Dma method is the default method for Esp8266
|
// Dma method is the default method for Esp8266
|
||||||
typedef NeoEsp8266DmaWs2812xMethod NeoWs2813Method;
|
typedef NeoEsp8266DmaWs2812xMethod NeoWs2813Method;
|
||||||
@@ -341,6 +411,7 @@ typedef NeoEsp8266DmaTm1829Method NeoTm1829Method;
|
|||||||
typedef NeoEsp8266DmaTm1914Method NeoTm1914Method;
|
typedef NeoEsp8266DmaTm1914Method NeoTm1914Method;
|
||||||
typedef NeoEsp8266DmaSk6812Method NeoLc8812Method;
|
typedef NeoEsp8266DmaSk6812Method NeoLc8812Method;
|
||||||
typedef NeoEsp8266DmaApa106Method NeoApa106Method;
|
typedef NeoEsp8266DmaApa106Method NeoApa106Method;
|
||||||
|
typedef NeoEsp8266DmaIntertekMethod NeoIntertekMethod;
|
||||||
|
|
||||||
typedef NeoEsp8266DmaWs2812xMethod Neo800KbpsMethod;
|
typedef NeoEsp8266DmaWs2812xMethod Neo800KbpsMethod;
|
||||||
typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod;
|
typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod;
|
||||||
@@ -357,6 +428,7 @@ typedef NeoEsp8266DmaInvertedTm1829Method NeoTm1829InvertedMethod;
|
|||||||
typedef NeoEsp8266DmaInvertedTm1914Method NeoTm1914InvertedMethod;
|
typedef NeoEsp8266DmaInvertedTm1914Method NeoTm1914InvertedMethod;
|
||||||
typedef NeoEsp8266DmaInvertedSk6812Method NeoLc8812InvertedMethod;
|
typedef NeoEsp8266DmaInvertedSk6812Method NeoLc8812InvertedMethod;
|
||||||
typedef NeoEsp8266DmaInvertedApa106Method NeoApa106InvertedMethod;
|
typedef NeoEsp8266DmaInvertedApa106Method NeoApa106InvertedMethod;
|
||||||
|
typedef NeoEsp8266DmaInvertedIntertekMethod NeoInvertedIntertekMethod;
|
||||||
|
|
||||||
typedef NeoEsp8266DmaInvertedWs2812xMethod Neo800KbpsInvertedMethod;
|
typedef NeoEsp8266DmaInvertedWs2812xMethod Neo800KbpsInvertedMethod;
|
||||||
typedef NeoEsp8266DmaInverted400KbpsMethod Neo400KbpsInvertedMethod;
|
typedef NeoEsp8266DmaInverted400KbpsMethod Neo400KbpsInvertedMethod;
|
||||||
|
@@ -142,20 +142,20 @@ public:
|
|||||||
|
|
||||||
i2sBufferSize = i2sBufferSize + T_SPEED::BreakMabSize;
|
i2sBufferSize = i2sBufferSize + T_SPEED::BreakMabSize;
|
||||||
|
|
||||||
// size is rounded up to nearest I2sByteBoundarySize
|
// size is rounded up to nearest c_I2sByteBoundarySize
|
||||||
i2sBufferSize = NeoUtil::RoundUp(i2sBufferSize, I2sByteBoundarySize);
|
i2sBufferSize = NeoUtil::RoundUp(i2sBufferSize, c_I2sByteBoundarySize);
|
||||||
|
|
||||||
// size of a looping silent space rounded up to nearest I2sByteBoundarySize
|
// size of a looping silent space rounded up to nearest c_I2sByteBoundarySize
|
||||||
size_t i2sZeroesSize = NeoUtil::RoundUp(T_SPEED::MtbpSize, I2sByteBoundarySize);
|
size_t i2sResetSize = NeoUtil::RoundUp(T_SPEED::MtbpSize, c_I2sByteBoundarySize);
|
||||||
|
|
||||||
// protocol limits use of full block size to I2sByteBoundarySize
|
// protocol limits use of full block size to c_I2sByteBoundarySize
|
||||||
size_t is2BufMaxBlockSize = (c_maxDmaBlockSize / I2sByteBoundarySize) * I2sByteBoundarySize;
|
size_t is2BufMaxBlockSize = (c_maxDmaBlockSize / c_I2sByteBoundarySize) * c_I2sByteBoundarySize;
|
||||||
|
|
||||||
_data = static_cast<uint8_t*>(malloc(_sizeData));
|
_data = static_cast<uint8_t*>(malloc(_sizeData));
|
||||||
// first "slot" cleared due to protocol requiring it to be zero
|
// first "slot" cleared due to protocol requiring it to be zero
|
||||||
memset(_data, 0x00, 1);
|
memset(_data, 0x00, 1);
|
||||||
|
|
||||||
AllocateI2s(i2sBufferSize, i2sZeroesSize, is2BufMaxBlockSize, T_SPEED::MtbpLevel);
|
AllocateI2s(i2sBufferSize, i2sResetSize, is2BufMaxBlockSize, T_SPEED::MtbpLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
NeoEsp8266I2sDmx512MethodBase([[maybe_unused]] uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
NeoEsp8266I2sDmx512MethodBase([[maybe_unused]] uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
||||||
@@ -204,8 +204,7 @@ public:
|
|||||||
}
|
}
|
||||||
FillBuffers();
|
FillBuffers();
|
||||||
|
|
||||||
// toggle state so the ISR reacts
|
WriteI2s();
|
||||||
_dmaState = NeoDmaState_Pending;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AlwaysUpdate()
|
bool AlwaysUpdate()
|
||||||
@@ -231,8 +230,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
// given 11 sending bits per pixel byte,
|
// given 11 sending bits per pixel byte,
|
||||||
static const uint16_t I2sBitsPerPixelBytes = 11;
|
static const uint16_t I2sBitsPerPixelBytes = 11;
|
||||||
// i2s sends 4 byte elements,
|
|
||||||
static const uint16_t I2sByteBoundarySize = 4;
|
|
||||||
|
|
||||||
const size_t _sizeData; // Size of '_data' buffer
|
const size_t _sizeData; // Size of '_data' buffer
|
||||||
uint8_t* _data; // Holds LED color values
|
uint8_t* _data; // Holds LED color values
|
||||||
|
@@ -25,6 +25,7 @@ License along with NeoPixel. If not, see
|
|||||||
-------------------------------------------------------------------------*/
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "NeoUtil.h"
|
||||||
#include "NeoEsp8266I2sMethodCore.h"
|
#include "NeoEsp8266I2sMethodCore.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP8266
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
@@ -71,8 +71,7 @@ enum NeoDmaState
|
|||||||
{
|
{
|
||||||
NeoDmaState_Idle,
|
NeoDmaState_Idle,
|
||||||
NeoDmaState_Pending,
|
NeoDmaState_Pending,
|
||||||
NeoDmaState_Sending,
|
NeoDmaState_Sending
|
||||||
NeoDmaState_Zeroing,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint16_t c_maxDmaBlockSize = 4095;
|
const uint16_t c_maxDmaBlockSize = 4095;
|
||||||
@@ -81,6 +80,13 @@ const uint8_t c_I2sPin = 3; // due to I2S hardware, the pin used is restricted t
|
|||||||
|
|
||||||
class NeoEsp8266I2sMethodCore
|
class NeoEsp8266I2sMethodCore
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
static const uint8_t c_StateBlockCount = 2;
|
||||||
|
static const size_t c_StateDataSize = 4; // mulitples of c_I2sByteBoundarySize
|
||||||
|
|
||||||
|
// i2s sends 4 byte elements,
|
||||||
|
static const uint16_t c_I2sByteBoundarySize = 4;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static NeoEsp8266I2sMethodCore* s_this; // for the ISR
|
static NeoEsp8266I2sMethodCore* s_this; // for the ISR
|
||||||
|
|
||||||
@@ -92,11 +98,16 @@ protected:
|
|||||||
size_t _i2sBufferSize; // total size of _i2sBuffer
|
size_t _i2sBufferSize; // total size of _i2sBuffer
|
||||||
uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
|
uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc
|
||||||
|
|
||||||
size_t _i2sZeroesSize; // total size of _i2sZeroes
|
size_t _i2sIdleDataTotalSize; // total size of represented zeroes, mulitple uses of _i2sIdleData
|
||||||
uint8_t* _i2sZeroes;
|
size_t _i2sIdleDataSize; // size of _i2sIdleData
|
||||||
|
uint8_t* _i2sIdleData;
|
||||||
|
|
||||||
uint16_t _is2BufMaxBlockSize; // max size based on size of a pixel of a single block
|
uint16_t _is2BufMaxBlockSize; // max size based on size of a pixel of a single block
|
||||||
|
|
||||||
|
size_t GetSendSize() const
|
||||||
|
{
|
||||||
|
return _i2sBufferSize + _i2sIdleDataTotalSize;
|
||||||
|
}
|
||||||
|
|
||||||
// This routine is called as soon as the DMA routine has something to tell us. All we
|
// This routine is called as soon as the DMA routine has something to tell us. All we
|
||||||
// handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
|
// handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
|
||||||
@@ -112,39 +123,15 @@ protected:
|
|||||||
|
|
||||||
if ((slc_intr_status & SLCIRXEOF) && s_this)
|
if ((slc_intr_status & SLCIRXEOF) && s_this)
|
||||||
{
|
{
|
||||||
switch (s_this->_dmaState)
|
if (s_this->_dmaState != NeoDmaState_Idle)
|
||||||
{
|
{
|
||||||
case NeoDmaState_Idle:
|
// first two items are the state blocks
|
||||||
break;
|
slc_queue_item* itemLoop = s_this->_i2sBufDesc;
|
||||||
|
slc_queue_item* itemLoopBreaker = itemLoop + 1;
|
||||||
|
// set to loop on idle items
|
||||||
|
itemLoopBreaker->next_link_ptr = itemLoop;
|
||||||
|
|
||||||
case NeoDmaState_Pending:
|
|
||||||
{
|
|
||||||
slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA;
|
|
||||||
|
|
||||||
// data block has pending data waiting to send, prepare it
|
|
||||||
// point last state block to top
|
|
||||||
(finished_item + 1)->next_link_ptr = s_this->_i2sBufDesc;
|
|
||||||
|
|
||||||
s_this->_dmaState = NeoDmaState_Sending;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NeoDmaState_Sending:
|
|
||||||
{
|
|
||||||
slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA;
|
|
||||||
|
|
||||||
// the data block had actual data sent
|
|
||||||
// point last state block to first state block thus
|
|
||||||
// just looping and not sending the data blocks
|
|
||||||
(finished_item + 1)->next_link_ptr = finished_item;
|
|
||||||
|
|
||||||
s_this->_dmaState = NeoDmaState_Zeroing;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NeoDmaState_Zeroing:
|
|
||||||
s_this->_dmaState = NeoDmaState_Idle;
|
s_this->_dmaState = NeoDmaState_Idle;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,21 +141,37 @@ protected:
|
|||||||
NeoEsp8266I2sMethodCore()
|
NeoEsp8266I2sMethodCore()
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
void AllocateI2s(const size_t i2sBufferSize,
|
void AllocateI2s(const size_t i2sBufferSize, // expected multiples of c_I2sByteBoundarySize
|
||||||
const size_t i2sZeroesSize,
|
const size_t i2sZeroesSize, // expected multiples of c_I2sByteBoundarySize
|
||||||
const size_t is2BufMaxBlockSize,
|
const size_t is2BufMaxBlockSize,
|
||||||
const uint8_t idleLevel)
|
const uint8_t idleLevel)
|
||||||
{
|
{
|
||||||
_i2sBufferSize = i2sBufferSize;
|
_i2sBufferSize = i2sBufferSize;
|
||||||
_i2sZeroesSize = i2sZeroesSize;
|
_i2sIdleDataTotalSize = i2sZeroesSize;
|
||||||
|
_i2sIdleDataSize = _i2sIdleDataTotalSize;
|
||||||
|
|
||||||
|
size_t countIdleQueueItems = 1;
|
||||||
|
if (_i2sIdleDataSize > 256)
|
||||||
|
{
|
||||||
|
// reuse a single idle data buffer of 256 with multiple dma slc_queue_items
|
||||||
|
countIdleQueueItems = _i2sIdleDataSize / 256 + 1;
|
||||||
|
_i2sIdleDataSize = 256;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_i2sIdleDataSize = NeoUtil::RoundUp(_i2sIdleDataSize, c_I2sByteBoundarySize);
|
||||||
|
}
|
||||||
_is2BufMaxBlockSize = is2BufMaxBlockSize;
|
_is2BufMaxBlockSize = is2BufMaxBlockSize;
|
||||||
|
|
||||||
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
|
_i2sBuffer = static_cast<uint8_t*>(malloc(_i2sBufferSize));
|
||||||
// no need to initialize it, it gets overwritten on every send
|
// no need to initialize it, it gets overwritten on every send
|
||||||
_i2sZeroes = static_cast<uint8_t*>(malloc(_i2sZeroesSize));
|
_i2sIdleData = static_cast<uint8_t*>(malloc(_i2sIdleDataSize));
|
||||||
memset(_i2sZeroes, idleLevel * 0xff, _i2sZeroesSize);
|
memset(_i2sIdleData, idleLevel * 0xff, _i2sIdleDataSize);
|
||||||
|
|
||||||
|
_i2sBufDescCount = (_i2sBufferSize / _is2BufMaxBlockSize) + 1 +
|
||||||
|
countIdleQueueItems +
|
||||||
|
c_StateBlockCount; // need more for state/latch blocks
|
||||||
|
|
||||||
_i2sBufDescCount = (_i2sBufferSize / _is2BufMaxBlockSize) + 1 + 2; // need two more for state/latch blocks
|
|
||||||
_i2sBufDesc = (slc_queue_item*)malloc(_i2sBufDescCount * sizeof(slc_queue_item));
|
_i2sBufDesc = (slc_queue_item*)malloc(_i2sBufDescCount * sizeof(slc_queue_item));
|
||||||
|
|
||||||
s_this = this; // store this for the ISR
|
s_this = this; // store this for the ISR
|
||||||
@@ -183,7 +186,7 @@ protected:
|
|||||||
|
|
||||||
free(_i2sBuffer);
|
free(_i2sBuffer);
|
||||||
free(_i2sBufDesc);
|
free(_i2sBufDesc);
|
||||||
free(_i2sZeroes);
|
free(_i2sIdleData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsIdle() const
|
bool IsIdle() const
|
||||||
@@ -191,6 +194,19 @@ protected:
|
|||||||
return (_dmaState == NeoDmaState_Idle);
|
return (_dmaState == NeoDmaState_Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DmaItemInit(slc_queue_item* item, uint8_t* data, size_t sizeData, slc_queue_item* itemNext)
|
||||||
|
{
|
||||||
|
item->owner = 1;
|
||||||
|
item->eof = 0; // no need to trigger interrupt generally
|
||||||
|
item->sub_sof = 0;
|
||||||
|
item->datalen = sizeData;
|
||||||
|
item->blocksize = sizeData;
|
||||||
|
item->buf_ptr = data;
|
||||||
|
item->unused = 0;
|
||||||
|
item->next_link_ptr = itemNext;
|
||||||
|
}
|
||||||
|
|
||||||
void InitializeI2s(const uint32_t i2sClockDivisor, const uint32_t i2sBaseClockDivisor)
|
void InitializeI2s(const uint32_t i2sClockDivisor, const uint32_t i2sBaseClockDivisor)
|
||||||
{
|
{
|
||||||
StopI2s();
|
StopI2s();
|
||||||
@@ -198,52 +214,61 @@ protected:
|
|||||||
pinMode(c_I2sPin, FUNCTION_1); // I2S0_DATA
|
pinMode(c_I2sPin, FUNCTION_1); // I2S0_DATA
|
||||||
|
|
||||||
uint8_t* is2Buffer = _i2sBuffer;
|
uint8_t* is2Buffer = _i2sBuffer;
|
||||||
uint32_t is2BufferSize = _i2sBufferSize;
|
uint8_t* is2BufferEnd = _i2sBuffer + _i2sBufferSize;
|
||||||
uint16_t indexDesc;
|
uint32_t is2BufferSize;
|
||||||
|
uint16_t indexDesc = 0;
|
||||||
|
|
||||||
|
// prepare the two state/latch descriptors
|
||||||
|
uint16_t stateDataSize = min(c_StateDataSize, _i2sIdleDataSize);
|
||||||
|
while (indexDesc < c_StateBlockCount)
|
||||||
|
{
|
||||||
|
DmaItemInit(&_i2sBufDesc[indexDesc], _i2sIdleData, stateDataSize, &(_i2sBufDesc[indexDesc + 1]));
|
||||||
|
|
||||||
|
indexDesc++;
|
||||||
|
}
|
||||||
|
|
||||||
// prepare main data block decriptors that point into our one static dma buffer
|
// prepare main data block decriptors that point into our one static dma buffer
|
||||||
for (indexDesc = 0; indexDesc < (_i2sBufDescCount - 2); indexDesc++)
|
is2BufferSize = _i2sBufferSize;
|
||||||
|
while (is2Buffer < is2BufferEnd)
|
||||||
{
|
{
|
||||||
uint32_t blockSize = (is2BufferSize > _is2BufMaxBlockSize) ? _is2BufMaxBlockSize : is2BufferSize;
|
uint32_t blockSize = (is2BufferSize > _is2BufMaxBlockSize) ? _is2BufMaxBlockSize : is2BufferSize;
|
||||||
|
|
||||||
_i2sBufDesc[indexDesc].owner = 1;
|
DmaItemInit(&_i2sBufDesc[indexDesc], is2Buffer, blockSize, &(_i2sBufDesc[indexDesc + 1]));
|
||||||
_i2sBufDesc[indexDesc].eof = 0; // no need to trigger interrupt generally
|
|
||||||
_i2sBufDesc[indexDesc].sub_sof = 0;
|
|
||||||
_i2sBufDesc[indexDesc].datalen = blockSize;
|
|
||||||
_i2sBufDesc[indexDesc].blocksize = blockSize;
|
|
||||||
_i2sBufDesc[indexDesc].buf_ptr = is2Buffer;
|
|
||||||
_i2sBufDesc[indexDesc].unused = 0;
|
|
||||||
_i2sBufDesc[indexDesc].next_link_ptr = reinterpret_cast<struct slc_queue_item*>(&(_i2sBufDesc[indexDesc + 1]));
|
|
||||||
|
|
||||||
is2Buffer += blockSize;
|
is2Buffer += blockSize;
|
||||||
is2BufferSize -= blockSize;
|
is2BufferSize -= blockSize;
|
||||||
|
indexDesc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the two state/latch descriptors
|
// last data item triggers EOF ISR
|
||||||
for (; indexDesc < _i2sBufDescCount; indexDesc++)
|
_i2sBufDesc[indexDesc - 1].eof = 1;
|
||||||
|
|
||||||
|
// prepare idle block decriptors that point into our one idle dma buffer
|
||||||
|
is2BufferSize = _i2sIdleDataTotalSize;
|
||||||
|
while (indexDesc < _i2sBufDescCount)
|
||||||
{
|
{
|
||||||
_i2sBufDesc[indexDesc].owner = 1;
|
uint32_t blockSize = (is2BufferSize > _i2sIdleDataSize) ? _i2sIdleDataSize : is2BufferSize;
|
||||||
_i2sBufDesc[indexDesc].eof = 0; // no need to trigger interrupt generally
|
|
||||||
_i2sBufDesc[indexDesc].sub_sof = 0;
|
DmaItemInit(&_i2sBufDesc[indexDesc], _i2sIdleData, blockSize, &(_i2sBufDesc[indexDesc + 1]));
|
||||||
_i2sBufDesc[indexDesc].datalen = sizeof(_i2sZeroes);
|
|
||||||
_i2sBufDesc[indexDesc].blocksize = sizeof(_i2sZeroes);
|
is2Buffer += blockSize;
|
||||||
_i2sBufDesc[indexDesc].buf_ptr = _i2sZeroes;
|
is2BufferSize -= blockSize;
|
||||||
_i2sBufDesc[indexDesc].unused = 0;
|
indexDesc++;
|
||||||
_i2sBufDesc[indexDesc].next_link_ptr = reinterpret_cast<struct slc_queue_item*>(&(_i2sBufDesc[indexDesc + 1]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the first state block will trigger the interrupt
|
// the last item will loop to the first item
|
||||||
_i2sBufDesc[indexDesc - 2].eof = 1;
|
_i2sBufDesc[indexDesc - 1].next_link_ptr = reinterpret_cast<struct slc_queue_item*>(&(_i2sBufDesc[0]));
|
||||||
|
|
||||||
// the last state block will loop to the first state block by defualt
|
// the last state block will loop to the first state block by defualt
|
||||||
_i2sBufDesc[indexDesc - 1].next_link_ptr = reinterpret_cast<struct slc_queue_item*>(&(_i2sBufDesc[indexDesc - 2]));
|
_i2sBufDesc[c_StateBlockCount - 1].next_link_ptr = reinterpret_cast<struct slc_queue_item*>(&(_i2sBufDesc[0]));
|
||||||
|
|
||||||
// setup the rest of i2s DMA
|
// setup the rest of i2s DMA
|
||||||
//
|
//
|
||||||
ETS_SLC_INTR_DISABLE();
|
ETS_SLC_INTR_DISABLE();
|
||||||
|
|
||||||
// start off in sending state as that is what it will be all setup to be
|
// start off in idel state as that is what it will be all setup to be
|
||||||
// for the interrupt
|
// for the interrupt
|
||||||
_dmaState = NeoDmaState_Sending;
|
_dmaState = NeoDmaState_Idle;
|
||||||
|
|
||||||
SLCC0 |= SLCRXLR | SLCTXLR;
|
SLCC0 |= SLCRXLR | SLCTXLR;
|
||||||
SLCC0 &= ~(SLCRXLR | SLCTXLR);
|
SLCC0 &= ~(SLCRXLR | SLCTXLR);
|
||||||
@@ -301,6 +326,18 @@ protected:
|
|||||||
I2SC |= I2STXS; // Start transmission
|
I2SC |= I2STXS; // Start transmission
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteI2s()
|
||||||
|
{
|
||||||
|
// first two items are the state blocks
|
||||||
|
slc_queue_item* itemLoopBreaker = &(_i2sBufDesc[1]);
|
||||||
|
slc_queue_item* itemData = itemLoopBreaker + 1;
|
||||||
|
|
||||||
|
// set to NOT loop on idle items
|
||||||
|
itemLoopBreaker->next_link_ptr = itemData;
|
||||||
|
|
||||||
|
_dmaState = NeoDmaState_Sending;
|
||||||
|
}
|
||||||
|
|
||||||
void StopI2s()
|
void StopI2s()
|
||||||
{
|
{
|
||||||
ETS_SLC_INTR_DISABLE();
|
ETS_SLC_INTR_DISABLE();
|
||||||
|
@@ -163,6 +163,8 @@ protected:
|
|||||||
// synchronous uart method
|
// synchronous uart method
|
||||||
//
|
//
|
||||||
// used by NeoEsp8266UartMethodBase
|
// used by NeoEsp8266UartMethodBase
|
||||||
|
// T_UARTFEATURE - (UartFeature0 | UartFeature1)
|
||||||
|
// T_UARTCONTEXT - (NeoEsp8266UartContext | NeoEsp8266UartInterruptContext)
|
||||||
//
|
//
|
||||||
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266Uart : public NeoEsp8266UartBase
|
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266Uart : public NeoEsp8266UartBase
|
||||||
{
|
{
|
||||||
@@ -217,6 +219,8 @@ protected:
|
|||||||
// every call to NeoPixelBus.Show() and must not be cached.
|
// every call to NeoPixelBus.Show() and must not be cached.
|
||||||
//
|
//
|
||||||
// used by NeoEsp8266UartMethodBase
|
// used by NeoEsp8266UartMethodBase
|
||||||
|
// T_UARTFEATURE - (UartFeature0 | UartFeature1)
|
||||||
|
// T_UARTCONTEXT - (NeoEsp8266UartContext | NeoEsp8266UartInterruptContext)
|
||||||
//
|
//
|
||||||
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266AsyncUart : public NeoEsp8266UartBase
|
template<typename T_UARTFEATURE, typename T_UARTCONTEXT> class NeoEsp8266AsyncUart : public NeoEsp8266UartBase
|
||||||
{
|
{
|
||||||
@@ -348,6 +352,11 @@ public:
|
|||||||
|
|
||||||
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
|
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
|
||||||
// implements the methods needed to operate as a NeoPixelBus method.
|
// implements the methods needed to operate as a NeoPixelBus method.
|
||||||
|
//
|
||||||
|
// T_SPEED - (NeoEsp8266UartSpeed*)
|
||||||
|
// T_BASE - (NeoEsp8266Uart | NeoEsp8266AsyncUart)
|
||||||
|
// T_INVERT - (NeoEsp8266UartNotInverted | NeoEsp8266UartInverted)
|
||||||
|
//
|
||||||
template<typename T_SPEED, typename T_BASE, typename T_INVERT>
|
template<typename T_SPEED, typename T_BASE, typename T_INVERT>
|
||||||
class NeoEsp8266UartMethodBase: public T_BASE
|
class NeoEsp8266UartMethodBase: public T_BASE
|
||||||
{
|
{
|
||||||
|
@@ -28,24 +28,67 @@ License along with NeoPixel. If not, see
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
// ESP32C3 I2S is not supported yet
|
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
|
|
||||||
static inline uint32_t getCycleCount(void)
|
static inline uint32_t getCycleCount(void)
|
||||||
{
|
{
|
||||||
uint32_t ccount;
|
uint32_t ccount;
|
||||||
|
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
__asm__ __volatile__("csrr %0,0x7e2":"=r" (ccount));
|
||||||
|
//ccount = esp_cpu_get_ccount();
|
||||||
|
#else
|
||||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||||
|
#endif
|
||||||
return ccount;
|
return ccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
|
void IRAM_ATTR neoEspBitBangWriteSpacingPixels(const uint8_t* pixels,
|
||||||
|
const uint8_t* end,
|
||||||
|
uint8_t pin,
|
||||||
|
uint32_t t0h,
|
||||||
|
uint32_t t1h,
|
||||||
|
uint32_t period,
|
||||||
|
size_t sizePixel,
|
||||||
|
uint32_t tSpacing,
|
||||||
|
bool invert)
|
||||||
{
|
{
|
||||||
const uint32_t pinRegister = _BV(pin);
|
uint32_t setValue = _BV(pin);
|
||||||
|
uint32_t clearValue = _BV(pin);
|
||||||
uint8_t mask = 0x80;
|
uint8_t mask = 0x80;
|
||||||
uint8_t subpix = *pixels++;
|
uint8_t subpix = *pixels++;
|
||||||
|
uint8_t element = 0;
|
||||||
uint32_t cyclesStart = 0; // trigger emediately
|
uint32_t cyclesStart = 0; // trigger emediately
|
||||||
uint32_t cyclesNext = 0;
|
uint32_t cyclesNext = 0;
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
volatile uint32_t* setRegister = &GPIO.out_w1ts.val;
|
||||||
|
volatile uint32_t* clearRegister = &GPIO.out_w1tc.val;
|
||||||
|
setValue = _BV(pin);
|
||||||
|
clearValue = _BV(pin);
|
||||||
|
#else
|
||||||
|
volatile uint32_t* setRegister = &GPIO.out_w1ts;
|
||||||
|
volatile uint32_t* clearRegister = &GPIO.out_w1tc;
|
||||||
|
#endif // defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
#else
|
||||||
|
uint32_t setRegister = PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS;
|
||||||
|
uint32_t clearRegister = PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TC_ADDRESS;
|
||||||
|
if (pin == 16)
|
||||||
|
{
|
||||||
|
setRegister = RTC_GPIO_OUT;
|
||||||
|
clearRegister = RTC_GPIO_OUT;
|
||||||
|
// reading AND writing RTC_GPIO_OUT is too slow inside the loop so
|
||||||
|
// we only do writing in the loop
|
||||||
|
clearValue = (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe);
|
||||||
|
setValue = clearValue | 1;
|
||||||
|
}
|
||||||
|
#endif // defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
|
if (invert)
|
||||||
|
{
|
||||||
|
std::swap(setRegister, clearRegister);
|
||||||
|
std::swap(setValue, clearValue);
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// do the checks here while we are waiting on time to pass
|
// do the checks here while we are waiting on time to pass
|
||||||
@@ -61,9 +104,9 @@ void IRAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint
|
|||||||
|
|
||||||
// set pin state
|
// set pin state
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
GPIO.out_w1ts = pinRegister;
|
*setRegister = setValue;
|
||||||
#else
|
#else
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
|
WRITE_PERI_REG(setRegister, setValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// wait for the LOW
|
// wait for the LOW
|
||||||
@@ -71,9 +114,9 @@ void IRAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint
|
|||||||
|
|
||||||
// reset pin start
|
// reset pin start
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
GPIO.out_w1tc = pinRegister;
|
*clearRegister = clearValue;
|
||||||
#else
|
#else
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
|
WRITE_PERI_REG(clearRegister, clearValue);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cyclesNext = cyclesStart;
|
cyclesNext = cyclesStart;
|
||||||
@@ -92,176 +135,22 @@ void IRAM_ATTR NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint
|
|||||||
// reset mask to first bit and get the next byte
|
// reset mask to first bit and get the next byte
|
||||||
mask = 0x80;
|
mask = 0x80;
|
||||||
subpix = *pixels++;
|
subpix = *pixels++;
|
||||||
|
|
||||||
|
// if pixel spacing is needed
|
||||||
|
if (tSpacing)
|
||||||
|
{
|
||||||
|
element++;
|
||||||
|
if (element == sizePixel)
|
||||||
|
{
|
||||||
|
element = 0;
|
||||||
|
|
||||||
|
// wait for pixel spacing
|
||||||
|
while ((getCycleCount() - cyclesNext) < tSpacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
void IRAM_ATTR NeoEspBitBangBase_send_pixels_pin16(uint8_t *pixels, uint8_t *end, uint32_t t0h, uint32_t t1h, uint32_t period)
|
|
||||||
{
|
|
||||||
uint8_t mask = 0x80;
|
|
||||||
uint8_t subpix = *pixels++;
|
|
||||||
uint32_t cyclesStart = 0; // trigger emediately
|
|
||||||
uint32_t cyclesNext = 0;
|
|
||||||
|
|
||||||
// reading and writing RTC_GPIO_OUT is too slow inside the loop
|
|
||||||
uint32_t gpio_clear = (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe);
|
|
||||||
uint32_t gpio_set = gpio_clear | 1;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// do the checks here while we are waiting on time to pass
|
|
||||||
uint32_t cyclesBit = t0h;
|
|
||||||
if (subpix & mask)
|
|
||||||
{
|
|
||||||
cyclesBit = t1h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// after we have done as much work as needed for this next bit
|
|
||||||
// now wait for the HIGH
|
|
||||||
while (((cyclesStart = getCycleCount()) - cyclesNext) < period);
|
|
||||||
|
|
||||||
// set pin state
|
|
||||||
WRITE_PERI_REG(RTC_GPIO_OUT, gpio_set);
|
|
||||||
|
|
||||||
// wait for the LOW
|
|
||||||
while ((getCycleCount() - cyclesStart) < cyclesBit);
|
|
||||||
|
|
||||||
// reset pin start
|
|
||||||
WRITE_PERI_REG(RTC_GPIO_OUT, gpio_clear);
|
|
||||||
|
|
||||||
cyclesNext = cyclesStart;
|
|
||||||
|
|
||||||
// next bit
|
|
||||||
mask >>= 1;
|
|
||||||
if (mask == 0)
|
|
||||||
{
|
|
||||||
// no more bits to send in this byte
|
|
||||||
// check for another byte
|
|
||||||
if (pixels >= end)
|
|
||||||
{
|
|
||||||
// no more bytes to send so stop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// reset mask to first bit and get the next byte
|
|
||||||
mask = 0x80;
|
|
||||||
subpix = *pixels++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
|
|
||||||
void IRAM_ATTR NeoEspBitBangBase_send_pixels_inv(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
|
|
||||||
{
|
|
||||||
const uint32_t pinRegister = _BV(pin);
|
|
||||||
uint8_t mask = 0x80;
|
|
||||||
uint8_t subpix = *pixels++;
|
|
||||||
uint32_t cyclesStart = 0; // trigger emediately
|
|
||||||
uint32_t cyclesNext = 0;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// do the checks here while we are waiting on time to pass
|
|
||||||
uint32_t cyclesBit = t0h;
|
|
||||||
if (subpix & mask)
|
|
||||||
{
|
|
||||||
cyclesBit = t1h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// after we have done as much work as needed for this next bit
|
|
||||||
// now wait for the HIGH
|
|
||||||
while (((cyclesStart = getCycleCount()) - cyclesNext) < period);
|
|
||||||
|
|
||||||
// set pin state
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
|
||||||
GPIO.out_w1tc = pinRegister;
|
|
||||||
#else
|
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// wait for the LOW
|
|
||||||
while ((getCycleCount() - cyclesStart) < cyclesBit);
|
|
||||||
|
|
||||||
// reset pin start
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
|
||||||
GPIO.out_w1ts = pinRegister;
|
|
||||||
#else
|
|
||||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cyclesNext = cyclesStart;
|
|
||||||
|
|
||||||
// next bit
|
|
||||||
mask >>= 1;
|
|
||||||
if (mask == 0)
|
|
||||||
{
|
|
||||||
// no more bits to send in this byte
|
|
||||||
// check for another byte
|
|
||||||
if (pixels >= end)
|
|
||||||
{
|
|
||||||
// no more bytes to send so stop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// reset mask to first bit and get the next byte
|
|
||||||
mask = 0x80;
|
|
||||||
subpix = *pixels++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
void IRAM_ATTR NeoEspBitBangBase_send_pixels_inv_pin16(uint8_t *pixels, uint8_t *end, uint32_t t0h, uint32_t t1h, uint32_t period)
|
|
||||||
{
|
|
||||||
uint8_t mask = 0x80;
|
|
||||||
uint8_t subpix = *pixels++;
|
|
||||||
uint32_t cyclesStart = 0; // trigger emediately
|
|
||||||
uint32_t cyclesNext = 0;
|
|
||||||
|
|
||||||
// reading and writing RTC_GPIO_OUT is too slow inside the loop
|
|
||||||
uint32_t gpio_clear = (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe);
|
|
||||||
uint32_t gpio_set = gpio_clear | 1;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
// do the checks here while we are waiting on time to pass
|
|
||||||
uint32_t cyclesBit = t0h;
|
|
||||||
if (subpix & mask)
|
|
||||||
{
|
|
||||||
cyclesBit = t1h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// after we have done as much work as needed for this next bit
|
|
||||||
// now wait for the HIGH
|
|
||||||
while (((cyclesStart = getCycleCount()) - cyclesNext) < period);
|
|
||||||
|
|
||||||
// set pin state
|
|
||||||
WRITE_PERI_REG(RTC_GPIO_OUT, gpio_clear);
|
|
||||||
|
|
||||||
// wait for the LOW
|
|
||||||
while ((getCycleCount() - cyclesStart) < cyclesBit);
|
|
||||||
|
|
||||||
// reset pin start
|
|
||||||
WRITE_PERI_REG(RTC_GPIO_OUT, gpio_set);
|
|
||||||
|
|
||||||
cyclesNext = cyclesStart;
|
|
||||||
|
|
||||||
// next bit
|
|
||||||
mask >>= 1;
|
|
||||||
if (mask == 0)
|
|
||||||
{
|
|
||||||
// no more bits to send in this byte
|
|
||||||
// check for another byte
|
|
||||||
if (pixels >= end)
|
|
||||||
{
|
|
||||||
// no more bytes to send so stop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// reset mask to first bit and get the next byte
|
|
||||||
mask = 0x80;
|
|
||||||
subpix = *pixels++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
#endif // !defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
#endif // defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
#endif // defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
|
@@ -28,221 +28,169 @@ License along with NeoPixel. If not, see
|
|||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
// ESP32C3 I2S is not supported yet
|
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
#include <eagle_soc.h>
|
#include <eagle_soc.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||||
|
#define CYCLES_LOOPTEST (1) // adjustment due to loop exit test instruction cycles
|
||||||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||||
|
#define CYCLES_LOOPTEST (2) // adjustment due to loop exit test instruction cycles
|
||||||
|
#else
|
||||||
#define CYCLES_LOOPTEST (4) // adjustment due to loop exit test instruction cycles
|
#define CYCLES_LOOPTEST (4) // adjustment due to loop exit test instruction cycles
|
||||||
|
#endif
|
||||||
|
|
||||||
class NeoEspSpeedWs2811
|
extern void neoEspBitBangWriteSpacingPixels(const uint8_t* pixels,
|
||||||
|
const uint8_t* end,
|
||||||
|
uint8_t pin,
|
||||||
|
uint32_t t0h,
|
||||||
|
uint32_t t1h,
|
||||||
|
uint32_t period,
|
||||||
|
size_t sizePixel,
|
||||||
|
uint32_t tSpacing,
|
||||||
|
bool invert);
|
||||||
|
|
||||||
|
|
||||||
|
class NeoEspNotInverted
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint8_t IdleLevel = LOW;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NeoEspInverted
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint8_t IdleLevel = HIGH;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NeoEspBitBangSpeedWs2811
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
|
const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
|
||||||
const static uint32_t T1H = (F_CPU / 1052632 - CYCLES_LOOPTEST); // 0.95us
|
const static uint32_t T1H = (F_CPU / 1052632 - CYCLES_LOOPTEST); // 0.95us
|
||||||
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 300;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NeoEspSpeedTm1814
|
class NeoEspBitBangSpeedWs2812x
|
||||||
{
|
|
||||||
public:
|
|
||||||
const static uint32_t T0H = (F_CPU / 2916666 - CYCLES_LOOPTEST); // 0.35us
|
|
||||||
const static uint32_t T1H = (F_CPU / 1666666 - CYCLES_LOOPTEST); // 0.75us
|
|
||||||
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspSpeedTm1829
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
|
|
||||||
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
|
||||||
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspSpeed800Mhz
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
|
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
|
||||||
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
||||||
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 300;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NeoEspSpeed400Mhz
|
class NeoEspBitBangSpeedSk6812
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
|
||||||
|
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
||||||
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 80;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tm1814 normal is inverted signal
|
||||||
|
class NeoEspBitBangSpeedTm1814
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t T0H = (F_CPU / 2916666 - CYCLES_LOOPTEST); // 0.35us
|
||||||
|
const static uint32_t T1H = (F_CPU / 1666666 - CYCLES_LOOPTEST); // 0.75us
|
||||||
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 200;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tm1829 normal is inverted signal
|
||||||
|
class NeoEspBitBangSpeedTm1829
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t T0H = (F_CPU / 3333333 - CYCLES_LOOPTEST); // 0.3us
|
||||||
|
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
||||||
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 200;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NeoEspBitBangSpeed800Kbps
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
|
||||||
|
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
||||||
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 50;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NeoEspBitBangSpeed400Kbps
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static uint32_t T0H = (F_CPU / 2000000 - CYCLES_LOOPTEST);
|
const static uint32_t T0H = (F_CPU / 2000000 - CYCLES_LOOPTEST);
|
||||||
const static uint32_t T1H = (F_CPU / 833333 - CYCLES_LOOPTEST);
|
const static uint32_t T1H = (F_CPU / 833333 - CYCLES_LOOPTEST);
|
||||||
const static uint32_t Period = (F_CPU / 400000 - CYCLES_LOOPTEST);
|
const static uint32_t Period = (F_CPU / 400000 - CYCLES_LOOPTEST);
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 50;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NeoEspSpeedApa106
|
class NeoEspBitBangSpeedApa106
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static uint32_t T0H = (F_CPU / 2857143 - CYCLES_LOOPTEST); // 0.35us
|
const static uint32_t T0H = (F_CPU / 2857143 - CYCLES_LOOPTEST); // 0.35us
|
||||||
const static uint32_t T1H = (F_CPU / 740741 - CYCLES_LOOPTEST); // 1.35
|
const static uint32_t T1H = (F_CPU / 740741 - CYCLES_LOOPTEST); // 1.35
|
||||||
const static uint32_t Period = (F_CPU / 606061 - CYCLES_LOOPTEST); // 1.65us
|
const static uint32_t Period = (F_CPU / 606061 - CYCLES_LOOPTEST); // 1.65us
|
||||||
|
|
||||||
|
static const uint32_t ResetTimeUs = 50;
|
||||||
|
const static uint32_t TInterPixel = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void NeoEspBitBangBase_send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period);
|
class NeoEspBitBangSpeedIntertek
|
||||||
extern void NeoEspBitBangBase_send_pixels_inv(uint8_t *pixels, uint8_t *end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period);
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
extern void NeoEspBitBangBase_send_pixels_pin16(uint8_t *pixels, uint8_t *end, uint32_t t0h, uint32_t t1h, uint32_t period);
|
|
||||||
extern void NeoEspBitBangBase_send_pixels_inv_pin16(uint8_t *pixels, uint8_t *end, uint32_t t0h, uint32_t t1h, uint32_t period);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class NeoEspPinset
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static uint8_t IdleLevel = LOW;
|
const static uint32_t T0H = (F_CPU / 2500000 - CYCLES_LOOPTEST); // 0.4us
|
||||||
|
const static uint32_t T1H = (F_CPU / 1250000 - CYCLES_LOOPTEST); // 0.8us
|
||||||
|
const static uint32_t Period = (F_CPU / 800000 - CYCLES_LOOPTEST); // 1.25us per bit
|
||||||
|
|
||||||
inline static void send_pixels_impl(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
|
const static uint32_t ResetTimeUs = 12470;
|
||||||
|
const static uint32_t TInterPixel = (F_CPU / 50000); // 20us
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T_SPEED, typename T_INVERTED> class NeoEspBitBangEncode : public T_SPEED, public T_INVERTED
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void WritePixels(uint8_t pin,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t sizeData,
|
||||||
|
size_t sizePixel)
|
||||||
{
|
{
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
neoEspBitBangWriteSpacingPixels(data,
|
||||||
if (pin == 16)
|
data + sizeData,
|
||||||
NeoEspBitBangBase_send_pixels_pin16(pixels, end, t0h, t1h, period);
|
pin,
|
||||||
else
|
T_SPEED::T0H,
|
||||||
NeoEspBitBangBase_send_pixels(pixels, end, pin, t0h, t1h, period);
|
T_SPEED::T1H,
|
||||||
#else
|
T_SPEED::Period,
|
||||||
NeoEspBitBangBase_send_pixels(pixels, end, pin, t0h, t1h, period);
|
sizePixel,
|
||||||
#endif
|
T_SPEED::TInterPixel,
|
||||||
|
T_INVERTED::IdleLevel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class NeoEspPinsetInverted
|
template<typename T_ENCODER> class NeoEspBitBangMethodBase
|
||||||
{
|
|
||||||
public:
|
|
||||||
const static uint8_t IdleLevel = HIGH;
|
|
||||||
|
|
||||||
inline static void send_pixels_impl(uint8_t* pixels, uint8_t* end, uint8_t pin, uint32_t t0h, uint32_t t1h, uint32_t period)
|
|
||||||
{
|
|
||||||
#if defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
if (pin == 16)
|
|
||||||
NeoEspBitBangBase_send_pixels_inv_pin16(pixels, end, t0h, t1h, period);
|
|
||||||
else
|
|
||||||
NeoEspBitBangBase_send_pixels_inv(pixels, end, pin, t0h, t1h, period);
|
|
||||||
#else
|
|
||||||
NeoEspBitBangBase_send_pixels_inv(pixels, end, pin, t0h, t1h, period);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
|
|
||||||
{
|
|
||||||
T_PINSET::send_pixels_impl(pixels, end, pin, T_SPEED::T0H, T_SPEED::T1H, T_SPEED::Period);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeedWs2811 : public NeoEspBitBangBase<NeoEspSpeedWs2811, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 300;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeedWs2812x : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 300;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeedSk6812 : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 80;
|
|
||||||
};
|
|
||||||
|
|
||||||
// normal is inverted signal
|
|
||||||
class NeoEspBitBangSpeedTm1814 : public NeoEspBitBangBase<NeoEspSpeedTm1814, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 200;
|
|
||||||
};
|
|
||||||
|
|
||||||
// normal is inverted signal
|
|
||||||
class NeoEspBitBangSpeedTm1829 : public NeoEspBitBangBase<NeoEspSpeedTm1829, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 200;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeed800Kbps : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeed400Kbps : public NeoEspBitBangBase<NeoEspSpeed400Mhz, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangSpeedApa106 : public NeoEspBitBangBase<NeoEspSpeedApa106, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeedWs2811 : public NeoEspBitBangBase<NeoEspSpeedWs2811, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 300;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeedWs2812x : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 300;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeedSk6812 : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 80;
|
|
||||||
};
|
|
||||||
|
|
||||||
// normal is inverted signal, so inverted is normal
|
|
||||||
class NeoEspBitBangInvertedSpeedTm1814 : public NeoEspBitBangBase<NeoEspSpeedTm1814, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 200;
|
|
||||||
};
|
|
||||||
|
|
||||||
// normal is inverted signal, so inverted is normal
|
|
||||||
class NeoEspBitBangInvertedSpeedTm1829 : public NeoEspBitBangBase<NeoEspSpeedTm1829, NeoEspPinset>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 200;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeed800Kbps : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeed400Kbps : public NeoEspBitBangBase<NeoEspSpeed400Mhz, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
class NeoEspBitBangInvertedSpeedApa106 : public NeoEspBitBangBase<NeoEspSpeedApa106, NeoEspPinsetInverted>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const uint32_t ResetTimeUs = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangMethodBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef NeoNoSettings SettingsObject;
|
typedef NeoNoSettings SettingsObject;
|
||||||
|
|
||||||
NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
|
||||||
|
_sizePixel(elementSize),
|
||||||
_sizeData(pixelCount * elementSize + settingsSize),
|
_sizeData(pixelCount * elementSize + settingsSize),
|
||||||
_pin(pin)
|
_pin(pin)
|
||||||
{
|
{
|
||||||
@@ -263,12 +211,12 @@ public:
|
|||||||
{
|
{
|
||||||
uint32_t delta = micros() - _endTime;
|
uint32_t delta = micros() - _endTime;
|
||||||
|
|
||||||
return (delta >= T_SPEED::ResetTimeUs);
|
return (delta >= T_ENCODER::ResetTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
digitalWrite(_pin, T_PINSET::IdleLevel);
|
digitalWrite(_pin, T_ENCODER::IdleLevel);
|
||||||
|
|
||||||
_endTime = micros();
|
_endTime = micros();
|
||||||
}
|
}
|
||||||
@@ -288,7 +236,7 @@ public:
|
|||||||
|
|
||||||
// Need 100% focus on instruction timing
|
// Need 100% focus on instruction timing
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
delay(1); // required
|
// delay(1); // required ?
|
||||||
portMUX_TYPE updateMux = portMUX_INITIALIZER_UNLOCKED;
|
portMUX_TYPE updateMux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
portENTER_CRITICAL(&updateMux);
|
portENTER_CRITICAL(&updateMux);
|
||||||
@@ -296,7 +244,10 @@ public:
|
|||||||
noInterrupts();
|
noInterrupts();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
T_SPEED::send_pixels(_data, _data + _sizeData, _pin);
|
T_ENCODER::WritePixels(_pin,
|
||||||
|
_data,
|
||||||
|
_sizeData,
|
||||||
|
_sizePixel);
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
portEXIT_CRITICAL(&updateMux);
|
portEXIT_CRITICAL(&updateMux);
|
||||||
@@ -329,6 +280,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const size_t _sizePixel; // size of a pixel in _data
|
||||||
const size_t _sizeData; // Size of '_data' buffer below
|
const size_t _sizeData; // Size of '_data' buffer below
|
||||||
const uint8_t _pin; // output pin number
|
const uint8_t _pin; // output pin number
|
||||||
|
|
||||||
@@ -339,14 +291,15 @@ private:
|
|||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2811, NeoEspPinset> NeoEsp32BitBangWs2811Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2811, NeoEspNotInverted>> NeoEsp32BitBangWs2811Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp32BitBangWs2812xMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2812x, NeoEspNotInverted>> NeoEsp32BitBangWs2812xMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp32BitBangSk6812Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedSk6812, NeoEspNotInverted>> NeoEsp32BitBangSk6812Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp32BitBangTm1814Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1814, NeoEspInverted>> NeoEsp32BitBangTm1814Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1829, NeoEspPinsetInverted> NeoEsp32BitBangTm1829Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1829, NeoEspInverted>> NeoEsp32BitBangTm1829Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp32BitBang800KbpsMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed800Kbps, NeoEspNotInverted>> NeoEsp32BitBang800KbpsMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp32BitBang400KbpsMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed400Kbps, NeoEspNotInverted>> NeoEsp32BitBang400KbpsMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedApa106, NeoEspPinset> NeoEsp32BitBangApa106Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedApa106, NeoEspNotInverted>> NeoEsp32BitBangApa106Method;
|
||||||
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedIntertek, NeoEspNotInverted>> NeoEsp32BitBangIntertekMethod;
|
||||||
|
|
||||||
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
|
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
|
||||||
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
|
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
|
||||||
@@ -354,14 +307,15 @@ typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2816Method;
|
|||||||
typedef NeoEsp32BitBangTm1814Method NeoEsp32BitBangTm1914Method;
|
typedef NeoEsp32BitBangTm1814Method NeoEsp32BitBangTm1914Method;
|
||||||
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
|
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
|
||||||
|
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp32BitBangWs2811InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2811, NeoEspInverted>> NeoEsp32BitBangWs2811InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp32BitBangWs2812xInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2812x, NeoEspInverted>> NeoEsp32BitBangWs2812xInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp32BitBangSk6812InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedSk6812, NeoEspInverted>> NeoEsp32BitBangSk6812InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp32BitBangTm1814InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1814, NeoEspNotInverted>> NeoEsp32BitBangTm1814InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1829, NeoEspPinset> NeoEsp32BitBangTm1829InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1829, NeoEspNotInverted>> NeoEsp32BitBangTm1829InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp32BitBang800KbpsInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed800Kbps, NeoEspInverted>> NeoEsp32BitBang800KbpsInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp32BitBang400KbpsInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed400Kbps, NeoEspInverted>> NeoEsp32BitBang400KbpsInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedApa106, NeoEspPinsetInverted> NeoEsp32BitBangApa106InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedApa106, NeoEspInverted>> NeoEsp32BitBangApa106InvertedMethod;
|
||||||
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedIntertek, NeoEspInverted>> NeoEsp32BitBangIntertekInvertedMethod;
|
||||||
|
|
||||||
typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2813InvertedMethod;
|
typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2813InvertedMethod;
|
||||||
typedef NeoEsp32BitBang800KbpsInvertedMethod NeoEsp32BitBangWs2812InvertedMethod;
|
typedef NeoEsp32BitBang800KbpsInvertedMethod NeoEsp32BitBangWs2812InvertedMethod;
|
||||||
@@ -369,16 +323,17 @@ typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2816InvertedMethod
|
|||||||
typedef NeoEsp32BitBangTm1814InvertedMethod NeoEsp32BitBangTm1914InvertedMethod;
|
typedef NeoEsp32BitBangTm1814InvertedMethod NeoEsp32BitBangTm1914InvertedMethod;
|
||||||
typedef NeoEsp32BitBangSk6812InvertedMethod NeoEsp32BitBangLc8812InvertedMethod;
|
typedef NeoEsp32BitBangSk6812InvertedMethod NeoEsp32BitBangLc8812InvertedMethod;
|
||||||
|
|
||||||
#else
|
#else // defined(ARDUINO_ARCH_ESP8266)
|
||||||
|
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2811, NeoEspPinset> NeoEsp8266BitBangWs2811Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2811, NeoEspNotInverted>> NeoEsp8266BitBangWs2811Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp8266BitBangWs2812xMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2812x, NeoEspNotInverted>> NeoEsp8266BitBangWs2812xMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp8266BitBangSk6812Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedSk6812, NeoEspNotInverted>> NeoEsp8266BitBangSk6812Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1814, NeoEspPinsetInverted> NeoEsp8266BitBangTm1814Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1814, NeoEspInverted>> NeoEsp8266BitBangTm1814Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedTm1829, NeoEspPinsetInverted> NeoEsp8266BitBangTm1829Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1829, NeoEspInverted>> NeoEsp8266BitBangTm1829Method;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp8266BitBang800KbpsMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed800Kbps, NeoEspNotInverted>> NeoEsp8266BitBang800KbpsMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp8266BitBang400KbpsMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed400Kbps, NeoEspNotInverted>> NeoEsp8266BitBang400KbpsMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedApa106, NeoEspPinset> NeoEsp8266BitBangApa106Method;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedApa106, NeoEspNotInverted>> NeoEsp8266BitBangApa106Method;
|
||||||
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedIntertek, NeoEspNotInverted>> NeoEsp8266BitBangIntertekMethod;
|
||||||
|
|
||||||
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
|
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
|
||||||
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
|
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
|
||||||
@@ -386,14 +341,15 @@ typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2816Method;
|
|||||||
typedef NeoEsp8266BitBangTm1814Method NeoEsp8266BitBangTm1914Method;
|
typedef NeoEsp8266BitBangTm1814Method NeoEsp8266BitBangTm1914Method;
|
||||||
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
|
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
|
||||||
|
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2811, NeoEspPinsetInverted> NeoEsp8266BitBangWs2811InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2811, NeoEspInverted>> NeoEsp8266BitBangWs2811InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp8266BitBangWs2812xInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedWs2812x, NeoEspInverted>> NeoEsp8266BitBangWs2812xInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp8266BitBangSk6812InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedSk6812, NeoEspInverted>> NeoEsp8266BitBangSk6812InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1814, NeoEspPinset> NeoEsp8266BitBangTm1814InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1814, NeoEspNotInverted>> NeoEsp8266BitBangTm1814InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedTm1829, NeoEspPinset> NeoEsp8266BitBangTm1829InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedTm1829, NeoEspNotInverted>> NeoEsp8266BitBangTm1829InvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang800KbpsInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed800Kbps, NeoEspInverted>> NeoEsp8266BitBang800KbpsInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang400KbpsInvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeed400Kbps, NeoEspInverted>> NeoEsp8266BitBang400KbpsInvertedMethod;
|
||||||
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedApa106, NeoEspPinsetInverted> NeoEsp8266BitBangApa106InvertedMethod;
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedApa106, NeoEspInverted>> NeoEsp8266BitBangApa106InvertedMethod;
|
||||||
|
typedef NeoEspBitBangMethodBase<NeoEspBitBangEncode<NeoEspBitBangSpeedIntertek, NeoEspInverted>> NeoEsp8266BitBangIntertekInvertedMethod;
|
||||||
|
|
||||||
typedef NeoEsp8266BitBangWs2812xInvertedMethod NeoEsp8266BitBangWs2813InvertedMethod;
|
typedef NeoEsp8266BitBangWs2812xInvertedMethod NeoEsp8266BitBangWs2813InvertedMethod;
|
||||||
typedef NeoEsp8266BitBang800KbpsInvertedMethod NeoEsp8266BitBangWs2812InvertedMethod;
|
typedef NeoEsp8266BitBang800KbpsInvertedMethod NeoEsp8266BitBangWs2812InvertedMethod;
|
||||||
@@ -401,9 +357,8 @@ typedef NeoEsp8266BitBangWs2812xInvertedMethod NeoEsp8266BitBangWs2816InvertedMe
|
|||||||
typedef NeoEsp8266BitBangTm1814InvertedMethod NeoEsp8266BitBangTm1914InvertedMethod;
|
typedef NeoEsp8266BitBangTm1814InvertedMethod NeoEsp8266BitBangTm1914InvertedMethod;
|
||||||
typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMethod;
|
typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMethod;
|
||||||
|
|
||||||
#endif
|
#endif // defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
// ESP bitbang doesn't have defaults and should avoided except for testing
|
// ESP bitbang doesn't have defaults and should avoided except for testing
|
||||||
|
|
||||||
#endif // !defined(CONFIG_IDF_TARGET_ESP32C3)
|
|
||||||
#endif // defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
#endif // defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
|
Reference in New Issue
Block a user