Revamp ESP32 SPI DMA support (#608)

* Renamed all of the SPI buses and provided classes for all of the valid combinations of bus and bit width

* Updated dotstar dma spi example to use new names and to work on all 4 supported esp32 variants
This commit is contained in:
Shlomo Zippel
2023-01-08 13:51:17 -08:00
committed by GitHub
parent 827937d375
commit d2199451c1
2 changed files with 98 additions and 156 deletions

View File

@@ -6,10 +6,28 @@
// There is serial output of the current state so you can confirm and follow along
//
//
// ESP32 SPI Buses and up to how many bits they support:
// ESP32: Spi1 (4 bit) | Spi2 (4 bit) | Spi3 (4 bit)
// ESP32-S2: | Spi2 (8 bit) | Spi3
// ESP32-S3: | Spi2 (8 bit) | Spi3 (4 bit)
// ESP32-C3: | Spi2 (4 bit) |
//
// If a DotStarEsp32DmaSpi method is used without specifying the bus number
// then Spi2 will be used by default
//
// In this demo if an alternate SPI bus is chosen then Spi3 will be used
#include <NeoPixelBus.h>
#define USE_DEFAULT_SPI_PORT 1
// C3 only has a single Spi bus
#if CONFIG_IDF_TARGET_ESP32C3
#define USE_ALTERNATE_SPI_PORT 0
#else
#define USE_ALTERNATE_SPI_PORT 1
#endif
#if (USE_DEFAULT_SPI_PORT == 1)
const uint16_t PixelCount = 4; // this example assumes 4 pixels, making it smaller will cause a failure
@@ -26,7 +44,7 @@
//NeoPixelBus<DotStarBgrFeature, DotStarMethod> strip(PixelCount, DotClockPin, DotDataPin);
// for hardware SPI (best performance) with default SPI peripheral
NeoPixelBus<DotStarBgrFeature, DotStarEsp32DmaVspiMethod> strip(PixelCount);
NeoPixelBus<DotStarBgrFeature, DotStarEsp32DmaSpiMethod> strip(PixelCount);
// DotStarEsp32DmaVspiMethod defaults to 10MHz clock speed. For other speeds, replace "DotStarSpiMethod" with another method specifying speed, e.g. "DotStarSpi2MhzMethod" (see wiki for more details)
// See DotStarTest_Esp32Advanced example for how to set clock speed at runtime
@@ -44,14 +62,14 @@
const int8_t DotChipSelectPin2 = -1; // -1 means the chip select signal won't be output, freeing up one pin compared to useSpiAlternatePins2=false
// for hardware SPI (best performance) with alternate SPI peripheral
NeoPixelBus<DotStarBgrFeature, DotStarEsp32DmaHspiMethod> strip2(PixelCount2);
NeoPixelBus<DotStarBgrFeature, DotStarEsp32DmaSpi3Method> strip2(PixelCount2);
// DotStarEsp32DmaHspiMethod defaults to 10MHz clock speed. For other speeds, replace "DotStarSpiMethod" with another method specifying speed, e.g. "DotStarHspi2MhzMethod" (see wiki for more details)
#endif
#define colorSaturation 128
// Note that both DotStarEsp32DmaVspiMethod and DotStarEsp32DmaHspiMethod can be used with DotStarLbgrFeature and DotStarWbgrFeature but to keep things simple those are excluded from this example, see DotStarTest for more details
// Note that both DotStarEsp32DmaSpiMethod and DotStarEsp32DmaSpi1Method can be used with DotStarLbgrFeature and DotStarWbgrFeature but to keep things simple those are excluded from this example, see DotStarTest for more details
RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0);

View File

@@ -29,75 +29,13 @@ License along with NeoPixel. If not, see
#include "driver/spi_master.h"
#if (defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)) && !defined(HSPI_HOST)
// HSPI_HOST depreciated in C3 & S3
#define HSPI_HOST SPI2_HOST
#endif
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
class Esp32VspiBus
{
public:
const static spi_host_device_t SpiHostDevice = VSPI_HOST;
const static int ParallelBits = 1;
};
#endif
class Esp32HspiBus
{
public:
const static spi_host_device_t SpiHostDevice = HSPI_HOST;
const static int ParallelBits = 1;
};
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
class Esp32Vspi2BitBus
{
public:
const static spi_host_device_t SpiHostDevice = VSPI_HOST;
const static int ParallelBits = 2;
};
#endif
class Esp32Hspi2BitBus
{
public:
const static spi_host_device_t SpiHostDevice = HSPI_HOST;
const static int ParallelBits = 2;
};
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
class Esp32Vspi4BitBus
{
public:
const static spi_host_device_t SpiHostDevice = VSPI_HOST;
const static int ParallelBits = 4;
};
#endif
class Esp32Hspi4BitBus
{
public:
const static spi_host_device_t SpiHostDevice = HSPI_HOST;
const static int ParallelBits = 4;
};
#if defined(CONFIG_IDF_TARGET_ESP32S3)
class Esp32Hspi8BitBus
{
public:
const static spi_host_device_t SpiHostDevice = HSPI_HOST;
const static int ParallelBits = 8;
};
#endif
template<typename T_SPISPEED, typename T_SPIBUS> class DotStarEsp32DmaSpiMethod
template<typename T_SPISPEED, typename T_SPIBUS> class _DotStarEsp32DmaSpiMethod
{
public:
typedef typename T_SPISPEED::SettingsObject SettingsObject;
DotStarEsp32DmaSpiMethod(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_DotStarEsp32DmaSpiMethod(uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_sizePixelData(pixelCount * elementSize + settingsSize),
_sizeEndFrame((pixelCount + 15) / 16) // 16 = div 2 (bit for every two pixels) div 8 (bits to bytes)
{
@@ -117,12 +55,12 @@ public:
}
// Support constructor specifying pins by ignoring pins
DotStarEsp32DmaSpiMethod(uint8_t, uint8_t, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
DotStarEsp32DmaSpiMethod(pixelCount, elementSize, settingsSize)
_DotStarEsp32DmaSpiMethod(uint8_t, uint8_t, uint16_t pixelCount, size_t elementSize, size_t settingsSize) :
_DotStarEsp32DmaSpiMethod(pixelCount, elementSize, settingsSize)
{
}
~DotStarEsp32DmaSpiMethod()
~_DotStarEsp32DmaSpiMethod()
{
if (_spiHandle)
{
@@ -302,94 +240,80 @@ private:
int8_t _ssPin;
};
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
// Clock Speed and Default Definitions for DotStarEsp32DmaVspi
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz, Esp32VspiBus> DotStarEsp32DmaVspi40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz, Esp32VspiBus> DotStarEsp32DmaVspi20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32VspiBus> DotStarEsp32DmaVspi10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz, Esp32VspiBus> DotStarEsp32DmaVspi5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz, Esp32VspiBus> DotStarEsp32DmaVspi2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz, Esp32VspiBus> DotStarEsp32DmaVspi1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz, Esp32VspiBus> DotStarEsp32DmaVspi500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz, Esp32VspiBus> DotStarEsp32DmaVspiHzMethod;
typedef DotStarEsp32DmaVspi10MhzMethod DotStarEsp32DmaVspiMethod;
// Unfortunately we have a bit of a mess with SPI bus names across different version of the ESP32
// e.g ESP32 has SPI, HSPI, and VSPI (1, 2, and 3), ESP32-S2 has SPI, FSPI, and HSPI (1, 2, and 3)
// and the S3 and C3 dropped the silly names entirely and just uses SPI1, SPI2, and SPI3.
//
// SPI1 can be only be used by ESP32 and supports up to 4 bit
// SPI2 supports up to 4 bit output across all of those devices (!) and supports 8 bit on S2 and S3
// SPI3 supports up to 4 bit output on ESP32 and S3, and 1 bit only on the S2
enum spi_bus_width_t {
WIDTH1 = 1,
WIDTH2 = 2,
WIDTH4 = 4,
WIDTH8 = 8,
};
template <spi_host_device_t bus, spi_bus_width_t bits=WIDTH1>
struct Esp32SpiBus
{
const static spi_host_device_t SpiHostDevice = bus;
const static int ParallelBits = bits;
};
// Define all valid ESP32 SPI Buses with a default speed
// SPI1 -- ESP32 Only
#if defined(CONFIG_IDF_TARGET_ESP32)
typedef Esp32SpiBus<SPI1_HOST, WIDTH1> Esp32Spi1Bus;
typedef Esp32SpiBus<SPI1_HOST, WIDTH2> Esp32Spi12BitBus;
typedef Esp32SpiBus<SPI1_HOST, WIDTH4> Esp32Spi14BitBus;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi1Bus> DotStarEsp32DmaSpi1Method;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi12BitBus> DotStarEsp32DmaSpi12BitMethod;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi14BitBus> DotStarEsp32DmaSpi14BitMethod;
#endif
// Clock Speed and Default Definitions for DotStarEsp32DmaHspi
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz, Esp32HspiBus> DotStarEsp32DmaHspi40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz, Esp32HspiBus> DotStarEsp32DmaHspi20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32HspiBus> DotStarEsp32DmaHspi10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz, Esp32HspiBus> DotStarEsp32DmaHspi5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz, Esp32HspiBus> DotStarEsp32DmaHspi2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz, Esp32HspiBus> DotStarEsp32DmaHspi1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz, Esp32HspiBus> DotStarEsp32DmaHspi500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz, Esp32HspiBus> DotStarEsp32DmaHspiHzMethod;
typedef DotStarEsp32DmaHspi10MhzMethod DotStarEsp32DmaHspiMethod;
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
// Clock Speed and Default Definitions for DotStarEsp32DmaVspi2Bit
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2Bit500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz,Esp32Vspi2BitBus> DotStarEsp32DmaVspi2BitHzMethod;
typedef DotStarEsp32DmaVspi2Bit10MhzMethod DotStarEsp32DmaVspi2BitMethod;
#endif
// Clock Speed and Default Definitions for DotStarEsp32DmaHspi2Bit
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2Bit500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz,Esp32Hspi2BitBus> DotStarEsp32DmaHspi2BitHzMethod;
typedef DotStarEsp32DmaHspi2Bit10MhzMethod DotStarEsp32DmaHspi2BitMethod;
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
// Clock Speed and Default Definitions for DotStarEsp32DmaVspi4Bit
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4Bit500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz,Esp32Vspi4BitBus> DotStarEsp32DmaVspi4BitHzMethod;
typedef DotStarEsp32DmaVspi4Bit10MhzMethod DotStarEsp32DmaVspi4BitMethod;
#endif
// Clock Speed and Default Definitions for DotStarEsp32DmaHspi4Bit
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4Bit500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz,Esp32Hspi4BitBus> DotStarEsp32DmaHspi4BitHzMethod;
typedef DotStarEsp32DmaHspi4Bit10MhzMethod DotStarEsp32DmaHspi4BitMethod;
// SPI2
typedef Esp32SpiBus<SPI2_HOST, WIDTH1> Esp32Spi2Bus;
typedef Esp32SpiBus<SPI2_HOST, WIDTH2> Esp32Spi22BitBus;
typedef Esp32SpiBus<SPI2_HOST, WIDTH4> Esp32Spi24BitBus;
#if SOC_SPI_SUPPORT_OCT
// Clock Speed and Default Definitions for DotStarEsp32DmaHspi8Bit
typedef DotStarEsp32DmaSpiMethod<SpiSpeed40Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit40MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed20Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit20MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit10MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed5Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit5MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed2Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit2MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed1Mhz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit1MhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeed500Khz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8Bit500KhzMethod;
typedef DotStarEsp32DmaSpiMethod<SpiSpeedHz,Esp32Hspi8BitBus> DotStarEsp32DmaHspi8BitHzMethod;
typedef Esp32SpiBus<SPI2_HOST, WIDTH8> Esp32Spi28BitBus;
#endif
typedef DotStarEsp32DmaHspi8Bit10MhzMethod DotStarEsp32DmaHspi8BitMethod;
#endif
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi2Bus> DotStarEsp32DmaSpi2Method;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi22BitBus> DotStarEsp32DmaSpi22BitMethod;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi24BitBus> DotStarEsp32DmaSpi24BitMethod;
#if SOC_SPI_SUPPORT_OCT
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi28BitBus> DotStarEsp32DmaSpi28BitMethod;
#endif
// SPI3
#if (defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3))
typedef Esp32SpiBus<SPI3_HOST, WIDTH1> Esp32Spi3Bus;
typedef Esp32SpiBus<SPI3_HOST, WIDTH2> Esp32Spi32BitBus;
typedef Esp32SpiBus<SPI3_HOST, WIDTH4> Esp32Spi34BitBus;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi3Bus> DotStarEsp32DmaSpi3Method;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi32BitBus> DotStarEsp32DmaSpi32BitMethod;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi34BitBus> DotStarEsp32DmaSpi34BitMethod;
#endif
#if defined(CONFIG_IDF_TARGET_ESP32S2)
typedef Esp32SpiBus<SPI3_HOST, WIDTH1> Esp32Spi3Bus;
typedef _DotStarEsp32DmaSpiMethod<SpiSpeed10Mhz, Esp32Spi3Bus> DotStarEsp32DmaSpi3Method;
#endif
// Default SpiDma methods if we don't care about bus. It's nice that every single ESP32 out there
// supports up to 4 bits on SPI2
typedef DotStarEsp32DmaSpi2Method DotStarEsp32DmaSpiMethod;
typedef DotStarEsp32DmaSpi22BitMethod DotStarEsp32DmaSpi2BitMethod;
typedef DotStarEsp32DmaSpi24BitMethod DotStarEsp32DmaSpi4BitMethod;
#if SOC_SPI_SUPPORT_OCT
typedef DotStarEsp32DmaSpi28BitMethod DotStarEsp32DmaSpi8BitMethod;
#endif