forked from Makuna/NeoPixelBus
C6 H2 P4 RMT
This commit is contained in:
@@ -27,7 +27,7 @@ License along with NeoPixel. If not, see
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
//----------------------------------------------------------
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -68,26 +68,24 @@ typedef NeoEsp32LcdX16Ws2816Method X16Ws2816Method;
|
||||
typedef NeoEsp32LcdX16Ws2812Method X16Ws2812Method;
|
||||
typedef NeoEsp32LcdX16Lc8812Method X16Lc8812Method;
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||
|
||||
//----------------------------------------------------------
|
||||
/* RMT doesnt have a X method yet
|
||||
typedef NeoEsp32Rmtx8Ws2812xMethod X8Ws2812xMethod;
|
||||
typedef NeoEsp32Rmtx8Ws2805Method X8Ws2805Method;
|
||||
typedef NeoEsp32Rmtx8Sk6812Method X8Sk6812Method;
|
||||
typedef NeoEsp32Rmtx8Tm1814Method X8Tm1814Method;
|
||||
typedef NeoEsp32Rmtx8Tm1829Method X8Tm1829Method;
|
||||
typedef NeoEsp32Rmtx8Tm1914Method X8Tm1914Method;
|
||||
typedef NeoEsp32Rmtx8800KbpsMethod X8800KbpsMethod;
|
||||
typedef NeoEsp32Rmtx8400KbpsMethod X8400KbpsMethod;
|
||||
typedef NeoEsp32Rmtx8Apa106Method X8Apa106Method;
|
||||
typedef NeoEsp32Rmtx8Ws2814Method X8Ws2814Method;
|
||||
typedef NeoEsp32Rmtx8Ws2813Method X8Ws2813Method;
|
||||
typedef NeoEsp32Rmtx8Ws2812dMethod X8Ws2812dMethod;
|
||||
typedef NeoEsp32Rmtx8Ws2811Method X8Ws2811Method;
|
||||
typedef NeoEsp32Rmtx8Ws2816Method X8Ws2816Method;
|
||||
typedef NeoEsp32Rmtx8Ws2812Method X8Ws2812Method;
|
||||
typedef NeoEsp32Rmtx8Lc8812Method X8Lc8812Method;
|
||||
*/
|
||||
typedef NeoEsp32RmtXWs2812xMethod XWs2812xMethod;
|
||||
typedef NeoEsp32RmtXWs2805Method XWs2805Method;
|
||||
typedef NeoEsp32RmtXSk6812Method XSk6812Method;
|
||||
typedef NeoEsp32RmtXTm1814Method XTm1814Method;
|
||||
typedef NeoEsp32RmtXTm1829Method XTm1829Method;
|
||||
typedef NeoEsp32RmtXTm1914Method XTm1914Method;
|
||||
typedef NeoEsp32RmtX800KbpsMethod X800KbpsMethod;
|
||||
typedef NeoEsp32RmtX400KbpsMethod X400KbpsMethod;
|
||||
typedef NeoEsp32RmtXApa106Method XApa106Method;
|
||||
typedef NeoEsp32RmtXWs2814Method XWs2814Method;
|
||||
typedef NeoEsp32RmtXWs2813Method XWs2813Method;
|
||||
typedef NeoEsp32RmtXWs2811Method XWs2811Method;
|
||||
typedef NeoEsp32RmtXWs2816Method XWs2816Method;
|
||||
typedef NeoEsp32RmtXLc8812Method XLc8812Method;
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
//----------------------------------------------------------
|
||||
@@ -127,6 +125,7 @@ typedef NeoEsp32I2s0X16Ws2816Method X16Ws2816Method;
|
||||
typedef NeoEsp32I2s0X16Ws2812Method X16Ws2812Method;
|
||||
typedef NeoEsp32I2s0X16Lc8812Method X16Lc8812Method;
|
||||
|
||||
|
||||
#else // plain old ESP32
|
||||
//----------------------------------------------------------
|
||||
#define NEO_X4_ALIAS
|
||||
@@ -192,7 +191,7 @@ typedef Rp2040x4Pio1Ws2812xMethod X4Ws2812xMethod;
|
||||
typedef Rp2040x4Pio1400KbpsMethod X4400KbpsMethod;
|
||||
#endif
|
||||
|
||||
// some plafforms do not have a native x4, so alias it to x8
|
||||
// some platforms do not have a native x4, so alias it to x8
|
||||
//
|
||||
#if defined(NEO_X4_ALIAS)
|
||||
typedef X8Ws2812xMethod X4Ws2813Method;
|
||||
|
@@ -28,7 +28,7 @@ License along with NeoPixel. If not, see
|
||||
|
||||
// ESP32 beyond C3 & S3 I2S is not supported yet
|
||||
// due to significant changes to interface
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C63) && !defined(CONFIG_IDF_TARGET_ESP32H6)
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||
|
||||
|
||||
extern "C"
|
||||
|
@@ -26,8 +26,9 @@ License along with NeoPixel. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
// ESP32C3/S3 I2S is not supported yet due to significant changes to interface
|
||||
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// ESP32 beyond C3 & S3 I2S is not supported yet
|
||||
// due to significant changes to interface
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
@@ -55,121 +55,6 @@ struct rmt_led_strip_encoder_t
|
||||
rmt_symbol_word_t reset_code;
|
||||
};
|
||||
|
||||
static size_t rmt_encode_led_strip(rmt_encoder_t* encoder, rmt_channel_handle_t channel, const void* primary_data, size_t data_size, rmt_encode_state_t* ret_state)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||
size_t encoded_symbols = 0;
|
||||
|
||||
switch (led_encoder->state)
|
||||
{
|
||||
case 0: // send RGB data
|
||||
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE)
|
||||
{
|
||||
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL)
|
||||
{
|
||||
// static_cast<AnimalFlags>(static_cast<int>(a) | static_cast<int>(b));
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
// fall-through
|
||||
case 1: // send reset code
|
||||
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||
sizeof(led_encoder->reset_code), &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE)
|
||||
{
|
||||
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_COMPLETE));
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL)
|
||||
{
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*ret_state = state;
|
||||
return encoded_symbols;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t* encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
delete led_encoder;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t* encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||
led_encoder->state = RMT_ENCODING_RESET;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t* config, rmt_encoder_handle_t* ret_encoder, uint32_t bit0, uint32_t bit1)
|
||||
{
|
||||
const char* TAG = "TEST_RMT"; //TODO: Remove later
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
rmt_led_strip_encoder_t* led_encoder = NULL;
|
||||
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
|
||||
rmt_bytes_encoder_config_t bytes_encoder_config;
|
||||
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||
rmt_symbol_word_t reset_code_config;
|
||||
|
||||
|
||||
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
led_encoder = new rmt_led_strip_encoder_t();
|
||||
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||
led_encoder->base.encode = rmt_encode_led_strip;
|
||||
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||
|
||||
bytes_encoder_config.bit0.val = bit0;
|
||||
bytes_encoder_config.bit1.val = bit1;
|
||||
|
||||
bytes_encoder_config.flags.msb_first = 1; // WS2812 transfer bit order: G7...G0R7...R0B7...B0 - TODO: more checks
|
||||
|
||||
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
|
||||
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
|
||||
|
||||
reset_code_config.level0 = 0;
|
||||
reset_code_config.duration0 = reset_ticks;
|
||||
reset_code_config.level1 = 0;
|
||||
reset_code_config.duration1 = reset_ticks;
|
||||
led_encoder->reset_code = reset_code_config;
|
||||
*ret_encoder = &led_encoder->base;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
// AddLog(2,"RMT:could not init led decoder");
|
||||
if (led_encoder)
|
||||
{
|
||||
if (led_encoder->bytes_encoder)
|
||||
{
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
}
|
||||
if (led_encoder->copy_encoder)
|
||||
{
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
}
|
||||
delete led_encoder;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NEOPIXELBUS_RMT_INT_FLAGS (ESP_INTR_FLAG_LOWMED)
|
||||
|
||||
|
||||
@@ -302,6 +187,121 @@ private:
|
||||
_dataSending = static_cast<uint8_t*>(malloc(_sizeData));
|
||||
// no need to initialize it, it gets overwritten on every send
|
||||
}
|
||||
|
||||
|
||||
static size_t rmt_encode_led_strip(rmt_encoder_t* encoder, rmt_channel_handle_t channel, const void* primary_data, size_t data_size, rmt_encode_state_t* ret_state)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||
size_t encoded_symbols = 0;
|
||||
|
||||
switch (led_encoder->state)
|
||||
{
|
||||
case 0: // send RGB data
|
||||
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE)
|
||||
{
|
||||
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL)
|
||||
{
|
||||
// static_cast<AnimalFlags>(static_cast<int>(a) | static_cast<int>(b));
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
// fall-through
|
||||
case 1: // send reset code
|
||||
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||
sizeof(led_encoder->reset_code), &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE)
|
||||
{
|
||||
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_COMPLETE));
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL)
|
||||
{
|
||||
state = static_cast<rmt_encode_state_t>(static_cast<uint8_t>(state) | static_cast<uint8_t>(RMT_ENCODING_MEM_FULL));
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*ret_state = state;
|
||||
return encoded_symbols;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t* encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
delete led_encoder;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t* encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t* led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||
led_encoder->state = RMT_ENCODING_RESET;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t* config, rmt_encoder_handle_t* ret_encoder, uint32_t bit0, uint32_t bit1)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
rmt_led_strip_encoder_t* led_encoder = NULL;
|
||||
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
|
||||
rmt_bytes_encoder_config_t bytes_encoder_config;
|
||||
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||
rmt_symbol_word_t reset_code_config;
|
||||
|
||||
|
||||
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
led_encoder = new rmt_led_strip_encoder_t();
|
||||
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||
led_encoder->base.encode = rmt_encode_led_strip;
|
||||
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||
|
||||
bytes_encoder_config.bit0.val = bit0;
|
||||
bytes_encoder_config.bit1.val = bit1;
|
||||
|
||||
bytes_encoder_config.flags.msb_first = 1; // WS2812 transfer bit order: G7...G0R7...R0B7...B0 - TODO: more checks
|
||||
|
||||
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, "TEST_RMT", "create bytes encoder failed");
|
||||
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, "TEST_RMT", "create copy encoder failed");
|
||||
|
||||
reset_code_config.level0 = 0;
|
||||
reset_code_config.duration0 = reset_ticks;
|
||||
reset_code_config.level1 = 0;
|
||||
reset_code_config.duration1 = reset_ticks;
|
||||
led_encoder->reset_code = reset_code_config;
|
||||
*ret_encoder = &led_encoder->base;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
// AddLog(2,"RMT:could not init led decoder");
|
||||
if (led_encoder)
|
||||
{
|
||||
if (led_encoder->bytes_encoder)
|
||||
{
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
}
|
||||
if (led_encoder->copy_encoder)
|
||||
{
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
}
|
||||
delete led_encoder;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// NOTE: While these are multi-instance auto channel selecting, there are limits
|
||||
@@ -315,6 +315,7 @@ private:
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811> NeoEsp32RmtXWs2811Method;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x> NeoEsp32RmtXWs2812xMethod;
|
||||
typedef NeoEsp32RmtXWs2812xMethod NeoEsp32RmtXWs2816Method;
|
||||
typedef NeoEsp32RmtXWs2812xMethod NeoEsp32RmtXWs2813Method;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2805> NeoEsp32RmtXWs2805Method;
|
||||
typedef NeoEsp32RmtXWs2805Method NeoEsp32RmtXWs2814Method;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812> NeoEsp32RmtXSk6812Method;
|
||||
@@ -333,6 +334,7 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps> NeoEsp32RmtX400KbpsMethod
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2811, NeoEsp32RmtInverted> NeoEsp32RmtXWs2811InvertedMethod;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2812x, NeoEsp32RmtInverted> NeoEsp32RmtXWs2812xInvertedMethod;
|
||||
typedef NeoEsp32RmtXWs2812xInvertedMethod NeoEsp32RmtXWs2816InvertedMethod;
|
||||
typedef NeoEsp32RmtXWs2812xInvertedMethod NeoEsp32RmtXWs2813InvertedMethod;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedWs2805, NeoEsp32RmtInverted> NeoEsp32RmtXWs2805InvertedMethod;
|
||||
typedef NeoEsp32RmtXWs2805InvertedMethod NeoEsp32RmtXWs2814InvertedMethod;
|
||||
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedSk6812, NeoEsp32RmtInverted> NeoEsp32RmtXSk6812InvertedMethod;
|
||||
@@ -350,7 +352,7 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtInverted> NeoE
|
||||
|
||||
// Normally I2s method is the default, defining NEOPIXEL_ESP32_RMT_DEFAULT
|
||||
// will switch to use RMT as the default method
|
||||
// The ESP32S2, ESP32S3, ESP32C3, ESP32C6 will allways default to RMT
|
||||
// The ESP32S2, ESP32S3, ESP32C3, ESP32C6 will always default to RMT
|
||||
|
||||
typedef NeoEsp32RmtXWs2805Method NeoWs2805Method;
|
||||
typedef NeoEsp32RmtXWs2811Method NeoWs2811Method;
|
||||
|
Reference in New Issue
Block a user