Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// If you set useSpiAlternatePins true, then these pins will be used instead. Any output-capable GPIO can be used.
const uint8_t DotClockPin = 18;
const uint8_t DotDataPin = 23;
const uint8_t MisoUnusedPin = -1;
const int8_t DotChipSelectPin = -1; // -1 means the chip select signal won't be output, freeing up one pin compared to useSpiAlternatePins=false

// for software bit bang (only use if neither SPI peripheral is available)
Expand Down Expand Up @@ -76,7 +77,7 @@ void setup()
#if (USE_DEFAULT_SPI_PORT == 1)
if (useSpiAlternatePins)
{
strip.Begin(DotClockPin, DotDataPin, DotDataPin, DotChipSelectPin);
strip.Begin(DotClockPin, MisoUnusedPin, DotDataPin, DotChipSelectPin);
}
else
{
Expand All @@ -90,7 +91,7 @@ void setup()
#if (USE_ALTERNATE_SPI_PORT == 1)
if (useSpiAlternatePins2)
{
strip2.Begin(DotClockPin2, DotDataPin2, DotDataPin2, DotChipSelectPin2);
strip2.Begin(DotClockPin2, MisoUnusedPin, DotDataPin2, DotChipSelectPin2);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
// If you set useSpiAlternatePins true, then these pins will be used instead. Any output-capable GPIO can be used.
const uint8_t DotClockPin = 18;
const uint8_t DotDataPin = 23;
const uint8_t MisoUnusedPin = -1;
const int8_t DotChipSelectPin = -1; // -1 means the chip select signal won't be output, freeing up one pin compared to useSpiAlternatePins=false

// for software bit bang (only use if neither SPI peripheral is available)
Expand Down Expand Up @@ -89,7 +90,7 @@ void setup()
#if (USE_DEFAULT_SPI_PORT == 1)
if (useSpiAlternatePins)
{
strip.Begin(DotClockPin, DotDataPin, DotDataPin, DotChipSelectPin);
strip.Begin(DotClockPin, MisoUnusedPin, DotDataPin, DotChipSelectPin);
}
else
{
Expand All @@ -103,7 +104,7 @@ void setup()
#if (USE_ALTERNATE_SPI_PORT == 1)
if (useSpiAlternatePins2)
{
strip2.Begin(DotClockPin2, DotDataPin2, DotDataPin2, DotChipSelectPin2);
strip2.Begin(DotClockPin2, MisoUnusedPin, DotDataPin2, DotChipSelectPin2);
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/internal/NeoMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ License along with NeoPixel. If not, see
#endif // ESP_IDF_VERSION_MAJOR < 5

// once we have a core3 i2s, then fix this
#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#include "methods/ESP/ESP32/Core_2_x/NeoEsp32I2sMethod.h"
#include "methods/ESP/ESP32/Core_2_x/NeoEsp32I2sXMethod.h"
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/internal/XMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ typedef NeoEsp32LcdX16Ws2812Method X16Ws2812Method;
typedef NeoEsp32LcdX16Lc8812Method X16Lc8812Method;


#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)

//----------------------------------------------------------
typedef NeoEsp32RmtXWs2812xMethod XWs2812xMethod;
Expand Down
6 changes: 4 additions & 2 deletions src/internal/methods/ESP/ESP32/Core_2_x/Esp32_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#include "stdlib.h"

// ESP32 C3, S3, C6, H2, and P4 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)
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
Expand Down Expand Up @@ -516,7 +516,9 @@ void i2sInit(uint8_t bus_num,
// conf1.rx_pcm_bypass = 1;

conf1.tx_stop_en = 0;
#if SOC_I2S_SUPPORTS_PCM_BYPASS
conf1.tx_pcm_bypass = 1;
#endif
i2s->conf1.val = conf1.val;
}

Expand Down Expand Up @@ -950,6 +952,6 @@ bool i2sGetClks(uint8_t bus_num,
}
#endif

#endif // !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#endif // !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2)

#endif // defined(ARDUINO_ARCH_ESP32)
Original file line number Diff line number Diff line change
Expand Up @@ -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(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)


extern "C"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32P4)

extern "C"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ License along with NeoPixel. If not, see

#if ESP_IDF_VERSION_MAJOR < 5

#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32H2)
#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(CONFIG_IDF_TARGET_ESP32C5) && !defined(CONFIG_IDF_TARGET_ESP32H2)

#include "../../../../NeoSettings.h"
#include "../../../../NeoBusChannel.h"
Expand Down
8 changes: 7 additions & 1 deletion src/internal/methods/ESP/ESP32/NeoEsp32LcdXMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,13 @@ class NeoEspLcdMonoBuffContext
.sibling_chan = NULL,
.direction = GDMA_CHANNEL_DIRECTION_TX,
.flags = {.reserve_sibling = 0}};
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
gdma_new_ahb_channel(&dma_chan_config, &_dmaChannel);
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4
gdma_new_axi_channel(&dma_chan_config, &_dmaChannel);
#else
gdma_new_channel(&dma_chan_config, &_dmaChannel);
#endif
gdma_connect(_dmaChannel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0));
gdma_strategy_config_t strategy_config = {.owner_check = false,
.auto_update_desc = false};
Expand Down Expand Up @@ -546,7 +552,7 @@ class NeoEsp32LcdMuxBus

uint8_t muxIdx = LCD_DATA_OUT0_IDX + _muxId;
esp_rom_gpio_connect_out_signal(pin, muxIdx, invert, false);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin], PIN_FUNC_GPIO);
gpio_set_drive_capability((gpio_num_t)pin, (gpio_drive_cap_t)3);
}

Expand Down
8 changes: 5 additions & 3 deletions src/internal/methods/ESP/ESP32/NeoEsp32RmtXMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ extern "C"
#include "esp_check.h"
}

static const char *TAG = "led_strip_rmt"; // TODO: Remove all TAG log stuff

struct led_strip_encoder_config_t
{
uint32_t resolution; /*!< Encoder resolution, in Hz */
Expand Down Expand Up @@ -279,7 +281,7 @@ template<typename T_SPEED, typename T_INVERTED = NeoEsp32RmtNotInverted> class N
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(&copy_encoder_config, &led_encoder->copy_encoder), err, "TEST_RMT", "create copy encoder failed");

Expand Down Expand Up @@ -355,7 +357,7 @@ typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeedGs1903, NeoEsp32RmtInverted> NeoEs
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed800Kbps, NeoEsp32RmtInverted> NeoEsp32RmtX800KbpsInvertedMethod;
typedef NeoEsp32RmtMethodBase<NeoEsp32RmtSpeed400Kbps, NeoEsp32RmtInverted> NeoEsp32RmtX400KbpsInvertedMethod;

#if defined(NEOPIXEL_ESP32_RMT_DEFAULT) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32S3)
#if defined(NEOPIXEL_ESP32_RMT_DEFAULT) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32S3)

// Normally I2s method is the default, defining NEOPIXEL_ESP32_RMT_DEFAULT
// will switch to use RMT as the default method
Expand Down Expand Up @@ -390,6 +392,6 @@ typedef NeoEsp32RmtXWs2812xInvertedMethod Neo800KbpsInvertedMethod;
typedef NeoEsp32RmtX400KbpsInvertedMethod Neo400KbpsInvertedMethod;


#endif // defined(NEOPIXEL_ESP32_RMT_DEFAULT) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
#endif // defined(NEOPIXEL_ESP32_RMT_DEFAULT) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5)

#endif
2 changes: 1 addition & 1 deletion src/internal/methods/ESP/ESP8266/NeoEsp8266UartMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ License along with NeoPixel. If not, see
#ifdef ARDUINO_ARCH_ESP8266

#include <Arduino.h>
#include "../NeoSettings.h"
#include "../../../NeoSettings.h"
#include "NeoEsp8266UartMethod.h"
#include <utility>
extern "C"
Expand Down
15 changes: 8 additions & 7 deletions src/internal/methods/ESP/NeoEspBitBangMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static inline uint32_t getCycleCount(void)
{
uint32_t ccount;

#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
__asm__ __volatile__("csrr %0,0x7e2":"=r" (ccount));
//ccount = esp_cpu_get_ccount();
#else
Expand All @@ -46,7 +46,8 @@ static inline uint32_t getCycleCount(void)
}

// Interrupt lock class, used for RAII interrupt disabling
class InterruptLock {
class InterruptLock
{
#if defined(ARDUINO_ARCH_ESP32)
portMUX_TYPE updateMux;
#endif
Expand All @@ -61,7 +62,7 @@ class InterruptLock {
}

inline void unlock()
{
{
#if defined(ARDUINO_ARCH_ESP32)
portEXIT_CRITICAL(&updateMux);
#else
Expand All @@ -76,12 +77,12 @@ class InterruptLock {
unlock();
lock();
}

inline InterruptLock()
#if defined(ARDUINO_ARCH_ESP32)
: updateMux(portMUX_INITIALIZER_UNLOCKED)
#endif
{
{
lock();
}

Expand Down Expand Up @@ -114,7 +115,7 @@ bool IRAM_ATTR neoEspBitBangWriteSpacingPixels(const uint8_t* pixels,
volatile uint32_t* setRegister;
volatile uint32_t* clearRegister;

#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4)
if (pin < 32)
{
setRegister = &GPIO.out_w1ts.val;
Expand All @@ -138,7 +139,7 @@ bool IRAM_ATTR neoEspBitBangWriteSpacingPixels(const uint8_t* pixels,
setRegister = &GPIO.out1_w1ts.val;
clearRegister = &GPIO.out1_w1tc.val;
}
#endif // defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2)
#endif // defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) || defined(CONFIG_IDF_TARGET_ESP32H2)

#else // just ESP8266
uint32_t setRegister = PERIPHS_GPIO_BASEADDR + GPIO_OUT_W1TS_ADDRESS;
Expand Down
16 changes: 16 additions & 0 deletions src/internal/methods/Rp2040/NeoRp2040PioInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,28 @@ class NeoRp2040PioInstance1
const PIO Instance;
};

#if NUM_PIOS == 3
class NeoRp2040PioInstance2
{
public:
NeoRp2040PioInstance2() :
Instance(pio2)
{};

const PIO Instance;
};
#endif

// dynamic channel support
class NeoRp2040PioInstanceN
{
public:
NeoRp2040PioInstanceN(NeoBusChannel channel) :
#if NUM_PIOS == 2
Instance(channel == NeoBusChannel_0 ? pio0 : pio1)
#elif NUM_PIOS == 3
Instance(channel == NeoBusChannel_0 ? pio0 : (channel == NeoBusChannel_1 ? pio1 : pio2))
#endif
{
}
NeoRp2040PioInstanceN() = delete; // no default constructor
Expand Down
17 changes: 14 additions & 3 deletions src/internal/methods/Rp2040/NeoRp2040PioMonoProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,12 @@ class NeoRp2040PioMonoProgram
public:
static inline uint add(PIO pio_instance)
{
size_t index = (pio_instance == pio0) ? 0 : 1;
size_t index =
#if NUM_PIOS == 2
(pio_instance == pio0) ? 0 : 1;
#elif NUM_PIOS == 3
(pio_instance == pio0) ? 0 : (pio_instance == pio1 ? 1 : 2);
#endif
if (s_loadedOffset[index] == c_ProgramNotLoaded)
{
assert(pio_can_add_program(pio_instance, &T_CADENCE::program));
Expand Down Expand Up @@ -203,10 +208,16 @@ class NeoRp2040PioMonoProgram
}

private:
static uint s_loadedOffset[2]; // singlet instance of loaded program, one for each PIO hardware unit
static uint s_loadedOffset[NUM_PIOS]; // singlet instance of loaded program, one for each PIO hardware unit
};

template<typename T_CADENCE>
uint NeoRp2040PioMonoProgram<T_CADENCE>::s_loadedOffset[] = {c_ProgramNotLoaded, c_ProgramNotLoaded};
uint NeoRp2040PioMonoProgram<T_CADENCE>::s_loadedOffset[] =
#if NUM_PIOS == 2
{c_ProgramNotLoaded, c_ProgramNotLoaded};
#elif NUM_PIOS == 3
{c_ProgramNotLoaded, c_ProgramNotLoaded, c_ProgramNotLoaded};
#endif


#endif
38 changes: 36 additions & 2 deletions src/internal/methods/Rp2040/NeoRp2040x4Method.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ class NeoRp2040x4MethodBase
if (_sizeData % 4 == 0)
{
// data is 4 byte aligned in size,
// use a 32 bit fifo word for effeciency
// use a 32 bit fifo word for efficiency
fifoWordBits = 32;
}
else if (_sizeData % 2 == 0)
{
// data is 2 byte aligned in size,
// use a 16 bit fifo word for effeciency
// use a 16 bit fifo word for efficiency
fifoWordBits = 16;
}

Expand Down Expand Up @@ -364,6 +364,23 @@ typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed800Kbps, NeoRp2040PioInstance1> R
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed400Kbps, NeoRp2040PioInstance1> Rp2040x4Pio1400KbpsMethod;
typedef Rp2040x4Pio1Ws2805Method Rp2040x4Pio1Ws2814Method;

#if NUM_PIOS == 3
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2811, NeoRp2040PioInstance2> Rp2040x4Pio2Ws2811Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2812x, NeoRp2040PioInstance2> Rp2040x4Pio2Ws2812xMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2812x, NeoRp2040PioInstance2> Rp2040x4Pio2Ws2816Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2805, NeoRp2040PioInstance2> Rp2040x4Pio2Ws2805Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedSk6812, NeoRp2040PioInstance2> Rp2040x4Pio2Sk6812Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1814, NeoRp2040PioInstance2, true> Rp2040x4Pio2Tm1814Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1829, NeoRp2040PioInstance2, true> Rp2040x4Pio2Tm1829Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1914, NeoRp2040PioInstance2, true> Rp2040x4Pio2Tm1914Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedApa106, NeoRp2040PioInstance2> Rp2040x4Pio2Apa106Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTx1812, NeoRp2040PioInstance2> Rp2040x4Pio2Tx1812Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedGs1903, NeoRp2040PioInstance2> Rp2040x4Pio2Gs1903Method;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed800Kbps, NeoRp2040PioInstance2> Rp2040x4Pio2800KbpsMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed400Kbps, NeoRp2040PioInstance2> Rp2040x4Pio2400KbpsMethod;
typedef Rp2040x4Pio2Ws2805Method Rp2040x4Pio2Ws2814Method;
#endif

// inverted
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2811, NeoRp2040PioInstanceN, true> Rp2040x4NWs2811InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2812x, NeoRp2040PioInstanceN, true> Rp2040x4NWs2812xInvertedMethod;
Expand Down Expand Up @@ -410,6 +427,23 @@ typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed800Kbps, NeoRp2040PioInstance1, t
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed400Kbps, NeoRp2040PioInstance1, true> Rp2040x4Pio1400KbpsInvertedMethod;
typedef Rp2040x4Pio1Ws2805InvertedMethod Rp2040x4Pio1Ws2814InvertedMethod;

#if NUM_PIOS == 3
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2811, NeoRp2040PioInstance2, true> Rp2040x4Pio2Ws2811InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2812x, NeoRp2040PioInstance2, true> Rp2040x4Pio2Ws2812xInvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2812x, NeoRp2040PioInstance2, true> Rp2040x4Pio2Ws2816InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedWs2805, NeoRp2040PioInstance2, true> Rp2040x4Pio2Ws2805InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedSk6812, NeoRp2040PioInstance2, true> Rp2040x4Pio2Sk6812InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1814, NeoRp2040PioInstance2> Rp2040x4Pio2Tm1814InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1829, NeoRp2040PioInstance2> Rp2040x4Pio2Tm1829InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTm1914, NeoRp2040PioInstance2> Rp2040x4Pio2Tm1914InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedApa106, NeoRp2040PioInstance2, true> Rp2040x4Pio2Apa106InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedTx1812, NeoRp2040PioInstance2, true> Rp2040x4Pio2Tx1812InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeedGs1903, NeoRp2040PioInstance2, true> Rp2040x4Pio2Gs1903InvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed800Kbps, NeoRp2040PioInstance2, true> Rp2040x4Pio2800KbpsInvertedMethod;
typedef NeoRp2040x4MethodBase<NeoRp2040PioSpeed400Kbps, NeoRp2040PioInstance2, true> Rp2040x4Pio2400KbpsInvertedMethod;
typedef Rp2040x4Pio2Ws2805InvertedMethod Rp2040x4Pio2Ws2814InvertedMethod;
#endif

// PIO 1 method is the default method, and still x4 instances
typedef Rp2040x4Pio1Ws2812xMethod NeoWs2813Method;
typedef Rp2040x4Pio1Ws2812xMethod NeoWs2812xMethod;
Expand Down