Invert support (#296)

* Esp8266Dma and Esp32Rmt

* EspBitBang

* Esp21I2s Invert Support

* esp8266 uart
This commit is contained in:
Michael Miller
2019-09-28 10:34:52 -07:00
committed by GitHub
parent 060c111782
commit 5ca0d58dce
10 changed files with 696 additions and 289 deletions
+11 -11
View File
@@ -201,7 +201,7 @@ void i2sSetDac(uint8_t bus_num, bool right, bool left) {
return;
}
i2sSetPins(bus_num, -1, -1, -1, -1);
i2sSetPins(bus_num, -1, -1, -1, -1, false);
I2S[bus_num].bus->conf2.lcd_en = 1;
I2S[bus_num].bus->conf.tx_right_first = 0;
I2S[bus_num].bus->conf2.camera_en = 0;
@@ -216,7 +216,7 @@ void i2sSetDac(uint8_t bus_num, bool right, bool left) {
}
}
void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in) {
void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in, bool invert) {
if (bus_num > 1) {
return;
}
@@ -228,42 +228,42 @@ void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in) {
if (ws >= 0) {
if (I2S[bus_num].ws != ws) {
if (I2S[bus_num].ws >= 0) {
gpio_matrix_out(I2S[bus_num].ws, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].ws, 0x100, invert, false);
}
I2S[bus_num].ws = ws;
pinMode(ws, OUTPUT);
gpio_matrix_out(ws, bus_num?I2S1O_WS_OUT_IDX:I2S0O_WS_OUT_IDX, false, false);
gpio_matrix_out(ws, bus_num?I2S1O_WS_OUT_IDX:I2S0O_WS_OUT_IDX, invert, false);
}
} else if (I2S[bus_num].ws >= 0) {
gpio_matrix_out(I2S[bus_num].ws, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].ws, 0x100, invert, false);
I2S[bus_num].ws = -1;
}
if (bck >= 0) {
if (I2S[bus_num].bck != bck) {
if (I2S[bus_num].bck >= 0) {
gpio_matrix_out(I2S[bus_num].bck, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].bck, 0x100, invert, false);
}
I2S[bus_num].bck = bck;
pinMode(bck, OUTPUT);
gpio_matrix_out(bck, bus_num?I2S1O_BCK_OUT_IDX:I2S0O_BCK_OUT_IDX, false, false);
gpio_matrix_out(bck, bus_num?I2S1O_BCK_OUT_IDX:I2S0O_BCK_OUT_IDX, invert, false);
}
} else if (I2S[bus_num].bck >= 0) {
gpio_matrix_out(I2S[bus_num].bck, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].bck, 0x100, invert, false);
I2S[bus_num].bck = -1;
}
if (out >= 0) {
if (I2S[bus_num].out != out) {
if (I2S[bus_num].out >= 0) {
gpio_matrix_out(I2S[bus_num].out, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].out, 0x100, invert, false);
}
I2S[bus_num].out = out;
pinMode(out, OUTPUT);
gpio_matrix_out(out, bus_num?I2S1O_DATA_OUT23_IDX:I2S0O_DATA_OUT23_IDX, false, false);
gpio_matrix_out(out, bus_num?I2S1O_DATA_OUT23_IDX:I2S0O_DATA_OUT23_IDX, invert, false);
}
} else if (I2S[bus_num].out >= 0) {
gpio_matrix_out(I2S[bus_num].out, 0x100, false, false);
gpio_matrix_out(I2S[bus_num].out, 0x100, invert, false);
I2S[bus_num].out = -1;
}
+1 -1
View File
@@ -20,7 +20,7 @@ typedef enum {
void i2sInit(uint8_t bus_num, uint32_t bits_per_sample, uint32_t sample_rate, i2s_tx_chan_mod_t chan_mod, i2s_tx_fifo_mod_t fifo_mod, size_t dma_count, size_t dma_len);
void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in);
void i2sSetPins(uint8_t bus_num, int8_t out, int8_t ws, int8_t bck, int8_t in, bool invert);
void i2sSetDac(uint8_t bus_num, bool right, bool left);
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);
+45 -12
View File
@@ -88,7 +88,19 @@ public:
const static uint8_t I2sBusNumber = 1;
};
template<typename T_SPEED, typename T_BUS> class NeoEsp32I2sMethodBase
class NeoEsp32I2sNotInverted
{
public:
const static bool Inverted = false;
};
class NeoEsp32I2sInverted
{
public:
const static bool Inverted = true;
};
template<typename T_SPEED, typename T_BUS, typename T_INVERT> class NeoEsp32I2sMethodBase
{
public:
NeoEsp32I2sMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
@@ -136,7 +148,7 @@ public:
{
size_t dmaCount = (_i2sBufferSize + I2S_DMA_MAX_DATA_LEN - 1) / I2S_DMA_MAX_DATA_LEN;
i2sInit(T_BUS::I2sBusNumber, 16, T_SPEED::I2sSampleRate, I2S_CHAN_STEREO, I2S_FIFO_16BIT_DUAL, dmaCount, 0);
i2sSetPins(T_BUS::I2sBusNumber, _pin, -1, -1, -1);
i2sSetPins(T_BUS::I2sBusNumber, _pin, -1, -1, -1, T_INVERT::Inverted);
}
void Update(bool)
@@ -191,17 +203,29 @@ private:
}
};
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero> NeoEsp32I2s0Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero> NeoEsp32I2s0Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero> NeoEsp32I2s0800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero> NeoEsp32I2s0400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero> NeoEsp32I2s0Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sNotInverted> NeoEsp32I2s0Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne> NeoEsp32I2s1Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne> NeoEsp32I2s1Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne> NeoEsp32I2s1800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne> NeoEsp32I2s1400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne> NeoEsp32I2s1Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Ws2812xMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Sk6812Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1800KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1400KbpsMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sNotInverted> NeoEsp32I2s1Apa106Method;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Ws2812xInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Sk6812InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0800KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusZero, NeoEsp32I2sInverted> NeoEsp32I2s0Apa106InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedWs2812x, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Ws2812xInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedSk6812, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Sk6812InvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed800Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1800KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeed400Kbps, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1400KbpsInvertedMethod;
typedef NeoEsp32I2sMethodBase<NeoEsp32I2sSpeedApa106, NeoEsp32I2sBusOne, NeoEsp32I2sInverted> NeoEsp32I2s1Apa106InvertedMethod;
// I2s Bus 1 method is the default method for Esp32
typedef NeoEsp32I2s1Ws2812xMethod NeoWs2813Method;
@@ -214,4 +238,13 @@ typedef NeoEsp32I2s1Apa106Method NeoApa106Method;
typedef NeoEsp32I2s1Ws2812xMethod Neo800KbpsMethod;
typedef NeoEsp32I2s1400KbpsMethod Neo400KbpsMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2813InvertedMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod NeoWs2812xInvertedMethod;
typedef NeoEsp32I2s1800KbpsInvertedMethod NeoWs2812InvertedMethod;
typedef NeoEsp32I2s1Sk6812InvertedMethod NeoSk6812InvertedMethod;
typedef NeoEsp32I2s1Sk6812InvertedMethod NeoLc8812InvertedMethod;
typedef NeoEsp32I2s1Apa106InvertedMethod NeoApa106InvertedMethod;
typedef NeoEsp32I2s1Ws2812xInvertedMethod Neo800KbpsInvertedMethod;
typedef NeoEsp32I2s1400KbpsInvertedMethod Neo400KbpsInvertedMethod;
#endif
+120 -9
View File
@@ -46,7 +46,7 @@ extern "C"
#include <driver/rmt.h>
}
class NeoEsp32RmtSpeedBase
class NeoEsp32RmtSpeed
{
public:
// ClkDiv of 2 provides for good resolution and plenty of reset resolution; but
@@ -58,20 +58,41 @@ public:
{
return ns / NsPerRmtTick;
}
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 15) | (FromNs(nsHigh));
}
public:
protected:
const static uint32_t RmtCpu = 80000000L; // 80 mhz RMT clock
const static uint32_t NsPerSecond = 1000000000L;
const static uint32_t RmtTicksPerSecond = (RmtCpu / RmtClockDivider);
const static uint32_t NsPerRmtTick = (NsPerSecond / RmtTicksPerSecond); // about 25
};
class NeoEsp32RmtSpeedBase : public NeoEsp32RmtSpeed
{
public:
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 15) | (FromNs(nsHigh));
}
const static rmt_idle_level_t IdleLevel = RMT_IDLE_LEVEL_LOW;
};
class NeoEsp32RmtInvertedSpeedBase : public NeoEsp32RmtSpeed
{
public:
// this is used rather than the rmt_item32_t as you can't correctly initialize
// it as a static constexpr within the template
inline constexpr static uint32_t Item32Val(uint16_t nsHigh, uint16_t nsLow)
{
return (FromNs(nsLow) << 16) | (1 << 31) | (FromNs(nsHigh));
}
const static rmt_idle_level_t IdleLevel = RMT_IDLE_LEVEL_HIGH;
};
class NeoEsp32RmtSpeedWs2812x : public NeoEsp32RmtSpeedBase
{
public:
@@ -112,6 +133,46 @@ public:
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtInvertedSpeedWs2812x : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(300000); // 300us
};
class NeoEsp32RmtInvertedSpeedSk6812 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(80000); // 80us
};
class NeoEsp32RmtInvertedSpeed800Kbps : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 850);
const static uint32_t RmtBit1 = Item32Val(800, 450);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtInvertedSpeed400Kbps : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(800, 1700);
const static uint32_t RmtBit1 = Item32Val(1600, 900);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtInvertedSpeedApa106 : public NeoEsp32RmtInvertedSpeedBase
{
public:
const static uint32_t RmtBit0 = Item32Val(400, 1250);
const static uint32_t RmtBit1 = Item32Val(1250, 400);
const static uint16_t RmtDurationReset = FromNs(50000); // 50us
};
class NeoEsp32RmtChannel0
{
public:
@@ -204,7 +265,7 @@ public:
config.tx_config.loop_en = false;
config.tx_config.idle_output_en = true;
config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
config.tx_config.idle_level = T_SPEED::IdleLevel;
config.tx_config.carrier_en = false;
config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
@@ -316,6 +377,7 @@ private:
}
};
// normal
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812Method;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel0> NeoEsp32Rmt0Apa106Method;
@@ -364,6 +426,55 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedApa106, NeoEsp32RmtChannel7> NeoEs
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7800KbpsMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7400KbpsMethod;
// inverted
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel0> NeoEsp32Rmt0Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel0> NeoEsp32Rmt0Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel0> NeoEsp32Rmt0Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel0> NeoEsp32Rmt0400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel1> NeoEsp32Rmt1Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel1> NeoEsp32Rmt1Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel1> NeoEsp32Rmt1Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel1> NeoEsp32Rmt1400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel2> NeoEsp32Rmt2Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel2> NeoEsp32Rmt2Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel2> NeoEsp32Rmt2Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel2> NeoEsp32Rmt2400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel3> NeoEsp32Rmt3Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel3> NeoEsp32Rmt3Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel3> NeoEsp32Rmt3Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel3> NeoEsp32Rmt3400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel4> NeoEsp32Rmt4Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel4> NeoEsp32Rmt4Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel4> NeoEsp32Rmt4Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel4> NeoEsp32Rmt4400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel5> NeoEsp32Rmt5Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel5> NeoEsp32Rmt5Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel5> NeoEsp32Rmt5Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel5> NeoEsp32Rmt5400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel6> NeoEsp32Rmt6Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel6> NeoEsp32Rmt6Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel6> NeoEsp32Rmt6Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel6> NeoEsp32Rmt6400KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedWs2812x, NeoEsp32RmtChannel7> NeoEsp32Rmt7Ws2812xInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedSk6812, NeoEsp32RmtChannel7> NeoEsp32Rmt7Sk6812InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeedApa106, NeoEsp32RmtChannel7> NeoEsp32Rmt7Apa106InvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed800Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtInvertedSpeed400Kbps, NeoEsp32RmtChannel7> NeoEsp32Rmt7400KbpsInvertedMethod;
// RMT is NOT the default method for Esp32,
// you are required to use a specific channel listed above
+108 -15
View File
@@ -65,7 +65,43 @@ struct slc_queue_item
uint32 next_link_ptr;
};
class NeoEsp8266DmaSpeed800KbpsBase
class NeoEsp8266DmaSpeedBase
{
public:
static const uint8_t Level = 0x00;
static uint16_t Convert(uint8_t value)
{
const uint16_t bitpatterns[16] =
{
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
return bitpatterns[value];
}
};
class NeoEsp8266DmaInvertedSpeedBase
{
public:
static const uint8_t Level = 0xFF;
static uint16_t Convert(uint8_t value)
{
const uint16_t bitpatterns[16] =
{
0b0111011101110111, 0b0111011101110001, 0b0111011100010111, 0b0111011100010001,
0b0111000101110111, 0b0111000101110001, 0b0111000100010111, 0b0111000100010001,
0b0001011101110111, 0b0001011101110001, 0b0001011100010111, 0b0001011100010001,
0b0001000101110111, 0b0001000101110001, 0b0001000100010111, 0b0001000100010001,
};
return bitpatterns[value];
}
};
class NeoEsp8266DmaSpeed800KbpsBase : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 3;
@@ -91,7 +127,7 @@ public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaSpeed400Kbps
class NeoEsp8266DmaSpeed400Kbps : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 6;
@@ -100,7 +136,7 @@ public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaSpeedApa106
class NeoEsp8266DmaSpeedApa106 : public NeoEsp8266DmaSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 4;
@@ -109,6 +145,52 @@ public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeed800KbpsBase : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
};
class NeoEsp8266DmaInvertedSpeedWs2812x : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 300;
};
class NeoEsp8266DmaInvertedSpeedSk6812 : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 80;
};
class NeoEsp8266DmaInvertedSpeed800Kbps : public NeoEsp8266DmaInvertedSpeed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeed400Kbps : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 6;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaInvertedSpeedApa106 : public NeoEsp8266DmaInvertedSpeedBase
{
public:
const static uint32_t I2sClockDivisor = 4;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ByteSendTimeUs = 17; // us it takes to send a single pixel element
const static uint32_t ResetTimeUs = 50;
};
enum NeoDmaState
{
NeoDmaState_Idle,
@@ -134,11 +216,11 @@ public:
memset(_pixels, 0x00, _pixelsSize);
_i2sBuffer = (uint8_t*)malloc(_i2sBufferSize);
memset(_i2sBuffer, 0x00, _i2sBufferSize);
memset(_i2sBuffer, T_SPEED::Level, _i2sBufferSize);
// _i2sBuffer[0] = 0b11101000; // debug, 1 bit then 0 bit
memset(_i2sZeroes, 0x00, sizeof(_i2sZeroes));
memset(_i2sZeroes, T_SPEED::Level, sizeof(_i2sZeroes));
_is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize;
@@ -392,20 +474,12 @@ private:
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 = (uint16_t*)_i2sBuffer;
uint8_t* pPixelsEnd = _pixels + _pixelsSize;
for (uint8_t* pPixel = _pixels; pPixel < pPixelsEnd; pPixel++)
{
*(pDma++) = bitpatterns[((*pPixel) & 0x0f)];
*(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f];
*(pDma++) = T_SPEED::Convert(((*pPixel) & 0x0f));
*(pDma++) = T_SPEED::Convert(((*pPixel) >> 4) & 0x0f);
}
}
@@ -437,15 +511,24 @@ private:
};
template<typename T_SPEED>
NeoEsp8266DmaMethodBase<T_SPEED>* NeoEsp8266DmaMethodBase<T_SPEED>::s_this;
// normal
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedWs2812x> NeoEsp8266DmaWs2812xMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedSk6812> NeoEsp8266DmaSk6812Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed800Kbps> NeoEsp8266Dma800KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed400Kbps> NeoEsp8266Dma400KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedApa106> NeoEsp8266DmaApa106Method;
// inverted
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedWs2812x> NeoEsp8266DmaInvertedWs2812xMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedSk6812> NeoEsp8266DmaInvertedSk6812Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed800Kbps> NeoEsp8266DmaInverted800KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeed400Kbps> NeoEsp8266DmaInverted400KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaInvertedSpeedApa106> NeoEsp8266DmaInvertedApa106Method;
// Dma method is the default method for Esp8266
typedef NeoEsp8266DmaWs2812xMethod NeoWs2813Method;
typedef NeoEsp8266DmaWs2812xMethod NeoWs2812xMethod;
@@ -457,4 +540,14 @@ typedef NeoEsp8266DmaApa106Method NeoApa106Method;
typedef NeoEsp8266DmaWs2812xMethod Neo800KbpsMethod;
typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod;
// inverted
typedef NeoEsp8266DmaInvertedWs2812xMethod NeoWs2813InvertedMethod;
typedef NeoEsp8266DmaInvertedWs2812xMethod NeoWs2812xInvertedMethod;
typedef NeoEsp8266DmaInverted800KbpsMethod NeoWs2812InvertedMethod;
typedef NeoEsp8266DmaInvertedSk6812Method NeoSk6812InvertedMethod;
typedef NeoEsp8266DmaInvertedSk6812Method NeoLc8812InvertedMethod;
typedef NeoEsp8266DmaInvertedApa106Method NeoApa106InvertedMethod;
typedef NeoEsp8266DmaInvertedWs2812xMethod Neo800KbpsInvertedMethod;
typedef NeoEsp8266DmaInverted400KbpsMethod Neo400KbpsInvertedMethod;
#endif
+97 -35
View File
@@ -88,14 +88,19 @@ private:
class UartFeatureBase
{
protected:
static void ConfigUart(uint8_t uartNum)
static void ConfigUart(uint8_t uartNum, bool invert)
{
// clear all invert bits
USC0(uartNum) &= ~((1 << UCDTRI) | (1 << UCRTSI) | (1 << UCTXI) | (1 << UCDSRI) | (1 << UCCTSI) | (1 << UCRXI));
// Invert the TX voltage associated with logic level so:
// - A logic level 0 will generate a Vcc signal
// - A logic level 1 will generate a Gnd signal
USC0(uartNum) |= (1 << UCTXI);
if (!invert)
{
// For normal operations,
// Invert the TX voltage associated with logic level so:
// - A logic level 0 will generate a Vcc signal
// - A logic level 1 will generate a Gnd signal
USC0(uartNum) |= (1 << UCTXI);
}
}
};
@@ -106,11 +111,11 @@ class UartFeature0 : UartFeatureBase
{
public:
static const uint32_t Index = 0;
static void Init(uint32_t baud)
static void Init(uint32_t baud, bool invert)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index);
ConfigUart(Index, invert);
}
};
@@ -121,11 +126,11 @@ class UartFeature1 : UartFeatureBase
{
public:
static const uint32_t Index = 1;
static void Init(uint32_t baud)
static void Init(uint32_t baud, bool invert)
{
// Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1)
Serial1.begin(baud, SERIAL_6N1, SERIAL_TX_ONLY);
ConfigUart(Index);
ConfigUart(Index, invert);
}
};
@@ -179,9 +184,9 @@ protected:
}
}
void InitializeUart(uint32_t uartBaud)
void InitializeUart(uint32_t uartBaud, bool invert)
{
T_UARTFEATURE::Init(uartBaud);
T_UARTFEATURE::Init(uartBaud, invert);
}
void UpdateUart(bool)
@@ -237,9 +242,9 @@ protected:
free(_pixelsSending);
}
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud)
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud, bool invert)
{
T_UARTFEATURE::Init(uartBaud);
T_UARTFEATURE::Init(uartBaud, invert);
// attach the context, which will enable the ISR
_context.Attach(T_UARTFEATURE::Index);
@@ -319,9 +324,21 @@ public:
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
class NeoEsp8266UartNotInverted
{
public:
const static bool Inverted = false;
};
class NeoEsp8266UartInverted
{
public:
const static bool Inverted = true;
};
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
// implements the methods needed to operate as a NeoPixelBus method.
template<typename T_SPEED, typename T_BASE>
template<typename T_SPEED, typename T_BASE, typename T_INVERT>
class NeoEsp8266UartMethodBase: public T_BASE
{
public:
@@ -342,7 +359,7 @@ public:
void Initialize()
{
this->InitializeUart(T_SPEED::UartBaud);
this->InitializeUart(T_SPEED::UartBaud, T_INVERT::Inverted);
// Inverting logic levels can generate a phantom bit in the led strip bus
// We need to delay 50+ microseconds the output stream to force a data
@@ -384,48 +401,93 @@ private:
};
// uart 0
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0400KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart0400KbpsMethod;
typedef NeoEsp8266Uart0Ws2812xMethod NeoEsp8266Uart0Ws2813Method;
typedef NeoEsp8266Uart0800KbpsMethod NeoEsp8266Uart0Ws2812Method;
typedef NeoEsp8266Uart0Sk6812Method NeoEsp8266Uart0Lc8812Method;
// uart 1
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>> NeoEsp8266Uart1400KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartNotInverted> NeoEsp8266Uart1400KbpsMethod;
typedef NeoEsp8266Uart1Ws2812xMethod NeoEsp8266Uart1Ws2813Method;
typedef NeoEsp8266Uart1800KbpsMethod NeoEsp8266Uart1Ws2812Method;
typedef NeoEsp8266Uart1Sk6812Method NeoEsp8266Uart1Lc8812Method;
// uart 0 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart0400KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart0400KbpsMethod;
typedef NeoEsp8266AsyncUart0Ws2812xMethod NeoEsp8266AsyncUart0Ws2813Method;
typedef NeoEsp8266AsyncUart0800KbpsMethod NeoEsp8266AsyncUart0Ws2812Method;
typedef NeoEsp8266AsyncUart0Sk6812Method NeoEsp8266AsyncUart0Lc8812Method;
// uart 1 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>> NeoEsp8266AsyncUart1400KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Ws2812xMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Sk6812Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1Apa106Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartNotInverted> NeoEsp8266AsyncUart1400KbpsMethod;
typedef NeoEsp8266AsyncUart1Ws2812xMethod NeoEsp8266AsyncUart1Ws2813Method;
typedef NeoEsp8266AsyncUart1800KbpsMethod NeoEsp8266AsyncUart1Ws2812Method;
typedef NeoEsp8266AsyncUart1Sk6812Method NeoEsp8266AsyncUart1Lc8812Method;
// inverted
//
// uart 0
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart0400KbpsInvertedMethod;
typedef NeoEsp8266Uart0Ws2812xInvertedMethod NeoEsp8266Uart0Ws2813InvertedMethod;
typedef NeoEsp8266Uart0800KbpsInvertedMethod NeoEsp8266Uart0Ws2812InvertedMethod;
typedef NeoEsp8266Uart0Sk6812InvertedMethod NeoEsp8266Uart0Lc8812InvertedMethod;
// uart 1
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart<UartFeature1, NeoEsp8266UartContext>, NeoEsp8266UartInverted> NeoEsp8266Uart1400KbpsInvertedMethod;
typedef NeoEsp8266Uart1Ws2812xInvertedMethod NeoEsp8266Uart1Ws2813InvertedMethod;
typedef NeoEsp8266Uart1800KbpsInvertedMethod NeoEsp8266Uart1Ws2812InvertedMethod;
typedef NeoEsp8266Uart1Sk6812InvertedMethod NeoEsp8266Uart1Lc8812InvertedMethod;
// uart 0 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature0, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart0400KbpsInvertedMethod;
typedef NeoEsp8266AsyncUart0Ws2812xInvertedMethod NeoEsp8266AsyncUart0Ws2813InvertedMethod;
typedef NeoEsp8266AsyncUart0800KbpsInvertedMethod NeoEsp8266AsyncUart0Ws2812InvertedMethod;
typedef NeoEsp8266AsyncUart0Sk6812InvertedMethod NeoEsp8266AsyncUart0Lc8812InvertedMethod;
// uart 1 async
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Ws2812xInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Sk6812InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1Apa106InvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1800KbpsInvertedMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart<UartFeature1, NeoEsp8266UartInterruptContext>, NeoEsp8266UartInverted> NeoEsp8266AsyncUart1400KbpsInvertedMethod;
typedef NeoEsp8266AsyncUart1Ws2812xInvertedMethod NeoEsp8266AsyncUart1Ws2813InvertedMethod;
typedef NeoEsp8266AsyncUart1800KbpsInvertedMethod NeoEsp8266AsyncUart1Ws2812InvertedMethod;
typedef NeoEsp8266AsyncUart1Sk6812InvertedMethod NeoEsp8266AsyncUart1Lc8812InvertedMethod;
#endif
+192 -35
View File
@@ -28,58 +28,195 @@ License along with NeoPixel. If not, see
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#if defined(ARDUINO_ARCH_ESP8266)
#include <eagle_soc.h>
#endif
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
// for esp8266, due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are
// moved into a C file so the attribute will be applied correctly
// >> this may have been fixed and is no longer a requirement <<
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin);
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin);
static uint32_t _getCycleCount(void) __attribute__((always_inline));
class NeoEspBitBangSpeedWs2812x
static inline uint32_t _getCycleCount(void)
{
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
#define CYCLES_LOOPTEST (4) // adjustment due to loop exit test instruction cycles
class NeoEspSpeed800Mhz
{
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
};
class NeoEspSpeed400Mhz
{
public:
const static uint32_t T0H = (F_CPU / 2000000 - CYCLES_LOOPTEST);
const static uint32_t T1H = (F_CPU / 833333 - CYCLES_LOOPTEST);
const static uint32_t Period = (F_CPU / 400000 - CYCLES_LOOPTEST);
};
class NeoEspPinset
{
public:
const static uint8_t IdleLevel = LOW;
inline const static void setPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
}
inline const static void resetPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
}
};
class NeoEspPinsetInverted
{
public:
const static uint8_t IdleLevel = HIGH;
inline const static void setPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister);
#endif
}
inline const static void resetPin(const uint32_t pinRegister)
{
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
}
};
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangBase
{
public:
static void ICACHE_RAM_ATTR send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
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 = T_SPEED::T0H;
if (subpix & mask)
{
cyclesBit = T_SPEED::T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = _getCycleCount()) - cyclesNext) < T_SPEED::Period);
// set pin state
T_PINSET::setPin(pinRegister);
// wait for the LOW
while ((_getCycleCount() - cyclesStart) < cyclesBit);
// reset pin start
T_PINSET::resetPin(pinRegister);
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++;
}
}
}
};
class NeoEspBitBangSpeedWs2812x : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 300;
};
class NeoEspBitBangSpeedSk6812
class NeoEspBitBangSpeedSk6812 : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 80;
};
class NeoEspBitBangSpeed800Kbps
class NeoEspBitBangSpeed800Kbps : public NeoEspBitBangBase<NeoEspSpeed800Mhz, NeoEspPinset>
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangSpeed400Kbps
class NeoEspBitBangSpeed400Kbps : public NeoEspBitBangBase<NeoEspSpeed400Mhz, NeoEspPinset>
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_400(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED> class NeoEspBitBangMethodBase
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;
};
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;
};
template<typename T_SPEED, typename T_PINSET> class NeoEspBitBangMethodBase
{
public:
NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) :
@@ -108,7 +245,7 @@ public:
void Initialize()
{
digitalWrite(_pin, LOW);
digitalWrite(_pin, T_PINSET::IdleLevel);
_endTime = micros();
}
@@ -168,27 +305,47 @@ private:
#if defined(ARDUINO_ARCH_ESP32)
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x> NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812> NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp32BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp32BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp32BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp32BitBang400KbpsMethod;
typedef NeoEsp32BitBangWs2812xMethod NeoEsp32BitBangWs2813Method;
typedef NeoEsp32BitBang800KbpsMethod NeoEsp32BitBangWs2812Method;
typedef NeoEsp32BitBangSk6812Method NeoEsp32BitBangLc8812Method;
typedef NeoEsp32BitBang400KbpsMethod NeoEsp32BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp32BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp32BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp32BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp32BitBang400KbpsInvertedMethod;
typedef NeoEsp32BitBangWs2812xInvertedMethod NeoEsp32BitBangWs2813InvertedMethod;
typedef NeoEsp32BitBang800KbpsInvertedMethod NeoEsp32BitBangWs2812InvertedMethod;
typedef NeoEsp32BitBangSk6812InvertedMethod NeoEsp32BitBangLc8812InvertedMethod;
typedef NeoEsp32BitBang400KbpsInvertedMethod NeoEsp32BitBangApa106InvertedMethod;
#else
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x> NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812> NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2812x, NeoEspPinset> NeoEsp8266BitBangWs2812xMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedSk6812, NeoEspPinset> NeoEsp8266BitBangSk6812Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps, NeoEspPinset> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps, NeoEspPinset> NeoEsp8266BitBang400KbpsMethod;
typedef NeoEsp8266BitBangWs2812xMethod NeoEsp8266BitBangWs2813Method;
typedef NeoEsp8266BitBang800KbpsMethod NeoEsp8266BitBangWs2812Method;
typedef NeoEsp8266BitBangSk6812Method NeoEsp8266BitBangLc8812Method;
typedef NeoEsp8266BitBang400KbpsMethod NeoEsp8266BitBangApa106Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedWs2812x, NeoEspPinsetInverted> NeoEsp8266BitBangWs2812xInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeedSk6812, NeoEspPinsetInverted> NeoEsp8266BitBangSk6812InvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed800Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang800KbpsInvertedMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangInvertedSpeed400Kbps, NeoEspPinsetInverted> NeoEsp8266BitBang400KbpsInvertedMethod;
typedef NeoEsp8266BitBangWs2812xInvertedMethod NeoEsp8266BitBangWs2813InvertedMethod;
typedef NeoEsp8266BitBang800KbpsInvertedMethod NeoEsp8266BitBangWs2812InvertedMethod;
typedef NeoEsp8266BitBangSk6812InvertedMethod NeoEsp8266BitBangLc8812InvertedMethod;
typedef NeoEsp8266BitBang400KbpsInvertedMethod NeoEsp8266BitBangApa106InvertedMethod;
#endif
// ESP bitbang doesn't have defaults and should avoided except for testing
-170
View File
@@ -1,170 +0,0 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for Esp8266 and Esp32.
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
<http://www.gnu.org/licenses/>.
-------------------------------------------------------------------------*/
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP8266)
#include <eagle_soc.h>
#endif
// ESP32 doesn't define ICACHE_RAM_ATTR
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR IRAM_ATTR
#endif
static uint32_t _getCycleCount(void) __attribute__((always_inline));
static inline uint32_t _getCycleCount(void)
{
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
#define CYCLES_LOOPTEST (4) // adjustment due to loop exit test instruction cycles
#define CYCLES_800_T0H (F_CPU / 2500000 - CYCLES_LOOPTEST) // 0.4us
#define CYCLES_800_T1H (F_CPU / 1250000 - CYCLES_LOOPTEST) // 0.8us
#define CYCLES_800 (F_CPU / 800000 - CYCLES_LOOPTEST) // 1.25us per bit
#define CYCLES_400_T0H (F_CPU / 2000000 - CYCLES_LOOPTEST)
#define CYCLES_400_T1H (F_CPU / 833333 - CYCLES_LOOPTEST)
#define CYCLES_400 (F_CPU / 400000 - CYCLES_LOOPTEST)
void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
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 = CYCLES_800_T0H;
if (subpix & mask)
{
cyclesBit = CYCLES_800_T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_800);
// set high
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
// wait for the LOW
while ((_getCycleCount() - cyclesStart) < cyclesBit);
// set low
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_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++;
}
}
}
void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
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 = CYCLES_400_T0H;
if (subpix & mask)
{
cyclesBit = CYCLES_400_T1H;
}
// after we have done as much work as needed for this next bit
// now wait for the HIGH
while (((cyclesStart = _getCycleCount()) - cyclesNext) < CYCLES_400);
// set high
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1ts = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister);
#endif
// wait for the LOW
while ((_getCycleCount() - cyclesStart) < cyclesBit);
// set low
#if defined(ARDUINO_ARCH_ESP32)
GPIO.out_w1tc = pinRegister;
#else
GPIO_REG_WRITE(GPIO_OUT_W1TC_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++;
}
}
}
#endif