ESP32 Hardware SPI Improvements - Options for using both SPI peripherals, and DMA (#441)

* Fix header file comment

* Add TwoWireHspiImpl and Example

* Add start of TwoWireEsp32DmaSpiImple (Currently just able to use HSPI and VSPI in parallel, no DMA)

* Update names for TwoWireEsp32DmaSpi and set set spi_bus using template not constructor

* Update example with new functionality and bugfixes

* DotStarEsp32DmaSpiMethod -

* Add 5MHz option to all SPI-based classes

* DotStarGenericMethod - Give option to use Vspi alias of Spi class if wanting to specify which SPI peripheral is used on the ESP32
- Add missing DotStarHspiHzMethod

* TwoWireHspiImple - bring up to date with applySettings() method

* DotStarTest_Esp32Advanced example - update to show how to change clock speed at runtime
- Remove commented out pins cluttering up example

* DotStarTest_Esp32DmaSpi example -

Co-authored-by: Louis Beaudoin <louis@embedded-creations.com>
This commit is contained in:
Louis Beaudoin
2021-04-12 22:59:09 +01:00
committed by GitHub
parent cc17ec6fa1
commit b90992fdc2
11 changed files with 783 additions and 3 deletions

View File

@@ -0,0 +1,159 @@
// DotStarTest_Esp32Advanced - This example only works on the ESP32
// This example will cycle between showing four pixels as Red, Green, Blue, White
// and then showing those pixels as Black. This example uses Hardware SPI on the ESP32
// with options to use alternate pins for SPI and drive two SPI ports using the alternate
// additional SPI hardware available on the ESP32.
//
// There is serial output of the current state so you can confirm and follow along
//
#include <NeoPixelBus.h>
#define USE_DEFAULT_SPI_PORT 1
#define USE_ALTERNATE_SPI_PORT 1
#if (USE_DEFAULT_SPI_PORT == 1)
const uint16_t PixelCount = 4; // this example assumes 4 pixels, making it smaller will cause a failure
// It's usually better to use alternate pins. If set to false, strip will use GPIO 18 for Clock, GPIO 23 for Data, and pin 5 will output a chip select signal
const bool useSpiAlternatePins = true;
// 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 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)
//NeoPixelBus<DotStarBgrFeature, DotStarMethod> strip(PixelCount, DotClockPin, DotDataPin);
// for hardware SPI (best performance) with default SPI peripheral
NeoPixelBus<DotStarBgrFeature, DotStarSpiMethod> strip(PixelCount);
// DotStarSpiMethod defaults to 10MHz clock speed. For other speeds, replace "DotStarSpiMethod" with another method specifying speed, e.g. "DotStarSpi2MhzMethod" (see wiki for more details)
// to change the SPI clock speed during runtime, use the "Hz" clock setting, e.g. DotStarSpiHzMethod, which default to 10MHz but supports updating during runtime
//NeoPixelBus<DotStarBgrFeature, DotStarSpiHzMethod> strip(PixelCount);
//#define SET_CLOCK_SPEED_DURING_RUNTIME // only define if using "Hz" clock method
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
const uint16_t PixelCount2 = 4; // this example assumes 4 pixels, making it smaller will cause a failure
// It's usually better to use alternate pins. If set to false, strip2 will use GPIO 14 for Clock, GPIO 13 for Data, and pin 15 will output a chip select signal
const bool useSpiAlternatePins2 = true;
// If you set useSpiAlternatePins2 true, then these pins will be used instead. Any output-capable GPIO can be used.
const uint8_t DotClockPin2 = 14;
const uint8_t DotDataPin2 = 13;
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, DotStarHspiMethod> strip2(PixelCount2);
// DotStarHspiMethod 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 DotStarSpiMethod and DotStarHspiMethod 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);
RgbColor blue(0, 0, colorSaturation);
RgbColor white(colorSaturation);
RgbColor black(0);
void setup()
{
Serial.begin(115200);
while (!Serial); // wait for serial attach
Serial.println();
Serial.println("Initializing...");
Serial.flush();
#if (USE_DEFAULT_SPI_PORT == 1)
if (useSpiAlternatePins)
{
strip.Begin(DotClockPin, DotDataPin, DotDataPin, DotChipSelectPin);
}
else
{
strip.Begin();
}
strip.ClearTo(black); // this resets all the DotStars to an off state
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
if (useSpiAlternatePins2)
{
strip2.Begin(DotClockPin2, DotDataPin2, DotDataPin2, DotChipSelectPin2);
}
else
{
strip2.Begin();
}
strip2.ClearTo(black); // this resets all the DotStars to an off state
strip2.Show();
#endif
Serial.println();
Serial.println("Running...");
}
void loop()
{
delay(5000);
#if (USE_DEFAULT_SPI_PORT == 1)
Serial.println("Default SPI Colors R, G, B, W...");
// set the colors,
strip.SetPixelColor(0, red);
strip.SetPixelColor(1, green);
strip.SetPixelColor(2, blue);
strip.SetPixelColor(3, white);
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
Serial.println("Alt SPI Colors W, B, G, R...");
// set the colors,
strip2.SetPixelColor(0, white);
strip2.SetPixelColor(1, blue);
strip2.SetPixelColor(2, green);
strip2.SetPixelColor(3, red);
strip2.Show();
#endif
delay(5000);
Serial.println("Off ...");
#if (USE_DEFAULT_SPI_PORT == 1)
#ifdef SET_CLOCK_SPEED_DURING_RUNTIME
uint32_t clockspeed = 5000000UL;
strip.SetMethodSettings(NeoSpiSettings(clockspeed));
#endif
// turn off the pixels
strip.SetPixelColor(0, black);
strip.SetPixelColor(1, black);
strip.SetPixelColor(2, black);
strip.SetPixelColor(3, black);
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
// turn off the pixels
strip2.SetPixelColor(0, black);
strip2.SetPixelColor(1, black);
strip2.SetPixelColor(2, black);
strip2.SetPixelColor(3, black);
strip2.Show();
#endif
}

View File

@@ -0,0 +1,148 @@
// DotStarTest_Esp32Advanced - This example only works on the ESP32
// This example will cycle between showing four pixels as Red, Green, Blue, White
// and then showing those pixels as Black. This example uses DMA to drive Hardware SPI on the ESP32
// with options to use alternate pins for SPI and drive two SPI ports
//
// There is serial output of the current state so you can confirm and follow along
//
#include <NeoPixelBus.h>
#define USE_DEFAULT_SPI_PORT 1
#define USE_ALTERNATE_SPI_PORT 1
#if (USE_DEFAULT_SPI_PORT == 1)
const uint16_t PixelCount = 4; // this example assumes 4 pixels, making it smaller will cause a failure
// It's usually better to use alternate pins. If set to false, strip will use GPIO 18 for Clock, GPIO 23 for Data, and pin 5 will output a chip select signal
const bool useSpiAlternatePins = true;
// 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 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)
//NeoPixelBus<DotStarBgrFeature, DotStarMethod> strip(PixelCount, DotClockPin, DotDataPin);
// for hardware SPI (best performance) with default SPI peripheral
NeoPixelBus<DotStarBgrFeature, DotStarEsp32DmaVspiMethod> 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
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
const uint16_t PixelCount2 = 4; // this example assumes 4 pixels, making it smaller will cause a failure
// It's usually better to use alternate pins. If set to false, strip2 will use GPIO 14 for Clock, GPIO 13 for Data, and pin 15 will output a chip select signal
const bool useSpiAlternatePins2 = true;
// If you set useSpiAlternatePins2 true, then these pins will be used instead. Any output-capable GPIO can be used.
const uint8_t DotClockPin2 = 14;
const uint8_t DotDataPin2 = 13;
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);
// 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
RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0);
RgbColor blue(0, 0, colorSaturation);
RgbColor white(colorSaturation);
RgbColor black(0);
void setup()
{
Serial.begin(115200);
while (!Serial); // wait for serial attach
Serial.println();
Serial.println("Initializing...");
Serial.flush();
#if (USE_DEFAULT_SPI_PORT == 1)
if (useSpiAlternatePins)
{
strip.Begin(DotClockPin, DotDataPin, DotDataPin, DotChipSelectPin);
}
else
{
strip.Begin();
}
strip.ClearTo(black); // this resets all the DotStars to an off state
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
if (useSpiAlternatePins2)
{
strip2.Begin(DotClockPin2, DotDataPin2, DotDataPin2, DotChipSelectPin2);
}
else
{
strip2.Begin();
}
strip2.ClearTo(black); // this resets all the DotStars to an off state
strip2.Show();
#endif
Serial.println();
Serial.println("Running...");
}
void loop()
{
delay(500);
#if (USE_DEFAULT_SPI_PORT == 1)
Serial.println("Default SPI Colors R, G, B, W...");
// set the colors,
strip.SetPixelColor(0, red);
strip.SetPixelColor(1, green);
strip.SetPixelColor(2, blue);
strip.SetPixelColor(3, white);
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
Serial.println("Alt SPI Colors W, B, G, R...");
// set the colors,
strip2.SetPixelColor(0, white);
strip2.SetPixelColor(1, blue);
strip2.SetPixelColor(2, green);
strip2.SetPixelColor(3, red);
strip2.Show();
#endif
delay(500);
Serial.println("Off ...");
#if (USE_DEFAULT_SPI_PORT == 1)
// turn off the pixels
strip.SetPixelColor(0, black);
strip.SetPixelColor(1, black);
strip.SetPixelColor(2, black);
strip.SetPixelColor(3, black);
strip.Show();
#endif
#if (USE_ALTERNATE_SPI_PORT == 1)
// turn off the pixels
strip2.SetPixelColor(0, black);
strip2.SetPixelColor(1, black);
strip2.SetPixelColor(2, black);
strip2.SetPixelColor(3, black);
strip2.Show();
#endif
}

View File

@@ -104,6 +104,7 @@ License along with NeoPixel. If not, see
#include "internal/NeoEsp32I2sMethod.h"
#include "internal/NeoEsp32RmtMethod.h"
#include "internal/NeoEspBitBangMethod.h"
#include "internal/DotStarEsp32DmaSpiMethod.h"
#elif defined(ARDUINO_ARCH_NRF52840) // must be before __arm__
@@ -172,13 +173,20 @@ public:
ClearTo(0);
}
// used by DotStartSpiMethod if pins can be configured
// used by DotStarSpiMethod/DotStarEsp32DmaSpiMethod if pins can be configured
void Begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
_method.Initialize(sck, miso, mosi, ss);
ClearTo(0);
}
// used by DotStarEsp32DmaSpiMethod if pins can be configured - reordered and extended version supporting quad SPI
void Begin(int8_t sck, int8_t dat0, int8_t dat1, int8_t dat2, int8_t dat3, int8_t ss)
{
_method.Initialize(sck, dat0, dat1, dat2, dat3, ss);
ClearTo(0);
}
void Show(bool maintainBufferConsistency = true)
{
if (!IsDirty())

View File

@@ -0,0 +1,335 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for DotStars using Esp32, DMA and SPI (APA102).
Written by Michael C. Miller.
DotStarEsp32DmaSpiMethod written by Louis Beaudoin (Pixelvation)
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/>.
-------------------------------------------------------------------------*/
#pragma once
#include "driver/spi_master.h"
class Esp32VspiBus
{
public:
static const spi_host_device_t SpiHostDevice = VSPI_HOST;
static const int dmaChannel = 1; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 1;
};
class Esp32HspiBus
{
public:
static const spi_host_device_t SpiHostDevice = HSPI_HOST;
static const int dmaChannel = 2; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 1;
};
class Esp32Vspi2BitBus
{
public:
static const spi_host_device_t SpiHostDevice = VSPI_HOST;
static const int dmaChannel = 1; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 2;
};
class Esp32Hspi2BitBus
{
public:
static const spi_host_device_t SpiHostDevice = HSPI_HOST;
static const int dmaChannel = 2; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 2;
};
class Esp32Vspi4BitBus
{
public:
static const spi_host_device_t SpiHostDevice = VSPI_HOST;
static const int dmaChannel = 1; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 4;
};
class Esp32Hspi4BitBus
{
public:
static const spi_host_device_t SpiHostDevice = HSPI_HOST;
static const int dmaChannel = 2; // arbitrary assignment, but based on the fact there are only two DMA channels and two available SPI ports, we need to split them somehow
static const int parallelBits = 4;
};
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) :
_sizePixelData(pixelCount * elementSize + settingsSize),
_sizeEndFrame((pixelCount + 15) / 16) // 16 = div 2 (bit for every two pixels) div 8 (bits to bytes)
{
_spiBufferSize = _sizeStartFrame + _sizePixelData + _sizeEndFrame;
// must have a 4 byte aligned buffer for i2s
uint32_t alignment = _spiBufferSize % 4;
if (alignment)
{
_spiBufferSize += 4 - alignment;
}
_data = static_cast<uint8_t*>(malloc(_spiBufferSize));
_dmadata = static_cast<uint8_t*>(heap_caps_malloc(_spiBufferSize, MALLOC_CAP_DMA));
// data cleared later in NeoPixelBus::Begin()
}
// 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()
{
if (_spiHandle)
{
DeInitSpiDevice();
esp_err_t ret = spi_bus_free(T_SPIBUS::SpiHostDevice);
ESP_ERROR_CHECK(ret);
}
free(_data);
free(_dmadata);
_spiHandle = NULL;
}
bool IsReadyToUpdate() const
{
spi_transaction_t t;
spi_transaction_t * tptr = &t;
esp_err_t ret = spi_device_get_trans_result(_spiHandle, &tptr, 0);
// We know the previous transaction completed if we got ESP_OK, and we know there's no transactions queued if tptr is unmodified
return (ret == ESP_OK || tptr == &t);
}
void Initialize(int8_t sck, int8_t dat0, int8_t dat1, int8_t dat2, int8_t dat3, int8_t ss)
{
memset(_data, 0x00, _sizeStartFrame);
memset(_data + _sizeStartFrame + _sizePixelData, 0x00, _spiBufferSize - (_sizeStartFrame + _sizePixelData));
_ssPin = ss;
esp_err_t ret;
spi_bus_config_t buscfg;
memset(&buscfg, 0x00, sizeof(buscfg));
buscfg.miso_io_num = dat1;
buscfg.mosi_io_num = dat0;
buscfg.sclk_io_num = sck;
buscfg.quadwp_io_num = dat2;
buscfg.quadhd_io_num = dat3;
buscfg.max_transfer_sz = _spiBufferSize;
//Initialize the SPI bus
ret=spi_bus_initialize(T_SPIBUS::SpiHostDevice, &buscfg, T_SPIBUS::dmaChannel);
ESP_ERROR_CHECK(ret);
InitSpiDevice();
}
void Initialize(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
Initialize(sck, mosi, miso, -1, -1, ss);
}
// If pins aren't specified, initialize bus with just the default SCK and MOSI pins for the SPI peripheral (no SS, no >1-bit pins)
void Initialize()
{
if (T_SPIBUS::SpiHostDevice == VSPI_HOST)
{
Initialize(SCK, -1, MOSI, -1, -1, -1);
}
else
{
Initialize(14, -1, 13, -1, -1, -1);
}
}
void Update(bool)
{
while(!IsReadyToUpdate());
memcpy(_dmadata, _data, _spiBufferSize);
memset(&_spiTransaction, 0, sizeof(spi_transaction_t));
_spiTransaction.length = (_spiBufferSize) * 8; // in bits not bytes!
if (T_SPIBUS::parallelBits == 1)
{
_spiTransaction.flags = 0;
}
if (T_SPIBUS::parallelBits == 2)
{
_spiTransaction.flags = SPI_TRANS_MODE_DIO;
}
if (T_SPIBUS::parallelBits == 4)
{
_spiTransaction.flags = SPI_TRANS_MODE_QIO;
}
_spiTransaction.tx_buffer = _dmadata;
esp_err_t ret = spi_device_queue_trans(_spiHandle, &_spiTransaction, 0); //Transmit!
assert(ret == ESP_OK); //Should have had no issues.
}
uint8_t* getData() const
{
return _data + _sizeStartFrame;
};
size_t getDataSize() const
{
return _sizePixelData;
};
void applySettings(const SettingsObject& settings)
{
_speed.applySettings(settings);
if (_spiHandle)
{
DeInitSpiDevice();
InitSpiDevice();
}
}
private:
void InitSpiDevice()
{
spi_device_interface_config_t devcfg = {};
devcfg.clock_speed_hz = _speed.Clock;
devcfg.mode = 0; //SPI mode 0
devcfg.spics_io_num = _ssPin; //CS pin
devcfg.queue_size = 1;
if (T_SPIBUS::parallelBits == 1)
{
devcfg.flags=0;
}
if (T_SPIBUS::parallelBits >= 2)
{
devcfg.flags=SPI_DEVICE_HALFDUPLEX;
}
//Allocate the LEDs on the SPI bus
esp_err_t ret=spi_bus_add_device(T_SPIBUS::SpiHostDevice, &devcfg, &_spiHandle);
ESP_ERROR_CHECK(ret);
}
void DeInitSpiDevice()
{
while(!IsReadyToUpdate());
esp_err_t ret = spi_bus_remove_device(_spiHandle);
ESP_ERROR_CHECK(ret);
}
const size_t _sizeStartFrame = 4;
const size_t _sizePixelData; // Size of '_data' buffer below, minus (_sizeStartFrame + _sizeEndFrame)
const size_t _sizeEndFrame;
size_t _spiBufferSize;
uint8_t* _data; // Holds start/end frames and LED color values
uint8_t* _dmadata; // Holds start/end frames and LED color values
spi_device_handle_t _spiHandle = NULL;
spi_transaction_t _spiTransaction;
T_SPISPEED _speed;
int8_t _ssPin;
};
// 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;
// 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;
// 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;
// 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;
// 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;
// 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;

View File

@@ -134,14 +134,37 @@ typedef DotStarMethodBase<TwoWireBitBangImple> DotStarMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> DotStarSpi40MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> DotStarSpi20MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> DotStarSpi10MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> DotStarSpi5MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> DotStarSpi2MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> DotStarSpi1MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed500Khz>> DotStarSpi500KhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeedHz>> DotStarSpiHzMethod;
typedef DotStarSpi10MhzMethod DotStarSpiMethod;
#endif
#if defined(ARDUINO_ARCH_ESP32)
// Give option to use Vspi alias of Spi class if wanting to specify which SPI peripheral is used on the ESP32
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed40Mhz>> DotStarVspi40MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> DotStarVspi20MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> DotStarVspi10MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> DotStarVspi5MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> DotStarVspi2MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> DotStarVspi1MhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeed500Khz>> DotStarVspi500KhzMethod;
typedef DotStarMethodBase<TwoWireSpiImple<SpiSpeedHz>> DotStarVspiHzMethod;
typedef DotStarSpi10MhzMethod DotStarVspiMethod;
#include "TwoWireHspiImple.h"
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed40Mhz>> DotStarHspi40MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed20Mhz>> DotStarHspi20MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed10Mhz>> DotStarHspi10MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed5Mhz>> DotStarHspi5MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed2Mhz>> DotStarHspi2MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed1Mhz>> DotStarHspi1MhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeed500Khz>> DotStarHspi500KhzMethod;
typedef DotStarMethodBase<TwoWireHspiImple<SpiSpeedHz>> DotStarHspiHzMethod;
typedef DotStarHspi10MhzMethod DotStarHspiMethod;
#endif

View File

@@ -129,6 +129,7 @@ typedef Lpd6803MethodBase<TwoWireBitBangImple> Lpd6803Method;
#include "TwoWireSpiImple.h"
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Lpd6803Spi20MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Lpd6803Spi10MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> Lpd6803Spi5MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Lpd6803Spi2MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Lpd6803Spi1MhzMethod;
typedef Lpd6803MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Lpd6803Spi500KhzMethod;

View File

@@ -129,6 +129,7 @@ typedef Lpd8806MethodBase<TwoWireBitBangImple> Lpd8806Method;
#include "TwoWireSpiImple.h"
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> Lpd8806Spi20MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> Lpd8806Spi10MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> Lpd8806Spi5MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> Lpd8806Spi2MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> Lpd8806Spi1MhzMethod;
typedef Lpd8806MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> Lpd8806Spi500KhzMethod;

View File

@@ -125,6 +125,7 @@ typedef P9813MethodBase<TwoWireBitBangImple> P9813Method;
#include "TwoWireSpiImple.h"
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> P9813Spi20MhzMethod;
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> P9813Spi10MhzMethod;
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> P9813Spi5MhzMethod;
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> P9813Spi2MhzMethod;
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> P9813Spi1MhzMethod;
typedef P9813MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> P9813Spi500KhzMethod;

View File

@@ -0,0 +1,92 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for DotStars using ESP32's alternate SPI (HSPI) (APA102/LPD8806).
Written by Michael C. Miller.
Minor changes adapting TwoWireSpiImple to support HSPI by Louis Beaudoin (Pixelvation)
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/>.
-------------------------------------------------------------------------*/
#pragma once
#include <SPI.h>
template<typename T_SPISPEED> class TwoWireHspiImple
{
public:
typedef typename T_SPISPEED::SettingsObject SettingsObject;
TwoWireHspiImple(uint8_t, uint8_t) // clock and data pins ignored for hardware SPI
{
_hspi = new SPIClass(HSPI);
}
~TwoWireHspiImple()
{
_hspi->end();
delete _hspi;
}
#if defined(ARDUINO_ARCH_ESP32)
// for cases where hardware SPI can have pins changed
void begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
_hspi->begin(sck, miso, mosi, ss);
}
#endif
void begin()
{
_hspi->begin();
}
void beginTransaction()
{
_hspi->beginTransaction(SPISettings(_speed.Clock, MSBFIRST, SPI_MODE0));
}
void endTransaction()
{
_hspi->endTransaction();
}
void transmitByte(uint8_t data)
{
_hspi->transfer(data);
}
void transmitBytes(const uint8_t* data, size_t dataSize)
{
// ESPs have a method to write without inplace overwriting the send buffer
// since we don't care what gets received, use it for performance
// FIX: but for what ever reason on Esp32, its not const
_hspi->writeBytes(const_cast<uint8_t*>(data), dataSize);
}
void applySettings(const SettingsObject& settings)
{
_speed.applySettings(settings);
}
private:
SPIClass * _hspi = NULL;
T_SPISPEED _speed;
};

View File

@@ -1,5 +1,5 @@
/*-------------------------------------------------------------------------
NeoPixel library helper functions for DotStars using general Pins (APA102/LPD8806).
NeoPixel library helper functions for DotStars using SPI (APA102/LPD8806).
Written by Michael C. Miller.
@@ -61,6 +61,17 @@ public:
static const uint32_t Clock = 10000000L;
};
class SpiSpeed5Mhz
{
public:
typedef NeoNoSettings SettingsObject;
SpiSpeed5Mhz() {};
static void applySettings(const SettingsObject& settings) {}
static const uint32_t Clock = 5000000L;
};
class SpiSpeed2Mhz
{
public:

View File

@@ -131,6 +131,7 @@ typedef Ws2801MethodBase<TwoWireBitBangImple> NeoWs2801Method;
#include "TwoWireSpiImple.h"
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed20Mhz>> NeoWs2801Spi20MhzMethod;
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed10Mhz>> NeoWs2801Spi10MhzMethod;
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed5Mhz>> NeoWs2801Spi5MhzMethod;
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed2Mhz>> NeoWs2801Spi2MhzMethod;
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed1Mhz>> NeoWs2801Spi1MhzMethod;
typedef Ws2801MethodBase<TwoWireSpiImple<SpiSpeed500Khz>> NeoWs2801Spi500KhzMethod;